K8S学习笔记之Kubernetes 部署策略详解

 

0x00 概述

Kubernetes中有几种不一样的方式发布应用,因此为了让应用在升级期间依然平稳提供服务,选择一个正确的发布策略就很是重要了。git

选择正确的部署策略是要依赖于咱们的业务需求的,下面咱们列出了一些可能会使用到的策略:github

  • 重建(recreate):中止旧版本部署新版本api

  • 滚动更新(rolling-update):一个接一个地以滚动更新方式发布新版本cookie

  • 蓝绿(blue/green):新版本与旧版本一块儿存在,而后切换流量app

  • 金丝雀(canary):将新版本面向一部分用户发布,而后继续全量发布负载均衡

  • A/B测(a/b testing):以精确的方式(HTTP 头、cookie、权重等)向部分用户发布新版本。A/B测其实是一种基于数据统计作出业务决策的技术。在 Kubernetes 中并不原生支持,须要额外的一些高级组件来完成改设置(好比Istio、Linkerd、Traefik、或者自定义 Nginx/Haproxy 等)。curl

你能够在Kubernetes集群上来对上面的这些策略进行测试,下面的仓库中有须要使用到的资源清单:https://github.com/ContainerSolutions/k8s-deployment-strategies分布式

接下来咱们来介绍下每种策略,看看在什么场景下面适合哪一种策略工具

 

0x01 重建(Recreate) - 最好在开发环境

策略定义为RecreateDeployment,会终止全部正在运行的实例,而后用较新的版原本从新建立它们。post

spec:
  replicas: 3
  strategy:
    type: Recreate

从新建立策略是一个虚拟部署,包括关闭版本A,而后在关闭版本A后部署版本B. 此技术意味着服务的停机时间取决于应用程序的关闭和启动持续时间。

咱们这里建立两个相关的资源清单文件,app-v1.yaml:

apiVersion: v1
kind: Service
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    targetPort: http
  selector:
    app: my-app
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
        version: v1.0.0
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9101"
    spec:
      containers:
      - name: my-app
        image: containersol/k8s-deployment-strategies
        ports:
        - name: http
          containerPort: 8080
        - name: probe
          containerPort: 8086
        env:
        - name: VERSION
          value: v1.0.0
        livenessProbe:
          httpGet:
            path: /live
            port: probe
          initialDelaySeconds: 5
          periodSeconds: 5
        readinessProbe:
          httpGet:
            path: /ready
            port: probe
          periodSeconds: 5

app-v2.yaml 文件内容以下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  replicas: 3
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
        version: v2.0.0
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9101"
    spec:
      containers:
      - name: my-app
        image: containersol/k8s-deployment-strategies
        ports:
        - name: http
          containerPort: 8080
        - name: probe
          containerPort: 8086
        env:
        - name: VERSION
          value: v2.0.0
        livenessProbe:
          httpGet:
            path: /live
            port: probe
          initialDelaySeconds: 5
          periodSeconds: 5
        readinessProbe:
          httpGet:
            path: /ready
            port: probe
          periodSeconds: 5

上面两个资源清单文件中的 Deployment 定义几乎是一直的,惟一不一样的是定义的环境变量VERSION值不一样,接下来按照下面的步骤来验证Recreate策略:

  1. 版本1提供服务
  2. 删除版本1
  3. 部署版本2
  4. 等待全部副本准备就绪

首先部署第一个应用:

$ kubectl apply -f app-v1.yaml
service "my-app" created
deployment.apps "my-app" created

测试版本1是否部署成功:

$ kubectl get pods -l app=my-app
NAME                      READY     STATUS    RESTARTS   AGE
my-app-7b4874cd75-m5kct   1/1       Running   0          19m
my-app-7b4874cd75-pc444   1/1       Running   0          19m
my-app-7b4874cd75-tlctl   1/1       Running   0          19m
$ kubectl get svc my-app
NAME      TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
my-app    NodePort   10.108.238.76   <none>        80:32532/TCP   5m
$ curl http://127.0.0.1:32532
Host: my-app-7b4874cd75-pc444, Version: v1.0.0

