在 Istio 服务网格中使用 Argo Rollouts 实现智能的渐进式发布

news2024/10/5 21:20:23

1 Argo Rollouts 介绍

Kubernetes 原生的 Deployment 利用 Rolling Update 滚动更新的策略在应用升级时提供基本的安全保证(例如就绪探针)。然而默认的滚动更新策略存在着一些明显的缺点,例如:

  • 无法控制流向新版本的流量。
  • 无法控制升级的速度,有可能过于激进地推进升级。
  • 在出现故障时无法进行自动回滚。
  • Readiness probe 仅支持对容器自身进行简单的探测,无法通过查询外部指标来验证更新,例如应用层面整体的请求成功率。

基于以上种种原因,Argo Rollouts[1] 应运而生。Argo Rollouts 可以为 Kubernetes 中的应用提供诸如蓝绿、金丝雀、金丝雀分析、渐进式发布等高级功能。在 Argo Rollouts 中,使用 Rollout 对象替代 Deployment 对象来管理 ReplicaSets 的创建,缩放和删除,这些 ReplicaSet 由 Rollout 资源中的 spec.template 定义,使用与 Deployment 对象相同的 pod 模板。除此之外,Rollout 对象还提供了额外的功能:

  • Blue-Green(蓝绿)Canary(金丝雀) 发布策略。
  • ingress Controller(例如 NGINX, Traefik, AWS ALB) 或者服务网格(例如 Istio, SMI)等进行集成,利用它们的流量整形能力在更新期间逐渐将流量转移到新版本。
  • 在更新的时候执行 Analysis 分析以推动渐进式发布,并根据分析的结果,决定继续更新或者回滚。Analysis 支持与 Prometheus,Datadog, CloudWatch 等监控组件集成来获取相关指标来进行分析。

另外 Analysis 分析会涉及到以下两个 CRD 资源:

  • AnalysisTemplate:AnalysisTemplate 是一个模板,它定义了如何执行金丝雀分析,例如它应该执行的指标、频率以及被视为成功或失败的值,AnalysisTemplate 还可以通过输入值进行参数化。
  • AnalysisRun:当分析开始时,会创建出一个 AnalysisRun 对象,AnalysisRun 是根据一个或多个 AnalysisTemplate 的定义以及输入的参数生成的。AnalysisRun 运行的结果有 3 种状态,分别是:Successful, Failed, Inconclusive,运行的结果分别影响 Rollout 的更新是否继续、中止或暂停。

Argo Rollouts Controller 是一个 Kubernetes 控制器[2] ,负责监视 Argo Rollouts 相关的 CRD 资源,并在资源发生更改时做出反应,另外 Argo Rollouts Controller 还会对 Service 和 VirtualService 进行调整来对流量进行干预。

关于蓝绿发布,金丝雀发布,渐进式交付等概念参见 Concepts[3]。

2 前提准备

在开始实验之前,你需要确保安装以下工具:

  • kind[4] 可以用来在本地运行和测试 Kubernetes 集群,它使用 Docker 容器来作为 Kubernetes 的节点。
  • kubectl[5]是用于管理 Kubernetes 的命令行界面(CLI)工具。
  • Argo Rollouts kubectl plugin[6] 是用于管理 Argo Rollouts 的 kubectl 插件。
  • Istioctl[7] 是用于管理 Istio 服务网格的命令行工具。

本实验涉及的所有文件可以在 Github 上找到。

https://github.com/cr7258/hands-on-lab/tree/main/argo-rollouts/istio

3 创建 Kubernetes 集群

执行以下命令,在本地创建一个 3 节点的 Kubernets 集群。

kind create cluster --config cluster.yaml

集群的配置文件 cluster.yaml 如下。

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: argo-rollout-testing
nodes:
- role: control-plane
- role: worker
- role: worker

4 部署 Istio

Istio 是一个开源的服务网格,以透明的接入到分布式服务中,提供了流量管理、安全、可观测性等丰富的功能。在本实验中,Argo Rollouts 将会借助 Istio 的服务治理能力对应用的流量进行控制,在更新时逐步将流量转移到新版本的服务上。执行以下命令,在 Kubernetes 集群中部署 Istio。使用 demo profile 会在集群部署 istio-egressgateway, istio-egressgateway, istiod 组件。关于不同 profile 的介绍参见 Installation Configuration Profiles[8]。

istioctl install --set profile=demo

确保 Istio 的相关组件都已正常运行。

