GitOps 实操手册 6: 实现 ArgoCD 高级发布策略

内容简介

本实验手册系列包含七个主题,涵盖了从应用容器化到 GitOps 工作流的实现与高级特性。通过这些实验手册,您将学习到如何构建、部署和管理应用,以及如何在 Kubernetes 集群上实现高效的持续交付流程。

以下是实验手册的七个章节:

  1. 应用程序容器化实验手册:学习如何将应用程序容器化,并为主流编程语言构建镜像。同时,了解如何缩减镜像体积和使用 GitHub Actions 自动构建镜像。
  2. 单节点 Kubernetes 集群部署实验手册:使用 kind 在本地部署单节点 Kubernetes 集群,安装基础服务,并熟悉 Kubernetes 的基本功能,如运行 Pod、调度工作负载、服务发布和自动扩缩容。
  3. 示例应用的部署和解析实验手册:深入了解示例应用的各个组件,学习如何在 Kubernetes 集群上部署、运行和管理这些组件,实现服务调用、应用配置和扩缩容等功能。
  4. 使用 Helm 定义应用实验手册:通过 Helm 对示例应用进行定义,以满足 GitOps 部署的需求。了解 Helm Chart 的创建和使用,以及预发布和生产环境的部署。
  5. 构建 GitOps 工作流实验手册:在 Kubernetes 集群上安装 ArgoCD,并使用 ArgoCD 定义示例应用进行部署,实现基于镜像版本变化触发的 GitOps 工作流。
  6. 实现 GitOps 高级发布策略实验手册:结合 ArgoCD 的高级特性,如 Argo Rollout、AnalysisTemplate 和 Argo Rollout Dashboard,实现蓝绿发布、金丝雀发布和自动渐进交付。
  7. ArgoCD 高级管理特性实验手册:探讨 ArgoCD 在 GitOps 场景中的高级特性,包括使用 ApplicationSet 实现多环境部署和使用 SealedSecret 保护密钥。

通过这七个实验手册,您将全面掌握应用容器化、Kubernetes 和 GitOps 的相关知识,为应用的持续交付提供可靠和高效的解决方案。

在前面的实验场景基础上,本实验手册将探讨如何利用 ArgoCD 的高级特性,如 Argo Rollout、AnalysisTemplate 以及 Argo Rollout Dashboard,实现更高级的发布策略,包括蓝绿发布、金丝雀发布和自动渐进交付。

本实验手册的主要实验环节包括:

  1. Argo Rollout 简介:了解 Argo Rollout 及其与 ArgoCD 的关系,以及 Argo Rollout 的核心概念。
  2. 蓝绿发布:使用 Argo Rollout 实现蓝绿发布策略,学习如何在两个版本之间平滑切换,最小化对用户的影响。
  3. 金丝雀发布:通过 Argo Rollout 实现金丝雀发布策略,逐步引入新版本的应用,对其进行逐步验证和监控,以便在出现问题时快速回滚。
  4. 自动渐进交付:利用 AnalysisTemplate 和 Argo Rollout 自动根据指标进行决策,实现自动化的渐进式发布过程。
  5. Argo Rollout Dashboard:探讨如何使用 Argo Rollout Dashboard 监控和管理发布策略,提供可视化的操作界面。

通过本实验手册,您将了解并实践如何在 GitOps 工作流中实现高级发布策略,从而使应用的发布更加稳定、安全和可控。

蓝绿发布

手动蓝绿发布

  1. 创建蓝色环境的 Deployment 和 Service
nano blue_deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: blue
  labels:
    app: blue
spec:
  replicas: 3
  selector:
    matchLabels:
      app: blue
  template:
    metadata:
      labels:
        app: blue
    spec:
      containers:
      - name: demo
        image: argoproj/rollouts-demo:blue
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: blue-service
  labels:
    app: blue
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
  selector:
    app: blue
  type: ClusterIP

在上面这段 Manifest 中,使用了 argoproj/rollouts-demo:blue 镜像创建了蓝色环境的 Deployment 工作负载,并且创建了名为 blue-service 的 Service 对象,同时通过 Service 选择器将 Service 和 Pod 进行了关联。

kubectl apply -f blue_deployment.yaml 

检查部署效果

kubectl wait pods -l app=blue --for condition=Ready --timeout=90s
root@node1:~# kubectl wait pods -l app=blue --for condition=Ready --timeout=90s
pod/blue-659f669c78-fsfmd condition met
pod/blue-659f669c78-qjsrf condition met
pod/blue-659f669c78-scmm5 condition met
  1. 创建 Ingress 策略,并指向蓝色环境的 Service
nano blue_ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo-ingress
spec:
  rules:
  - host: "bluegreen.demo"
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: blue-service
            port:
              number: 80
kubectl apply -f blue_ingress.yaml   

修改host文件,增加类似条目
127.0.0.1 bluegreen.demo

