背景
在发布应用时,经常需要先上线一个新版本,用较小的流量去测试一下该新版本的可用性。但是Kubernetes的ingress resource 并没有实现流量控制与切分的功能,导致针对同一个域名下的路径,只能有一个service来进行服务。这样对于灰度发布十分不利,下面我们就来介绍一下阿里云容器服务的蓝绿发布功能,轻松实现流量切分。
前置条件
既然需要进行蓝绿发布,那么应该已经有一个老服务在正常的对外提供服务中。我们这里以nginx 为例,假定已经有一个nginx deployment
通过NodePort
对外暴露端口,并且有一个ingress正在对外提供服务。我们使用的模板如下:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
run: old-nginx
name: old-nginx
spec:
replicas: 1
selector:
matchLabels:
run: old-nginx
template:
metadata:
labels:
run: old-nginx
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/xianlu/old-nginx
imagePullPolicy: Always
name: old-nginx
ports:
- containerPort: 80
protocol: TCP
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
labels:
run: old-nginx
name: old-nginx
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
run: old-nginx
sessionAffinity: None
type: NodePort
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: echo
spec:
backend:
serviceName: default-http-backend
servicePort: 80
rules:
- host: mini-echo.io
http:
paths:
- path: /
backend:
serviceName: old-nginx
servicePort: 80
可以看到已经创建好的ingrsss地址
[root@iZwz91e2au5xvyw5jdpqp7Z manifests]# kubectl get ing
NAME HOSTS ADDRESS PORTS AGE
echo mini-echo.io 47.106.45.47 80 3m
我们在本机通过curl
访问可以看到如下效果
~ curl -H "Host: mini-echo.io" http://47.106.45.47
old
进行蓝绿发布
- 创建新的deployment与service
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
run: new-nginx
name: new-nginx
spec:
replicas: 1
selector:
matchLabels:
run: new-nginx
template:
metadata:
labels:
run: new-nginx
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/xianlu/new-nginx
imagePullPolicy: Always
name: new-nginx
ports:
- containerPort: 80
protocol: TCP
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
labels:
run: new-nginx
name: new-nginx
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
run: new-nginx
sessionAffinity: None
type: NodePort
可以看到,唯一的变化就是,所有的old-nginx 都变成了new-nginx。
- 修改ingress
主要增加两个地方:
- 增加
annotations
,标签ingress.aliyun.weight/new-nginx: "50"
代表,/后面为新服务的服务名,也就是新的service name
。后面的50代表百分比,以%为单位,50代表新服务占领百分之50的流量。此标签的完整含义为,将流量的百分之50打到新的服务的pod
里面。 - 第二处为指定对应的新的
serviceName
。这里是和上面老服务并列,即在相同的Path 下,挂两个不同的service ,分别对应于两个新老应用。
- 效果
~ curl -H "Host: mini-echo.io" http://47.106.45.47
old
~ curl -H "Host: mini-echo.io" http://47.106.45.47
new
~ curl -H "Host: mini-echo.io" http://47.106.45.47
old
~ curl -H "Host: mini-echo.io" http://47.106.45.47
new
~ curl -H "Host: mini-echo.io" http://47.106.45.47
old
~ curl -H "Host: mini-echo.io" http://47.106.45.47
new
可以看到,执行六次请求,分别得到三次新服务,三次老服务的返回,这表明权重设置生效了。
流量完全切换到新服务
只需要将新服务的百分比写到100就可以,再看一下效果。
~ curl -H "Host: mini-echo.io" http://47.106.45.47
new
~ curl -H "Host: mini-echo.io" http://47.106.45.47
new
~ curl -H "Host: mini-echo.io" http://47.106.45.47
new
~ curl -H "Host: mini-echo.io" http://47.106.45.47
new
~ curl -H "Host: mini-echo.io" http://47.106.45.47
new
可以看到,流量都打到了新服务。
完成蓝绿发布
只需要将设置权重的annotation 删除即可,然后将下面对应的serviceName
也删除,这样就恢复了原本ingress的原貌,同时将原来的老服务改成了新的服务。下面再来看一下效果:
~ curl -H "Host: mini-echo.io" http://47.106.45.47
new
~ curl -H "Host: mini-echo.io" http://47.106.45.47
new
~ curl -H "Host: mini-echo.io" http://47.106.45.47
new
~ curl -H "Host: mini-echo.io" http://47.106.45.47
new
~ curl -H "Host: mini-echo.io" http://47.106.45.47
new
可以看到,新的服务已经上线,这就完成了整个蓝绿发布的完整生命周期。