> kubectl get pod -n istio-system
NAME                                    READY   STATUS    RESTARTS   AGE
istio-egressgateway-5bdd756dfd-sbxfv    1/1     Running   0          2m26s
istio-ingressgateway-67f7b5f88d-wb7q5   1/1     Running   0          2m26s
istiod-58c6454c57-44tn4                 1/1     Running   0          3m

5 部署 Argo Rollouts Controller

创建一个新的命名空间 argo-rollouts,并在里面部署 Argo Rollouts Controller。

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

确保 Argo Rollouts Controller 已正常运行。

> kubectl get pod -n argo-rollouts
NAME                             READY   STATUS    RESTARTS   AGE
argo-rollouts-7f75b9fb76-fxjns   1/1     Running   0          84s

6 部署 Prometheus

Prometheus 是一个开源监控系统和时序数据库,可以使用 Prometheus 来记录 Istio 相关的指标数据从而追踪 Istio 和服务网格中应用程序的健康状况。

Istio 提供了一个基本的示例[9] 安装来快速启动和运行 Prometheus,我们先将该资源文件下载下来。

wget https://raw.githubusercontent.com/istio/istio/release-1.16/samples/addons/prometheus.yaml

用于在第 9 小节中我们需要借助请求的指标(istio_requests_total)来分析新版本应用的健康状态,而该指标来自 Envoy 的统计数据,Envoy 是 Istio 服务网格中的数据平面,因此我们需要在 Prometheus 的配置文件中添加以下内容:

- job_name: 'envoy-stats'
  metrics_path: /stats/prometheus
  kubernetes_sd_configs:
  - role: pod

  relabel_configs:
  - source_labels: [__meta_kubernetes_pod_container_port_name]
    action: keep
    regex: '.*-envoy-prom'

修改完成后,应用该资源文件。确认 Prometheus 已经正常运行。

kubectl get pod -n istio-system -l app=prometheus
NAME                         READY   STATUS    RESTARTS   AGE
prometheus-85949fddb-dbwhd   2/2     Running   0          30s

等待 Prometheus 部署成功后,可以执行以下命令,打开 Prometheus Dashboard。

istioctl dashboard prometheus

点击 Status -> Target 确认可以发现 envoy-stats 。

7 部署 Kiali

kiali 是一款用于管理 istio 服务网格的可视化工具,提供了服务拓扑、全链路跟踪、指标遥测、健康探测、配置校验等功能。

Istio 提供了一个基本的示例[10] 安装来快速启动和运行 Kiali。执行以下命令,在集群中部署 Kiali。

kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.16/samples/addons/kiali.yaml

确认 Kiali 的相关组件已经正常运行。

> kubectl get pod -n istio-system -l app=kiali
NAME                    READY   STATUS    RESTARTS   AGE
kiali-849958788-r8ml9   1/1     Running   0          65s

执行以下命令,打开 Kiali Dashboard。

istioctl dashboard kiali

8 部署应用

接下来开始部署我们的应用程序。首先创建一个 Namespace rollouts-demo 用于部署应用,添加 Lable istio-injection: enabled 表示在该 Namespace 启用 Istio 自动注入 ,在后面我们需要通过 Istio 的 VirtualService 和 Gateway 对流量进行管理。

apiVersion: v1
kind: Namespace
metadata:
  labels:
    istio-injection: enabled
  name: rollouts-demo

然后分别为 Stable 和 Canary 两个服务各创建一个 Service。当前这两个 Service 除了名字以外,其他内容完全相同。

apiVersion: v1
kind: Service
metadata:
  name: myapp-canary-svc
  namespace: rollouts-demo
spec:
  ports:
  - port: 80
    targetPort: http
    protocol: TCP
    name: http
  selector:
    app: myapp
    # 进行金丝雀发布时,Argo Rollouts Controller 会自动帮我们添加 Canary 服务 Pod 的 label,例如:
    # rollouts-pod-template-hash: 55bdff45cb

---
apiVersion: v1
kind: Service
metadata:
  name: myapp-stable-svc
  namespace: rollouts-demo
spec:
  ports:
  - port: 80
    targetPort: http
    protocol: TCP
    name: http
  selector:
    app: myapp
    # 进行金丝雀发布时,Argo Rollouts Controller 会自动帮我们添加 Stable 服务 Pod 的 label,例如:
    # rollouts-pod-template-hash: 85f45f96

创建 VirtualService,其中包含一条 HTTP 路由,路由名称以及 Destination 会和后面创建的 Rollout 资源进行关联。当前我们将 stable Service 的权重设置为 100,canary Service 的权重设置为 0,表示所有流量刚开始只发往 stable Service。

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: myapp-vsvc
  namespace: rollouts-demo
