首页 Linux教程【GitOps系列】金丝雀发布与GitOps的完美结合:自动化部署的未来

【GitOps系列】金丝雀发布与GitOps的完美结合:自动化部署的未来

运维派隶属马哥教育旗下专业运维社区,是国内成立最早的IT运维技术社区,欢迎关注公众号:yunweipai
领取学习更多免费Linux云计算、Python、Docker、K8s教程关注公众号:马哥linux运维

前言

蓝绿发布是一种通过资源冗余来换取回滚效率的发布方式,结合 Argo Rollout ,能够很方便地实现自动化的流量切换。
但是它的缺点也是比较明显的:当新环境准备好之后,流量将进行全量切换, 无法对新环境进行小规模的流量验证。
为了更好地了解新环境的性能和潜在的问题,最好的办法是让新的环境接收一小部分生产流量。通常,我们会把一定比例的生产流量转发到新的环境,以此来验证新环境的表现。这种发布方式就叫做 金丝雀发布,又叫做灰度发布

金丝雀发布概述

架构概览:

【GitOps系列】金丝雀发布与GitOps的完美结合:自动化部署的未来插图
在这里插入图片描述

这张架构图中,我们会对同一个应用部署两套环境,一套是 Prod 生产环境,另一套是 Canary 金丝雀环境。这两套环境分别由不同的 Service 通过选择器进行关联,最外层通过 Ingress-Nginx 网关将流量按不同的比例转发到 Service 当中。比如,图中 20% 的流量将会转发到金丝雀环境,80% 的流量会转发到生产环境,这实际上是一种流量负载均衡的算法。
除了以不同比例分发流量以外,金丝雀发布还可以通过特定的 Header 来进行识别和分发流量,如下图所示:

【GitOps系列】金丝雀发布与GitOps的完美结合:自动化部署的未来插图1
在这里插入图片描述


常规流量将仍然访问生产环境,而请求头中带有 X-Canary 的请求将会被转发到金丝雀环境,以此将流量进行区分。
这两种方式在发布过程中具有极强的灵活性,第一种以不同比例分发流量的方式可以很方便地进行灰度验证,避免大规模故障。第二种识别特定请求的方式则更加精准,可以很方便地控制让什么类型的用户访问金丝雀环境,例如对不同地域、不同性别、年龄的用户进行金丝雀实验。

金丝雀实战

创建生产环境

 cat prod_deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: prod
  labels:
    app: prod
spec:
  replicas: 1
  selector:
    matchLabels:
      app: prod
  template:
    metadata:
      labels:
        app: prod
    spec:
      containers:
      - name: demo
        image: argoproj/rollouts-demo:blue
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: prod-service
  labels:
    app: prod
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
  selector:
    app: prod
  type: ClusterIP

kubectl apply -f prod_deployment.yaml 
kubectl wait pods -l app=prod --for condition=Ready --timeout=90s
pod/prod-96bc479bb-jm2kd condition met







![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)

AI写代码

创建生产环境的 Ingress 策略:

 cat prod_ingress.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: prod-ingress
spec:
  entryPoints:
    - web
  routes:
    - match: Host(`canary.demo`) && PathPrefix(`/`)
      kind: Rule
      services:
        - name: prod-service
          port: 80

kubectl apply -f prod_ingress.yaml 
ingressroute.traefik.containo.us/prod-ingress created







![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)

AI写代码

访问生产环境 http://canary.demo/

【GitOps系列】金丝雀发布与GitOps的完美结合:自动化部署的未来插图2
在这里插入图片描述

浏览器每秒钟会向后端发出 50 个请求,蓝色的方块代表后端返回接口的内容为 blue,对应的是argoproj/rollouts-demo:blue版本的镜像,用来模拟生产环境。

部署金丝雀环境

 apiVersion: apps/v1
kind: Deployment
metadata:
  name: canary
  labels:
    app: canary
