Argo Rollouts 實現藍綠 - 金絲雀發佈
Argo Rollouts 是一個 Kubernetes Operator 實現,它爲 Kubernetes 提供更加高級的部署能力,如藍綠、金絲雀、金絲雀分析、實驗和漸進式交付功能,爲雲原生應用和服務實現自動化、基於 GitOps 的逐步交付。
支持如下特性:
-
藍綠更新策略
-
金絲雀更新策略
-
更加細粒度、加權流量拆分
-
自動回滾
-
手動判斷
-
可定製的指標查詢和業務 KPI 分析
-
Ingress 控制器集成:NGINX,ALB
-
服務網格集成:Istio,Linkerd,SMI
-
Metrics 指標集成:Prometheus、Wavefront、Kayenta、Web、Kubernetes Jobs、Datadog、New Relic
實現原理
與 Deployment 對象類似,Argo Rollouts 控制器將管理 ReplicaSets 的創建、縮放和刪除,這些 ReplicaSet 由 Rollout 資源中的 spec.template
定義,使用與 Deployment 對象相同的 pod 模板。
當 spec.template
變更時,這會向 Argo Rollouts 控制器發出信號,表示將引入新的 ReplicaSet,控制器將使用 spec.strategy
字段內的策略來確定從舊 ReplicaSet 到新 ReplicaSet 的 rollout 將如何進行,一旦這個新的 ReplicaSet 被放大(可以選擇通過一個 Analysis),控制器會將其標記爲穩定
。
如果在 spec.template
從穩定的 ReplicaSet 過渡到新的 ReplicaSet 的過程中發生了另一次變更(即在發佈過程中更改了應用程序版本),那麼之前的新 ReplicaSet 將縮小,並且控制器將嘗試發佈反映更新 spec.template
字段的 ReplicasSet。
相關概念
在繼續之前我們先來了解一些基本的概念。
Rollout(滾動)
Rollout 是一個 Kubernetes 的 CRD 資源,相當於 Kubernetes Deployment 對象,在需要更高級的部署或漸進式交付功能的情況下,它旨在取代 Deployment 對象,Rollout 提供了 Kubernetes Deployment 所不能提供的功能。
-
藍綠部署
-
金絲雀部署
-
與 Ingress 控制器和服務網格整合,實現高級流量路由
-
與用於藍綠和金絲雀分析的指標提供者集成
-
根據成功或失敗的指標,自動發佈或回滾
漸進式交付
漸進式交付是以受控和漸進的方式發佈產品更新的過程,從而降低發佈的風險,通常將自動化和指標分析結合起來以驅動更新的自動升級或回滾。
漸進式交付通常被描述爲持續交付的演變,將 CI/CD 中的速度優勢擴展到部署過程。通過將新版本限制在一部分用戶,觀察和分析正確的行爲,然後逐漸增加更多的流量,同時不斷驗證其正確性。
部署策略
雖然業界使用了一致的術語來描述各種部署策略,但這些策略的實現往往因工具而異,爲了明確 Argo Rollouts 的行爲方式,以下是 Argo Rollouts 提供的各種部署策略實施的描述。
-
RollingUpdate(滾動更新):慢慢地用新版本替換舊版本,隨着新版本的出現,舊版本會慢慢縮減,以保持應用程序的總數量。這是 Deployment 對象的默認策略。
-
Recreate(重新創建):Recreate 會在啓動新版本之前刪除舊版本的應用程序,這可確保應用程序的兩個版本永遠不會同時運行,但在部署期間會出現停機時間。
-
Blue-Green(藍綠):藍綠髮布(有時稱爲紅黑)指同時部署了新舊兩個版本的應用程序,在此期間,只有舊版本的應用程序會收到生產流量,這允許開發人員在將實時流量切換到新版本之前針對新版本進行測試。
Blue-Green
- Canary(金絲雀):金絲雀發佈指將一部分用戶暴露在新版本的應用程序中,而將其餘流量提供給舊版本,一旦新版本被驗證是正確的,新版本可以逐漸取代舊版本。Ingress 控制器和服務網格,如 NGINX Ingress 和 Istio,可以使金絲雀的流量拆分模式比原生的更復雜(例如,實現非常細粒度的流量分割,或基於 HTTP 頭的分割)。
Canary
上面顯示了一個有兩個階段的金絲雀(10% 和 33% 的流量進入新版本),通過使用 Argo Rollouts,我們可以根據實際的使用情況定義確切的階段數和流量百分比。
場景
-
用戶希望在新版本開始爲生產環境提供服務之前對其進行最後一分鐘的功能測試,通過 BlueGreen 策略,Argo Rollouts 允許用戶指定預覽服務和活動服務,Rollout 將配置預覽服務以將流量發送到新版本,同時活動服務繼續接收生產流量。一旦達到要求,則可以將預覽服務提升爲新的活動服務。
-
在新版本開始接收實時流量之前,需要預先執行一套通用步驟,通過使用 BlueGreen 策略,用戶可以在不接收來自活動服務的流量的情況下啓動新版本,一旦這些步驟執行完畢,就可以將流量切換到新版本了。
-
用戶希望在幾個小時內將一小部分生產流量提供給他們應用程序的新版本。之後,他們希望縮小新版本規模,並查看一些指標以確定新版本與舊版本相比是否具有性能問題,然後他們將決定是否爲切換到新版本。使用金絲雀策略,rollout 可以用新版本擴大 ReplicaSet 的規模,以接收指定百分比的流量,等待指定的時間,然後將百分比設置回 0,然後等待用戶滿意後再發布,爲所有的流量提供服務。
-
一個用戶想慢慢給新版增加生產流量,先給它一小部分的實時流量,然後等待一段時間再給新版本更多的流量,最終,新版本將接收所有生產流量。使用金絲雀策略,用戶指定他們希望新版本接收的百分比以及在百分比之間等待的時間。
-
用戶想要使用 Deployment 中的正常滾動更新策略,如果用戶使用沒有步驟的金絲雀策略,rollout 將使用 maxSurge 和最大不可用值來滾動到新版本。
架構
下面展示了由 Argo Rollouts 管理的 Deployment 的所有組件。
argo rollouts 架構
Rollout Controller
這是主控制器,用於監視集羣的事件並在 Rollout 類型的資源發生更改時做出反應。控制器將讀取 rollout 的所有詳細信息,並使集羣處於 rollout 定義中描述的相同狀態。
請注意,Argo Rollouts 不會篡改或響應正常 Deployment 資源上發生的任何變更,這意味着你可以在一個使用其他方法部署應用的集羣中安裝 Argo Rollouts。
Rollout 資源
Rollout 資源是 Argo Rollouts 引入和管理的一種自定義 Kubernetes 資源,它與原生的 Kubernetes Deployment 資源基本兼容,但有額外的字段來控制更加高級的部署方法,如金絲雀和藍 / 綠部署。
Argo Rollouts 控制器將只對 Rollout 資源中的變化做出反應,不會對正常的 Deployment 資源做任何事情,所以如果你想用 Argo Rollouts 管理你的 Deployment,你需要將你的 Deployment 遷移到 Rollouts。
舊版和新版的 ReplicaSets
這些是標準的 Kubernetes ReplicaSet 資源的實例,Argo Rollouts 給它們添加了一些額外的元數據,以便跟蹤屬於應用程序的不同版本。
還要注意的是,參加 Rollout 的 ReplicaSet 完全由控制器自動管理,你不應該用外部工具來篡改它們。
Ingress/Service
用戶的流量進入集羣后,被重定向到合適的版本,Argo Rollouts 使用標準的 Kubernetes Service 資源,但有一些額外的元數據。
Argo Rollouts 在網絡配置上非常靈活,首先,可以在 Rollout 期間使用不同的服務,這些服務僅適用於新版本、僅適用於舊版本或兩者都適用。特別是對於 Canary 部署,Argo Rollouts 支持多種服務網格和 Ingress 解決方案,用於按特定百分比拆分流量,而不是基於 Pod 數量進行簡單的配置。
Analysis 與 AnalysisRun
Analysis
是一種自定義 Kubernetes 資源,它將 Rollout 連接到指標提供程序,併爲某些指標定義特定閾值,這些閾值將決定 Rollout 是否成功。對於每個 Analysis,你可以定義一個或多個指標查詢及其預期結果,如果指標查詢正常,則 Rollout 將繼續操作;如果指標顯示失敗,則自動回滾;如果指標無法提供成功 / 失敗的答案,則暫停發佈。
Analysis 只是關於要查詢哪些指標的模板。附加到 Rollout 的實際結果是 AnalysisRun
自定義資源,你可以在特定 Rollout 上或在集羣上全局定義 Analysis 以供多個 rollout 共享。
請注意,在 Rollout 中使用 Analysis 和指標是完全可選的,你可以通過 API 或 CLI 手動暫停和促進發布或使用其他外部方法(例如冒煙測試)。你不需要僅使用 Argo Rollouts 的 Metrics 解決方案,你還可以在 Rollout 中混合自動(即基於 Analysis)和手動步驟。
除了指標之外,你還可以通過運行 Kubernetes Job 或運行 webhook 來決定發佈的成功與否。
Metric Providers
Argo Rollouts 包括幾個流行的指標提供者的原生集成,你可以在 Analysis 資源中使用,來自動提升或回滾發佈。
CLI 和 UI(圖中未顯示)
還可以使用 Argo Rollouts CLI 或集成 UI 查看和管理 Rollout,兩者都是可選的。
安裝
直接使用下面的命令安裝 Argo Rollouts:
➜ ~ kubectl create namespace argo-rollouts
➜ ~ kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/download/v1.0.2/install.yaml
這裏會創建一個名爲 argo-rollouts
的命名空間,Argo Rollouts 控制器運行在下面。
➜ ~ kubectl get pods -n argo-rollouts
NAME READY STATUS RESTARTS AGE
argo-rollouts-6fdcf89f7c-7z2mh 1/1 Running 0 58s
此外,我們還可以安裝一個 kubectl 插件,對於命令行管理和可視化發佈非常方便。
我們這裏是 Mac 系統,可以直接使用下面的命令進行安裝:
➜ ~ brew install argoproj/tap/kubectl-argo-rollouts
當然也可以手動進行安裝,使用 curl 安裝 Argo Rollouts kubectl 插件:
➜ ~ curl -LO https://github.com/argoproj/argo-rollouts/releases/download/v1.0.2/kubectl-argo-rollouts-darwin-amd64
然後賦予 kubectl-argo-rollouts
二進制文件可執行權限:
➜ ~ chmod +x ./kubectl-argo-rollouts-darwin-amd64
將該二進制文件移動到你的 PATH 路徑下面去:
➜ ~ sudo mv ./kubectl-argo-rollouts-darwin-amd64 /usr/local/bin/kubectl-argo-rollouts
執行下面的命令來驗證插件是否安裝成功:
➜ ~ kubectl argo rollouts version
kubectl-argo-rollouts: v1.0.2+7a23fe5
BuildDate: 2021-06-15T19:36:10Z
GitCommit: 7a23fe5dbf78181248c48af8e5224246434e7f99
GitTreeState: clean
GoVersion: go1.16.3
Compiler: gc
Platform: darwin/amd64
使用
接下來我們通過幾個簡單的示例來說明 Rollout 的部署、升級、發佈和中斷等操作,以此來展示 Rollouts 的各種功能。
1. 部署 Rollout
首先我們部署一個 Rollout 資源和一個針對該資源的 Kubernetes Service 對象,這裏我們示例中的 Rollout 採用了金絲雀的更新策略,將 20% 的流量發送到金絲雀上,然後手動發佈,最後在升級的剩餘時間內逐漸自動增大流量,可以通過如下所示的 Rollout 來描述這個策略:
# basic-rollout.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: rollouts-demo
spec:
replicas: 5 # 定義5個副本
strategy: # 定義升級策略
canary: # 金絲雀發佈
steps: # 發佈的節奏
- setWeight: 20
- pause: {} # 會一直暫停
- setWeight: 40
- pause: {duration: 10}
- setWeight: 60
- pause: {duration: 10}
- setWeight: 80
- pause: {duration: 10}
revisionHistoryLimit: 2 # 下面部分其實是和 Deployment 兼容的
selector:
matchLabels:
app: rollouts-demo
template:
metadata:
labels:
app: rollouts-demo
spec:
containers:
- name: rollouts-demo
image: argoproj/rollouts-demo:blue
ports:
- name: http
containerPort: 8080
protocol: TCP
resources:
requests:
memory: 32Mi
cpu: 5m
還包括一個如下所示的 Service 資源對象:
# basic-service.yaml
apiVersion: v1
kind: Service
metadata:
name: rollouts-demo
spec:
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app: rollouts-demo
直接創建上面的兩個資源對象:
➜ ~ kubectl apply -f basic-rollout.yaml
➜ ~ kubectl apply -f basic-service.yaml
任何 Rollout 的初始創建都會立即將副本擴展到 100%(跳過任何金絲雀升級步驟、分析等...),因爲還沒有發生升級。
Argo Rollouts 的 kubectl 插件允許我們可視化 Rollout 以及相關資源對象,並展示實時狀態變化,要在部署過程中觀察 Rollout,可以通過運行插件的 get rollout --watch
命令,比如:
➜ ~ kubectl argo rollouts get rollout rollouts-demo --watch
watch rollouts
2. 更新 Rollout
上面已經部署完成,接下來就需要執行更新了,和 Deployment 類似,對 Pod 模板字段的任何變更都會導致新的版本(即 ReplicaSet)被部署,更新 Rollout 通常是修改容器鏡像的版本,然後執行 kubectl apply
,爲了方便,rollouts 插件還單獨提供了一個 set image
的命令,比如這裏我們運行以下所示命令,用 yellow
版本的容器更新上面的 Rollout:
➜ ~ kubectl argo rollouts set image rollouts-demo \
rollouts-demo=argoproj/rollouts-demo:yellow
在 rollout 更新期間,控制器將通過 Rollout 更新策略中定義的步驟進行。這個示例的 rollout 爲金絲雀設置了 20% 的流量權重,並一直暫停 rollout,直到用戶取消或促進發布。在更新鏡像後,再次觀察 rollout,直到它達到暫停狀態。
➜ ~ kubectl argo rollouts get rollout rollouts-demo --watch
watch rollouts
當 demo rollout 到達第二步時,我們可以從插件中看到,Rollout 處於暫停狀態,現在有 5 個副本中的 1 個運行新版本的 pod,其餘 4 個仍然運行舊版本,這相當於 setWeight: 20
步驟所定義的 20% 的金絲雀權重。
3. Promote Rollout
經過上面的更新後,Rollout 現在處於暫停狀態,當一個 Rollout 到達一個沒有持續時間的暫停步驟時,它將一直保持在暫停狀態,直到它被恢復 / 提升。要手動將 Rollout 切換到下一個步驟,請運行插件的 promotion
命令。
➜ ~ kubectl argo rollouts promote rollouts-demo
切換後 Rollout 將繼續執行剩餘的步驟。在我們的例子中,剩餘的步驟是完全自動化的,所以 Rollout 最終會完成步驟,直到它已經完全過渡到新版本。再次觀察 Rollout,直到它完成所有步驟。
➜ ~ kubectl argo rollouts get rollout rollouts-demo --watch
watch rollouts
promote 命令還支持用
--full
標誌跳過所有剩餘步驟和分析。
可以看到 stable
版本已經切換到 revision:2
這個 ReplicaSet 了。在更新過程中,無論何時,無論是通過失敗的金絲雀分析自動中止,還是由用戶手動中止,Rollout 都會退回到 stable
版本。
4. 中斷 Rollout
接下來我們來了解如何在更新過程中手動中止 Rollout,首先,使用 set image
命令部署一個新的 red
版本的容器,並等待 rollout 再次達到暫停的步驟。
➜ ~ kubectl argo rollouts set image rollouts-demo \
rollouts-demo=argoproj/rollouts-demo:red
watch rollouts
這一次我們將中止更新,而不是將滾動切換到下一步,這樣它就回到了 stable
版本,該插件同樣提供了一個 abort
命令,可以在更新過程中的任何時候手動中止 Rollout。
➜ ~ kubectl argo rollouts abort rollouts-demo
當中止滾動時,它將擴大 ReplicaSet 的 stable
版本(在本例中是 yellow
版本),並縮小任何其他版本。儘管 ReplicaSet 的穩定版本可能正在運行,並且是健康的,但整個 Rollout 仍然被認爲是退化的,因爲期望的版本(red
版本)不是實際運行的版本。
watch rollouts
爲了使 Rollout 再次被認爲是健康的而不是有問題的版本,有必要將所需的狀態改回以前的穩定版本。在我們的例子中,我們可以簡單地使用之前的 yellow
鏡像重新運行 set image
命令即可。
➜ ~ kubectl argo rollouts set image rollouts-demo \
rollouts-demo=argoproj/rollouts-demo:yellow
運行這個命令後,可以看到 Rollout 立即變成了 health 狀態,而且沒有任何關於創建新 ReplicaSets 的動態。
watch rollouts
當 Rollout 還沒有達到預期狀態(例如,它被中止了,或者正在更新中),而穩定版本的資源清單被重新應用,Rollout 檢測到這是一個回滾,而不是一個更新,並將通過跳過分析和步驟快速部署穩定的 ReplicaSet。
上面例子中的 Rollout 沒有使用 Ingress 控制器或服務網格來控制流量。相反,它使用正常的 Kubernetes Service 來實現近似的金絲雀權重,基於新舊副本數量的比例來實現。所以,這個 Rollout 有一個限制,即它只能實現 20% 的最小加權,通過擴展 5 個 pod 中的一個來運行新版本。爲了實現更細粒度的金絲雀,這就需要一個 Ingress 控制器或服務網格了,這部分我們可以在後續服務網格的學習中來介紹。
Dashboard
Argo Rollouts Kubectl 插件可以提供一個本地 Dashboard,來可視化你的 Rollouts。
要啓動這個 Dashboard,需要在包含 Rollouts 資源對象的命名空間中運行 kubectl argo rollouts dashboard
命令,然後訪問localhost:3100
即可。
argo rollouts ui
點擊 Rollout 可以進行詳細頁面,在詳細頁面可以看到 Rollout 的配置信息,還可以直接在 UI 界面上執行一些常用的操作,比如重啓、重啓、中斷等。
rollouts detail
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/vTzrNUrG3UvAIQUfbSruow