spec:
  gateways:
  - myapp-gateway # 关联 Gateway 资源
  hosts:
  - myapp.apps.argoproj.io # 客户端访问的 host
  http:
  - name: primary # 关联 Rollout 的 canary.trafficRouting.istio.virtualService.routes
    route:
    - destination:
        host: myapp-stable-svc # 关联 Rollout 的 canary.stableService
      weight: 100 # 当进行金丝雀发布时,Argo Rollouts Controller 会自动帮助我们调整权重
    - destination:
        host: myapp-canary-svc # 关联 Rollout 的 canary.canaryService
      weight: 0

当进行金丝雀发布时,Argo Rollouts Controller 会自动帮我们做以下事情:

  • 修改 canary Service 的 spec.selector ,添加 rollouts-pod-template-hash label 以匹配 canary 服务的 Pod。
  • 修改 stable Service 的 spec.selector ,添加 rollouts-pod-template-hash label 以匹配 Stable 服务的 Pod。
  • 修改 VirtualService 的 spec.http[].route[].weight 来匹配当前期望的流量比例。

创建 Gateway 资源,接收从客户端入访的流量。

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: myapp-gateway
  namespace: rollouts-demo
spec:
  selector:
    istio: ingressgateway # 默认创建的 istio ingressgateway pod 有这个 Label
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*" # 匹配所有 host

9 创建 Rollout 和 AnalysisTemplate

创建一个 AnalysisTemplate 资源,当分析开始时延迟 60s 后启动,每隔 20s 向 Prometheus 查询我们自定义的 PromQL 语句,它没有结束时间,一直持续到停止或失败。该语句表示查询 canary Service 的请求成功率,指标来源于第 6 小节中配置的从 Envoy 采集到的统计数据。

如果查询到的指标值小于 90%,并且存在三个这样的测量值,则分析被视为失败。失败的分析会导致 Rollout 中止,canary Service 的权重将会被设置回零。否则,如果 Rollout 完成所有 的 steps 步骤,则认为本次 Rollout 更新是成功的,之后 Argo Rollouts Controller 将停止运行分析。

apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
  name: istio-success-rate
  namespace: rollouts-demo
spec:
  args:
  - name: service
  - name: namespace
  metrics:
  - name: success-rate
    initialDelay: 60s # 延迟 60s 后启动
    interval: 20s # 查询指标的频率
    successCondition: len(result) == 0 || result[0] > 0.90 # 成功条件:测量值为空(指标还没采集到)或者大于 90%
    failureLimit: 3 # 3 次不满足 successCondition 则视为失败
    provider: 
      prometheus:
        address: http://prometheus.istio-system:9090 # Prometheus 地址
        query: >+ # 查询语句
          sum(rate(istio_requests_total{
            reporter="source",
            destination_service=~"{{args.service}}.{{args.namespace}}.svc.cluster.local",
            response_code!~"5.*"}[2m])
          )
          /
          sum(rate(istio_requests_total{
            reporter="source",
            destination_service=~"{{args.service}}.{{args.namespace}}.svc.cluster.local"}[2m])
          )
          unless sum(rate(istio_requests_total{
            reporter="source",
            destination_service=~"{{args.service}}.{{args.namespace}}.svc.cluster.local"}[2m])
          ) == 0

创建 Rollout 资源引用上面创建的 AnalysisTemplates,并传入 servicenamespace 两个参数。然后关联 canary Service,stable Service 以及 Istio VirtualService。在 steps 中设置 Rollout 升级的步骤,一开始会给 canary Service 分配 20% 的流量,需要手动确认通过才会进行下一阶段,然后每隔 60s 依次把 canary Service 的流量增加 20%。Analysis 分析从第 2 步开始,也就是从流量是 20% 的时候开始,也可以设置在后面的阶段再开始分析。

apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: myapp
  namespace: rollouts-demo