实际demo场景中为
192.168.1.231 bluegreen.demo

  1. 访问蓝色环境
    http://bluegreen.demo

在这里插入图片描述

在这个页面里,浏览器每秒钟会向后端发出 50 个请求,蓝色的方块代表后端返回接口的内容为 blue,对应 blue 版本的镜像,代表蓝色环境。

  1. 创建绿色环境的 Deployment 和 Service
nano green_deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: green
  labels:
    app: green
spec:
  replicas: 3
  selector:
    matchLabels:
      app: green
  template:
    metadata:
      labels:
        app: green
    spec:
      containers:
      - name: demo
        image: argoproj/rollouts-demo:green
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: green-service
  labels:
    app: green
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
  selector:
    app: green
  type: ClusterIP
kubectl apply -f green_deployment.yaml 
kubectl wait pods -l app=green --for condition=Ready --timeout=90s
root@node1:~# kubectl wait pods -l app=green --for condition=Ready --timeout=90s
pod/green-79c9fb755d-8lrds condition met
pod/green-79c9fb755d-bdm9m condition met
pod/green-79c9fb755d-f8d6k condition met
  1. 更新 Ingress 策略,并指向绿色环境
nano green_ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo-ingress
spec:
  rules:
  - host: "bluegreen.demo"
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: green-service
            port:
              number: 80
kubectl apply -f green_ingress.yaml
  1. 访问绿色环境

    http://bluegreen.demo

将会看到请求将逐渐从蓝色切换到绿色

蓝绿发布自动化

到这里,都是通过创建 Kubernetes 原生对象并修改 Ingress 策略的方式来完成蓝绿发布的。这存在一些缺点,首先,在更新过程中,一般只关注镜像版本的变化,而不会去操作 Ingress 策略;其次,这种方式不利于将蓝绿发布和 GitOps 流水线进行整合

  1. 安装 Argo Rollout

Argo Rollout 是一款专门提供 Kubernetes 高级部署能力的自动化工具,它可以独立运行,同时也可以和 ArgoCD 协同在 GitOps 流水线中来使用。

在使用之前,需要先安装它,可以通过下面的命令进行安装。

kubectl create namespace argo-rollouts  
kubectl apply -n argo-rollouts -f https://ghproxy.com/https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml

安装完成后,等待 Argo Rollout 工作负载就绪。

kubectl wait --for=condition=Ready pods --all -n argo-rollouts --timeout=300s
root@node1:~# kubectl create namespace argo-rollouts
namespace/argo-rollouts created
root@node1:~# kubectl apply -n argo-rollouts -f https://ghproxy.com/https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml
customresourcedefinition.apiextensions.k8s.io/analysisruns.argoproj.io created
customresourcedefinition.apiextensions.k8s.io/analysistemplates.argoproj.io created
customresourcedefinition.apiextensions.k8s.io/clusteranalysistemplates.argoproj.io created
customresourcedefinition.apiextensions.k8s.io/experiments.argoproj.io created
customresourcedefinition.apiextensions.k8s.io/rollouts.argoproj.io created
serviceaccount/argo-rollouts created
clusterrole.rbac.authorization.k8s.io/argo-rollouts created
clusterrole.rbac.authorization.k8s.io/argo-rollouts-aggregate-to-admin created
clusterrole.rbac.authorization.k8s.io/argo-rollouts-aggregate-to-edit created
clusterrole.rbac.authorization.k8s.io/argo-rollouts-aggregate-to-view created
clusterrolebinding.rbac.authorization.k8s.io/argo-rollouts created
secret/argo-rollouts-notification-secret created
service/argo-rollouts-metrics created
deployment.apps/argo-rollouts created
root@node1:~# kubectl wait --for=condition=Ready pods --all -n argo-rollouts --timeout=300s
pod/argo-rollouts-58d887958b-rb6qb condition met

  1. 创建 Rollout 对象

和手动实施蓝绿发布的过程不同的是,为了实现自动化,Argo Rollout 采用了自定义资源(CRD)的方式来管理工作负载。

nano blue-green-rollout.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: bluegreen-demo
  labels:
    app: bluegreen-demo
spec:
  replicas: 3
  revisionHistoryLimit: 1
  selector:
    matchLabels:
      app: bluegreen-demo
  template:
    metadata:
      labels:
        app: bluegreen-demo
    spec:
      containers:
      - name: bluegreen-demo
        image: argoproj/rollouts-demo:blue
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 8080
          protocol: TCP
        resources:
          requests:
            memory: 32Mi
            cpu: 5m
  strategy:
    blueGreen:
      autoPromotionEnabled: true
      activeService: bluegreen-demo