能够看到版本1的应用正常运行了。为了查看部署的运行状况,打开一个新终端并运行如下命令:

$ watch kubectl get pods -l app=my-app

而后部署版本2的应用:

$ kubectl apply -f app-v2.yaml

这个时候能够观察上面新开的终端中的 Pod 列表的变化,能够看到以前的3个 Pod 都会先处于Terminating状态,而且3个 Pod 都被删除后才开始建立新的 Pod。

而后测试第二个版本应用的部署进度:

$ while sleep 0.1; do curl http://127.0.0.1:32532; done
curl: (7) Failed connect to 127.0.0.1:32532; Connection refused
curl: (7) Failed connect to 127.0.0.1:32532; Connection refused
......
Host: my-app-f885c8d45-sp44p, Version: v2.0.0
Host: my-app-f885c8d45-t8g7g, Version: v2.0.0
Host: my-app-f885c8d45-sp44p, Version: v2.0.0
......

能够看到最开始的阶段服务都是处于不可访问的状态,而后到第二个版本的应用部署成功后才正常访问,能够看到如今访问的数据是版本2了。

最后,能够执行下面的命令来清空上面的资源对象:

$ kubectl delete all -l app=my-app

结论:

  • 应用状态所有更新

  • 停机时间取决于应用程序的关闭和启动消耗的时间

 

0x02 滚动更新(rolling-update)

滚动更新经过逐个替换实例来逐步部署新版本的应用,直到全部实例都被替换完成为止。它一般遵循如下过程:在负载均衡器后面使用版本 A 的实例池,而后部署版本 B 的一个实例,当服务准备好接收流量时(Readiness Probe 正常),将该实例添加到实例池中,而后从实例池中删除一个版本 A 的实例并关闭,以下图所示:

下图是滚动更新过程应用接收流量的示意图:

 

下面是 Kubernetes 中经过 Deployment 来进行滚动更新的关键参数:

spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 2        # 一次能够添加多少个Pod
      maxUnavailable: 1  # 滚动更新期间最大多少个Pod不可用

如今仍然使用上面的 app-v1.yaml 这个资源清单文件,新建一个定义滚动更新的资源清单文件 app-v2-rolling-update.yaml,文件内容以下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  replicas: 10
  # maxUnavailable设置为0能够彻底确保在滚动更新期间服务不受影响,还可使用百分比的值来进行设置。
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
        version: v2.0.0
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9101"
    spec:
      containers:
      - name: my-app
        image: containersol/k8s-deployment-strategies
        ports:
        - name: http
          containerPort: 8080
        - name: probe
          containerPort: 8086
        env:
        - name: VERSION
          value: v2.0.0
        livenessProbe:
          httpGet:
            path: /live
            port: probe
          initialDelaySeconds: 5
          periodSeconds: 5
        readinessProbe:
          httpGet:
            path: /ready
            port: probe
          # 初始延迟设置高点能够更好地观察滚动更新过程
          initialDelaySeconds: 15
          periodSeconds: 5

上面的资源清单中咱们在环境变量中定义了版本2,而后经过设置strategy.type=RollingUpdate来定义该 Deployment 使用滚动更新的策略来更新应用,接下来咱们按下面的步骤来验证滚动更新策略:

  1. 版本1提供服务
  2. 部署版本2
  3. 等待直到全部副本都被版本2替换完成

一样,首先部署版本1应用:

$ kubectl apply -f app-v1.yaml
service "my-app" created
deployment.apps "my-app" created

测试版本1是否部署成功:

$ kubectl get pods -l app=my-app
NAME                      READY     STATUS    RESTARTS   AGE
my-app-7b4874cd75-h8c4d   1/1       Running   0          47s
my-app-7b4874cd75-p4l8f   1/1       Running   0          47s
my-app-7b4874cd75-qnt7p   1/1       Running   0          47s
$ kubectl get svc my-app
NAME      TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
my-app    NodePort   10.109.99.184   <none>        80:30486/TCP   1m
$ curl http://127.0.0.1:30486
Host: my-app-7b4874cd75-qnt7p, Version: v1.0.0