spec:
  revisionHistoryLimit: 2
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: argoproj/rollouts-demo:blue
        ports:
        - name: http
          containerPort: 8080
          protocol: TCP
        resources:
          requests:
            memory: 32Mi
            cpu: 5m
  strategy:
    canary:
      canaryService: myapp-canary-svc # 关联 canary Service
      stableService: myapp-stable-svc # 关联 stable Service
      analysis:
        startingStep: 1   # step 的索引,从第 2 个 step 开始分析(20%),第 1 个是 0% 初始的时候
        templates:
        - templateName: istio-success-rate # 使用的 AnalysisTemplates
        args:   # 传入 AnalysisTemplates 的参数
        - name: service
          value: myapp-canary-svc
        - name: namespace
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
      trafficRouting:
        istio:
          virtualService:
            name: myapp-vsvc # 关联的 Istio virtualService
            routes:
            - primary
      steps:
      - setWeight: 20
      - pause: {}         # 需要手动确认通过
      - setWeight: 40
      - pause: {duration: 60s}
      - setWeight: 60
      - pause: {duration: 60s}
      - setWeight: 80
      - pause: {duration: 60s}

10 应用升级

10.1 应用升级前

Argo Rollouts 为我们提供了可视化的 UI 界面方便观察和管理 Rollout 更新。执行以下命令,打开 Argo Rollouts Dashboard。

kubectl argo rollouts dashboard

浏览器输入 http://localhost:3100/rollouts 访问页面。可以看到,当前所有的流量都发往了 stable Service。

除了在图形化界面操作以外,也可以选择使用 Argo Rollout 的命令行工具。执行以下命令获取 Rollout 当前的状态。更多关于命令行的使用方法参见 Rollouts Commands[11]。

kubectl argo rollouts get rollout -n rollouts-demo myapp

接下来我们来访问一下应用程序的界面,首先执行以下命令,通过 kubectl port-forward 将 istio ingressgateway 暴露到本地的 28888 端口。

kubectl port-forward -n istio-system svc/istio-ingressgateway 28888:80

由于 VirtualService 根据客户端的 host 进行路由转发,当前我们并没有 DNS 服务器能够解析到在 VirtualService 中设置的域名 myapp.apps.argoproj.io, 因此我们需要在本地主机上添加一条 host 记录。

127.0.0.1  myapp.apps.argoproj.io

在浏览器输入 http://myapp.apps.argoproj.io:28888 访问应用页面,在升级前的应用是 blue 版本。

10.2 第一次升级

执行以下命令,更新应用服务的镜像为 yellow 版本。

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

你也可以在 Dashboard 上修改镜像版本来触发 Rollout 更新。

现在 canary Service 的流量会维持在 20% 左右,需要等待我们 PROMOTE 推进才会进入到下一阶段。

观察应用界面,发现现在已经开始有少量的黄色方块出现。

在 Kiali 面板可以看到当前 canary Service 和 stable Service 的流量比接近我们设置的 2:8。点击 Display -> 勾选 Traffic Distribution 可以在 Kiali Graph 上显示流量的百分比。

查看 VirtualService 可以发现服务的 weight 值被 Argo Rollouts Controller 修改了。

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: myapp-vsvc
  namespace: rollouts-demo
spec:
  gateways:
  - myapp-gateway
  hosts:
  - myapp.apps.argoproj.io
  http:
  - name: primary
    route:
    - destination:
        host: myapp-stable-svc
      weight: 80
    - destination:
        host: myapp-canary-svc
      weight: 20

查看 canary 和 stable Service 会发现 Argo Rollout Controller 为我们自动添加的选择标签来匹配 canary 和 stable 的 Pod。

apiVersion: v1
kind: Service
metadata:
  annotations:
    argo-rollouts.argoproj.io/managed-by-rollouts: myapp
  name: myapp-canary-svc
  namespace: rollouts-demo
spec:
  clusterIP: 10.96.34.227
  clusterIPs:
  - 10.96.34.227
  internalTrafficPolicy: Cluster
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - name: http
    port: 80
    targetPort: http
  selector:
    app: myapp
    rollouts-pod-template-hash: 55bdff45cb # Argo Rollout Controller 自动添加的选择标签
---
apiVersion: v1
kind: Service
metadata:
  annotations:
    argo-rollouts.argoproj.io/managed-by-rollouts: myapp
  name: myapp-stable-svc
  namespace: rollouts-demo
spec:
  clusterIP: 10.96.187.30
  clusterIPs:
  - 10.96.187.30
  internalTrafficPolicy: Cluster
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - name: http
    port: 80
    targetPort: http
  selector:
    app: myapp
    rollouts-pod-template-hash: 85f45f96 # Argo Rollout Controller 自动添加的选择标签

此时 AnalysisRun 会被创建出来,在后台分析 canary Service 的健康状态。

> kubectl get analysisruns.argoproj.io -n rollouts-demo
NAME                 STATUS    AGE
myapp-55bdff45cb-2   Running   4m3s