这是一个 Argo Rollout 资源的配置文件,用于在 Kubernetes 集群中执行蓝绿部署。这个 Argo Rollout 配置文件定义了一个蓝绿部署,使用 argoproj/rollouts-demo:blue 镜像,并且将新版本自动提升为活跃版本,下面是对整个配置文件的解释:

  • apiVersion: 指定使用的 API 版本,这里为 argoproj.io/v1alpha1。
  • kind: 指定资源类型,这里为 Rollout,表示这是一个 Argo Rollout 资源。
  • metadata:
    • name: 资源的名称,这里为 bluegreen-demo。
    • labels: 资源的标签,这里为 app: bluegreen-demo。
  • spec: 定义 Rollout 的规格。
    • replicas: 指定应用副本数,这里为 3。
    • revisionHistoryLimit: 保留的旧版本副本数量,这里设置为 1,表示只保留一个旧版本副本。
    • selector: 选择器,用于选取与此 Rollout 匹配的 Pod。
      • matchLabels: 需要匹配的标签,这里为 app: bluegreen-demo。
    • template: 定义 Pod 模板。
      • metadata: 指定 Pod 的元数据。
        • labels: 给 Pod 添加标签,这里为 app: bluegreen-demo。
      • spec: 定义 Pod 规格。
        • containers: 定义容器列表。
          • name: 容器名称,这里为 bluegreen-demo。
          • image: 容器使用的镜像,这里为 argoproj/rollouts-demo:blue。
          • imagePullPolicy: 镜像拉取策略,这里为 IfNotPresent。
          • ports: 定义容器端口列表。
            • name: 端口名称,这里为 http。
            • containerPort: 容器端口号,这里为 8080。
            • protocol: 传输协议,这里为 TCP。
          • resources: 定义容器资源请求。
            • requests: 定义容器资源请求限制。
              • memory: 请求内存资源,这里为 32Mi。
              • cpu: 请求 CPU 资源,这里为 5m。
    • strategy: 定义部署策略。
      • blueGreen: 指定蓝绿部署策略。
        • autoPromotionEnabled: 是否自动将新版本应用提升为活跃版本。这里设置为 true,表示自动提升。
        • activeService: 用于指向活跃版本的 Kubernetes 服务名称,这里为 bluegreen-demo。

如果仔细观察,会发现在这个 Rollout 对象中,它大部分的字段定义和 Kubernetes 原生的 Deployment 工作负载并没有太大的区别,只是将 apiVersion 从 apps/v1 修改为了 argoproj.io/v1alpha1,同时将 kind 字段从 Deployment 修改为了 Rollout,并且增加了 strategy 字段。在容器配置方面,Rollout 对象同样也使用了 argoproj/rollouts-demo:blue 来创建蓝色环境。

需要留意的是,strategy 字段是用来定义部署策略的。其中,autoPromotionEnabled 字段表示自动实施蓝绿发布,activeService 用来关联蓝绿发布的 Service,也就是在后续要创建的 Service 名称。

总结来说,当将这段 Rollout 对象应用到集群内之后,Argo Rollout 首先会创建 Kubernetes 原生对象 ReplicaSet,然后,ReplicaSet 会创建对应的 Pod。

在理解了它们的关系之后,接下来创建 Rollout 对象。和普通资源一样,可以通过 kubectl apply 来创建。

kubectl apply -f blue-green-rollout.yaml
  1. 创建 Service 和 Ingress

创建好 Rollout 对象之后,还需要创建 Service 和 Ingress 策略,这和之前手动实施蓝绿发布的过程是一致的。

创建服务

nano blue-green-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: bluegreen-demo
  labels:
    app: bluegreen-demo
spec:
  ports:
  - port: 80
    targetPort: http
    protocol: TCP
    name: http
  selector:
    app: bluegreen-demo
kubectl apply -f blue-green-service.yaml 

创建ingress

nano  blue-green-ingress.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: bluegreen-demo
spec:
  rules:
  - host: "bluegreen.auto"
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: bluegreen-demo
            port:
              number: 80
kubectl apply -f blue-green-ingress.yaml 

更新host记录

127.0.0.1 bluegreen.auto

演示环境中为

192.168.1.231 bluegreen.auto

  1. 访问蓝色环境

配置完 Hosts 之后,接下来就可以访问由 Argo Rollout 创建的蓝色环境了。使用浏览器访问 http://bluegreen.auto 应该能看到和手动实施蓝绿发布一样的页面。

  1. 蓝绿发布自动化

现在,假设需要更新到绿色环境,在 Argo Rollout 的帮助下,只需要修改 Rollout 对象中的镜像版本就可以了,流量切换过程将由 Argo Rollout 自动控制。要更新到绿色环境,需要编辑 blue-green-rollout.yaml 文件的 image 字段,将 blue 修改为 green 版本。

nano blue-green-rollout.yaml
containers:
- name: bluegreen-demo
  image: argoproj/rollouts-demo:green #改为green

然后,使用 kubectl apply 将这段 Rollout 对象重新应用到集群内。

kubectl apply -f blue-green-rollout.yaml

