在這篇指南中,你将獲得使用
Kubernetes
和
Istio
使用
GitOps
進行漸進式傳遞(
Progressive Delivery
)的實際經驗。
介紹
gitops-istio
GitOps 是什麼?
GitOps
是一種進行持續傳遞的方式,它使用
Git
作為聲明性(
declarative
)基礎設施和工作負載(
workloads
)的真實來源。 對于
Kubernetes
,這意味着使用
git push
而不是
kubectl apply/delete
或
helm install/upgrade
。
在這個
workshop
中,您将使用
GitHub
來托管配置存儲庫,并将 Flux 作為
GitOps
傳遞解決方案。
什麼是漸進式傳遞?
漸進傳遞是進階部署模式(如金絲雀
canaries
、功能标志
feature flags
和A/B測試
A/B testing
)的總稱。漸進傳遞技術通過讓應用程式開發人員和
SRE
團隊對爆炸半徑
blast radius
進行細粒度控制,進而降低在生産中引入新軟體版本的風險。
在這個
workshop
中,您将使用 Flagger 和
Prometheus
為您的應用程式自動執行
Canary
釋出和
A/B Testing
。

準備工作
您将需要具有
LoadBalancer
支援的
Kubernetes
叢集 v1.16 或更高版本。 出于測試目的,您可以使用帶有
2
個
CPU
和
4GB
記憶體的
Minikube
。
使用
Homebrew
安裝
flux
CLI:
brew install fluxcd/tap/flux
macOS AMD64/ARM64
、
Linux AMD64/ARM
和
Windows
的二進制檔案可在 flux2 release page 下載下傳。
驗證您的叢集是否滿足前提條件:
flux check --pre
使用
Homebrew
安裝
jq
和
yq
:
brew install jq yq
Fork
這個倉庫并克隆它:
git clone https://github.com/<YOUR-USERNAME>/gitops-istio
cd gitops-istio
Cluster bootstrap
使用
flux bootstrap
指令,您可以在
Kubernetes
叢集上安裝
Flux
并将其配置為從
Git
存儲庫管理自身。如果叢集上存在
Flux
元件,則
bootstrap
指令将在需要時執行更新。
通過指定您的
GitHub
存儲庫
fork URL
來引導
Flux
:
flux bootstrap git \
--author-email=<YOUR-EMAIL> \
--url=ssh://[email protected]/<YOUR-USERNAME>/gitops-istio \
--branch=main \
--path=clusters/my-cluster
上面的指令需要
ssh-agent
,如果您使用的是
Windows
,請參閱 flux bootstrap github 文檔。
在引導時,
Flux
生成一個
SSH key
并列印
public key
。
為了用
git
同步你的叢集狀态,你需要複制
public key
并使用
write
建立一個
deploy key
通路你的
GitHub
倉庫。在
GitHub
上轉到 Settings > Deploy keys 點選 Add deploy key,
勾選☑️ Allow write access,粘貼 Flux
public key
并單擊 Add key。
當
Flux
通路你的存儲庫時,它會做以下事情:
- 安裝
Istio operator
- 等待
控制平面準備好Istio
- 安裝
、Flagger
和Prometheus
Grafana
- 建立
公共網關Istio
- 建立
命名空間prod
namespace
- 建立負載測試器(
)load tester
deployment
- 建立前端(
)frontend
和金絲雀deployment
canary
- 建立後端(
)backend
和金絲雀deployment
canary
使用
Istio
引導叢集時,定義
apply
順序很重要。對于要使用
Istio sidecar
注入的應用程式
pod
,
Istio
控制平面必須在應用程式之前啟動并運作。
在
Flux v2
中,你可以通過定義對象之間的依賴關系來指定執行順序。例如,在 clusters/my-cluster/apps.yaml 中我們告訴
Flux
,
apps
的協調取決于一個
istio-system
:
apiVersion: kustomize.toolkit.fluxcd.io/v1beta1
kind: Kustomization
metadata:
name: apps
namespace: flux-system
spec:
interval: 30m0s
dependsOn:
- name: istio-system
sourceRef:
kind: GitRepository
name: flux-system
path: ./apps
首先觀測
Flux
安裝
Istio
,然後觀測
demo apps
:
watch flux get kustomizations
您可以使用以下指令跟蹤 Flux
reconciliation
日志:
flux logs --all-namespaces --follow --tail=10
Istio 定制和更新
您可以使用位于 istio/system/profile.yaml 的
IstioOperator
資源自定義 Istio 安裝:
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
name: istio-default
namespace: istio-system
spec:
profile: demo
components:
pilot:
k8s:
resources:
requests:
cpu: 10m
memory: 100Mi
修改
Istio
設定後,您可以将更改推送到
git
,
Flux
将在叢集上應用它。
Istio operator
将根據您的更改重新配置
Istio
控制平面。
當新的
Istio
版本可用時,
update-istio
GitHub Action workflow 工作流将打開一個
pull request
,其中包含更新
Istio Operator
所需的清單更新。新的
Istio
版本通過
e2e
workflow 在
Kubernetes Kind
上進行測試,當
PR
合并到主分支時,
Flux
将在叢集内更新
Istio
。
應用程式引導
當
Flux
将
Git
存儲庫與您的叢集同步時,它将建立前端/後端部署(
frontend/backend deployment
)、
HPA
和一個金絲雀對象
canary object
。
Flagger
使用
canary
定義建立了一系列對象:
Kubernetes deployments
、
ClusterIP services
、
Istio
目标規則(
destination rules
)和虛拟服務(
virtual services
)。這些對象在網格(
mesh
)上公開(
expose
)應用程式,并推動金絲雀分析(
canary analysis
)和推廣(
promotion
)。
# applied by Flux
deployment.apps/frontend
horizontalpodautoscaler.autoscaling/frontend
canary.flagger.app/frontend
# generated by Flagger
deployment.apps/frontend-primary
horizontalpodautoscaler.autoscaling/frontend-primary
service/frontend
service/frontend-canary
service/frontend-primary
destinationrule.networking.istio.io/frontend-canary
destinationrule.networking.istio.io/frontend-primary
virtualservice.networking.istio.io/frontend
檢查
Flagger
是否成功初始化了金絲雀:
kubectl -n prod get canaries
NAME STATUS WEIGHT
backend Initialized 0
frontend Initialized 0
當
frontend-primary
部署上線時,
Flager
會将所有流量路由到主
Pod
,并将
frontend
部署
scale
到零。
使用以下指令查找
Istio
入口網關(
ingress gateway
)位址:
kubectl -n istio-system get svc istio-ingressgateway -ojson | jq .status.loadBalancer.ingress
打開浏覽器并導航到入口位址,您将看到前端
UI
。
金絲雀釋出
Flagger
實作了一個控制循環,該控制循環在測量關鍵性能名額(如
HTTP
請求成功率、請求平均持續時間和
pod
運作狀況)的同時,逐漸将流量轉移到金絲雀。在分析
KPI
的基礎上,将金絲雀更新或中止,并将分析結果釋出到
Slack
。
金絲雀分析由以下任何對象的更改觸發:
- 部署
(容器鏡像、指令、端口、環境等)PodSpec
-
和ConfigMaps
作為卷(Secrets
)挂載或映射到環境變量volumes
對于不接收恒定流量的工作負載,
Flagger
可以配置一個
webhook
,當它被調用時,将啟動一個目标工作負載的負載測試。
canary
配置可以在 apps/backend/canary.yaml 上找到。
從 GitHub 拉取更改:
git pull origin main
要觸發後端應用程式的金絲雀部署,請碰撞容器鏡像:
yq e '.images[0].newTag="5.0.1"' -i ./apps/backend/kustomization.yaml
送出和推送更改:
git add -A && \
git commit -m "backend 5.0.1" && \
git push origin main
告訴 Flux 拉取更改或等待一分鐘讓 Flux 自行檢測更改:
flux reconcile source git flux-system
觀測 Flux 将您的叢集與最新送出進行協調:
watch flux get kustomizations
幾秒鐘後,
Flager
檢測到部署修訂(
deployment revision
)已更改并開始新的
rollout
:
$ kubectl -n prod describe canary backend
Events:
New revision detected! Scaling up backend.prod
Starting canary analysis for backend.prod
Pre-rollout check conformance-test passed
Advance backend.prod canary weight 5
...
Advance backend.prod canary weight 50
Copying backend.prod template spec to backend-primary.prod
Promotion completed! Scaling down backend.prod
在分析過程中,
Grafana
可以監控金絲雀的程序。您可以通過端口轉發通路儀表闆:
kubectl -n istio-system port-forward svc/flagger-grafana 3000:80
Istio
儀表闆的
URL
是
http://localhost:3000/d/flagger-istio/istio-canary?refresh=10s&orgId=1&var-namespace=prod&var-primary=backend-primary&var-canary=backend
請注意,如果在金絲雀分析(
canary analysis
)期間對部署應用了新的更改,
Flagger
将重新啟動分析階段。
A/B 測試
除了權重路由(
weighted routing
),
Flagger
還可以配置為根據
HTTP
比對條件将流量路由到金絲雀。在
A/B
測試場景中,您将使用
HTTP headers
或
cookie
來定位使用者的特定部分。這對于需要會話(
session
)關聯的前端應用程式特别有用。
您可以通過指定
HTTP
比對條件和疊代次數來啟用
A/B
測試:
analysis:
# schedule interval (default 60s)
interval: 10s
# max number of failed metric checks before rollback
threshold: 10
# total number of iterations
iterations: 12
# canary match condition
match:
- headers:
user-agent:
regex: ".*Firefox.*"
- headers:
cookie:
regex: "^(.*?;)?(type=insider)(;.*)?$"
上述配置将針對
Firefox
使用者和擁有内部
cookie
的使用者運作兩分鐘的分析。 前端配置可以在
apps/frontend/canary.yaml
中找到。
通過更新前端容器鏡像觸發部署:
yq e '.images[0].newTag="5.0.1"' -i ./apps/frontend/kustomization.yaml
git add -A && \
git commit -m "frontend 5.0.1" && \
git push origin main
flux reconcile source git flux-system
Flager
檢測到部署修訂已更改并開始
A/B
測試:
$ kubectl -n istio-system logs deploy/flagger -f | jq .msg
New revision detected! Scaling up frontend.prod
Waiting for frontend.prod rollout to finish: 0 of 1 updated replicas are available
Pre-rollout check conformance-test passed
Advance frontend.prod canary iteration 1/10
...
Advance frontend.prod canary iteration 10/10
Copying frontend.prod template spec to frontend-primary.prod
Waiting for frontend-primary.prod rollout to finish: 1 of 2 updated replicas are available
Promotion completed! Scaling down frontend.prod
您可以通過以下方式監控所有金絲雀:
$ watch kubectl get canaries --all-namespaces
NAMESPACE NAME STATUS WEIGHT
prod frontend Progressing 100
prod backend Succeeded 0
基于 Istio 名額的復原
Flagger
使用
Istio
遙測提供的名額來驗證金絲雀工作負載。 前端應用 analysis 定義了兩個名額檢查:
metrics:
- name: error-rate
templateRef:
name: error-rate
namespace: istio-system
thresholdRange:
max: 1
interval: 30s
- name: latency
templateRef:
name: latency
namespace: istio-system
thresholdRange:
max: 500
interval: 30s
用于檢查錯誤率(
error rate
)和延遲的 Prometheus 查詢,位于 flagger-metrics.yaml
在金絲雀分析期間,您可以生成
HTTP 500 errors
和高延遲(
high latency
)來測試
Flagger
的復原。
生成 HTTP 500 errors:
watch curl -b 'type=insider' http://<INGRESS-IP>/status/500
生成延遲:
watch curl -b 'type=insider' http://<INGRESS-IP>/delay/1
當失敗的檢查次數達到金絲雀分析門檻值(
threshold
)時,流量将路由回主伺服器,金絲雀縮放為零,并将推出(
rollout
)标記為失敗。
$ kubectl -n istio-system logs deploy/flagger -f | jq .msg
New revision detected! Scaling up frontend.prod
Pre-rollout check conformance-test passed
Advance frontend.prod canary iteration 1/10
Halt frontend.prod advancement error-rate 31 > 1
Halt frontend.prod advancement latency 2000 > 500
...
Rolling back frontend.prod failed checks threshold reached 10
Canary failed! Scaling down frontend.prod
您可以使用針對 Prometheus、Datadog 和 Amazon CloudWatch 的自定義名額檢查來擴充分析。
有關為
Slack
、
MS Teams
、
Discord
或
Rocket
配置
canary
分析警報的資訊,請參閱文檔。
我是為少
微信:uuhells123
公衆号:黑客下午茶
加我微信(互相學習交流),關注公衆号(擷取更多學習資料~)