一样,在一个新终端中执行下面命令观察 Pod 变化:

$ watch kubectl get pods -l app=my-app

而后部署滚动更新版本2应用

$ kubectl apply -f app-v2-rolling-update.yaml
deployment.apps "my-app" configured

这个时候在上面的 watch 终端中能够看到多了不少 Pod,还在建立当中,并无一开始就删除以前的 Pod,一样,这个时候执行下面命令,测试应用状态:

$ while sleep 0.1; do curl http://127.0.0.1:30486; done
Host: my-app-7b4874cd75-vrlj7, Version: v1.0.0
......
Host: my-app-7b4874cd75-vrlj7, Version: v1.0.0
Host: my-app-6b5479d97f-2fk24, Version: v2.0.0
Host: my-app-7b4874cd75-p4l8f, Version: v1.0.0
......
Host: my-app-6b5479d97f-s5ctz, Version: v2.0.0
Host: my-app-7b4874cd75-5ldqx, Version: v1.0.0
......
Host: my-app-6b5479d97f-5z6ww, Version: v2.0.0

咱们能够看到上面的应用并无出现不可用的状况,最开始访问到的都是版本1的应用,而后偶尔会出现版本2的应用,直到最后全都变成了版本2的应用,而这个时候看上面 watch 终端中 Pod 已经所有变成10个版本2的应用了,咱们能够看到这就是一个逐步替换的过程。

若是在滚动更新过程当中发现新版本应用有问题,咱们能够经过下面的命令来进行一键回滚:

$ kubectl rollout undo deploy my-app
deployment.apps "my-app"

若是你想保持两个版本的应用都存在,那么咱们也能够执行 pause 命令来暂停更新:

$ kubectl rollout pause deploy my-app
deployment.apps "my-app" paused

这个时候咱们再去循环访问咱们的应用就能够看到偶尔会出现版本1的应用信息了。

若是新版本应用程序没问题了,也能够继续恢复更新:

$ kubectl rollout resume deploy my-app
deployment.apps "my-app" resumed

最后,能够执行下面的命令来清空上面的资源对象:

$ kubectl delete all -l app=my-app

结论:

  • 版本在实例之间缓慢替换
  • rollout/rollback 可能须要必定时间
  • 没法控制流量

 

0x03 蓝/绿(blue/green) - 最好用来验证 API 版本问题

蓝/绿发布是版本2 与版本1 一块儿发布,而后流量切换到版本2,也称为红/黑部署。蓝/绿发布与滚动更新不一样,版本2(绿) 与版本1()一块儿部署,在测试新版本知足要求后,而后更新更新 Kubernetes 中扮演负载均衡器角色的 Service 对象,经过替换 label selector 中的版本标签来将流量发送到新版本,以下图所示:

下面是蓝绿发布策略下应用方法的示例图:

在 Kubernetes 中,咱们能够用两种方法来实现蓝绿发布,经过单个 Service 对象或者 Ingress 控制器来实现蓝绿发布,实际操做都是相似的,都是经过 label 标签去控制。

实现蓝绿发布的关键点就在于 Service 对象中 label selector 标签的匹配方法,好比咱们从新定义版本1 的资源清单文件 app-v1-single-svc.yaml,文件内容以下:

 

apiVersion: v1
kind: Service
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    targetPort: http
  # 注意这里咱们匹配 app 和 version 标签,当要切换流量的时候,咱们更新 version 标签的值,好比:v2.0.0
  selector:
    app: my-app
    version: v1.0.0
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app-v1
  labels:
    app: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
      version: v1.0.0
  template:
    metadata:
      labels:
        app: my-app
        version: v1.0.0
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9101"
    spec:
      containers:
      - name: my-app
        image: containersol/k8s-deployment-strategies
        ports:
        - name: http
          containerPort: 8080
        - name: probe
          containerPort: 8086
        env:
        - name: VERSION
          value: v1.0.0
        livenessProbe:
          httpGet:
            path: /live
            port: probe
          initialDelaySeconds: 5
          periodSeconds: 5
        readinessProbe:
          httpGet:
            path: /ready
            port: probe
          periodSeconds: 5

