什麼是灰階釋出
灰階釋出,又稱金絲雀釋出,是将應用的舊版本A與新版本B同時部署在環境中,業務請求可能會被路由到版本A的後端上,也可能會被路由到版本B的後端上。您可以自定義灰階釋出政策,快速調整版本A和B的流量占比。
灰階釋出可以在釋出新版本應用時,自定義控制新版本應用流量比重,漸進式完成新版本應用的全量上線,最大限度地控制新版本釋出帶來的業務風險,降低故障帶來的影響面,同時支援快速復原。
在傳統的應用部署方式下,可以通過使用Nginx配置upstream來實作灰階釋出以及流量控制等。那麼在今天雲原生大行其道的前提之下,我們有哪幾種方式呢?
目前社群有Ingress 、Linkerd 以及 Istio等幾種方案來實作灰階釋出。目前也有相應的開源方案實作了以上幾種灰階釋出方案。更加詳細的可以參考
Flagger社群Flagger介紹
Flagger是一個漸進的傳遞工具,它自動化了運作在Kubernetes上的應用程式的釋出過程。在度量度量和運作一緻性測試的同時,通過逐漸地将流量轉移到新版本,它減少了在生産中引入新軟體版本的風險。
Flagger通過使用服務網格(App mesh, Istio,Linkerd)或Ingress控制器(Contour, Gloo, NGINX, Skipper, Traefik)進行流量路由的方式實作了多種部署政策(Canary釋出,A/B測試,藍/綠鏡像)。同時Flagger可以與
Prometheus等監控工具進行結合,通過采集運作期的metrics,來實作更加自動化的釋出能力。同時也可以與Slack、MS Teams等工具內建實作告警。
那麼ACK在社群Flagger版本的基礎上,結合業務發展的階段,做了不同的政策,例如手動釋出的支援、內建釘釘報警等。更多的能力會在後續的版本中進行增強
下面是Flagger的概覽圖以及灰階釋出的流程圖。
Flagger概覽圖:

灰階釋出流程圖:
灰階釋出
- 建立一個ACK叢集,具體可以參考 建立ACK叢集
- 在叢集中安裝Flagger控制器,具體可以參考 安裝灰階釋出元件
- 建立灰階釋出測試應用,其中包括對應的Deployment,Service和Ingress。可以将下邊的yaml儲存到本地為podinfo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: podinfo
name: podinfo
namespace: default
spec:
minReadySeconds: 5
progressDeadlineSeconds: 60
replicas: 4
revisionHistoryLimit: 5
selector:
matchLabels:
app: podinfo
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 1
type: RollingUpdate
template:
metadata:
labels:
app: podinfo
spec:
containers:
- image: 'registry.cn-hangzhou.aliyuncs.com/acs/rollouts-demo:blue'
imagePullPolicy: IfNotPresent
name: podinfod
ports:
- containerPort: 8080
name: http
protocol: TCP
readinessProbe:
failureThreshold: 3
initialDelaySeconds: 5
periodSeconds: 10
successThreshold: 1
tcpSocket:
port: 8080
timeoutSeconds: 5
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
---
apiVersion: v1
kind: Service
metadata:
name: my-podinfo-svc
namespace: default
spec:
clusterIP: 172.24.8.231
ports:
- name: http
port: 80
protocol: TCP
targetPort: 8080
selector:
app: podinfo
sessionAffinity: None
type: ClusterIP
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
labels:
app: podinfo
name: podinfo
namespace: default
spec:
rules:
- host: app.example.com
http:
paths:
- backend:
serviceName: my-podinfo-svc
servicePort: 80
- 建立灰階釋出,可以将如下的儲存到本地檔案為 podinfo-canary.yaml
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
annotations:
# 該處的annotations 務必主要,加了該注解後執行ACK實作的邏輯
alicloud.canary.extension.switch: 'true'
name: podinfo-default
namespace: default
spec:
analysis:
# 定義webhooks
webhooks:
- name: "canary released"
# webhook類型,更多的webhook類型如下:
type: post-rollout
timeout: "5s"
# webhook位址
url: https://enaeqge6875ahr8.m.pipedream.net
# webhook中繼資料,
metadata:
data: "{\"msgtype\": \"text\",\"text\": {\"content\": \"deploy success\"}}"
# 定義灰階版本每次增加的Replica數量
canaryReplicas: 1
canaryWeight: 0
interval: 3s
maxReplicas: 4
maxWeight: 100
# 步長
stepWeight: 20
threshold: 5
# 對應的應用的Ingress配置
ingressRef:
apiVersion: extensions/v1beta1
kind: Ingress
name: podinfo
provider: nginx
# 對應Deployment的Service配置
service:
name: my-podinfo-svc
port: 80
targetPort: 8080
# 灰階釋出的目标,為Deployment
targetRef:
apiVersion: apps/v1
kind: Deployment
name: podinfo
更多的webhooks類型如下
// RolloutHook execute webhook during the canary analysis
RolloutHook HookType = "rollout"
// PreRolloutHook execute webhook before routing traffic to canary
PreRolloutHook HookType = "pre-rollout"
// PreRolloutHook execute webhook after the canary analysis
PostRolloutHook HookType = "post-rollout"
// ConfirmRolloutHook halt canary analysis until webhook returns HTTP 200
ConfirmRolloutHook HookType = "confirm-rollout"
// ConfirmPromotionHook halt canary promotion until webhook returns HTTP 200
ConfirmPromotionHook HookType = "confirm-promotion"
// EventHook dispatches Flagger events to the specified endpoint
EventHook HookType = "event"
// RollbackHook rollback canary analysis if webhook returns HTTP 200
RollbackHook HookType = "rollback"
- 修改灰階釋出的版本,該處主要值得是修改對應的鏡像版本
通過上述的步驟建立完測試應用以及對應的灰階釋出以後,可以通過ACK控制台觀察灰階釋出的狀态,當狀态有初始化中->初始化完畢後,可以修改對應的釋出應用的鏡像版本。如下圖左上方紅色框标記處,點選編輯。
目前ACK的測試鏡像提供了Tag為blue和green的鏡像,根據部署應用的Tag修改為其相反的即可。
- 等待釋出完成
當完成以上部署後,等待灰階釋出的自動完成。最終可以通過灰階釋出的事件看到完成的釋出過程。如下圖
- 完成釋出以後,在控制台點選完成,或者使用API來删除本次的灰階釋出。這個過程中,會回收由本次釋出而建立的Deployment,Service,Ingress等資源。
通過以上步驟,就可以完成一次全自動化的基于Ingress的灰階釋出。
- 由于在灰階釋出中,我們定義了相應的webhook。當灰階釋出完成後,我們會收到相應的調用。在本次測試中,我們使用了 https://pipedream.com/ 的一個webhook測試平台,我們可以從下圖看到webhook正确接收到了我們的測試資料。
總結
在該示例中,我們主要是通過Flagger控制改變Ingress的注解的方式來完成自動化的灰階釋出。同時配置對應的webhook,可以在應用釋出完成後做相應的事情。例如進行內建測試等。