现在,返回到浏览器,等待十几秒后,应该就能看到请求里开始出现绿色环境了。

几秒钟后,所有请求都变成了绿色方格,这表示蓝绿发布的自动化过程已经完成。相比较手动的方式,在使用 Argo Rollout 进行蓝绿发布的过程中,不再需要手动去切换流量,除了更新镜像版本以外,也无需关注其他的 Kubernetes 对象

  1. 访问 Argo Rollout Dashboard

安装

curl -LO https://github.com/argoproj/argo-rollouts/releases/latest/download/kubectl-argo-rollouts-linux-amd64
chmod +x ./kubectl-argo-rollouts-linux-amd64
sudo mv ./kubectl-argo-rollouts-linux-amd64 /usr/local/bin/kubectl-argo-rollouts

查看版本

kubectl argo rollouts version
root@node1:~# kubectl argo rollouts version
kubectl-argo-rollouts: v1.4.0+e40c9fe
  BuildDate: 2023-01-09T20:20:38Z
  GitCommit: e40c9fe8a2f7fee9d8ee1c56b4c6c7b983fce135
  GitTreeState: clean
  GoVersion: go1.19.4
  Compiler: gc
  Platform: linux/amd64

再开一个session,运行下列命令

kubectl argo rollouts dashboard

然后,使用浏览器访问 http://localhost:3100/rollouts 打开 Dashboard,实验场景中是:http://192.168.1.231:3100/rollouts

点击进入 Rollout 的详情界面,在这里,能够以图形化的方式来查看 Rollout 的信息或进行回滚操作。

金丝雀发布

手动金丝雀发布

  1. 创建生产环境的 Deployment 和 Service
nano 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: IfNotPresent
        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
  1. 创建生产环境 Ingress 策略,并指向生产环境的 Service
nano blue_ingress_canary.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: prod-ingress
spec:
  rules:
  - host: "canary.demo"
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: prod-service
            port:
              number: 80
kubectl apply -f blue_ingress_canary.yaml

更新host记录
127.0.0.1 canary.demo

demo环境为

192.168.1.231 canary.demo

  1. 访问生产环境

配置完 Hosts 之后,接下来就可以访问生产环境了。使用浏览器访问 http://canary.demo 应该能看到像下面截图的页面。
在这里插入图片描述

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

  1. 创建金丝雀环境的 Deployment 和 Service
nano canary_deployment.yaml
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: IfNotPresent
        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
  1. 创建金丝雀环境 Ingress 策略,并实现按比例分发和识别特殊流量分发
nano canary_ingress.yaml
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

apiVersionkind: 这两个字段定义了Kubernetes资源的类型。在这个例子中,资源类型是networking.k8s.io/v1Ingress,表示这是一个Kubernetes Ingress资源。

  • metadata: 包含了有关Ingress的元数据,如名称和注解。
    • name: 定义了Ingress的名称,为canary-ingress-canary
    • annotations: 包含了与Ingress相关的注解信息。
      • kubernetes.io/ingress.class: 指定了Ingress控制器的类型,为nginx
      • nginx.ingress.kubernetes.io/canary: 标识这是一个金丝雀Ingress,值为"true"
      • nginx.ingress.kubernetes.io/canary-weight: 指定金丝雀部署流量的权重,为"20",表示20%的流量将被路由到金丝雀服务。
      • nginx.ingress.kubernetes.io/canary-by-header: 指定通过HTTP头字段X-Canary来识别和路由金丝雀流量。
  • spec: 包含了Ingress的详细配置。
    • rules: 定义了Ingress的转发规则。
      • host: 指定了访问该Ingress的域名,为canary.demo
      • http: 定义了与HTTP相关的转发规则。
        • paths: 定义了基于URL路径的转发规则。
          • pathType: 定义了路径匹配的类型,为Prefix,表示使用前缀匹配。
          • path: 定义了路径前缀,为/
          • backend: 定义了请求转发的目标服务。
            • service: 定义了目标服务的相关配置。
              • name: 目标服务的名称,为canary-service
              • port: 目标服务的端口配置。
                • number: 目标服务的端口号,为80。

这个Ingress配置文件实现了将外部流量路由到canary-service服务的金丝雀部署。其中,20%的流量将被发送到金丝雀服务,而带有X-Canary头的请求也将被路由到金丝雀服务。

所以,上面的 Ingress 策略实际上同时配置了基于请求流量比例以及请求头的金丝雀策略。

kubectl apply -f canary_ingress.yaml
  1. 访问生产环境

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

在这里插入图片描述

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

自动金丝雀发布

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

但是借助 Argo Rollout 的自动金丝雀发布功能,就能很好地解决这些问题。

在使用 Argo Rollout 之前,需要先在集群里安装它,并在本地安装好 Argo Rollout kubectl 插件。

  1. 创建 Rollout 对象