spec:
  replicas: 1
  selector:
    matchLabels:
      app: canary
  template:
    metadata:
      labels:
        app: canary
    spec:
      containers:
      - name: demo
        image: argoproj/rollouts-demo:green
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: canary-service
  labels:
    app: canary
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
  selector:
    app: canary
  type: ClusterIP

kubectl apply -f canary_deployment.yaml 
deployment.apps/canary created
service/canary-service created







![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)

AI写代码

配置金丝雀策略

生产环境和金丝雀环境都已经准备好,接下来我们需要配置金丝雀环境的 Ingress 策略:

 apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: canary-ingress-canary
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "20"
    nginx.ingress.kubernetes.io/canary-by-header: "X-Canary"
spec:
  rules:
  - host: "canary.demo"
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: canary-service
            port:
              number: 80

如果你用的是Traefik,可以用下边的YAML配置
cat myapp-traefikService.yaml 
apiVersion: traefik.containo.us/v1alpha1
kind: TraefikService
metadata:
  name: wrr
spec:
  weighted:
    services:
      - name: prod-service
        weight: 10
        port: 80
      - name: canary-service
        weight: 80
        port: 80

cat myapp-ingress.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: myapp
spec:
  entryPoints:
    - web
  routes:
  - match: Host(`canary.demo`) && PathPrefix(`/`)
    kind: Rule
    services: # 加权轮循时,后端service不再是k8s的service,而是traefik的TraefikService
    - name: wrr     
      kind: TraefikService







![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)

AI写代码

相比较生产环境的 Ingress 策略,这段金丝雀环境的 Ingress 策略在 metadata.annotations 字段上明显的差异:
nginx.ingress.kubernetes.io/canary 字段的值为 true,表示启用金丝雀发布策略。
nginx.ingress.kubernetes.io/canary-weight 字段的值为 20,表示将 20% 的流量转发到金丝雀环境当中,实际上这是负载均衡的加权轮询机制。
nginx.ingress.kubernetes.io/canary-by-header 字段的值为 X-Canary,代表当 Header 中包含 X-Canary 时,则无视流量比例规则,将请求直接转发到金丝雀环境中。
所以,上面的 Ingress 策略实际上同时配置了 基于请求流量比例以及请求头的金丝雀策略。

会看到生产环境(蓝色方块)和金丝雀环境(绿色方块)的流量比例将按照配置的 4:1 来分布,如下图右下角所示:

【GitOps系列】金丝雀发布与GitOps的完美结合:自动化部署的未来插图3
在这里插入图片描述

现在,只需要调整金丝雀环境的 Ingress 策略,分次提升 canary-weight 的值直到 100%,也就实现了一次完整的金丝雀发布过程。

金丝雀发布自动化

上面提到手动金丝雀发布过程比较麻烦,我们除了需要手动创建生产和金丝雀两个环境以外,还需要手动配置 Ingress 策略,如果想要调整金丝雀环境的流量比例,那么就需要多次修改 Ingress 策略。这种发布方式效率很低,并且最后将金丝雀环境提升为生产环境时也需要手动处理。
但是借助 Argo Rollout 的自动金丝雀发布功能,就能很好地解决这些问题。

创建 Rollout 对象

 cat canary-rollout.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: canary-demo
  labels:
    app: canary-demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: canary-demo
  template:
    metadata:
      labels:
        app: canary-demo
    spec:
      containers:
      - name: canary-demo
        image: argoproj/rollouts-demo:blue
        imagePullPolicy: Always
        ports:
        - name: http
          containerPort: 8080
          protocol: TCP
        resources:
          requests:
            memory: 32Mi
            cpu: 5m
  strategy:
    canary:
      canaryService: canary-demo-canary
      stableService: canary-demo
      canaryMetadata:
        labels:
          deployment: canary
      stableMetadata:
        labels:
          deployment: stable
      trafficRouting:
        nginx:
          stableIngress: canary-demo
          additionalIngressAnnotations:
            canary-by-header: X-Canary
        #traefik:
        #  weightedTraefikServiceName: traefik-service
      steps:
        - setWeight: 20
        - pause: {}
        - setWeight: 50
        - pause:
            duration: 30s
        - setWeight: 70
        - pause:
            duration: 30s