> kubectl get analysisruns.argoproj.io -n rollouts-demo myapp-55bdff45cb-2 -oyaml
apiVersion: argoproj.io/v1alpha1
kind: AnalysisRun
metadata:
  annotations:
    rollout.argoproj.io/revision: "2"
  creationTimestamp: "2022-12-08T04:07:52Z"
  generation: 12
  labels:
    rollout-type: Background
    rollouts-pod-template-hash: 55bdff45cb
  name: myapp-55bdff45cb-2
  namespace: rollouts-demo
  ownerReferences:
  - apiVersion: argoproj.io/v1alpha1
    blockOwnerDeletion: true
    controller: true
    kind: Rollout
    name: myapp
    uid: 7ec02222-1fc3-4a5e-8cd8-8b6eb7d425a4
  resourceVersion: "171599"
  uid: 3f096c6c-7c6f-4a3f-a96a-e493416b23f8
spec:
  args:
  - name: service
    value: myapp-canary-svc
  - name: namespace
    value: rollouts-demo
  metrics:
  - initialDelay: 60s
    interval: 20s
    name: success-rate
    provider:
      prometheus:
        address: http://prometheus.istio-system:9090
        query: | # 模板
          sum(rate(istio_requests_total{
            reporter="source",
            destination_service=~"{{args.service}}.{{args.namespace}}.svc.cluster.local",
            response_code!~"5.*"}[2m])
          ) / sum(rate(istio_requests_total{
            reporter="source",
            destination_service=~"{{args.service}}.{{args.namespace}}.svc.cluster.local"}[2m])
          ) unless sum(rate(istio_requests_total{
            reporter="source",
            destination_service=~"{{args.service}}.{{args.namespace}}.svc.cluster.local"}[2m])
          ) == 0
    successCondition: len(result) == 0 || result[0] > 0.90
status:
  dryRunSummary: {}
  metricResults:
  - count: 10
    measurements: # 查询结果
    - finishedAt: "2022-12-08T04:08:52Z"
      phase: Successful
      startedAt: "2022-12-08T04:08:52Z"
      value: '[1]'
    - finishedAt: "2022-12-08T04:09:12Z"
      phase: Successful
      startedAt: "2022-12-08T04:09:12Z"
      value: '[1]'
    - finishedAt: "2022-12-08T04:09:32Z"
      phase: Successful
      startedAt: "2022-12-08T04:09:32Z"
      value: '[1]'
    - finishedAt: "2022-12-08T04:09:52Z"
      phase: Successful
      startedAt: "2022-12-08T04:09:52Z"
      value: '[1]'
    - finishedAt: "2022-12-08T04:10:12Z"
      phase: Successful
      startedAt: "2022-12-08T04:10:12Z"
      value: '[1]'
    - finishedAt: "2022-12-08T04:10:32Z"
      phase: Successful
      startedAt: "2022-12-08T04:10:32Z"
      value: '[1]'
    - finishedAt: "2022-12-08T04:10:52Z"
      phase: Successful
      startedAt: "2022-12-08T04:10:52Z"
      value: '[1]'
    - finishedAt: "2022-12-08T04:11:12Z"
      phase: Successful
      startedAt: "2022-12-08T04:11:12Z"
      value: '[1]'
    - finishedAt: "2022-12-08T04:11:32Z"
      phase: Successful
      startedAt: "2022-12-08T04:11:32Z"
      value: '[1]'
    - finishedAt: "2022-12-08T04:11:52Z"
      phase: Successful
      startedAt: "2022-12-08T04:11:52Z"
      value: '[]'
    metadata:
      ResolvedPrometheusQuery: |
        # 渲染后的 PromQL 查询语句
        sum(rate(istio_requests_total{
          reporter="source",
          destination_service=~"myapp-canary-svc.rollouts-demo.svc.cluster.local",
          response_code!~"5.*"}[2m])
        ) / sum(rate(istio_requests_total{
          reporter="source",
          destination_service=~"myapp-canary-svc.rollouts-demo.svc.cluster.local"}[2m])
        ) unless sum(rate(istio_requests_total{
          reporter="source",
          destination_service=~"myapp-canary-svc.rollouts-demo.svc.cluster.local"}[2m])
        ) == 0
    name: success-rate
    phase: Running
    successful: 10
  phase: Running
  runSummary:
    count: 1
  startedAt: "2022-12-08T04:07:52Z"

我们可以将 AnalysisRun 的 PromQL 查询语句复制到 Prometheus 中进行查询。