nano 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: IfNotPresent
        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
      steps:
        - setWeight: 20
        - pause: {}
        - setWeight: 50
        - pause:
            duration: 30s
        - setWeight: 70
        - pause:
            duration: 30s
kubectl apply -f canary-rollout.yaml                        

strategy 部分定义了 Rollout 资源的升级策略。在这个例子中,使用了金丝雀(canary)策略。以下是 strategy 部分的详细解释:

  1. canary: 表示使用金丝雀策略进行部署。

  2. canaryService: 用于定义金丝雀服务的名称。金丝雀服务将处理金丝雀版本的流量。在这个例子中,金丝雀服务的名称是 canary-demo-canary

  3. stableService: 用于定义稳定版本的服务名称。稳定服务将处理稳定版本的流量。在这个例子中,稳定服务的名称是 canary-demo

  4. canaryMetadata: 包含要应用于金丝雀副本的元数据。在这个例子中,添加了一个名为 deployment 的标签,值为 canary

  5. stableMetadata: 包含要应用于稳定副本的元数据。在这个例子中,添加了一个名为 deployment 的标签,值为 stable

  6. trafficRouting: 定义了如何将流量路由到金丝雀和稳定版本之间的配置。

    • nginx: 使用 Nginx Ingress 控制器作为流量路由器。
      • stableIngress: 定义了指向稳定版本的 Nginx Ingress 资源的名称。在这个例子中,稳定 Ingress 的名称是 canary-demo
      • additionalIngressAnnotations: 定义了额外的 Ingress 注解。在这个例子中,指定了金丝雀流量应通过带有 X-Canary HTTP 头的请求触发。
  7. steps: 定义了金丝雀部署的步骤。在这个例子中,有以下步骤:

    • setWeight: 20: 将金丝雀版本的流量权重设置为 20%。
    • pause: {}: 暂停金丝雀部署进程,直到用户手动恢复或满足某些条件。
    • setWeight: 50: 将金丝雀版本的流量权重设置为 50%。
    • pause: { duration: 30s }: 暂停金丝雀部署进程 30 秒。
    • setWeight: 70: 将金丝雀版本的流量权重设置为 70%。
    • pause: { duration: 30s }: 再次暂停金丝雀部署进程 30 秒。
  8. 创建 Service 和 Ingress 对象

创建 service

nano 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

创建ingress

nano canary-demo-ingress.yaml
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
kubectl apply -f canary-demo-ingress.yaml

设置host

127.0.0.1 canary.auto

demo 环境为

192.168.1.231 canary.auto

  1. 访问生产环境

配置好 Hosts 之后,就可以访问生产环境了。使用浏览器访问 http://canary.auto 应该能看到和手动部署生产环境一样的界面,全部是蓝色方块

  1. 金丝雀发布自动化
nano canary-rollout.yaml
containers:
- name: canary-demo
  image: argoproj/rollouts-demo:green # 修改为green
kubectl apply -f canary-rollout.yaml

现在,返回浏览器,等待十几秒后,应该能看到代表金丝雀环境的绿色方块开始出现,并大致占到总请求数的 20%,如下图右下角所示。

在这里插入图片描述

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

for i in `seq 1 10`; do curl -H "X-Canary: always" http://canary.auto/color; done
$ 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"
  1. 访问 Argo Rollout Dashboard

要访问 Argo Rollout Dashboard,需要先安装 Argo Rollout kubectl 插件,接下来启用 Dashboard

kubectl argo rollouts dashboard

然后,使用浏览器访问 http://localhost:3100/rollouts 打开 Dashboard。

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

在这里插入图片描述

从上面的截图可以看出,金丝雀发布一共有 6 个阶段,当前处于第二个暂停阶段,这和在 Rollout 里的定义是一致的。

接下来,通过手动批准的方式让金丝雀发布进入下一个步骤。可以使用 kubectl argo rollouts promote 命令来让金丝雀发布继续运行。

kubectl argo rollouts promote canary-demo
root@node1:~# kubectl argo rollouts promote canary-demo
rollout 'canary-demo' promoted

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

在这里插入图片描述

自动渐进交付

创建生产环境

创建Rollout对象

nano rollout-with-analysis.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: canary-demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: canary-demo
  strategy:
    canary:
      analysis:
        templates:
        - templateName: success-rate
        startingStep: 2
        args:
        - name: ingress
          value: canary-demo
      canaryService: canary-demo-canary
      stableService: canary-demo
      trafficRouting:
        nginx:
          stableIngress: canary-demo
      steps:
      - setWeight: 20
      - pause:
          duration: 1m
      - setWeight: 40
      - pause:
          duration: 1m
      - setWeight: 60
      - pause:
          duration: 1m
      - setWeight: 80
      - pause:
          duration: 1m
  template:
    metadata:
      labels:
        app: canary-demo
    spec:
      containers:
      - image: argoproj/rollouts-demo:blue
        imagePullPolicy: IfNotPresent
        name: canary-demo
        ports:
        - containerPort: 8080
          name: http
          protocol: TCP
        resources:
          requests:
            cpu: 5m
            memory: 32Mi