![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)

AI写代码

spec.template 字段和 Deployment 工作负载的字段定义是一致的,在这里,我们使用了 argoproj/rollouts-demo:blue 镜像来创建生产环境的工作负载,并定义了 strategy.canary 字段,它代表使用金丝雀发布的策略。其他的字段也简单介绍一下:
canaryService 表示金丝雀 Service 的名称;
stableService 表示生产环境 Service 的名称,同样也需要在稍后创建。
canaryMetadata 和 stableMetadata 字段表示在金丝雀发布时,会将额外的标签增加到 Pod 中,它可以区分不同环境的 Pod。
trafficRouting.nginx 字段表示使用 Ingress-Nginx 来管理流量,同时,trafficRouting.nginx.stableIngress 字段用来指定 Ingress 名称,这个 Ingress 需要我们提前创建。
trafficRouting.nginx.additionalIngressAnnotations 字段用来配置特定的 金丝雀流量识别策略,这里的含义是当请求头出现 X-Canary 时,就将流量转发到金丝雀环境中。
此外,还有一项重要的配置:canary.steps, 它是用来描述如何进行自动化金丝雀发布。

在这个例子中,自动化金丝雀的配置如下:

  1. 将金丝雀环境的流量比例配置为 20%。
  2. 暂停金丝雀发布,直到手动批准。
  3. 将金丝雀环境的流量比例配置为 50%,并持续 30 秒。
  4. 将金丝雀环境的流量比例配置为 70%,并持续 30 秒。
  5. 完成金丝雀发布,此时金丝雀环境成为新的生产环境,并接收所有的生产流量。

创建 Service 和 Ingress 对象

首先创建用于生产环境的 canary-demo 和金丝雀环境的 canary-demo-canary Service 对象,将下面的内容保存为 canary-demo-service.yaml 文件。

 apiVersion: v1
kind: Service
metadata:
  name: canary-demo
  labels:
    app: canary-demo
spec:
  ports:
  - port: 80
    targetPort: http
    protocol: TCP
    name: http
  selector:
    app: canary-demo
---
apiVersion: v1
kind: Service
metadata:
  name: canary-demo-canary
  labels:
    app: canary-demo
spec:
  ports:
  - port: 80
    targetPort: http
    protocol: TCP
    name: http
  selector:
    app: canary-demo

$ kubectl apply -f canary-demo-service.yaml







![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)

AI写代码

创建 Ingress 对象,我们把 canary.auto 作为生产环境和金丝雀环境的域名,并且将后端 Service 配置为 canary-demo

 apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: canary-demo
  labels:
    app: canary-demo
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
    - host: canary.auto
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: canary-demo
                port:
                  name: http

如果用的是Traefik,可以参考以下配置:
cat wrr-traefif_service.yaml 
apiVersion: traefik.containo.us/v1alpha1
kind: TraefikService
metadata:
  name: traefik-service
spec:
  weighted:
    services:
      - name: canary-demo # k8s service name that you need to create for stable application version
        port: 80
      - name: canary-demo-canary # k8s service name that you need to create for new application version
        port: 80
---
cat canary-demo-ingress.yaml 
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: canary-demo
  labels:
    app: canary-demo
spec:
  entryPoints:
    - web
  routes:
    - match: Host(`canary.auto`) && PathPrefix(`/`)
      kind: Rule
      services:
        - name: canary-demo
          port: http







![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)

AI写代码

访问生产环境

配置域名解析之后,然后访问 http://canary.auto/

【GitOps系列】金丝雀发布与GitOps的完美结合:自动化部署的未来插图4
在这里插入图片描述

金丝雀发布自动化

