首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

借助Rancher持续交付,3步实现金丝雀发布!

从 Rancher 2.5 起,Rancher 借助 Fleet 提供了大规模交付的 GitOps 功能,允许用户使用 GitOps 的方法管理其集群的状态。

金丝雀发布是一个被软件开发者广泛使用的方法,它可以用来向一部分用户发布新版本的应用程序,并根据可用性、延迟或自定义指标等指标来扩大规模,进而为更多用户提供服务。在本文中,我们将探索如何使用持续交付来为你的应用程序工作负载执行金丝雀发布。

实际的金丝雀发布将由一个名为 Flagger 的项目执行。Flagger 作为 Kubernetes operator 运行。它允许用户指定一个自定义对象,该对象会通知 Flagger 观察一个部署并创建额外的主要部署(primary deployment)和金丝雀部署。作为本文的一部分,我们将使用 Flagger 与 Istio 作为服务网格。

简而言之,当我们创建一个部署时,Flagger 会将该部署克隆到一个主部署。然后它修改与原始部署相关的服务以指向这个新的主部署。该主部署本身会被缩减到 0。

Flagger 使用 Istio virtualservices 来执行实际的金丝雀发布。当一个新版本的应用程序被部署时,Flagger 将原始部署缩减到原始规格,并将金丝雀服务关联到部署。

现在,一定比例的流量被路由到这个金丝雀服务。基于预定义的指标,Flagger 开始将越来越多的流量路由到这个金丝雀服务。一旦 100%的流量被迁移到金丝雀服务,主部署就会以原始部署相同的规格重新创建。

接下来,将更新 virtualservice 以将 100%的流量返回到主服务。在流量转换之后,原始部署被缩减为 0,Flagger operator 等待并监控后续的部署更新。

Flagger 执行金丝雀发布

为了开始使用 Flagger,我们需要执行以下操作:

  1. 设置监控和 Istio
  2. 设置 Flagger 和 flagger-loadtest
  3. 部署一个 demo 程序并执行金丝雀发布

1.设置监控和 Istio

为了设置 monitoring 和 istio,我们将在持续交付中设置几个 ClusterGroups:

监控

代码语言:javascript
复制

apiVersion: fleet.cattle.io/v1alpha1
kind: ClusterGroup
metadata:
  name: monitoring
  namespace: fleet-default
spec:
  selector:
    matchLabels:
      monitoring: enable

Istio

代码语言:javascript
复制

apiVersion: fleet.cattle.io/v1alpha1
kind: ClusterGroup
metadata:
  name: istio
  namespace: fleet-default
spec:
  selector:
    matchLabels:
      istio: enabled

现在,我们将设置我们的 monitoring 和 istio Gitrepos 以指向使用这些 ClusterGroups:

监控 repo

代码语言:javascript
复制

apiVersion: fleet.cattle.io/v1alpha1
kind: GitRepo
metadata:
  name: monitoring
  namespace: fleet-default
spec:
  branch: master
  insecureSkipTLSVerify: false
  paths:
  - monitoring
  - monitoring-crd
  repo: https://github.com/ibrokethecloud/core-bundles
  targets:
  - clusterGroup: monitoring

Istio repo

代码语言:javascript
复制

apiVersion: fleet.cattle.io/v1alpha1
kind: GitRepo
metadata:
  name: istio
  namespace: fleet-default
spec:
  branch: master
  insecureSkipTLSVerify: false
  paths:
  - istio
  - kiali
  repo: https://github.com/ibrokethecloud/core-bundles
  targets:
  - clusterGroup: istio

为了触发部署,我们将使用所需的标签为这些 ClusterGroups 分配一个集群:

在几分钟之内,监控和 istio 应用程序应该在指定集群上安装完毕。

2.设置 Flagger 和 flagger-loadtest

作为安装 Flagger 的一部分,我们将安装 flagger-loadtest 以帮助在我们的工作负载上生成请求。

请注意:flagger-loadtest 仅在本次 demo 中需要。在实际应用场景中,你的应用程序将会使用真实的流量。Flagger 将根据来自真实流量的指标启动切换。

我们将设置一个 ClusterGroup 金丝雀,如下所示:

代码语言:javascript
复制

apiVersion: fleet.cattle.io/v1alpha1
kind: ClusterGroup
metadata:
  name: canary
  namespace: fleet-default
spec:
  selector:
    matchLabels:
      canary: enabled

