什么是金丝雀发布
17世纪,英国矿井工人发现,金丝雀对瓦斯这种气体十分敏感。空气 中哪怕有极其微量的瓦斯气体,金丝雀也会停止歌唱;当瓦斯含量超过一 定限度时,人类依旧毫无察觉,而金丝雀却早已毒发身亡。当时在采矿设 备相对简陋的条件下,工人们每次下井都会带上一只金丝雀作为瓦斯检测 工具,以便在危险状况下紧急撤离。
我们在直接发布最新版本时容易出现问题,我们将新版本缓慢的推向新用户,验证没有问题后再全量发布。这样可以降低新版本直接导入生产环境带来的风险。
maxUnavailable与maxSurge
-
maxSurge:升级过程中存在的pod数可超过replicas的个数。
-
maxUnavailable:升级过程中可用的pod数不能小于maxUnavailable值。
推荐设置
- maxSurge = 1
- maxUnavailable = 0
如果线上pod期望值为10,更新时会先创建一个新版本pod,再删除一个旧版本pod,更新过程非常平滑。计算公式如下
(目标副本数-maxUnavailable) <= 线上实际Ready副本数 <= (目标副本数+maxSurge)
10 <= 实际副本数 <= 11
实践
deploy.yaml入下
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
使用kubectl apply -f 创建后可以看到3个pod正常启动。
执行滚动更新,升级镜像版本的同时停止更新,这样将只会创建一个新版本pod实现金丝雀发布,命令如下
kubectl set image deployments my-app nginx=nginx:1.19.4 && kubectl rollout pause deployments my-app
观察新版本pod没有问题后,再执行全量更新:
kubectl rollout resume deployments my-app
可以看到老版本在销毁,新版本在创建,这样滚动更新就完成了
金丝雀deployment实现灰度
主要的思路是创建一个标签相同的、名称不同的deployment,根据service的匹配规则就会把流量分给新版本的pod。有问题的情况下可以直接删除deployment。
实践
老版本deploy.yaml如下
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
新版本deploy如下
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-canary
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.19.4
ports:
- containerPort: 80
新老版本对比
- template标签相同
- 金丝雀pod期望值为1
- deploy名称不同
- 镜像版本不同
观察新版本pod运行正常后可以将金丝雀deploy删除,将老版本的yaml文件修改镜像后启动,利用k8s的滚动更新逐步升级