现在,我们已经创建好了生产环境。接下来,我们继续进行自动化的金丝雀发布。
假设我们需要更新生产环境,并需要将生产环境的argoproj/rollouts-demo:blue镜像更新为 argoproj/rollouts-demo:green 镜像。此时,我们只需要修改 Rollout 对象的 image 字段,将 blue 修改为 green 即可。

 containers:
- name: canary-demo
  image: argoproj/rollouts-demo:green

kubectl apply -f canary-rollout.yaml
rollout.argoproj.io/canary-demo configured





AI写代码
【GitOps系列】金丝雀发布与GitOps的完美结合:自动化部署的未来插图5
在这里插入图片描述

同时,在 Rollout 对象中还配置了 canary-by-header 参数,所以当我们使用特定的 Header 请求时,流量将被转发到金丝雀环境中,你可以使用 curl 来验证:

 $ for i in `seq 1 10`; do curl -H "X-Canary: always" http://canary.auto/color; done
"green""green""green""green""green""green""green""green""green""green"





AI写代码

从上面的请求命令我们会发现,当 Header 中携带了 X-Canary: always 之后,将返回 green 字符串,也就是金丝雀环境的 green 镜像。

访问 Argo Rollout Dashboard

【GitOps系列】金丝雀发布与GitOps的完美结合:自动化部署的未来插图6
在这里插入图片描述

接下来,点击卡片进入 canary-demo 详情,在这里我们将看到金丝雀发布的完整步骤以及当前所处的阶段。

【GitOps系列】金丝雀发布与GitOps的完美结合:自动化部署的未来插图7
在这里插入图片描述


从截图我们可以看出,金丝雀发布一共有 6 个阶段,当前处于第二个暂停阶段,这和我们在 Rollout 里的定义是一致的。
接下来,通过手动批准的方式让金丝雀发布进入下一个步骤。你可以使用 kubectl argo rollouts promote 命令来让金丝雀发布继续运行。

 kubectl argo rollouts promote canary-demo
rollout 'canary-demo' promoted





AI写代码

之后,金丝雀发布将会按照我们预定的步骤运行。首先将金丝雀环境的流量比例设置为 50%,停留 30 秒,然后将金丝雀环境的流量比例设置为 70%,再停留 30 秒,最后将金丝雀环境提升为生产环境。当金丝雀发布完成之后,Argo Rollout 将同时自动对老的环境进行缩容操作,如下图所示:

【GitOps系列】金丝雀发布与GitOps的完美结合:自动化部署的未来插图8
在这里插入图片描述
【GitOps系列】金丝雀发布与GitOps的完美结合:自动化部署的未来插图9
在这里插入图片描述

自动化原理

Argo Rollout 实际上是在不同的金丝雀发布阶段,通过修改 ReplicaSet、Service 和 Ingress 对象来实现自动化的。
在刚开始创建生产环境时,Ingress、Service 和 Rollout 对象的关系如下图所示:

【GitOps系列】金丝雀发布与GitOps的完美结合:自动化部署的未来插图10
在这里插入图片描述


上面的这条流量链路比较简单,首先,最外层 Ingress 在接收到流量后会将其转发到生产环境的 Service,Service 又通过选择器来匹配被 Rollout 对象管理的 Pod。

当我们修改了 Rollout 的镜像版本并进行金丝雀发布时,Rollout 对象会创建一个新的金丝雀环境的 ReplicaSet 对象,并修改 Service 的标签选择器来匹配到金丝雀环境的 Pod。然后,再生成一个额外的 Ingress 对象来匹配需要转发到金丝雀环境的流量,包括按权重以及匹配 Header 的规则,如下图所示:

【GitOps系列】金丝雀发布与GitOps的完美结合:自动化部署的未来插图11
在这里插入图片描述


当处于不同的金丝雀阶段时,Argo Rollout 会自动修改 Ingress 对象的 nginx.ingress.kubernetes.io/canary-weight 注解的值,以此来控制不同比例的流量进入金丝雀环境。

