当服务迭代更新升级时,需要使用灰度发布保证系统的稳定性。ALB Ingress Controller支持设置注解,将请求流量按比例匹配到灰度服务。本文介绍如何使用ALB Ingress实现服务的灰度发布。
canary注解说明
ALB Ingress支持使用canary注解实现基于Header、Cookie、Weight灰度发布。三种灰度策略优先级为Header>Cookie>Weight。同时配置三种策略时,优先级高的策略优先进行灰度。关于canary注解的详细说明,请参见通过注解实现灰度发布。步骤一:部署服务
- 通过kubectl工具连接集群。
- 部署服务tea。
- 使用以下内容,创建tea-deploy.yaml。
apiVersion: apps/v1
kind: Deployment
metadata:
name: tea
spec:
replicas: 1
selector:
matchLabels:
app: tea
template:
metadata:
labels:
app: tea
spec:
containers:
- name: tea
image: registry.cn-hangzhou.aliyuncs.com/acs-sample/old-nginx:latest
ports:
- containerPort: 80
- 执行以下命令,部署服务tea。
kubectl apply -f tea-deploy.yaml
- 部署名为tea-svc的Service。
- 使用以下内容,创建tea-svc.yaml。
apiVersion: v1
kind: Service
metadata:
name: tea-svc
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
app: tea
type: NodePort
- 执行以下命令,部署Service。
kubectl apply -f tea-svc.yaml
- 部署名为tea-ingress的Ingress。
- 使用以下内容,创建tea-ingress.yaml。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tea-ingress
spec:
ingressClassName: alb
rules:
- host: demo.domain.ingress.top
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: tea-svc
port:
number: 80
- 执行以下命令,部署Ingress。
kubectl apply -f tea-ingress.yaml
步骤二:灰度发布新版本服务
部署新版本服务和Ingress,使得当请求Header为location: hz
时将路由到新版本服务canary,其他请求Header以及不携带请求Header将以50%的权重路由到新版本服务canary。
- 部署新版本服务canary。
- 使用以下内容,创建canary-deploy.yaml。
apiVersion: apps/v1
kind: Deployment
metadata:
name: canary
spec:
replicas: 1
selector:
matchLabels:
app: canary
template:
metadata:
labels:
app: canary
spec:
containers:
- name: canary
image: registry.cn-hangzhou.aliyuncs.com/acs-sample/new-nginx:latest
ports:
- containerPort: 80
- 执行以下命令,部署canary。
kubectl apply -f canary-deploy.yaml
- 部署名为canary-svc的Service。
- 使用以下内容,创建canary-svc.yaml。
apiVersion: v1
kind: Service
metadata:
name: canary-svc
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
app: canary
type: NodePort
- 执行以下命令,部署Service。
kubectl apply -f canary-svc.yaml
- 部署基于Header分配流量的Ingress。
- 使用以下内容,创建canary-header-ingress.yaml。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
alb.ingress.kubernetes.io/canary: "true"
alb.ingress.kubernetes.io/canary-by-header: "location"
alb.ingress.kubernetes.io/canary-by-header-value: "hz"
name: canary-header-ingress
namespace: default
spec:
ingressClassName: alb
rules:
- host: demo.domain.ingress.top
http:
paths:
- backend:
service:
name: canary-svc
port:
number: 80
path: /
pathType: Prefix
- alb.ingress.kubernetes.io/canary:设置为true,表示启用canary注解功能。
- alb.ingress.kubernetes.io/canary-by-header与alb.ingress.kubernetes.io/canary-by-header-value:设置请求Header的键值对。本文设置为
location: hz
,表示请求Header为location: hz
,请求流量会被分配到新版本服务;对于其他Header,将会忽略Header,并通过灰度优先级将请求流量分配到其他规则设置的新版本服务。
- 执行以下命令,部署基于Header分配流量的Ingress。
kubectl apply -f canary-header-ingress.yaml
- 部署基于权重分配流量的Ingress。
- 使用以下内容,创建canary-weight-ingress.yaml。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
alb.ingress.kubernetes.io/canary: "true"
alb.ingress.kubernetes.io/canary-weight: "50"
name: canary-weight-ingress
namespace: default
spec:
ingressClassName: alb
rules:
- host: demo.domain.ingress.top
http:
paths:
- backend:
service:
name: canary-svc
port:
number: 80
path: /
pathType: Prefix
alb.ingress.kubernetes.io/canary-weight:设置路由到新版本服务的流量百分比。本文设置为50,表示50%流量将路由到新版本服务。
- 执行以下命令,部署基于权重分配流量的Ingress。
kubectl apply -f canary-weight-ingress.yaml
- 验证灰度发布新版本服务是否成功。
- 执行以下命令,获取ALB实例访问地址。
kubectl get ing
预期输出:
NAME CLASS HOSTS ADDRESS PORTS AGE
canary-header-ingress alb demo.domain.ingress.top alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com 80 8m23s
canary-weight-ingress alb demo.domain.ingress.top alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com 80 8m16s
tea-ingress alb demo.domain.ingress.top alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com 80 7m5s
- 执行以下命令,多次使用携带
location: hz
请求头的请求访问服务。curl -H Host:demo.domain.ingress.top -H "location:hz" http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com
预期输出:
new
多次使用携带location: hz
请求头的请求访问服务,都返回new
的结果,说明使用携带location: hz
请求头的请求访问服务时,请求都路由到新版本服务。
- 多次执行以下命令,使不携带请求头的请求访问服务。
curl -H Host:demo.domain.ingress.top http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com
多次不携带请求头的请求访问服务,50%概率返回new
的结果,50%概率返回old
的结果,说明不携带请求头的请求访问服务时,请求按照50%权重路由到新版本服务。
- 多次执行以下命令,使携带
location: bj
请求头的请求访问服务。curl -H Host:demo.domain.ingress.top -H "location:bj" http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com
多次携带location: bj
请求头的请求访问服务,50%概率返回new
的结果,50%概率返回old
的结果,说明携带location: bj
请求头的请求访问服务时,请求按照50%权重路由到新版本服务。
根据以上结果,可以看到当请求Header为location: hz
时将路由到新版本服务canary,不携带请求Header以及其他请求Header以50%的权重路由到新版本服务canary,说明灰度发布canary服务成功。
步骤三:下线老版本服务
系统运行一段时间后,当新版本服务已经稳定并且符合预期后,需要下线老版本的服务,仅保留新版本服务在线上运行。为了达到该目标,需要将原服务的Ingress中的Service修改为新版本服务的Service,使得流量都路由到新版本服务,然后删除灰度Ingress。
- 执行以下命令,将tea-ingress.yaml文件中的Service由tea-svc修改为canary-svc。
vim tea-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tea-ingress
spec:
ingressClassName: alb
rules:
- host: demo.domain.ingress.top
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: canary-svc
port:
number: 80
- 执行以下命令,使修改后的Ingress生效。
Kubectl apply -f tea-ingress.yaml
- 验证下线老版本服务是否成功。
- 执行以下命令,多次使用携带
location: hz
请求头的请求访问服务。curl -H Host:demo.domain.ingress.top -H "location:hz" http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com
预期输出:
new
多次使用携带location: hz
请求头的请求访问服务,都返回new
的结果,说明使用携带location: hz
请求头的请求访问服务时,请求都路由到新版本服务。
- 执行以下命令,多次使用不携带请求头的请求访问服务。
curl -H Host:demo.domain.ingress.top http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com
预期输出:
new
多次使用不携带请求头的请求访问服务,都返回new
的结果,说明使用不携带请求头的请求访问服务时,请求都路由到新版本服务。
- 执行以下命令,使多次携带
location: bj
请求头的请求访问服务。curl -H Host:demo.domain.ingress.top -H "location:bj" http://alb-ny3ute4r8yevni****.cn-chengdu.alb.aliyuncs.com
预期输出:
new
多次使用携带location: bj
请求头的请求访问服务,都返回new
的结果,说明使用携带location: bj
请求头的请求访问服务时,请求都路由到新版本服务。
根据以上结果,可以看到携带location: hz
请求头,携带其他请求头,或者不携带请求头的请求都路由到新版本服务,说明下线老版本服务成功。
- 执行以下命令,删除名为canary-weight-ingress和canary-header-ingress的灰度Ingress。
kubectl delete ing canary-weight-ingress canary-header-ingress