这个配置文件定义了一个使用金丝雀部署策略的Rollout资源。在strategy部分,可以看到以下设置:

  1. canary:表示要使用金丝雀部署策略。
  2. analysis:此部分定义了在金丝雀部署过程中要执行的分析模板和参数。这个例子中使用了名为success-rate的模板,并在第2步开始应用分析。args部分传递了参数ingress,其值为canary-demo
  3. canaryService:用于金丝雀版本的Kubernetes服务。
  4. stableService:用于稳定版本的Kubernetes服务。
  5. trafficRouting:配置流量路由。在这个例子中,使用了NGINX ingress来路由流量。
  6. steps:定义了金丝雀部署过程中的逐步权重调整和暂停。根据这些步骤,金丝雀版本将逐渐接收更多的流量,从20%开始,每次增加20%,直到达到80%。在每次权重调整后,暂停1分钟以观察金丝雀版本的性能。

这个Rollout资源将按照指定的金丝雀部署策略和权重调整步骤逐渐将流量切换到新版本。在流量切换的过程中,根据分析模板success-rate对应用程序进行评估,以确保新版本在实际环境中的表现达到预期。

kubectl apply -f rollout-with-analysis.yaml

创建 service (复用上个模块的服务)

nano 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

创建 ingress

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

创建用于自动金丝雀分析的 AnalysisTemplate 模板

nano analysis-success.yaml
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
  name: success-rate
spec:
  args:
  - name: ingress
  metrics:
  - name: success-rate
    interval: 10s
    failureLimit: 3
    successCondition: result[0] > 0.90
    provider:
      prometheus:
        address: http://prometheus-kube-prometheus-prometheus.prometheus:9090
        query: >+
          sum(
            rate(nginx_ingress_controller_requests{ingress="{{args.ingress}}",status!~"[4-5].*"}[60s]))
            /
            sum(rate(nginx_ingress_controller_requests{ingress="{{args.ingress}}"}[60s])
          )

这个配置文件定义了一个名为success-rateAnalysisTemplate资源。AnalysisTemplate用于定义度量指标、查询和条件,以在Argo Rollouts的金丝雀部署过程中评估应用程序的表现。以下是关于这个配置文件的详细解释:

  1. metadata部分中的name设置了AnalysisTemplate的名称为success-rate
  2. spec部分定义了模板的具体参数和度量指标。
  3. args:定义了模板需要的输入参数。在这个例子中,只有一个参数ingress
  4. metrics:定义了度量指标的集合。在这个例子中,只有一个度量指标success-rate
    • interval:度量指标的采集间隔,此例中设置为10秒。
    • failureLimit:在分析过程中允许的失败次数,此例中设置为3次。
    • successCondition:成功条件,此例中设置为result[0] > 0.90,表示只有当成功率大于90%时,应用程序才被认为是成功的。
    • provider:定义了度量指标数据来源。此例中使用Prometheus作为度量指标的提供者。
      • address:Prometheus实例的地址。
      • query:Prometheus查询表达式,用于计算应用程序的成功率。这个查询计算了过去60秒内非4xx和5xx状态码的请求占总请求的比例。

这个AnalysisTemplate资源定义了一个成功率度量指标,用于在Argo Rollouts的金丝雀部署过程中评估应用程序的性能。根据这个模板的配置,只有当应用程序的成功率高于90%时,部署才会继续进行。如果在分析过程中出现3次失败,金丝雀部署将被视为失败,回滚到之前的稳定版本。

kubectl apply -f analysis-success.yaml

配置 hosts

127.0.0.1 progressive.auto

Demo 环境的配置

192.168.1.231 progressive.auto

接下来,使用浏览器访问 http://progressive.auto 应该能看全蓝色块界面。

安装 Prometheus 并配置 Ingress-Nginx

安装 Prometheus

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm upgrade prometheus prometheus-community/kube-prometheus-stack \
--namespace prometheus  --create-namespace --install \
--set prometheus.prometheusSpec.podMonitorSelectorNilUsesHelmValues=false \
--set prometheus.prometheusSpec.serviceMonitorSelectorNilUsesHelmValues=false

在上面的安装命令中,我使用 --set 对安装参数进行了配置,这是为了让它后续能够顺利获取到 Ingress-Nginx 的监控指标。

kubectl wait --for=condition=Ready pods --all -n prometheus

配置 ingress-nginx

为了让 Prometheus 能够顺利地获取到 HTTP 请求指标,需要打开 Ingress-Nginx Metric 指标端口。

首先需要为 Ingress-Nginx Deployment 添加容器的指标端口,可以执行下面的命令来完成。