当前我们请求的成功率为 100%(1),接下来点击 PROMOTE 推进 Rollout 更新。

此时在应用界面可以看到有越来越多的黄色方格。

在 Kiali 上也可以观察到越来越多的流量开始往 canary Service 倾斜。

查看 VirtualService 发现 weight 值再次被 Argo Rollouts Controller 修改了。

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: myapp-vsvc
  namespace: rollouts-demo
spec:
  gateways:
  - myapp-gateway
  hosts:
  - myapp.apps.argoproj.io
  http:
  - name: primary
    route:
    - destination:
        host: myapp-stable-svc
      weight: 60
    - destination:
        host: myapp-canary-svc
      weight: 40

等待一会后,升级完成,此时应用界面全部都是黄色的方格。

在 Kiali 上可以看到流量只发往一个 Service 了,这里我觉得 Kiali 的显示有些问题,此时应该全部指向 stable Service,而不是 canary Service,因为当完成升级后,Argo Rollouts Controller 会把 stable Service 的 spec.selector 改成新的 yellow 版本的 Pod 的 Label。

并且 VirtualService 的 destination 也会将 100% 的流量权重设置到 stable Service 上。

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: myapp-vsvc
  namespace: rollouts-demo
spec:
  gateways:
  - myapp-gateway
  hosts:
  - myapp.apps.argoproj.io
  http:
  - name: primary
    route:
    - destination:
        host: myapp-stable-svc
      weight: 100
    - destination:
        host: myapp-canary-svc
      weight: 0

10.3 第二次升级

执行以下命令,进行第二次升级,将应用升级到 green 版本。

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

观察应用界面,可以看到开始出现少量绿色方格。

点击 PROMOTE 推进 Rollout 更新。

接下来我们模拟应用在升级过程中出现了故障,点击界面上方的绿色按钮,并将访问 ERROR 的比例设置为 65%。

观察 Kiali 界面,可以看到此时访问 canary Service 的流量出现的红色,表明有请求失败,右侧的方框显示了当前请求的成功和失败的比例。

在 Prometheus 界面查询之前的 PromQL 语句,可以看到当前 canary Service 的请求成功率仅有 30% 左右。

查看 Argo Rollouts 界面,发现 Analysis 分析已经失败,Rollout 开始自动回退。

10.4 修复 ERROR 后重新升级

假设经过排查后,我们修复了这个问题,执行以下命令,准备重新升级。

kubectl argo rollouts set image myapp -n rollouts-demo myapp=argoproj/rollouts-demo:purple

这次我们升级到 purple 版本。

点击 PROMOTE 推进 Rollout。

等待一会,这次顺利完成了升级。

11 清理环境

完成实验后,执行以下命令删除 Kubernetes 集群。

kind delete clusters argo-rollout-testing

12 总结

在本文中我们介绍了如何使用 Argo Rollouts 结合 Istio 服务网格中丰富的流量治理以及可观测性能力;并通过 Argo Rollouts 提供的 Analysis 机制,在应用升级时对应用的健康状态进行分析,根据分析结果自动决定是否继续更新或者回滚,从而实现了智能的渐进式发布。

13 参考资料

  • [1] Argo Rollouts 官方文档: https://argoproj.github.io/argo-rollouts/
  • [2] Kubernetes 控制器: https://kubernetes.io/docs/concepts/architecture/controller/
  • [3] Concepts: https://argoproj.github.io/argo-rollouts/concepts/
  • [4] kind: https://kind.sigs.k8s.io/docs/user/quick-start/#installatio
  • [5] kubectl: https://kubernetes.io/docs/tasks/tools/
  • [6] Argo Rollouts kubectl plugin: https://argoproj.github.io/argo-rollouts/installation/#kubectl-plugin-installation
  • [7] Istioctl: https://istio.io/latest/docs/setup/getting-started/#download
  • [8] Installation Configuration Profiles: https://istio.io/latest/docs/setup/additional-setup/config-profiles/
  • [9] Prometheus 安装: https://istio.io/latest/docs/ops/integrations/prometheus/#option-1-quick-start
  • [10] Kiali 安装: https://istio.io/latest/docs/ops/integrations/kiali/#installation
  • [11] Rollouts Commands: https://argoproj.github.io/argo-rollouts/generated/kubectl-argo-rollouts/kubectl-argo-rollouts/
  • [12] Argo Rollouts Demo: https://www.youtube.com/watch?v=hIL0E2gLkf8
  • [13] 使用 Argo Rollouts 实现渐进式发布: https://mp.weixin.qq.com/s/BP9MfGAgPiOYx_EpNOWqjQ
  • [14] Argo Rollouts 实现蓝绿/金丝雀发布: https://mp.weixin.qq.com/s/vTzrNUrG3UvAIQUfbSruow
  • [15] Canary Deployment in Kubernetes (Part 3) — Smart Canary Deployment using Argo Rollouts and Prometheus: https://jhandguy.github.io/posts/smart-canary-deployment/
  • [16] Understanding Istio Telemetry v2: https://blog.christianposta.com/understanding-istio-telemetry-v2/
  • [17] How to monitor Istio, the Kubernetes service mesh: https://sysdig.com/blog/monitor-istio/
  • [18] How to configure Prometheus-Operator & scrape metrics from Istio 1.6: https://tetrate.io/blog/how-to-configure-prometheus-operator-scrape-metrics-from-istio-1-6/#Install-Prometheus
  • [19] Progressive Delivery with Argo Rollouts: Canary with Analysis: https://www.infracloud.io/blogs/progressive-delivery-argo-rollouts-canary-analysis/

