Kubernetes高階部署元件 Argo Rollout

Jas0n0ss發表於2024-08-07

Argo介紹

https://argoproj.github.io/

Argo 是一個開源專案,旨在提供一套用於在 Kubernetes 上執行和管理容器化工作負載的工具。
Argo 專案最早在2017年由Applatix公司創立開源,在2018年被美國加利福尼的 Intuit 公司收購併持續維護,並得到了廣泛的社群支援。

Argo 專案主要包括以下幾個子專案,每個子專案都有其特定的用途:

  • Argo Workflows:

簡介: Argo Workflows 是一個 Kubernetes 原生的工作流引擎,用於在 Kubernetes 叢集上創 建、管理和協調容器化任務。
用途: 支援DAG(有向無環圖 Directed Acyclic Graph),複雜的工作流定義和依賴管理,適用 於資料處理、機器學習訓練和 CI/CD 管道等場景。

特性: 提供視覺化介面、支援各種程式語言的模板、內建重試和錯誤處理機制。

  • Argo CD:

簡介: Argo CD 是一個用於 Kubernetes 的持續交付工具,透過宣告式的 GitOps 方法來管理 Kubernetes 資源。
用途: 將 Git 倉庫中的配置和應用程式宣告與 Kubernetes 叢集的實際狀態進行同步。
特性: 提供視覺化的同步狀態監控、自動回滾、支援多種 Git 提供商、提供豐富的 RBAC(基 於角色的訪問控制)。

  • Argo Events:

簡介: Argo Events 是一個事件驅動的工作流自動化框架,允許使用者根據特定的事件觸發工作 流。
用途: 透過各種事件源(如 GitHub、S3、HTTP 請求等)觸發 Argo Workflows 或 Kubernetes 資源。

特性: 支援多種事件源、靈活的事件依賴管理、提供事件驅動的自動化功能。

  • Argo Rollouts:

簡介: Argo Rollouts 是一個用於管理 Kubernetes 中高階部署策略的工具。
用途: 支援藍綠部署、金絲雀部署、分階段釋出等高階釋出策略,確保應用程式的平滑升級和 回滾。
特性: 提供視覺化的釋出狀態監控、細粒度的流量控制、內建指標和健康檢查功能。

這些子專案協同工作,為在 Kubernetes 上實現高效、可擴充套件和自動化的應用程式交付提供了強大的工 具集。

Argo Rollouts 介紹

Argo Rollouts 是 Argo 開源專案的一部分。Argo Rollouts 是一個用於漸進式交付的 Kubernetes 控制器,相當於增強版的deployment資源Argo Rollouts 包括一組自定義資源定義 (CRD),向 Kubernetes 引入藍綠部署blue-green、金絲雀 釋出canary、金絲雀分析canary analysis、漸進式交付progressive delivery 等高階部署功能。

Argo Rollouts 支援與ServiceMesh(Istio、Linkerd和SMI)和Ingress Controller 整合,以利用其流量 治理能力,並在更新期間逐漸將流量轉移到新版本。

Argo Rollouts 還能夠查詢和解釋來自多種指標系統(Prometheus、Kubernetes Jobs、Datadog等) 的指標來檢查Blue-Green或Canary部署結果,並根據結果自動決定執行升級或回滾

釋出模式:

藍綠髮布:

藍綠髮布提供了一種零當機的部署方式。不停老版本,部署新版本進行測試,確認OK,將流量切到新版本,然後老版本同時也升級到新版本。始終有兩個版本同時線上,有問題可以快速切換。

如下灰度釋出的大致流程

先切分20%的流量到新版本,若表現正常,逐步增加流量佔比,繼續測試新版本表現。若新版本一直很穩定,那麼將所有流量都切分到新版本,並下線老版本。

2.gif

切分20%的流量到新版本後,新版本出現異常,則快速將流量切回老版本。

3.gif

金絲雀釋出(灰度釋出):

採用金絲雀部署,可以在生產環境的基礎設施中小範圍的部署新的應用程式碼。一旦應用簽署釋出,只有少數使用者被路由到它。最大限度的降低影響。如果沒有錯誤發生,新版本可以逐漸推廣到整個基礎設施。下圖示範了金絲雀部署:

6.jpg

部署 Argo Rollouts

https://argoproj.github.io/argo-rollouts/installation/

[root@rocky01 ~] # kubectl create namespace argo-rollouts
[root@rocky01 ~] # kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml
#生成API群組和CRD資源
[root@rocky01 ~] # kubectl api-resources --api-group argoproj.io
NAME                       SHORTNAMES   APIVERSION             NAMESPACED   KIND
analysisruns               ar           argoproj.io/v1alpha1   true         AnalysisRun
analysistemplates          at           argoproj.io/v1alpha1   true         AnalysisTemplate
clusteranalysistemplates   cat          argoproj.io/v1alpha1   false        ClusterAnalysisTemplate
experiments                exp          argoproj.io/v1alpha1   true         Experiment
rollouts                   ro           argoproj.io/v1alpha1   true         Rollout
[root@rocky01 ~] # kubectl get all -n argo-rollouts
NAME                                READY   STATUS    RESTARTS   AGE
pod/argo-rollouts-bdbddf5fb-zftjw   1/1     Running   0          3m21s

NAME                            TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/argo-rollouts-metrics   ClusterIP   10.68.187.95   <none>        8090/TCP   3m21s

NAME                            READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/argo-rollouts   1/1     1            1           3m21s

NAME                                      DESIRED   CURRENT   READY   AGE
replicaset.apps/argo-rollouts-bdbddf5fb   1         1         1       3m21s

部署 Dashboard

[root@rocky01 ~] # kubectl apply -n argo-rollouts -f  https://github.com/argoproj/argo-rollouts/releases/latest/download/dashboard-install.yaml
[root@rocky01 ~] # kubectl get svc -n argo-rollouts
NAME                      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
argo-rollouts-dashboard   ClusterIP   10.68.192.197   <none>        3100/TCP   40s
argo-rollouts-metrics     ClusterIP   10.68.187.95    <none>        8090/TCP   6m10s
#準備ingress清單檔案實現外部訪問,注意:需要提前部署ingress-nginx
[root@rocky01 ~] # kubectl create ingress -n argo-rollouts --rule="rollout.k8slab.io/*=argo-rollouts-dashboard:3100" --class=nginx  rollouts
[root@rocky01 ~] # kubectl get ingress -n argo-rollouts
NAME       CLASS   HOSTS               ADDRESS         PORTS   AGE
rollouts   nginx   rollout.k8slab.io   192.168.5.239   80      18s
[root@rocky01 ~] # nslookup rollout.k8slab.io
Server:		192.168.5.1
Address:	192.168.5.1#53

Name:	rollout.k8slab.io
Address: 192.168.5.239
[root@rocky01 ~] # kubectl config set-context context-lab --namespace argo-rollouts #更改預設ns為argo-rollouts

部署 kubectl argo rollouts 命令外掛

argo rollouts 沒有提供相關專用命令管理 argo rollouts 資源,可以透過安裝kubectl的外掛實現管理argo rollouts的命令功能.

[root@rocky01 ~] # wget -O  /usr/local/bin/kubectl-argo-rollouts https://github.com/argoproj/argo-rollouts/releases/latest/download/kubectl-argo-rollouts-linux-amd64 && chmod +x /usr/local/bin/kubectl-argo-rollouts
[root@rocky01 ~] # kubectl-argo-rollouts version
kubectl-argo-rollouts: v1.7.1+6a99ea9
  BuildDate: 2024-06-24T22:46:25Z
  GitCommit: 6a99ea9908e8f1e816ccd71e4c35adbbbbdd5f6c
  GitTreeState: clean
  GoVersion: go1.21.11
  Compiler: gc
  Platform: linux/amd64
[root@rocky01 ~] #  echo 'source <(kubectl argo rollouts completion bash)' >> ~/.bashrc && source ~/.bashrc

kubectl argo rollouts 命令常見用法:

#更新應用
kubectl argo rollouts set image ROLLOUT_NAME CONTAINTER=NEW_IMAGE
#檢視
kubectl argo rollouts get rollout ROLLOUT_NAME --watch
#繼續更新
kubectl-argo-rollouts promote ROLLOUT_NAME [flags]
#中止更新
kubectl-argo-rollouts abort ROLLOUT_NAME [fags]
#再次重新更新
kubectl-argo-rollouts retry rollout ROLLOUT_NAME [fags]
#回滾
kubectl-argo-rollouts undo ROLLOUT_NAME [flags]

基礎案例:

https://github.com/argoproj/argo-rollouts/tree/master/examples

結合 Service 進行 Canary 部署

https://github.com/argoproj/argo-rollouts/blob/master/examples/rollout-rolling-update.yaml

案例說明:

  • 部署 Argo Rollouts 和 dashboard 及 kubectl argo rollouts 命令外掛 部署 ingress-nginx
  • 準備一個有兩個新舊版本的myapp應用
  • 依賴一個Service的排程功能, 透過Pod 數量來實現灰度釋出
  • 基於Pod 數量來實現流量的分配, 所以精確程度不足
# vim rollouts-canary-service-myapp.yaml
# 
---
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: rollouts-myapp
spec:
  replicas: 10 
  strategy:
    canary:
      steps:
      - setWeight: 10 # 先發布10%,待人為確認後,再繼續釋出
      - pause: {}     # 需要人為確認的動作
      - setWeight: 20
      - pause: {duration: 20}
      - setWeight: 30
      - pause: {duration: 20}
      - setWeight: 40
      - pause: {duration: 20}
      - setWeight: 60
      - pause: {duration: 20}
      - setWeight: 80
      - pause: {duration: 20}
  revisionHistoryLimit: 5
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: registry.cn-beijing.aliyuncs.com/wangxiaochun/myapp:v1.0
        ports:
        - name: http
          containerPort: 80
          protocol: TCP
        resources:
          requests:
            memory: 32Mi
            cpu: 50m
        livenessProbe:
          httpGet:
            path: '/'
            port: 80
            scheme: HTTP
          initialDelaySeconds: 3
        readinessProbe:
          httpGet:
            path: '/'
            port: 80
            scheme: HTTP
          initialDelaySeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: myapp
spec:
  ports:
  - port: 80
    targetPort: http
    protocol: TCP
    name: http
  selector:
    app: myapp
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp
spec:
  ingressClassName: "nginx"
  rules:
    - host: myapp.k8slab.io
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: myapp
                port:
                  number: 80
---
[root@rocky01 ~] # vim rollouts-canary-service-myapp.yaml
[root@rocky01 ~] # kubectl apply -f rollouts-canary-service-myapp.yaml -n argo-rollouts
rollout.argoproj.io/rollouts-myapp created
service/myapp created
ingress.networking.k8s.io/myapp created
[root@rocky01 ~] # kubectl get ingress
NAME       CLASS   HOSTS               ADDRESS         PORTS   AGE
myapp      nginx   myapp.k8slab.io     192.168.5.239   80      30s
[root@rocky01 ~] # curl myapp.k8slab.io
<h1>Welcome to MyAPP v1.0</h1>

實施映象更新
[root@rocky01 ~] # kubectl-argo-rollouts set image rollouts-myapp myapp=registry.cn-beijing.aliyuncs.com/wangxiaochun/myapp:v2.0
rollout "rollouts-myapp" image updated
[root@rocky01 ~] # kubectl-argo-rollouts status rollouts-myapp
[root@rocky01 ~] # kubectl-argo-rollouts get rollout rollouts-myapp

image-20240807034900514

在頁面上點選了 Promote以後,就會每隔20S,更新10%的資源。

[root@rocky01 ~] # kubectl-argo-rollouts promote rollouts-myapp

實施回滾
[root@rocky01 ~] # kubectl-argo-rollouts undo rollouts-myapp

結合Service進行Blue-Green部署

進階案例

結合Prometheus指標進行Analysis實現canary部署

結合Prometheus指標進行Analysis實現Blue- Green部署

相關文章