最后,当金丝雀发布的所有阶段都完成之后,Argo Rollout 还会自动将金丝雀环境提升为生产环境。具体的做法是,修改金丝雀环境的 Ingress 策略,将nginx.ingress.kubernetes.io/canary-weight注解的值修改为 0,同时将旧生产环境的 Service 的选择器修改为匹配金丝雀环境的 Pod,最后再将旧的生产环境的 ReplicaSet 缩容为 0,达到将金丝雀环境提升为生产环境的目的,如下图所示:

【GitOps系列】金丝雀发布与GitOps的完美结合:自动化部署的未来插图12
在这里插入图片描述

结语

首先了解了什么是金丝雀发布以及如何通过手动的方式来实践它。它和蓝绿发布有一点类似,比如在发布过程都需要同时部署两套环境。不同的是,金丝雀发布的核心是通过为 Ingress-Nginx 添加注解来实现的。
在金丝雀发布的过程中,主要有两种流量分发方式。第一种是通过流量的比例进行分发,第二种是通过特定的 Header 来识别。
以手动的方式来实施金丝雀部署比较繁琐,并且效率低下。所以接着了解了如何通过 Argo Rollout 来自动化金丝雀发布过程。
通过 Rollout 对象,我们可以把金丝雀发布的过程完整地定义出来,比如将金丝雀发布分成若干个阶段,每个阶段使用不同的流量比例并且持续不同的时间。同时,还可以为金丝雀发布配置手动确认的过程。
在实际的业务场景中,通常我们会尽量拉长金丝雀发布的时间,比如持续数小时渐进式地发布,以便更多的流量流向金丝雀环境。其次,通过特定的 Header 来识别流量是一种非常好的工程实践,比如你可以将特定地域、性别、年龄的用户作为目标群体来进行金丝雀发布,让特定的用户才能访问新的版本。如果你仔细留意过,会发现自己在使用一些大型应用的时候,很可能都作为“灰度”用户曾经参与了金丝雀发布过程。
最后,要在 GitOps 实践金丝雀发布也非常容易,只需要将工作负载的Kind 和 apiVersion字段分别修改成Rollout 和 argoproj.io/v1alpha1就可以了。结合 ArgoCD,就可以很方便地在 GitOps 工作流中使用金丝雀发布了。

链接:https://yinwu.blog.csdn.net/article/details/132007622?spm=1001.2014.3001.5502

(版权归原作者所有,侵删)

文末福利

就目前来说,传统运维冲击年薪30W+的转型方向就是SRE&DevOps岗位。

为了帮助大家早日摆脱繁琐的基层运维工作,给大家整理了一套高级运维工程师必备技能资料包,内容有多详实丰富看下图!

共有 20 个模块

【GitOps系列】金丝雀发布与GitOps的完美结合:自动化部署的未来插图13

1.38张最全工程师技能图谱

【GitOps系列】金丝雀发布与GitOps的完美结合:自动化部署的未来插图14

2.面试大礼包

【GitOps系列】金丝雀发布与GitOps的完美结合:自动化部署的未来插图15

3.Linux书籍

【GitOps系列】金丝雀发布与GitOps的完美结合:自动化部署的未来插图16

4.go书籍

【GitOps系列】金丝雀发布与GitOps的完美结合:自动化部署的未来插图17

······

6.自动化运维工具

【GitOps系列】金丝雀发布与GitOps的完美结合:自动化部署的未来插图18

18.消息队列合集

【GitOps系列】金丝雀发布与GitOps的完美结合:自动化部署的未来插图19

以上所有资料获取请扫码

备注:最新运维资料

【GitOps系列】金丝雀发布与GitOps的完美结合:自动化部署的未来插图20

100%免费领取

(后台不再回复,扫码一键领取)

本文链接:https://www.yunweipai.com/47226.html

网友评论comments

发表回复

您的电子邮箱地址不会被公开。

暂无评论

Copyright © 2012-2022 YUNWEIPAI.COM - 运维派 京ICP备16064699号-6
扫二维码
扫二维码
返回顶部