Linkerd 2.10(Step by Step)(二) 自動化的金絲雀發布
通過結合 Linkerd 和 Flagger 來根據服務指標自動金絲雀(canary)發布,從而降低部署風險。
Linkerd 2.10 中文手冊持續修正更新中:
https://linkerd.hacker-linner.com/
Linkerd 2.10 系列
- 快速上手 Linkerd v2 Service Mesh(服務網格)
- 騰訊云 K8S 集群實戰 Service Mesh—Linkerd2 & Traefik2 部署 emojivoto 應用
- 詳細了解 Linkerd 2.10 基礎功能,一起步入 Service Mesh 微服務架構時代
- Linkerd 2.10(Step by Step)—1. 將您的服務添加到 Linkerd
Linkerd 的流量拆分(traffic split)功能允許您在服務之間動態轉移流量。這可用于實施低風險部署策略,如藍綠(blue-green)部署和金絲雀(canaries)。
但簡單地將流量從一個服務版本轉移到下一個版本只是一個開始。我們可以將流量拆分與 Linkerd 的自動黃金指標(golden metrics)遙測相結合, 并根據觀察到的指標推動流量決策。例如,我們可以逐漸將流量從舊部署轉移到新部署, 同時持續監控其成功率。如果在任何時候成功率下降, 我們可以將流量轉移回原始部署并退出發布。理想情況下,我們的用戶始終保持快樂(remain happy),沒有注意到任何事情!
在本教程中,我們將引導您了解如何將 Linkerd 與 Flagger 結合使用, 后者是一種漸進式交付工具, 可將 Linkerd 的指標和流量拆分綁定在一個控制循環中, 從而實現全自動、指標感知的金絲雀部署。
先決條件
- 要使用本指南,您需要在集群上安裝 Linkerd 及其 Viz 擴展。
如果您還沒有這樣做,請按照安裝Linkerd 指南進行操作。
- Flagger 的安裝依賴于 kubectl 1.14 或更新版本。
安裝 Flagger
Linkerd 將管理實際的流量路由, 而 Flagger 會自動執行創建新 Kubernetes 資源(resources)、 觀察指標(watching metrics)和逐步將用戶發送到新版本的過程。要將 Flagger 添加到您的集群并將其配置為與 Linkerd 一起使用,請運行:
- kubectl apply -k github.com/fluxcd/flagger/kustomize/linkerd
- # customresourcedefinition.apiextensions.k8s.io/alertproviders.flagger.app created
- # customresourcedefinition.apiextensions.k8s.io/canaries.flagger.app created
- # customresourcedefinition.apiextensions.k8s.io/metrictemplates.flagger.app created
- # serviceaccount/flagger created
- # clusterrole.rbac.authorization.k8s.io/flagger created
- # clusterrolebinding.rbac.authorization.k8s.io/flagger created
- # deployment.apps/flagger created
此命令添加:
- Canary
CRD 可以配置發布的方式。
- RBAC 授予 Flagger 修改它需要的所有資源的權限,例如部署(deployments)和服務(services)。
- 配置為與 Linkerd 控制平面交互的控制器。
要觀察直到一切正常運行,您可以使用 kubectl:
- kubectl -n linkerd rollout status deploy/flagger
- # Waiting for deployment "flagger" rollout to finish: 0 of 1 updated replicas are available...
- # deployment "flagger" successfully rolled out
設置 demo
該 demo 由三個組件組成:負載生成器(load generator)、部署(deployment)和前端(frontend)。部署會創建一個 pod,該 pod 會返回一些信息,例如名稱。您可以使用響應(responses)來觀察隨著 Flagger 編排的增量部署。由于需要某種活動流量才能完成操作,因此負載生成器可以更輕松地執行部署。這些組件的拓撲結構如下所示:
要將這些組件添加到您的集群并將它們包含在 Linkerd 數據平面中,請運行:
- kubectl create ns test && \
- kubectl apply -f https://run.linkerd.io/flagger.yml
- # namespace/test created
- # deployment.apps/load created
- # configmap/frontend created
- # deployment.apps/frontend created
- # service/frontend created
- # deployment.apps/podinfo created
- # service/podinfo created
通過運行以下命令驗證一切是否已成功啟動:
- kubectl -n test rollout status deploy podinfo
- # Waiting for deployment "podinfo" rollout to finish: 0 of 1 updated replicas are available...
- # deployment "podinfo" successfully rolled out
通過在本地轉發前端服務并通過運行在本地的 http://localhost:8080 來打開檢查它:
- kubectl -n test port-forward svc/frontend 8080
我這里,為方便看到真實的一個 demo,直接加個 IngressRoute。
ingress-route.yaml
- apiVersion: traefik.containo.us/v1alpha1
- kind: IngressRoute
- metadata:
- name: podinfo-dashboard-route
- namespace: test
- spec:
- entryPoints:
- - websecure
- tls:
- secretName: hacker-linner-cert-tls
- routes:
- - match: Host(`podinfo.hacker-linner.com`)
- kind: Rule
- services:
- - name: frontend
- port: 8080
你可以直接訪問 https://podinfo.hacker-linner.com。
流量轉移發生在連接的客戶端而不是服務器端。來自網格外部的任何請求都不會被轉移,并且將始終被定向到主后端。 LoadBalancer 類型的服務將表現出這種行為,因為源不是網格的一部分。要轉移外部流量,請將入口控制器添加到網格中。
配置發布
在更改任何內容之前,您需要配置發布應如何在集群上推出(rolled out)。該配置包含在 Canary 定義中。要應用于您的集群,請運行:
- cat <<EOF | kubectl apply -f -
- apiVersion: flagger.app/v1beta1
- kind: Canary
- metadata:
- name: podinfo
- namespace: test
- spec:
- targetRef:
- apiVersion: apps/v1
- kind: Deployment
- name: podinfo
- service:
- port: 9898
- analysis:
- interval: 10s
- threshold: 5
- stepWeight: 10
- maxWeight: 100
- metrics:
- - name: request-success-rate
- thresholdRange:
- min: 99
- interval: 1m
- - name: request-duration
- thresholdRange:
- max: 500
- interval: 1m
- EOF
Flagger 控制器正在監視這些定義(definitions),并將在集群上創建一些新的資源。要觀察這個過程,運行:
- kubectl -n test get ev --watch
將創建一個名為 podinfo-primary 的新部署, 其副本數量與 podinfo 具有的副本數量相同 一旦新 Pod 準備就緒,原始部署將縮減為零。這提供了由 Flagger 作為實現細節管理的部署,并維護您的原始配置文件和工作流。看到以下行后,一切都已設置:
- 0s Normal Synced canary/podinfo Initialization done! podinfo.test
除了托管部署之外,還創建了一些服務來協調應用程序的新舊版本之間的路由流量。這些可以使用 kubectl -n test get svc 查看,應該如下所示:
- NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
- frontend ClusterIP 10.7.251.33 <none> 8080/TCP 96m
- podinfo ClusterIP 10.7.252.86 <none> 9898/TCP 96m
- podinfo-canary ClusterIP 10.7.245.17 <none> 9898/TCP 23m
- podinfo-primary ClusterIP 10.7.249.63 <none> 9898/TCP 23m
此時,拓撲看起來有點像:
本指南沒有涉及 Flagger 提供的所有功能。如果您有興趣將 Canary 版本與 HPA 相結合、 處理自定義指標或進行其他類型的版本發布 (例如 A/B 測試),請務必閱讀文檔。
開始推出(rollout)
作為一個系統,Kubernetes resources 有兩個主要部分:spec 和 status。當控制器看到 spec 時,它會盡其所能使當前系統的 status 與 spec 相匹配。通過部署,如果任何 pod 規范配置發生更改,控制器將啟動 rollout。默認情況下,部署控制器(deployment controller)將協調滾動更新(rolling update)。
在這個例子中,Flagger 會注意到部署的規范(spec)發生了變化, 并開始編排金絲雀部署(canary rollout)。要啟動此過程,您可以通過運行以下命令將鏡像更新為新版本:
- kubectl -n test set image deployment/podinfo \
- podinfod=quay.io/stefanprodan/podinfo:1.7.1
對 pod 規范的任何修改(例如更新環境變量或annotation)都會導致與更新 image 相同的行為。
更新時,金絲雀部署 (podinfo) 將擴大(scaled up)。準備就緒后,Flagger 將開始逐步更新 TrafficSplit CRD。配置 stepWeight 為 10,每增加一次,podinfo 的權重就會增加 10。對于每個周期,都會觀察成功率,只要超過 99% 的閾值,Flagger 就會繼續推出(rollout)。要查看整個過程,請運行:
- kubectl -n test get ev --watch
在發生更新時,資源和流量在較高級別將如下所示:
更新完成后,這張圖會變回上一節的圖。
您可以在 1.7.1 和 1.7.0 之間切換 image 標簽以再次開始發布(rollout)。
Resource
canary resource 會更新當前狀態和進度,你可以通過運行以下命令來查看:
- watch kubectl -n test get canary
在幕后,Flagger 正在通過更新流量拆分 resource 來拆分主后端和金絲雀后端之間的流量。要查看此配置在推出期間如何更改,請運行:
- kubectl -n test get trafficsplit podinfo -o yaml
每次增加都會增加 podinfo-canary 的權重并減少 podinfo-primary 的權重。一旦部署成功,podinfo-primary 的權重將重新設置為 100, 并且底層金絲雀部署(podinfo)將被縮減。
指標
隨著流量從主要部署轉移到金絲雀部署,Linkerd 提供了對請求目的地發生的事情的可見性。這些指標顯示后端實時接收流量并衡量成功率(success rate)、延遲(latencies)和吞吐量(throughput)。在 CLI 中,您可以通過運行以下命令來觀看:
- watch linkerd viz -n test stat deploy --from deploy/load
對于更直觀的東西,您可以使用儀表板。通過運行 linkerd viz dashboard 啟動它, 然后查看 podinfo 流量拆分的詳細信息頁面。
瀏覽器
再次訪問 http://localhost:8080。刷新頁面將顯示新版本和不同標題顏色之間的切換。或者,運行 curl http://localhost:8080 將返回一個 類似于以下內容的 JSON 響應:
- {
- "hostname": "podinfo-primary-74459c7db8-lbtxf",
- "version": "1.7.0",
- "revision": "4fc593f42c7cd2e7319c83f6bfd3743c05523883",
- "color": "blue",
- "message": "greetings from podinfo v1.7.0",
- "goos": "linux",
- "goarch": "amd64",
- "runtime": "go1.11.2",
- "num_goroutine": "6",
- "num_cpu": "8"
- }
隨著推出的繼續,這種 response 會慢慢改變。
清理
要進行清理,請從集群中刪除 Flagger 控制器并通過運行以下命令刪除 test 命名空間:
- kubectl delete -k github.com/fluxcd/flagger/kustomize/linkerd && \
- kubectl delete ns test
【編輯推薦】