14 欢迎关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/78314.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

tensorflow入门(四)如何用tensorflow训练神经网络

参考 如何用tensorflow训练神经网络 - 云社区 - 腾讯云 在使用神经网络解决实际的分类或回归问题时需要设置好参数取值。下面介绍使用监督学习的方式来合理地设置参数取值,同时也将给出tensorflow程序来完成这个过程。设置神经网络参数的过程就是神经网络的训练过…

基于JDBC的MySQL数据库编程

✨博客主页: 荣 ✨系列专栏: MySQL ✨一句短话: 难在坚持,贵在坚持,成在坚持! 文章目录一. JDBC概述二. JDBC前置工作1. 准备好MySQL驱动包2. 创建项目三. JDBC的使用步骤1. 创建数据源DataSourece2. 连接数据库3. 构造并执行sql语句4. 释放资源5. sql语句不要写死(以插入为例)…

C++入门基础07:函数定义与声明、函数传参(传值、传地址、传引用)、函数重载

C入门基础07:函数定义与声明、函数传参(传值、传地址、传引用)、函数重载 1、函数定义与声明 函数是一起执行一个任务的一组语句。每个程序(C/C)都有一个主函数 main() , 所有简单的程序都可以定义其他额…

1563_AURIX_TC275_EVR的控制寄存器

全部学习汇总: GreyZhang/g_TC275: happy hacking for TC275! (github.com) 1. 连续的写入必须确保是解锁状态,否则的话可能会导致所有的总线阻塞。 2. 多核系统中,尽量写入之后再读取一下确认写入的状态。 这里是过压以及欠压的几个监控结果…

if、for、while结构的用法

分支与循环的流程控制一、分支流程控制1. if分支语句结构1). 单分支2). 双分支3). 三元运算符(双分支的简化)4). 多分支二. 循环流程控制1. while循环语句语法结构1.while循环用法2.while 的死循环3. while else的用法2. for循环语句语法结构1. for和ran…

嵌入式开发学习之--串口通讯(上)

提示:本篇开始学习各种通讯方式,重中之重。 文章目录前言一、 串口通讯协议简介1.1 物理层1.2 协议层1.2.1 基本组成。1.2.2 波特率1.2.3 起始和终止位1.2.4 有效数据1.2.5 数据校验二、USART结构体详解总结前言 作为一个嵌入式的开发者,解析…

网页木马挂马的实现与防范

一、网页挂马是什么 不少用户都碰到过这样的现象:打开一个网站,结果页面还没显示,杀毒软件就开始报警,提示检测到木马病毒。有经验的朋友会知道这是网页恶意代码,这就是典型的网页挂马现象。那么是什么原因导致了这种…

数据库概论之MySQL表的增删改查 - 进阶版本1

MySQL表的增删改查 - 进阶1、数据库约束1.1 约束类型1.2 NULL约束1.3 UNIQUE约束1.4 DEFAULT约束1.5 PRIMARY约束1.6 FOREIGN KEY外键约束1.6.1 语法1.6.2 工作原理2、表的设计2.1 一对一2.2 一对多2.3 多对多大家好,已经好久没更新了 , 学校的学业有点忙 , 没有额外…

[论文解析] Denoising Diffusion Probabilistic Models

文章目录OverviewsWhat problem is addressed in the paper?What is the key to the solution?What is the main contribution?Contents扩散概率模型背景算法实验结论Overviews What problem is addressed in the paper? We present high quality image synthesis result…

