隨著雲原生技術的普及和落地,越來越多的雲原生應用被部署到生產環境中,由於雲原生應用通常都是基於雲的分佈式部署模式,且每個應用可能是由多個功能組件互相調用來一起提供完整的服務的,每個組件都有自己獨立的迭代流程和計劃。在這種情況下,功能組件越多,意味著應用的發佈管理越複雜,如果沒有一個好的方案或者系統來管理複雜應用的發佈上線的話,業務面臨的風險也是非常大的。開源社區在複雜應用發佈管理方面逐漸開始發力,本文對其中2種針對上層應用發佈管理的方案進行對比和分析,它們就是Intuit的ArgoCD和ArgoRollouts結合的方案以及Weaveworks的Flux和Flagger結合的方案。
ArgoCD和Flux(或者Flux CD)的主要職責都是監聽Git Repository源中的應用編排變化,並與當前環境中應用運行狀態進行對比,自動化同步拉取應用變更並部署到進群中。
ArgoRollouts和Flagger的主要職責都是執行更復雜的應用發佈策略,比如藍綠髮布、金絲雀發佈、AB Testing等。
1. ArgoCD與Flux CD
ArgoCD與Flux CD的主要職責是監聽Git Repositories變化,對比當前應用運行狀態與期望運行狀態的差異,然後自動拉取變更並同步部署到集群環境中。但架構設計與功能支持上有很多差異點。本文從以下幾個方面對其進行對比分析。
1.1 ArgoCD
1.1.1 架構
ArgoCD包括3個主要組件:
API Server
ArgoCD API server是一個gRPC/REST風格的server,提供API給Web UI,CLI以及其他CI/CD做系統調用或集成,包括以下職責:
- 應用管理和狀態上報
- 執行應用變更,如同步、回滾等
- Git Repository和集群憑證的管理(存儲為k8s secret)
- 對外部身份提供者進行身份驗證(添加外部集群)
- RBAC增強
- 監聽和轉發Git webhook事件
Repository Server
repossitory server是一個內部服務,維護一個Git Repo中應用編排文件的本地緩存。支持以下參數設置:
- repository URL
- revision (commit, tag, branch)
- application path,Git Repo中的subpath
- 模板化的參數設置,如parameters, ksonnet environments, helm values.yaml
Application Controller
Application Controller是一個Kubernetes Controller,主要工作是持續監聽應用當前運行狀態與期望狀態(Git Repo中描述的狀態)的不同。自動檢測應用OutOfSync狀態並根據Sync測試執行下一步動作。
1.1.2 Web UI
Argo UI之前是Argo組織下一個獨立的項目,現在已經合併到Argo CD項目裡。Argo CD的UI基本已經實現了Argcd CLI的大部分功能,用戶可以通過UI做以下事情:
- 配置和連接遠端Git Repositories
- 配置用於連接私有Git Repositories的憑證
- 添加管理不同的k8s集群
- 配置project
- 創建應用
- 動態展示應用當前運行狀態
- 應用發佈
- 應用歷史版本回滾
1.1.3 多集群管理
ArgoCD支持管理多集群。 ArgoCD可以添加管理多個集群,它以secret的方式存儲外部集群的憑證,secret中包括一個與被託管集群kube-system命名空間下名為argocd-manager的ServiceAccount相關聯的k8s API bearer token,和連接被託管集群API Server方式信息。支持revoke。
1.1.4 應用管理能力
ArgoCD下有明確的應用的概念,基本上覆蓋了一個應用生命週期內所有需要的操作;此外,ArgoCD支持引用單一Git Repository在不同集群中創建不同應用,實際上我們還可以利用這個能力配合應用的定製化能力,實現在不同集群中創建相同應用的場景。
應用生命週期管理:
$ argocd app -h
Available Commands:
actions Manage Resource actions
create Create an application
delete Delete an application
diff Perform a diff against the target and live state.
edit Edit application
get Get application details
history Show application deployment history
list List applications
manifests Print manifests of an application
patch Patch application
patch-resource Patch resource in an application
rollback Rollback application to a previous deployed version by History ID
set Set application parameters
sync Sync an application to its target state
terminate-op Terminate running operation of an application
unset Unset application parameters
wait Wait for an application to reach a synced and healthy state
引用單一Git Repository在不同集群中創建應用,下面是一個引用https://github.com/haoshuwei/argocd-samples.git
在ack-pre、ack-pro和gke-pro 3個k8s集群中創建應用的示例:
$ argocd cluster list
SERVER NAME VERSION STATUS MESSAGE
https://xxx.xx.xxx.xxx:6443 ack-pro 1.14+ Successful
https://xx.xx.xxx.xxx gke-pro 1.14+ Successful
https://xxx.xx.xxx.xxx:6443 ack-pre 1.14+ Successful
https://kubernetes.default.svc 1.14+ Successful
創建應用ack-pre
,部署argocd-samples
項目下overlays/pre
子目錄裡的編排文件,分支為latest
,應用部署到api server為https://xx.xx.xxx.xxx:6443
的集群,命名空間為argocd-samples
, 同步策略為automated
$ argocd app create --project default --name ack-pre --repo https://github.com/haoshuwei/argocd-samples.git --path overlays/pre --dest-server https://xx.xx.xxx.xxx:6443 --dest-namespace argocd-samples --revision latest --sync-policy automated
創建應用ack-pro
,部署argocd-samples
項目下overlays/pro
子目錄裡的編排文件,分支為master
,應用部署到api server為https://xx.xx.xxx.xxx:6443
的集群,命名空間為argocd-samples
, 同步策略為automated
$ argocd app create --project default --name ack-pro --repo https://github.com/haoshuwei/argocd-samples.git --path overlays/pro --dest-server https://xx.xx.xxx.xxx:6443 --dest-namespace argocd-samples --revision master --sync-policy automated
創建應用gke-pro
,部署argocd-samples
項目下overlays/gke
子目錄裡的編排文件,分支為master
,應用部署到api server為https://xx.xx.xxx.xxx
的集群,命名空間為argocd-samples
, 同步策略為automated
$ argocd app create --project default --name gke-pro --repo https://github.com/haoshuwei/argocd-samples.git --path overlays/gke --dest-server https://xx.xx.xxx.xxx --dest-namespace argocd-samples --revision master
1.1.5 kubernetes應用編排工具支持
ArgoCD支持Kustomize應用、Helm Charts、Ksonnet應用、Jsonnet文件,並且可以通過管理和配置插件的方式支持其他你想要使用的編排工具。
1.1.6 安全
ArgoCD只設置了一個內置的admin用戶,只能登錄用戶才可以進行下一步操作。ArgoCD認為一個內置的admin用戶主要用於管理和配置比App資源更底層的集群資源,App資源的變更歷史記錄都需要在Git Provider端進行審計。儘管如此,ArgoCD也支持了其他用戶使用SSO的方式進行登錄,比如通過OAuth2接入阿里雲RAM服務或GitHub:
另外,ArgoCD在App資源的上層又抽象出來一個Project的概念,Project是應用管理的一個邏輯上的組,每一個應用都要屬於且只能屬於一個組,針對多團隊合作的情景而設計的一個概念。它的主要作用包括:限制指定的Git Repository才可以被部署;限制應用只能被部署到指定clusters的指定namespace下;限制指定的資源類型可以被部署或不能被部署;定義project roles來提供對應用的角色訪問控制RBAC。
1.1.7 應用的自動化同步能力
ArgoCD只監聽Git Repository源中的代碼變更,不關心容器鏡像倉庫中鏡像tag的變換。應用的同步策略有兩種:automated
和none
1.1.8 Git Repositories支持
支持ssh、git、http/https協議;
支持自簽發證書添加、ssh known hosts添加
私有倉庫的設置支持private token和ssh private key
1.2 Flux CD
1.2.1 架構
Flux是Weaveworks公司在2016年發起的開源項目,2019年8月成為CNCF基金會的一個孵化項目。
Fluxd
Flux daemon, 主要職責是持續監聽用戶配置的Git Repo中Kubernetes資源編排文件的變化,然後同步部署到集群中; 它還可以檢測容器鏡像倉庫中image更新,提交更新到用戶Git Repo,然後同步部署到集群中。 以上同步部署動作均基於用戶設置的策略。
1.2.2 Web UI
Flux CD目前不提供UI。
1.2.3 多集群管理
Flux CD不支持多集群管理,需要在每個集群中部署Flux CD組件。
1.2.4 應用管理能力
Flux CD 下需要配置flux連接你的目標Git Repository並將應用同步部署到k8s集群中。 如果你想使用單一Git Repository部署應用到不同集群,則需要在每個集群中部署flux併為每個集群設置唯一的git tag。
$ fluxctl -h
Available Commands:
automate Turn on automatic deployment for a workload.
deautomate Turn off automatic deployment for a workload.
help Help about any command
identity Display SSH public key
install Print and tweak Kubernetes manifests needed to install Flux in a Cluster
list-images Show deployed and available images.
list-workloads List workloads currently running in the cluster.
lock Lock a workload, so it cannot be deployed.
policy Manage policies for a workload.
release Release a new version of a workload.
save save workload definitions to local files in cluster-native format
sync synchronize the cluster with the git repository, now
unlock Unlock a workload, so it can be deployed.
version Output the version of fluxctl
1.2.5 kubernetes應用編排工具支持
Flux CD支持配置使用Helm Operator部署Helm Charts,支持Kustomize應用。
1.2.6 安全
Flux CD支持管理和使用戶k8s集群多租特性,分為集群管理員和普通開發測試團隊兩種角色,團隊成員只能修改自己所以命名空間下的應用,對集群級別的應用或者其他命名空間下的應用無任何操作權限。此外,對於每個團隊或者命名空間來說,只能指定的一個Git Repository,對應地需要啟動一個Flux實例。
1.2.7 應用的自動化同步能力
FluxCD 除了監聽Git Repository源中的代碼變更之外,還可以監聽docker registry中與當前運行應用相同的鏡像的tag變化,可以根據不同策略決定是否把鏡像tag變化的信息自動commit到Git Repository源中,然後再同步部署到集群中。
1.2.8 Git Repositories支持
私有倉庫的設置只支持ssh private key
2.ArgoRollouts與Flagger
ArgoRollouts與Flagger的主要職責都是執行更復雜的應用發佈策略,比如藍綠髮布、金絲雀發佈、AB Testing等。目前ArgoRollouts部署並不依賴istio環境,Flagger則必須在istio環境下才能正常工作。
2.1 ArgoRollouts
2.1.1 Istio、Service Mesh或App Mesh的支持
在流量管理方面,ArgoRollouts只支持istio和ingress,目前還不支持Service Mesh或App Mesh,不過社區下一階段的主要工作就是做這部分的支持。
一個ArgoRollouts結合istio對流量進行管理的編排示例:
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: rollout-example
spec:
...
strategy:
canary:
steps:
- setWeight: 5
- pause:
duration: 600
canaryService: canary-svc # required
stableService: stable-svc # required
trafficRouting:
istio:
virtualService:
name: rollout-vsvc # required
routes:
- primary # At least one route is required
其中名為rollout-vsvc
的istio自定義資源VirtualService
的編排為:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: rollout-vsvc
spec:
gateways:
- istio-rollout-gateway
hosts:
- istio-rollout.dev.argoproj.io
http:
- name: primary
route:
- destination:
host: stable-svc
weight: 100
- destination:
host: canary-svc
weight: 0
在發佈應用的時候,ArgoRollouts會根據spec.strategy.steps
的設置來動態修改rollout-vsvc
中stable-svc
和canary-svc
的權重比例,直到應用發佈完畢。
2.1.2 全自動漸進式應用發佈支持
全自動漸進式應用發佈是指能使運行在k8s體系上的應用發佈流程全自動化(無人蔘與), 它能減少發佈的人為關注時間, 並且在發佈過程中能自動識別一些風險(例如:RT,成功率,自定義metrics)並執行回滾操作。
ArgoRollouts使用AnalysisTemplate
AnalysisRun
和Experiment
3種crd資源來分析從Prometheus查詢到的監控指標,然後進行決策決定應用是否繼續進一步發佈。
示例:
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: guestbook
spec:
...
strategy:
canary:
analysis:
templates:
- templateName: success-rate
startingStep: 2 # delay starting analysis run
# until setWeight: 40%
args:
- name: service-name
value: guestbook-svc.default.svc.cluster.local
steps:
- setWeight: 20
- pause: {duration: 600}
- setWeight: 40
- pause: {duration: 600}
- setWeight: 60
- pause: {duration: 600}
- setWeight: 80
- pause: {duration: 600}
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: success-rate
spec:
args:
- name: service-name
metrics:
- name: success-rate
interval: 5m
successCondition: result >= 0.95
failureLimit: 3
provider:
prometheus:
address: http://prometheus.example.com:9090
query: |
sum(irate(
istio_requests_total{reporter="source",destination_service=~"{{args.service-name}}",response_code!~"5.*"}[5m]
)) /
sum(irate(
istio_requests_total{reporter="source",destination_service=~"{{args.service-name}}"}[5m]
))
在上面的例子中,應用的發佈策略為每600s
增加20%的路由權重到新版本應用上,這個動作有AnalysisRun
執行,依賴於AnalysisTemplate
中定義的success-rate
,success-rate
是根據從Prometheus系統中查詢到的數據進行計算得出的,如果某一次success-rate
小於95%,則ArgoRollouts會進行回滾操作,否則逐漸增加權重到100%完成應用發佈。
2.2 Flagger
2.2.1 Istio、Service Mesh或App Mesh的支持
Flagger需要結合Istio, Linkerd, App Mesh, NGINX, Contour or Gloo等的流量管理能力以及Prometheus的指標收集與分析來完成應用的全自動化、漸進式的金絲雀發佈。
Flagger通過spec.provider來指定使用哪種流量管理方案來發布應用:
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: podinfo
namespace: test
spec:
# service mesh provider (optional)
# can be: kubernetes, istio, linkerd, appmesh, nginx, contour, gloo, supergloo
provider: istio
# deployment reference
targetRef:
apiVersion: apps/v1
kind: Deployment
name: podinfo
Flagger已經與GKE Istio以及EKS App Mesh做了很好的集成並開放給用戶使用:
2.2.2 全自動漸進式應用發佈支持
Flagger的canary analysis資源中定義了應用發佈策略、用於驗證新版本的指標、webhook擴展測試驗證能力和告警設置:
analysis:
# schedule interval (default 60s)
interval:
# max number of failed metric checks before rollback
threshold:
# max traffic percentage routed to canary
# percentage (0-100)
maxWeight:
# canary increment step
# percentage (0-100)
stepWeight:
# total number of iterations
# used for A/B Testing and Blue/Green
iterations:
# canary match conditions
# used for A/B Testing
match:
- # HTTP header
# key performance indicators
metrics:
- # metric check
# alerting
alerts:
- # alert provider
# external checks
webhooks:
- # hook
一個示例如下:
analysis:
# schedule interval (default 60s)
interval: 1m
# max number of failed metric checks before rollback
threshold: 10
# max traffic percentage routed to canary
# percentage (0-100)
maxWeight: 50
# canary increment step
# percentage (0-100)
stepWeight: 5
# validation (optional)
metrics:
- name: request-success-rate
# builtin Prometheus check
# minimum req success rate (non 5xx responses)
# percentage (0-100)
thresholdRange:
min: 99
interval: 1m
- name: request-duration
# builtin Prometheus check
# maximum req duration P99
# milliseconds
thresholdRange:
max: 500
interval: 30s
- name: "database connections"
# custom Prometheus check
templateRef:
name: db-connections
thresholdRange:
min: 2
max: 100
interval: 1m
# testing (optional)
webhooks:
- name: "conformance test"
type: pre-rollout
url: http://flagger-helmtester.test/
timeout: 5m
metadata:
type: "helmv3"
cmd: "test run podinfo -n test"
- name: "load test"
type: rollout
url: http://flagger-loadtester.test/
metadata:
cmd: "hey -z 1m -q 10 -c 2 http://podinfo.test:9898/"
# alerting (optional)
alerts:
- name: "dev team Slack"
severity: error
providerRef:
name: dev-slack
namespace: flagger
- name: "qa team Discord"
severity: warn
providerRef:
name: qa-discord
- name: "on-call MS Teams"
severity: info
providerRef:
name: on-call-msteams
對以上示例進行分解分析,
analysis:
# schedule interval (default 60s)
interval: 1m
# max number of failed metric checks before rollback
threshold: 10
# max traffic percentage routed to canary
# percentage (0-100)
maxWeight: 50
# canary increment step
# percentage (0-100)
stepWeight: 5
以上編排字段設置定義了應用發佈過程中,流量最大隻能切換到50%(maxWeight:50),總共執行10次(maxWeight/stepWeight),每次流量切換的增量為5%(stepWeight:5),每次執行間隔為1m(interval: 1m),期間允許10次metrics驗證失敗(threshold: 10),若超過10次則進行回滾操作。
metrics:
- name: request-success-rate
# builtin Prometheus check
# minimum req success rate (non 5xx responses)
# percentage (0-100)
thresholdRange:
min: 99
interval: 1m
- name: request-duration
# builtin Prometheus check
# maximum req duration P99
# milliseconds
thresholdRange:
max: 500
interval: 30s
- name: "database connections"
# custom Prometheus check
templateRef:
name: db-connections
thresholdRange:
min: 2
max: 100
interval: 1m
以上編排字段設置定義了3種metrics檢查:request-success-rate(請求成功率)不能超過99%,request-duration(RT均值)不能超過500ms,然後還有一個自定義metrics檢查,即database connections最小不能小於2,最大不能大於100。
webhooks:
- name: "conformance test"
type: pre-rollout
url: http://flagger-helmtester.test/
timeout: 5m
metadata:
type: "helmv3"
cmd: "test run podinfo -n test"
- name: "load test"
type: rollout
url: http://flagger-loadtester.test/
metadata:
cmd: "hey -z 1m -q 10 -c 2 http://podinfo.test:9898/"
以上編排字段設置定義了2種類型的webhook:名為"conformance test"類型為pre-rollout的webhooks需要在流量權重增加之前執行,名為"load test"類型為rollout的webhooks在metrics檢查執行期間運行。
alerts:
- name: "dev team Slack"
severity: error
providerRef:
name: dev-slack
namespace: flagger
- name: "qa team Discord"
severity: warn
providerRef:
name: qa-discord
- name: "on-call MS Teams"
severity: info
providerRef:
name: on-call-msteams
以上編排字段設置定義了發佈過程中的通知策略,severity表示通知信息的等級,如error、warn、info等,providerRef引用了不同AlterProvider的詳細信息,如slack,msteams、dingding等。
3. GitOps Engine
2019年11月,Weaveworks宣佈和Intuit合作共建Argo Flux,主要針對Kubernetes應用發佈的GitOps解決方案,AWS作為活躍開發者也加入其中,AWS的BlackRock會是第一個使用此方案的企業級應用服務。這個項目就是GitOps Engine 。Argo組織正在以一個整體加入CNCF開源基金會,Flux和Flagger已經是CNCF基金會的孵化項目,從基金會的角度是希望他們能尋找一些可以合作的方式的,另外兩者在解決方案上確實有很多相似的地方,兩家公司也希望能集合2個社區的開源力量做出一個更優秀的GitOps解決方案來。不過從目前來看,GitOps Engine還沒有特別大的動作。
GitOps Engine第一步動作是整合ArgoCD和Flux當前已具備的核心能力,未來社區還會考慮ArgoRollouts與Flagger的結合。 我們對齊保持持續關注。
持續更新,如有偏差,歡迎指正。
參考資料
https://argoproj.github.io/argo-cd/
https://argoproj.github.io/argo-rollouts/
[https://github.com/fluxcd/flux]()https://github.com/fluxcd/flux
https://docs.fluxcd.io/en/1.18.0/introduction.html
https://github.com/weaveworks/flagger
https://www.weave.works/blog/flux-joins-the-cncf-sandbox
https://docs.flagger.app/
https://www.weave.works/blog/argo-flux-join-forces