上面定义的资源对象中,最重要的就是 Service 中 label selector 的定义:

selector:
  app: my-app
  version: v1.0.0

版本2 的应用定义和之前同样,新建文件 app-v2-single-svc.yaml,文件内容以下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app-v2
  labels:
    app: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
      version: v2.0.0
  template:
    metadata:
      labels:
        app: my-app
        version: v2.0.0
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9101"
    spec:
      containers:
      - name: my-app
        image: containersol/k8s-deployment-strategies
        ports:
        - name: http
          containerPort: 8080
        - name: probe
          containerPort: 8086
        env:
        - name: VERSION
          value: v2.0.0
        livenessProbe:
          httpGet:
            path: /live
            port: probe
          initialDelaySeconds: 5
          periodSeconds: 5
        readinessProbe:
          httpGet:
            path: /ready
            port: probe
          periodSeconds: 5

而后按照下面的步骤来验证使用单个 Service 对象实现蓝/绿部署的策略:

  1. 版本1 应用提供服务
  2. 部署版本2 应用
  3. 等到版本2 应用所有部署完成
  4. 切换入口流量从版本1 到版本2
  5. 关闭版本1 应用

首先,部署版本1 应用:

$ kubectl apply -f app-v1-single-svc.yaml
service "my-app" created
deployment.apps "my-app-v1" created

测试版本1 应用是否部署成功

$ kubectl get pods -l app=my-app
NAME                         READY     STATUS    RESTARTS   AGE
my-app-v1-7b4874cd75-7xh6s   1/1       Running   0          41s
my-app-v1-7b4874cd75-dmq8f   1/1       Running   0          41s
my-app-v1-7b4874cd75-t64z7   1/1       Running   0          41s
$ kubectl get svc -l app=my-app
NAME      TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
my-app    NodePort   10.106.184.144   <none>        80:31539/TCP   50s
$ curl http://127.0.0.1:31539
Host: my-app-v1-7b4874cd75-7xh6s, Version: v1.0.0

一样,新开一个终端,执行以下命令观察 Pod 变化:

$ watch kubectl get pod -l app=my-app

而后部署版本2 应用:

$ kubectl apply -f app-v2-single-svc.yaml
deployment.apps "my-app-v2" created

而后在上面 watch 终端中能够看到会多3个my-app-v2开头的 Pod,待这些 Pod 部署成功后,咱们再去访问当前的应用:

$ while sleep 0.1; do curl http://127.0.0.1:31539; done
Host: my-app-v1-7b4874cd75-dmq8f, Version: v1.0.0
Host: my-app-v1-7b4874cd75-dmq8f, Version: v1.0.0
......

咱们会发现访问到的都是版本1 的应用,和咱们刚刚部署的版本2 没有任何关系,这是由于咱们 Service 对象中经过 label selector 匹配的是version=v1.0.0这个标签,咱们能够经过修改 Service 对象的匹配标签,将流量路由到标签version=v2.0.0的 Pod 去:

$ kubectl patch service my-app -p '{"spec":{"selector":{"version":"v2.0.0"}}}'
service "my-app" patched

而后再去访问应用,能够发现如今都是版本2 的信息了:

$ while sleep 0.1; do curl http://127.0.0.1:31539; done
Host: my-app-v2-f885c8d45-r5m6z, Version: v2.0.0
Host: my-app-v2-f885c8d45-r5m6z, Version: v2.0.0
......

若是你须要回滚到版本1,一样只须要更改 Service 的匹配标签便可:

$ kubectl patch service my-app -p '{"spec":{"selector":{"version":"v1.0.0"}}}'

若是新版本已经彻底符合咱们的需求了,就能够删除版本1 的应用了:

$ kubectl delete deploy my-app-v1

最后,一样,执行以下命令清理上述资源对象:

$ kubectl delete all -l app=my-app

结论:

  • 实时部署/回滚

  • 避免版本问题,由于一次更改是整个应用的改变

  • 须要两倍的资源

  • 在发布到生产以前,应该对整个应用进行适当的测试

 