【Java面试】说说类加载机制(流程)

文章目录加载流程装载(Load)链接(Link)验证(Verify)准备(Prepare)解析(Resolve)初始化(Initialize)卸载(Unload)加载流程 类的加载流程如下: 转载(Load)->链接(Link)->初始化(Initialize)->使用(Use)->卸载(Unload) 其中链接又包含验证(Verify)&#x…

rabbitMQ延时队列——TTL和DLX

一. 场景:“订单下单成功后,15分钟未支付自动取消” 1.传统处理超时订单 采取定时任务轮训数据库订单,并且批量处理。其弊端也是显而易见的;对服务器、数据库性会有很大的要求, 并且当处理大量订单起来会很力不从…

flask前后端项目--实例-前端部分:-4-vue-Element Plus

flask前后端项目--实例-前端部分:-4-vue-Element Plus组件添加事项 一、实验测试步骤 1.Element Plus添加 1.先备份App.VUE,然后修改app.vue的内容,数据来源资Element Plus的表格table 2. 数据来源资Element Plus的表格table 3. 运行服务&…

023_SSS_Neural 3D Video Synthesis from Multi-view Video(CVPR2022)

Neural 3D Video Synthesis from Multi-view Video(CVPR2022) 本文提出了一种新的3D视频生成方法,这种方法能够以紧凑但富有表现力的表示形式表示动态真实世界场景的多视图视频记录,从而实现高质量的视图合成和运动插值。 1. Introduction 本文的主要…

百度地图 ( 一 ) 显示地图

1.百度地图 百度地图开放平台 https://lbsyun.baidu.com/ 使用百度地图时导入JavaScript包 <script type"text/javascript" src"http://api.map.baidu.com/api?v2.0&ak您的密钥"></script>1.1.如何申请 ak 密钥 在 开发平台 找 控制…

ChatGPT注册流程

1.访问官网点击 Sign up https://chat.openai.com/auth/login 2.输入你的邮箱 3.点击Continue下一步: 4.输入密码继续下一步&#xff1a; 5.然后你的邮箱会受到一封邮件&#xff08;如果没收到请检查垃圾邮箱&#xff09;&#xff1a; 6.点击验证邮箱按钮&#xff0c;会跳到…

MySQL 5.7中文乱码与远程链接问题

MySQL 5.7中文乱码与远程链接问题1. MySQL 5.7中文乱码2. 远程链接问题3. 不区分表大小写4. 超过最大连接数5. 时区问题5. GROUP BY 问题配置集合重启MySQL1. MySQL 5.7中文乱码 当我们直接在数据库里面输入中文时&#xff0c;保存后出现&#xff1a; Incorrect string value&…

LeetCode 第 244 场周赛题解

前言 这是 2021-06-06 的一场 LeetCode 周赛&#xff0c;本场周赛的题目相较而以往而言比较简单&#xff0c;基本上想到点上就可以做出来&#xff0c;主要涉及到矩阵的旋转、贪心、滑动窗口、前缀和、二分查找等知识点。 第 244 场周赛链接&#xff1a;https://leetcode-cn.c…

SpringBoot+Vue实现前后端分离的学校快递站点管理系统

文末获取源码 开发语言&#xff1a;Java 使用框架&#xff1a;spring boot 前端技术&#xff1a;JavaScript、Vue.js 、css3 开发工具&#xff1a;IDEA/MyEclipse/Eclipse、Visual Studio Code 数据库&#xff1a;MySQL 5.7/8.0 数据库管理工具&#xff1a;phpstudy/Navicat JD…

机器人开发--雷达lidar

机器人开发--雷达lidar1 介绍2 分类2.1 整体分类2.2 机械式&#xff08;三角&ToF&#xff09;三角测距激光雷达ToF测距激光雷达3 机械式单线ToF激光雷达3.1 扫描原理3.2 不同材料反射率3.3 核心参数参考1 介绍 激光雷达&#xff08;英文&#xff1a;Laser Radar &#xff…

2023最新SSM计算机毕业设计选题大全(附源码+LW)之java制造类企业erp23725

面对老师五花八门的设计要求&#xff0c;首先自己要明确好自己的题目方向&#xff0c;并且与老师多多沟通&#xff0c;用什么编程语言&#xff0c;使用到什么数据库&#xff0c;确定好了&#xff0c;在开始着手毕业设计。 1&#xff1a;选择课题的第一选择就是尽量选择指导老师…