kubectl patch deployment ingress-nginx-controller -n ingress-nginx --type='json' -p='[{"op": "add", "path": "/spec/template/spec/containers/0/ports/-", "value": {"name": "prometheus","containerPort":10254}}]'
kubectl patch service ingress-nginx-controller -n ingress-nginx --type='json' -p='[{"op": "add", "path": "/spec/ports/-", "value": {"name": "prometheus","port":10254,"targetPort":"prometheus"}}]'
root@node1:~# kubectl patch deployment ingress-nginx-controller -n ingress-nginx --type='json' -p='[{"op": "add", "path": "/spec/template/spec/containers/0/ports/-", "value": {"name": "prometheus","containerPort":10254}}]'
deployment.apps/ingress-nginx-controller patched
root@node1:~# kubectl patch service ingress-nginx-controller -n ingress-nginx --type='json' -p='[{"op": "add", "path": "/spec/ports/-", "value": {"name": "prometheus","port":10254,"targetPort":"prometheus"}}]'
service/ingress-nginx-controller patched

配置 ServiceMonitor 对象

为了让 Prometheus 能够抓取到 Ingress-Nginx 指标,还需要创建 ServiceMonitor 对象,它可以为 Prometheus 配置指标获取的策略。将下面的内容保存为 servicemonitor.yaml 文件。

nano servicemonitor.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: nginx-ingress-controller-metrics
  namespace: prometheus
  labels:
    app: nginx-ingress
    release: prometheus-operator
spec:
  endpoints:
  - interval: 10s
    port: prometheus
  selector:
    matchLabels:
      app.kubernetes.io/instance: ingress-nginx
      app.kubernetes.io/name: ingress-nginx
  namespaceSelector:
    matchNames:
    - ingress-nginx

这是一个 Prometheus 的 ServiceMonitor 资源配置文件,用于在 Kubernetes 集群中监控 Nginx Ingress Controller 的指标。下面是对整个配置文件的解释:

  • apiVersion: 指定使用的 API 版本,这里为 monitoring.coreos.com/v1。
  • kind: 指定资源类型,这里为 ServiceMonitor,表示这是一个 Prometheus ServiceMonitor 资源。
  • metadata:
    • name: 资源的名称,这里为 nginx-ingress-controller-metrics。
    • namespace: 资源所在的命名空间,这里为 prometheus。
    • labels: 资源的标签,这里有两个标签,app: nginx-ingress 和 release: prometheus-operator。
  • spec: 定义 ServiceMonitor 的规格。
    • endpoints: 定义要监控的端点列表。
      • interval: 抓取指标的时间间隔,这里为 10s。
      • port: 端口名称,这里为 prometheus。
    • selector: 选择器,用于选取与此 ServiceMonitor 匹配的 Kubernetes 服务。
      • matchLabels: 需要匹配的标签,这里有两个标签,app.kubernetes.io/instance: ingress-nginx 和 app.kubernetes.io/name: ingress-nginx。
    • namespaceSelector: 用于选择要监控的命名空间。
      • matchNames: 匹配的命名空间列表,这里只有一个 ingress-nginx。

这个 ServiceMonitor 配置文件定义了如何监控 Nginx Ingress Controller 的指标。它将从 prometheus 命名空间下的 ingress-nginx 命名空间中具有特定标签的服务抓取指标。指标抓取间隔为 10 秒。

kubectl apply -f servicemonitor.yaml

验证 ingress-nginx 指标

接下来,验证 Prometheus 是否已经成功获取到了 Ingress-Nginx 指标,这将决定自动金丝雀分析是否能成功获取到数据。

可以进入 Prometheus 控制台验证是否成功获取了 Ingress-Nginx 指标。

nano prometheus-ui.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: prometheus-ui
  namespace: prometheus
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
  # Use the host you used in your kubernetes Ingress Configurations
  - host: prometheus.demo
    http:
      paths:
      - backend:
          service:
            name: prometheus-kube-prometheus-prometheus
            port:
              number: 9090
        path: /
        pathType: Prefix
kubectl apply -f prometheus-ui.yaml

接下来,使用浏览器打开 http://prometheus.demo 进入控制台,在搜索框中输入 nginx_ingress,如果出现一系列指标,则说明 Prometheus 和 Ingress-Nginx 已经配置完成,如下图所示。

在这里插入图片描述

自动渐进式交付成功

使用另一种更新镜像的方法,通过 Argo Rollout kubectl 插件来更新镜像

kubectl argo rollouts set image canary-demo canary-demo=argoproj/rollouts-demo:green

注意:由于受上一个实验的影响,此处也可以手动在rollouts控制界面里手动选择使用blue镜像

使用浏览器访问 http://localhost:3100/rollouts 进入控制台,观察自动渐进式交付过程。可以看到目前处在 20% 金丝雀流量的下一阶段,也就是暂停1 分钟的阶段。

在这里插入图片描述