0x04 金丝雀(Canary) - 让部分用户参与测试

金丝雀部署是让部分用户访问到新版本应用,在 Kubernetes 中,可使用两个具备相同 Pod 标签的 Deployment 来实现金丝雀部署。新版本的副本和旧版本的一块儿发布。在一段时间后若是没有检测到错误,则能够扩展新版本的副本数量并删除旧版本的应用。

若是须要按照具体的百分比来进行金丝雀发布,须要尽量的启动多的 Pod 副本,这样计算流量百分比的时候才方便,好比,若是你想将 1% 的流量发送到版本 B,那么咱们就须要有一个运行版本 B 的 Pod 和 99 个运行版本 A 的 Pod,固然若是你对具体的控制策略不在乎的话也就无所谓了,若是你须要更精确的控制策略,建议使用服务网格(如 Istio),它们能够更好地控制流量。

在下面的例子中,咱们使用 Kubernetes 原生特性来实现一个穷人版的金丝雀发布,若是你想要对流量进行更加细粒度的控制,请使用豪华版本的 Istio。下面是金丝雀发布的应用请求示意图:

 

接下来咱们按照下面的步骤来验证金丝雀策略:

  1. 10个副本的版本1 应用提供服务
  2. 版本2 应用部署1个副本(意味着小于10%的流量)
  3. 等待足够的时间来确认版本2 应用足够稳定没有任何错误信息
  4. 将版本2 应用扩容到10个副本
  5. 等待全部实例完成
  6. 关闭版本1 应用

 首先,建立版本1 的应用资源清单,app-v1-canary.yaml,内容以下:

 

apiVersion: v1
kind: Service
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    targetPort: http
  selector:
    app: my-app
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app-v1
  labels:
    app: my-app
spec:
  replicas: 10
  selector:
    matchLabels:
      app: my-app
      version: v1.0.0
  template:
    metadata:
      labels:
        app: my-app
        version: v1.0.0
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9101"
    spec:
      containers:
      - name: my-app
        image: containersol/k8s-deployment-strategies
        ports:
        - name: http
          containerPort: 8080
        - name: probe
          containerPort: 8086
        env:
        - name: VERSION
          value: v1.0.0
        livenessProbe:
          httpGet:
            path: /live
            port: probe
          initialDelaySeconds: 5
          periodSeconds: 5
        readinessProbe:
          httpGet:
            path: /ready
            port: probe
          periodSeconds: 5

其中核心的部分也是 Service 对象中的 label selector 标签,不在具备版本相关的标签了,而后定义版本2 的资源清单文件,app-v2-canary.yaml,文件内容以下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app-v2
  labels:
    app: my-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
      version: v2.0.0
  template:
    metadata:
      labels:
        app: my-app
        version: v2.0.0
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9101"
    spec:
      containers:
      - name: my-app
        image: containersol/k8s-deployment-strategies
        ports:
        - name: http
          containerPort: 8080
        - name: probe
          containerPort: 8086
        env:
        - name: VERSION
          value: v2.0.0
        livenessProbe:
          httpGet:
            path: /live
            port: probe
          initialDelaySeconds: 5
          periodSeconds: 5
        readinessProbe:
          httpGet:
            path: /ready
            port: probe
          periodSeconds: 5

版本1 和版本2 的 Pod 都具备一个共同的标签app=my-app,因此对应的 Service 会匹配两个版本的 Pod。

首先,部署版本1 应用:

$ kubectl apply -f app-v1-canary.yaml
service "my-app" created
deployment.apps "my-app-v1" created

而后测试版本1 应用是否正确部署了:

$ kubectl get svc -l app=my-app
NAME          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
my-app        NodePort    10.105.133.213   <none>        80:30760/TCP   47s
$ curl http://127.0.0.1:30760
Host: my-app-v1-7b4874cd75-tsh2s, Version: v1.0.0

一样,新开一个终端,查看 Pod 的变化:

$ watch kubectl get po

而后部署版本2 应用:

$ kubectl apply -f app-v2-canary.yaml
deployment.apps "my-app-v2" created