现在我们可以设置 flagger Gitrepo 来使用这个 ClusterGroup

代码语言:javascript
复制

apiVersion: fleet.cattle.io/v1alpha1
kind: GitRepo
metadata:
name: flagger
namespace: fleet-default
spec:
branch: master
insecureSkipTLSVerify: false
paths:
- flagger
- flagger-loadtest
repo: https://github.com/ibrokethecloud/user-bundles
targets:
- clusterGroup: canary

如我们之前所了解的,要触发部署我们将分配一个集群到 Flagger ClusterGroup

在几分钟之内,Flagger 和 flagger-loadtest helm charts 将会被部署到该集群

请注意,在部署 Flagger 时,它将所有的标签和注释从源部署中复制到金丝雀和主部署中。持续交付将使用对象上的标签来核对和识别它们属于哪个底层的 Bundle。Flagger 对此进行了设置,在默认设置中,持续交付将报告不在 GitRepo 中的额外的主部署和金丝雀部署。

为了避免这种情况,Flagger helm chart 中的 includeLabelPrefix 设置被传递并设置为 dummy,以指示 Flagger 只包括前缀为 dummy 的标签。这有助于我们绕过持续交付的 reconciliation logic。

fleet.yaml 如下所示:

代码语言:javascript
复制

defaultNamespace: istio-system
helm:
releaseName: flagger
repo: https://flagger.app
chart: flagger
version: 1.6.2
values:
crd.create: true
meshProvider: istio
metricsServer: http://rancher-monitoring-prometheus.cattle-monitoring-system:9090
includeLabelPrefix: dummy
diff:
comparePatches:
- apiVersion: apps/v1
kind: Deployment
name: flagger
namespace: istio-system
operations:
- {"op": "remove", "path": "/spec/template/spec/containers/0/resources/limits/cpu"}
- {"op": "remove", "path": "/spec/template/spec/containers/0/volumeMounts"}
- {"op": "remove", "path": "/spec/template/spec/volumes"}

所有基础服务设置完成后,我们现在可以开始部署我们的工作负载。

3.部署 Demo 应用程序并进行金丝雀发布

现在我们添加 canary-demo-app GitRepo 到目标 canaryClusterGroup

代码语言:javascript
复制

apiVersion: fleet.cattle.io/v1alpha1
kind: GitRepo
metadata:
  name: canary-demo-app
  namespace: fleet-default
spec:
  branch: master
  insecureSkipTLSVerify: false
  paths:
  - canary-demo-app
  repo: https://github.com/ibrokethecloud/user-bundles
  targets:
  - clusterGroup: canary

这将出发 demo app 的部署到 canary-demo 命名空间。

代码语言:javascript
复制

(⎈ |digitalocean:canary-demo)
~
▶ kubectl get deployment
NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
fleet-simple-app           0/0     0            0           80s
fleet-simple-app-primary   1/1     1            1           80s
(⎈ |digitalocean:canary-demo)

控制发布行为的金丝雀对象如下:

代码语言:javascript
复制

apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
  name: fleet-simple-app
  namespace: canary-demo
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: fleet-simple-app
  service:
    port: 8080
  analysis:
    interval: 1m
    threshold: 10
    maxWeight: 50
    stepWeight: 10
    metrics:
      - name: request-success-rate
        thresholdRange:
          min: 99
        interval: 1m
      - name: request-duration
        thresholdRange:
          max: 500
        interval: 1m
    webhooks:
      - name: load-test
        url: http://flagger-loadtester.loadtester/
        timeout: 5s
        metadata:
          type: cmd
          cmd: "hey -z 1m -q 10 -c 2 http://fleet-simple-app-canary.canary-demo:8080"

这里面的关键项目时 webhook 来进行负载测试,以产生足够的指标让 Flagger 能够开始切换流量。

我们同时能够看到金丝雀对象的状态,如下所示:

代码语言:javascript
复制

(⎈ |digitalocean:canary-demo)
~
▶ kubectl get canary
NAME               STATUS        WEIGHT   LASTTRANSITIONTIME
fleet-simple-app   Initialized   0        2021-03-22T06:25:17Z

我们现在可以通过更新 canary-demo-app 的 GitRepo,用新版本的镜像来触发金丝雀发布。在几分钟之后,我们应该看到源部署使用来自 GitRepo 的新镜像进行扩展。此外,金丝雀对象变成 Progressing 状态,金丝雀发布的比重发生变化。

