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%的流量到新版本,若表現正常,逐步增加流量佔比,繼續測試新版本表現。若新版本一直很穩定,那麼將所有流量都切分到新版本,並下線老版本。
切分20%的流量到新版本後,新版本出現異常,則快速將流量切回老版本。
金絲雀釋出(灰度釋出):
採用金絲雀部署,可以在生產環境的基礎設施中小範圍的部署新的應用程式碼。一旦應用簽署釋出,只有少數使用者被路由到它。最大限度的降低影響。如果沒有錯誤發生,新版本可以逐漸推廣到整個基礎設施。下圖示範了金絲雀部署:
部署 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
在頁面上點選了 Promote
以後,就會每隔20S,更新10%的資源。
[root@rocky01 ~] # kubectl-argo-rollouts promote rollouts-myapp
實施回滾
[root@rocky01 ~] # kubectl-argo-rollouts undo rollouts-myapp