1分钟后,将进入到 40% 金丝雀流量阶段,从这个阶段开始,自动金丝雀分析开始工作,直到最后金丝雀发布完成,金丝雀环境提升为了生产环境,这时自动分析也完成了,如下图所示。

在这里插入图片描述

到这里,一次完整的自动渐进式交付就完成了。

自动渐进式交付失败

在上面的实验中,由于应用返回的 HTTP 状态码都是 200 ,所以金丝雀分析自然是会成功的。

接下来,来尝试进行自动渐进式交付失败的实验。

经过了自动渐进式交付成功的实验之后,当前生产环境中的镜像为 argoproj/rollouts-demo:green,继续使用 Argo Rollout kubectl 插件来更新镜像,并将镜像版本修改为 yellow 版本。

kubectl argo rollouts set image canary-demo canary-demo=argoproj/rollouts-demo:yellow

接下来,重新返回 http://progressive.auto 打开应用,等待一段时间后,会看到请求开始出现黄色方块,如下图所示。

在这里插入图片描述

接下来,让应用返回错误的 HTTP 状态码。可以滑动界面上的 ERROR 滑动块,将错误率设置为 50%,如下图所示。

在这里插入图片描述

现在,会在黄色方块中看到带有红色描边的方块,这代表本次请求返回的 HTTP 状态码不等于 200,说明成功控制了一部分请求返回错误。

2 分钟后,金丝雀发布会进入到 40% 流量的阶段,此时自动分析将开始进行。现在,进入 Argo Rollout 控制台。

使用浏览器打开 http://localhost:3100/rollouts 进入发布详情,等待一段时间后,金丝雀分析将失败,如下图所示。

在这里插入图片描述

此时,Argo Rollout 将执行自动回滚操作,这时候重新返回 http://progressive.auto 打开应用,会看到黄色方块的流量消失,所有请求被绿色方块取代,说明已经完成回滚了,如下图所示。

在这里插入图片描述

到这里,一次完整的渐进式交付失败实验就成功了。

后记

本课程体系旨在为学员提供一套全面的云原生技术学习路径,包括容器技术、Kubernetes 部署和管理、Ingress 管理、持久化存储、应用部署、可观测性、服务网格、DevOps 工具链和流水线以及 GitOps 等方面的内容。通过学习这套课程体系,学员将掌握云原生技术的关键概念、原理和实践方法,从而提升云原生应用的部署、管理和协作效率。

  1. Docker 技术实战:学习容器技术的基础知识,包括 Docker 的运作原理、核心组件以及应用部署和监控管理。
  2. Kubernetes 部署和管理实战:深入了解 Kubernetes 的核心概念和基础组件,掌握 Kubernetes 集群的部署、管理和监控技能。
  3. Kubernetes Ingress 管理与运维:学习 Kubernetes Ingress 的概念、工作机制和运维管理方法,提升 Ingress 的部署和管理能力。
  4. Kubernetes 持久化存储实践:探讨 Kubernetes 持久化存储的原理、实现方式和实际应用,提高在 Kubernetes 上实现持久化存储的能力。
  5. Kubernetes 应用部署和管理:学习 Kubernetes 应用部署和管理的基本概念、原理和实现方法,掌握在 Kubernetes 上部署和管理应用的技巧。
  6. Kubernetes 可观测性实践:研究 Kubernetes 可观测性实践的概念、原理和实现方法,涉及监控、日志记录和分析等方面。
  7. 基于 Istio 的服务网格实战:深入了解基于 Istio 的服务网格概念、原理和实现方法,包括服务路由、流量管理、弹性能力和微服务可观测性等。
  8. DevOps 工具链与流水线实践:探讨 DevOps 工具链与流水线的概念、原理和实现方法,涵盖自动化构建、测试、部署和监控等环节。
  9. GitOps 云原生应用的高效部署与管理:全面掌握 GitOps 原理、技术和工具,提高云原生应用部署、管理和协作效率。

通过对这九门课程的学习,学员可以:

  1. 熟练运用 Docker 和 Kubernetes 进行容器化应用的部署和管理。
  2. 掌握 Ingress 和持久化存储在 Kubernetes 集群中的配置和管理方法。
  3. 了解 Kubernetes 可观测性实践,提高应用监控、日志和分析的能力。
  4. 探究 Istio 服务网格的原理和实现,实现微服务的高可用、弹性和安全。
  5. 运用 DevOps 工具链和流水线实现自动化构建、测试、部署和监控。
  6. 掌握 GitOps 的原理和技术,提升云原生应用的部署、管理和协作效率。

本课程体系适合对云原生技术感兴趣的开发者、运维工程师、架构师等专业人士。课程内容丰富、实践性强,旨在帮助学员在实际工作中更好地应用云原生技术,为企业的数字化转型做出贡献。

如果希望获得更详细的课程介绍,请联系: info@cloudzun.com

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值