代码语言:javascript
复制

▶ kubectl get deploy
NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
fleet-simple-app           1/1     1            1           6m5s
fleet-simple-app-primary   1/1     1            1           6m5s
(⎈ |digitalocean:canary-demo)
~
▶ kubectl get canary
NAME               STATUS        WEIGHT   LASTTRANSITIONTIME
fleet-simple-app   Progressing   0        2021-03-22T06:30:17Z
▶ kubectl get canary
NAME               STATUS        WEIGHT   LASTTRANSITIONTIME
fleet-simple-app   Progressing   10       2021-03-22T06:31:17Z

执行中的金丝雀还与 Istio virtualservice 中不断变化的比重相对应。

代码语言:javascript
复制

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  creationTimestamp: "2021-03-22T06:25:17Z"
  generation: 2
  managedFields:
  - apiVersion: networking.istio.io/v1alpha3
    fieldsType: FieldsV1
    fieldsV1:
      f:metadata:
        f:ownerReferences:
          .: {}
          k:{"uid":"6ae2a7f1-6949-484b-ab48-c385e9827a11"}:
            .: {}
            f:apiVersion: {}
            f:blockOwnerDeletion: {}
            f:controller: {}
            f:kind: {}
            f:name: {}
            f:uid: {}
      f:spec:
        .: {}
        f:gateways: {}
        f:hosts: {}
        f:http: {}
    manager: flagger
    operation: Update
    time: "2021-03-22T06:25:17Z"
  name: fleet-simple-app
  namespace: canary-demo
  ownerReferences:
  - apiVersion: flagger.app/v1beta1
    blockOwnerDeletion: true
    controller: true
    kind: Canary
    name: fleet-simple-app
    uid: 6ae2a7f1-6949-484b-ab48-c385e9827a11
  resourceVersion: "10783"
  uid: b5aaaf34-7b16-4ba9-972c-b60756943da8
spec:
  gateways:
  - mesh
  hosts:
  - fleet-simple-app
  http:
  - route:
    - destination:
        host: fleet-simple-app-primary
      weight: 90
    - destination:
        host: fleet-simple-app-canary
      weight: 10

再过一会儿,我们应该看到 Flagger 在推动金丝雀发布,并且主要的部署被切换到新版本。

代码语言:javascript
复制

▶ kubectl get canary
NAME               STATUS      WEIGHT   LASTTRANSITIONTIME
fleet-simple-app   Promoting   0        2021-03-22T06:37:17Z


▶ kubectl get pods
NAME                                        READY   STATUS    RESTARTS   AGE
fleet-simple-app-64cd54dfd-tkk8v            2/2     Running   0          9m2s
fleet-simple-app-primary-854d4d84b5-qgfc8   2/2     Running   0          74s

在最终完成部署之后,我们应该看到原来的部署被缩减:

代码语言:javascript
复制

▶ kubectl get canary
NAME               STATUS       WEIGHT   LASTTRANSITIONTIME
fleet-simple-app   Finalising   0        2021-03-22T06:38:17Z
(⎈ |digitalocean:canary-demo)
~
▶ kubectl get pods
NAME                                        READY   STATUS        RESTARTS   AGE
fleet-simple-app-64cd54dfd-tkk8v            2/2     Terminating   0          9m53s
fleet-simple-app-primary-854d4d84b5-qgfc8   2/2     Running       0          2m5s
▶ kubectl get deploy
NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
fleet-simple-app           0/0     0            0           15m
fleet-simple-app-primary   1/1     1            1           15m

在这之后,金丝雀对象应该是成功状态:

代码语言:javascript
复制

▶ kubectl get canary
NAME               STATUS      WEIGHT   LASTTRANSITIONTIME
fleet-simple-app   Succeeded   0        2021-03-22T06:39:17Z

大功告成!在本文中,我们展示了如何使用持续交付、利用第三方工具(如 Flagger)来为我们的工作负载执行金丝雀发布。欢迎跟着本教程进行操作,如果有任何问题,也欢迎扫描文末二维码,添加小助手为好友,进入 Rancher 官方技术交流群与各位 Rancher 用户一起交流。

本文转载自:RancherLabs(ID:RancherLabs)

原文链接:借助Rancher持续交付,3步实现金丝雀发布!

  • 发表于:
  • 本文为 InfoQ 中文站特供稿件
  • 首发地址https://www.infoq.cn/article/uiyFDKwomaVp9QgLh9MW
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券