k8s金丝雀发布(灰度发布)

1,009 阅读2分钟

什么是金丝雀发布

17世纪,英国矿井工人发现,金丝雀对瓦斯这种气体十分敏感。空气 中哪怕有极其微量的瓦斯气体,金丝雀也会停止歌唱;当瓦斯含量超过一 定限度时,人类依旧毫无察觉,而金丝雀却早已毒发身亡。当时在采矿设 备相对简陋的条件下,工人们每次下井都会带上一只金丝雀作为瓦斯检测 工具,以便在危险状况下紧急撤离。

我们在直接发布最新版本时容易出现问题,我们将新版本缓慢的推向新用户,验证没有问题后再全量发布。这样可以降低新版本直接导入生产环境带来的风险。

滚动更新.png

maxUnavailable与maxSurge

  • maxSurge:升级过程中存在的pod数可超过replicas的个数。

  • maxUnavailable:升级过程中可用的pod数不能小于maxUnavailable值。

max作用方式.png

推荐设置

  • 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.png

观察新版本pod没有问题后,再执行全量更新:

kubectl rollout resume deployments my-app

滚动更新完成pod.png 可以看到老版本在销毁,新版本在创建,这样滚动更新就完成了

金丝雀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的滚动更新逐步升级