什么是灰度发布
灰度发布,又称金丝雀发布,是将应用的旧版本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,可以在应用发布完成后做相应的事情。例如进行集成测试等。