而后在 watch 终端页面能够看到多了一个 Pod,如今一共 11 个 Pod,其中只有1 个 Pod 运行新版本应用,而后一样能够循环访问该应用,查看是否会有版本2 的应用信息:

$ while sleep 0.1; do curl http://127.0.0.1:30760; done
Host: my-app-v1-7b4874cd75-bhxbp, Version: v1.0.0
Host: my-app-v1-7b4874cd75-wmcqc, Version: v1.0.0
Host: my-app-v1-7b4874cd75-tsh2s, Version: v1.0.0
Host: my-app-v1-7b4874cd75-ml58j, Version: v1.0.0
Host: my-app-v1-7b4874cd75-spsdv, Version: v1.0.0
Host: my-app-v2-f885c8d45-mc2fx, Version: v2.0.0
......

正常状况下能够看到大部分都是返回的版本1 的应用信息,偶尔会出现版本2 的应用信息,这就证实咱们的金丝雀发布成功了,待确认了版本2 的这个应用没有任何问题后,能够将版本2 应用扩容到10 个副本:

$ kubectl scale --replicas=10 deploy my-app-v2
deployment.extensions "my-app-v2" scaled

其实这个时候访问应用的话新版本和旧版本的流量分配是1:1了,确认了版本2 正常后,就能够删除版本1 的应用了:

$ kubectl delete deploy my-app-v1
deployment.extensions "my-app-v1" deleted

最终留下的是 10 个新版本的 Pod 了,到这里咱们的整个金丝雀发布就完成了。

一样,最后,执行下面的命令删除上面的资源对象:

$ kubectl delete all -l app=my-app

结论:

  • 部分用户获取新版本
  • 方便错误和性能监控
  • 快速回滚
  • 发布较慢
  • 流量精准控制很浪费(99%A / 1%B = 99 Pod A,1 Pod B)
# 若是你对新功能的发布没有信心,建议使用金丝雀发布的策略。

 

0x05 A/B测试(A/B testing) - 最适合部分用户的功能测试

A/B 测试其实是一种基于统计信息而非部署策略来制定业务决策的技术,与业务结合很是紧密。可是它们也是相关的,也可使用金丝雀发布来实现。

除了基于权重在版本之间进行流量控制以外,A/B 测试还能够基于一些其余参数(好比 Cookie、User Agent、地区等等)来精肯定位给定的用户群,该技术普遍用于测试一些功能特性的效果,而后按照效果来进行肯定。

# 咱们常常能够在今日头条的客户端中就会发现有大量的 A/B 测试,同一个地区的用户看到的客户端有很大不一样。

要使用这些细粒度的控制,仍然仍是建议使用 Istio,能够根据权重或 HTTP 头等来动态请求路由控制流量转发。

下面是使用 Istio 进行规则设置的示例,由于 Istio 还不太稳定,如下示例规则未来可能会更改:

route:
- tags:
  version: v1.0.0
  weight: 90
- tags:
  version: v2.0.0
  weight: 10

关于在 Istio 中具体如何作 A/B 测试,咱们这里就再也不详细介绍了,咱们在istio-book文档中有相关的介绍。

结论:

  • 几个版本并行运行
  • 彻底控制流量分配
  • 特定的一个访问错误难以排查,须要分布式跟踪
  • Kubernetes 没有直接的支持,须要其余额外的工具

 

0x06 总结

 发布应用有许多种方法,当发布到开发/测试环境的时候,重建或者滚动更新一般是一个不错的选择。在生产环境,滚动更新或者蓝绿发布比较合适,可是新版本的提早测试是很是有必要的。若是你对新版本的应用不是颇有信心的话,那应该使用金丝雀发布,将用户的影响降到最低。最后,若是你的公司须要在特定的用户群体中进行新功能的测试,例如,移动端用户请求路由到版本 A,桌面端用户请求路由到版本 B,那么你就看使用A/B 测试,经过使用 Kubernetes 服务网关的配置,能够根据某些请求参数来肯定用户应路由的服务。

 

参考

相关文章
相关标签/搜索