K8S 企业容器云03 - 部署策略

11 分钟读完

版本发布的多种部署策略

常见部署策略比较

部署策略比较

Canary Deployment

金丝雀部署是一种分阶段增量部署:

  • 新增小规模新版本环境承担一小部分用户(金丝雀)流量;

  • 经过测试观察,若新版本环境功能正常稳定,将新版本部署完全展开并删除旧环境;

  • 若不符合预期,则删除小集群,将影响范围控制在少量用户群;

有时会用单独一个集群作为金丝雀分析基准环境(canary analysis下图蓝色阴影区)

Canary Deployment

This technique is mostly used when the tests are lacking or not reliable or if there is little confidence about the stability of the new release on the platform.

动态示意图

Canary Deployment 动态

新版本集群承担少量流量,逐渐展开

Canary 流量切换

K8S Native

通过 v1 & v2 两个版本模拟实验

# vim app-v1.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    targetPort: http
  selector:
    app: my-app
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app-v1
  labels:
    app: my-app
spec:
  replicas: 10
  selector:
    matchLabels:
      app: my-app
      version: v1.0.0
  template:
    metadata:
      labels:
        app: my-app
        version: v1.0.0
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9101"
    spec:
      containers:
      - name: my-app
        image: containersol/k8s-deployment-strategies
        ports:
        - name: http
          containerPort: 8080
        - name: probe
          containerPort: 8086
        env:
        - name: VERSION
          value: v1.0.0
        livenessProbe:
          httpGet:
            path: /live
            port: probe
          initialDelaySeconds: 5
          periodSeconds: 5
        readinessProbe:
          httpGet:
            path: /ready
            port: probe
          periodSeconds: 5

创建 10 个 v1 副本提供服务

# kubectl apply -f app-v1.yaml

# watch kubectl get pod -l app=my-app
Every 2.0s: kubectl get pod -l app=my-app
k01: Sun Sep 29 15:38:12 2019

NAME                         READY   STATUS    RESTARTS   AGE
my-app-v1-5b4755fccf-2qqwd   1/1     Running   0          73s
my-app-v1-5b4755fccf-5hqvj   1/1     Running   0          73s
my-app-v1-5b4755fccf-g6r6n   1/1     Running   0          73s
my-app-v1-5b4755fccf-gqpjc   1/1     Running   0          73s
my-app-v1-5b4755fccf-hv69c   1/1     Running   0          73s
my-app-v1-5b4755fccf-kv24m   1/1     Running   0          73s
my-app-v1-5b4755fccf-l9n4j   1/1     Running   0          73s
my-app-v1-5b4755fccf-p2zp8   1/1     Running   0          73s
my-app-v1-5b4755fccf-px747   1/1     Running   0          73s
my-app-v1-5b4755fccf-qdwv9   1/1     Running   0          73s

# kubectl get service -l app=my-app
NAME     TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
my-app   NodePort   10.110.141.72   <none>        80:31541/TCP   2m9s

持续访问业务,查看响应节点

# while sleep 1; do curl  10.110.141.72; done
Host: my-app-v1-5b4755fccf-g6r6n, Version: v1.0.0
Host: my-app-v1-5b4755fccf-p2zp8, Version: v1.0.0
Host: my-app-v1-5b4755fccf-l9n4j, Version: v1.0.0
Host: my-app-v1-5b4755fccf-kv24m, Version: v1.0.0
Host: my-app-v1-5b4755fccf-hv69c, Version: v1.0.0
Host: my-app-v1-5b4755fccf-px747, Version: v1.0.0
Host: my-app-v1-5b4755fccf-px747, Version: v1.0.0
Host: my-app-v1-5b4755fccf-2qqwd, Version: v1.0.0
Host: my-app-v1-5b4755fccf-kv24m, Version: v1.0.0
...

再写一个 v2 版本

# vim app-v2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app-v2
  labels:
    app: my-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
      version: v2.0.0
  template:
    metadata:
      labels:
        app: my-app
        version: v2.0.0
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9101"
    spec:
      containers:
      - name: my-app
        image: containersol/k8s-deployment-strategies
        ports:
        - name: http
          containerPort: 8080
        - name: probe
          containerPort: 8086
        env:
        - name: VERSION
          value: v2.0.0
        livenessProbe:
          httpGet:
            path: /live
            port: probe
          initialDelaySeconds: 5
          periodSeconds: 5
        readinessProbe:
          httpGet:
            path: /ready
            port: probe
          periodSeconds: 5
# kubectl apply -f app-v2.yaml

新增一个 v2 副本

# watch kubectl get pod -l app=my-app
Every 2.0s: kubectl get pod -l app=my-app
k01: Sun Sep 29 15:55:39 2019

NAME                         READY   STATUS    RESTARTS   AGE
my-app-v1-5b4755fccf-2qqwd   1/1     Running   0          18m
my-app-v1-5b4755fccf-5hqvj   1/1     Running   0          18m
my-app-v1-5b4755fccf-g6r6n   1/1     Running   0          18m
my-app-v1-5b4755fccf-gqpjc   1/1     Running   0          18m
my-app-v1-5b4755fccf-hv69c   1/1     Running   0          18m
my-app-v1-5b4755fccf-kv24m   1/1     Running   0          18m
my-app-v1-5b4755fccf-l9n4j   1/1     Running   0          18m
my-app-v1-5b4755fccf-p2zp8   1/1     Running   0          18m
my-app-v1-5b4755fccf-px747   1/1     Running   0          18m
my-app-v1-5b4755fccf-qdwv9   1/1     Running   0          18m
my-app-v2-759bffd84f-fs79p   1/1     Running   0          17s

返回少量 v2 响应

# while sleep 1; do curl  10.110.141.72; done
Host: my-app-v1-5b4755fccf-p2zp8, Version: v1.0.0
Host: my-app-v1-5b4755fccf-qdwv9, Version: v1.0.0
Host: my-app-v1-5b4755fccf-2qqwd, Version: v1.0.0
Host: my-app-v1-5b4755fccf-px747, Version: v1.0.0
Host: my-app-v1-5b4755fccf-hv69c, Version: v1.0.0
Host: my-app-v1-5b4755fccf-g6r6n, Version: v1.0.0
Host: my-app-v2-759bffd84f-fs79p, Version: v2.0.0
Host: my-app-v1-5b4755fccf-qdwv9, Version: v1.0.0
Host: my-app-v2-759bffd84f-fs79p, Version: v2.0.0
Host: my-app-v1-5b4755fccf-gqpjc, Version: v1.0.0
Host: my-app-v1-5b4755fccf-kv24m, Version: v1.0.0
Host: my-app-v1-5b4755fccf-p2zp8, Version: v1.0.0
Host: my-app-v1-5b4755fccf-hv69c, Version: v1.0.0
Host: my-app-v1-5b4755fccf-l9n4j, Version: v1.0.0
Host: my-app-v1-5b4755fccf-p2zp8, Version: v1.0.0
...

经过测试和等待观察,若 v2 版本功能正常稳定

将 v2 副本扩展到 10 个

# kubectl scale --replicas=10 deploy my-app-v2

目前环境中 v1 & v2 多副本并存

# watch kubectl get pod -l app=my-app
Every 2.0s: kubectl get pod -l app=my-app
k01: Sun Sep 29 16:02:19 2019

NAME                         READY   STATUS    RESTARTS   AGE
my-app-v1-5b4755fccf-2qqwd   1/1     Running   0          25m
my-app-v1-5b4755fccf-5hqvj   1/1     Running   0          25m
my-app-v1-5b4755fccf-g6r6n   1/1     Running   0          25m
my-app-v1-5b4755fccf-gqpjc   1/1     Running   0          25m
my-app-v1-5b4755fccf-hv69c   1/1     Running   0          25m
my-app-v1-5b4755fccf-kv24m   1/1     Running   0          25m
my-app-v1-5b4755fccf-l9n4j   1/1     Running   0          25m
my-app-v1-5b4755fccf-p2zp8   1/1     Running   0          25m
my-app-v1-5b4755fccf-px747   1/1     Running   0          25m
my-app-v1-5b4755fccf-qdwv9   1/1     Running   0          25m
my-app-v2-759bffd84f-24rhg   1/1     Running   0          82s
my-app-v2-759bffd84f-8rkbl   1/1     Running   0          81s
my-app-v2-759bffd84f-97wxf   1/1     Running   0          81s
my-app-v2-759bffd84f-fs79p   1/1     Running   0          6m57s
my-app-v2-759bffd84f-jt4pk   1/1     Running   0          81s
my-app-v2-759bffd84f-lbsvx   1/1     Running   0          81s
my-app-v2-759bffd84f-ncmr5   1/1     Running   0          81s
my-app-v2-759bffd84f-qrxnv   1/1     Running   0          81s
my-app-v2-759bffd84f-tggtq   1/1     Running   0          81s
my-app-v2-759bffd84f-vqxn9   1/1     Running   0          81s

返回响应基本均摊

# while sleep 1; do curl  10.110.141.72; done
Host: my-app-v1-5b4755fccf-hv69c, Version: v1.0.0
Host: my-app-v1-5b4755fccf-g6r6n, Version: v1.0.0
Host: my-app-v2-759bffd84f-qrxnv, Version: v2.0.0
Host: my-app-v2-759bffd84f-jt4pk, Version: v2.0.0
Host: my-app-v2-759bffd84f-vqxn9, Version: v2.0.0
Host: my-app-v1-5b4755fccf-hv69c, Version: v1.0.0
Host: my-app-v1-5b4755fccf-l9n4j, Version: v1.0.0
Host: my-app-v1-5b4755fccf-qdwv9, Version: v1.0.0
Host: my-app-v2-759bffd84f-vqxn9, Version: v2.0.0
Host: my-app-v1-5b4755fccf-p2zp8, Version: v1.0.0
Host: my-app-v1-5b4755fccf-gqpjc, Version: v1.0.0
Host: my-app-v2-759bffd84f-ncmr5, Version: v2.0.0
Host: my-app-v2-759bffd84f-97wxf, Version: v2.0.0
...

下线全部 v1 副本

# kubectl delete deploy my-app-v1

# while sleep 1; do curl  10.110.141.72; done
Host: my-app-v2-759bffd84f-fs79p, Version: v2.0.0
Host: my-app-v2-759bffd84f-97wxf, Version: v2.0.0
Host: my-app-v2-759bffd84f-qrxnv, Version: v2.0.0
Host: my-app-v2-759bffd84f-tggtq, Version: v2.0.0
Host: my-app-v2-759bffd84f-ncmr5, Version: v2.0.0
Host: my-app-v2-759bffd84f-97wxf, Version: v2.0.0
Host: my-app-v2-759bffd84f-fs79p, Version: v2.0.0
Host: my-app-v2-759bffd84f-lbsvx, Version: v2.0.0
Host: my-app-v2-759bffd84f-24rhg, Version: v2.0.0
...

清除实验环境

# kubectl delete all -l app=my-app
pod "my-app-v2-759bffd84f-24rhg" deleted
pod "my-app-v2-759bffd84f-8rkbl" deleted
pod "my-app-v2-759bffd84f-97wxf" deleted
pod "my-app-v2-759bffd84f-fs79p" deleted
pod "my-app-v2-759bffd84f-jt4pk" deleted
pod "my-app-v2-759bffd84f-lbsvx" deleted
pod "my-app-v2-759bffd84f-ncmr5" deleted
pod "my-app-v2-759bffd84f-qrxnv" deleted
pod "my-app-v2-759bffd84f-tggtq" deleted
pod "my-app-v2-759bffd84f-vqxn9" deleted
service "my-app" deleted
deployment.apps "my-app-v2" deleted
replicaset.apps "my-app-v2-759bffd84f" deleted

Istio & Helm

补充

Blue/Green Deployment

蓝绿部署

  • 在线上版本集群(蓝)之外单独部署新版本集群(绿);

  • 经过测试新版本符合要求,通过 LB 将流量完全切换到新版本;

  • 观察无误后,删除旧版本集群;

Blue/Green Deployment

动态示意图

Blue/Green Deployment 动态

流量直接全量切换

Blue/Green 流量切换

Single Service

复用前面的 app-v1&v2.yaml

Service 的选择器同时匹配 app & version

# vim app-v1.yaml
...
selector:
  app: my-app
  version: v1.0.0
...

将副本数均设为 3

# vim app-v1.yaml & app-v2.yaml
...
spec:
  replicas: 3
...

创建 app-v1 业务集群

# kubectl apply -f app-v1.yaml

# kubectl get pods -l app=my-app
NAME                         READY   STATUS    RESTARTS   AGE
my-app-v1-5b4755fccf-22fz4   1/1     Running   0          29s
my-app-v1-5b4755fccf-mkjqr   1/1     Running   0          29s
my-app-v1-5b4755fccf-s8d5g   1/1     Running   0          29s

# kubectl get service my-app -o wide
NAME     TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE   SELECTOR
my-app   NodePort   10.104.179.119   <none>        80:30784/TCP   35m   app=my-app,version=v1.0.0

创建 app-v2 业务集群

# kubectl apply -f app-v2.yaml

# kubectl rollout status deploy my-app-v2 -w
Waiting for deployment "my-app-v2" rollout to finish: 0 of 3 updated replicas are available...
Waiting for deployment "my-app-v2" rollout to finish: 1 of 3 updated replicas are available...
Waiting for deployment "my-app-v2" rollout to finish: 2 of 3 updated replicas are available...
deployment "my-app-v2" successfully rolled out

目前存在 my-app-v1 & my-app-v2 (蓝绿)两个集群

但业务流量只走 v1

# kubectl get pods -l app=my-app
NAME                         READY   STATUS    RESTARTS   AGE
my-app-v1-5b4755fccf-22fz4   1/1     Running   0          42m
my-app-v1-5b4755fccf-mkjqr   1/1     Running   0          42m
my-app-v1-5b4755fccf-s8d5g   1/1     Running   0          42m
my-app-v2-759bffd84f-q8lxg   1/1     Running   0          114s
my-app-v2-759bffd84f-x8w8d   1/1     Running   0          114s
my-app-v2-759bffd84f-zz244   1/1     Running   0          114s

# kubectl get deploy -o wide
NAME        READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS   IMAGES                                   SELECTOR
my-app-v1   3/3     3            3           3h16m   my-app       containersol/k8s-deployment-strategies   app=my-app,version=v1.0.0
my-app-v2   3/3     3            3           156m    my-app       containersol/k8s-deployment-strategies   app=my-app,version=v2.0.0

# while sleep 1; do curl 10.104.179.119; done
Host: my-app-v1-5b4755fccf-s8d5g, Version: v1.0.0
Host: my-app-v1-5b4755fccf-22fz4, Version: v1.0.0
Host: my-app-v1-5b4755fccf-22fz4, Version: v1.0.0
Host: my-app-v1-5b4755fccf-s8d5g, Version: v1.0.0
Host: my-app-v1-5b4755fccf-22fz4, Version: v1.0.0
Host: my-app-v1-5b4755fccf-mkjqr, Version: v1.0.0
...

对 v2 集群进行功能测试及验证,确认正常后

将业务切到 v2,观察响应变化

# kubectl patch service my-app -p '{"spec":{"selector":{"version":"v2.0.0"}}}'
service/my-app patched

# while sleep 1; do curl 10.104.179.119; done
Host: my-app-v1-5b4755fccf-22fz4, Version: v1.0.0
Host: my-app-v1-5b4755fccf-s8d5g, Version: v1.0.0
Host: my-app-v1-5b4755fccf-22fz4, Version: v1.0.0
Host: my-app-v1-5b4755fccf-mkjqr, Version: v1.0.0
Host: my-app-v2-759bffd84f-zz244, Version: v2.0.0
Host: my-app-v2-759bffd84f-q8lxg, Version: v2.0.0
Host: my-app-v2-759bffd84f-q8lxg, Version: v2.0.0
Host: my-app-v2-759bffd84f-x8w8d, Version: v2.0.0
Host: my-app-v2-759bffd84f-zz244, Version: v2.0.0
Host: my-app-v2-759bffd84f-zz244, Version: v2.0.0
...

若需要回滚,则切回 v1 集群

# kubectl patch service my-app -p '{"spec":{"selector":{"version":"v1.0.0"}}}'
service/my-app patched

# while sleep 1; do curl 10.104.179.119; done
Host: my-app-v2-759bffd84f-zz244, Version: v2.0.0
Host: my-app-v2-759bffd84f-q8lxg, Version: v2.0.0
Host: my-app-v2-759bffd84f-x8w8d, Version: v2.0.0
Host: my-app-v2-759bffd84f-zz244, Version: v2.0.0
Host: my-app-v2-759bffd84f-x8w8d, Version: v2.0.0
Host: my-app-v2-759bffd84f-zz244, Version: v2.0.0
Host: my-app-v1-5b4755fccf-s8d5g, Version: v1.0.0
Host: my-app-v1-5b4755fccf-mkjqr, Version: v1.0.0
Host: my-app-v1-5b4755fccf-22fz4, Version: v1.0.0
Host: my-app-v1-5b4755fccf-22fz4, Version: v1.0.0
Host: my-app-v1-5b4755fccf-s8d5g, Version: v1.0.0
...

长期观察无误后,删除旧版本集群,释放资源

# kubectl delete deploy my-app-v1

清除实验环境

# kubectl delete all -l app=my-app
pod "my-app-v2-759bffd84f-q8lxg" deleted
pod "my-app-v2-759bffd84f-x8w8d" deleted
pod "my-app-v2-759bffd84f-zz244" deleted
service "my-app" deleted
deployment.apps "my-app-v2" deleted
replicaset.apps "my-app-v2-759bffd84f" deleted

Multiple Services

补充

Ramped Deployment

渐进部署也称滚动部署:

  • 线上业务由 LB 管理的 v1 实例集群承担;

  • 新增一个 v2 业务实例,等服务就绪后,加入 LB 池;

  • 下线一个 v1 实例,释放资源;

  • 直到所有 v1 实例逐一被全部替换

Ramped Deployment

通过业务前端负载均衡配合新、旧版本实例替换,承载流量

Ramped 流量切换

滚动发布

maxSurge: 单次加入负载的新版本实例数量

maxUnavailable: 滚动更新过程中允许的不可访问实例数量

# vim app-v1.yaml

复用 app-v1.yaml,Deployment 的 selector 去掉 ‘version’ 字段

deployment name 去掉 v1 标识

apiVersion: v1
kind: Service
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    targetPort: http
  selector:
    app: my-app
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  replicas: 10
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
        version: v1.0.0
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9101"
    spec:
      containers:
      - name: my-app
        image: containersol/k8s-deployment-strategies
        ports:
        - name: http
          containerPort: 8080
        - name: probe
          containerPort: 8086
        env:
        - name: VERSION
          value: v1.0.0
        livenessProbe:
          httpGet:
            path: /live
            port: probe
          initialDelaySeconds: 5
          periodSeconds: 5
        readinessProbe:
          httpGet:
            path: /ready
            port: probe
          periodSeconds: 5

创建 v1 业务实例,查看各项信息

# kubectl apply -f app-v1.yaml

# kubectl get deployment -l app=my-app -o wide
NAME     READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES                                   SELECTOR
my-app   10/10   10           10          10m   my-app       containersol/k8s-deployment-strategies   app=my-app

# kubectl get pods -l app=my-app
NAME                      READY   STATUS    RESTARTS   AGE
my-app-5b4755fccf-2clg2   1/1     Running   0          12m
my-app-5b4755fccf-579cp   1/1     Running   0          12m
my-app-5b4755fccf-6p52j   1/1     Running   0          12m
my-app-5b4755fccf-dks9q   1/1     Running   0          12m
my-app-5b4755fccf-dlq74   1/1     Running   0          12m
my-app-5b4755fccf-kbf87   1/1     Running   0          12m
my-app-5b4755fccf-kpm8x   1/1     Running   0          12m
my-app-5b4755fccf-mjp6g   1/1     Running   0          12m
my-app-5b4755fccf-s4z6l   1/1     Running   0          12m
my-app-5b4755fccf-wlpsj   1/1     Running   0          12m

# kubectl get service -l app=my-app -o wide
NAME     TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE   SELECTOR
my-app   NodePort   10.110.122.235   <none>        80:31495/TCP   13m   app=my-app

编辑 v2 业务,在 ‘strategy’ 中定义 ‘maxSurge’ & ‘maxUnavailable’ 参数

此外, readinessProbe 指针区的 ‘initialDelaySeconds’ 设置大一些,观察效果更明显

# vim app-v2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  replicas: 10

  # define the rolling update strategy
  # 'maxSurge': how many pod add at a time
  # 'maxUnavailable': how many pod can be unavailable during the rolling update

  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
        version: v2.0.0
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9101"
    spec:
      containers:
      - name: my-app
        image: containersol/k8s-deployment-strategies
        ports:
        - name: http
          containerPort: 8080
        - name: probe
          containerPort: 8086
        env:
        - name: VERSION
          value: v2.0.0
        livenessProbe:
          httpGet:
            path: /live
            port: probe
          initialDelaySeconds: 5
          periodSeconds: 5
        readinessProbe:
          httpGet:
            path: /ready
            port: probe

          # set 'initialDelaySeconds' to a high value
          # to have a better visibility of the ramped deployment
          initialDelaySeconds: 15
          periodSeconds: 5

应用 v2 模板,查看更替情况

# kubectl apply -f app-v2.yaml
deployment.apps/my-app configured

实时监控 pods 变化

# watch kubectl get pods -l app=my-app

Every 2.0s: kubectl get pods -l app=my-app
k01: Sat Oct 12 11:11:24 2019

NAME                      READY   STATUS    RESTARTS   AGE          
my-app-5b4755fccf-2clg2   1/1     Running   0          16m          
my-app-5b4755fccf-579cp   1/1     Running   0          16m          
my-app-5b4755fccf-6p52j   1/1     Running   0          16m          
my-app-5b4755fccf-dks9q   1/1     Running   0          16m          
my-app-5b4755fccf-dlq74   1/1     Running   0          16m          
my-app-5b4755fccf-kbf87   1/1     Running   0          16m          
my-app-5b4755fccf-kpm8x   1/1     Running   0          16m          
my-app-5b4755fccf-mjp6g   1/1     Running   0          16m          
my-app-5b4755fccf-s4z6l   1/1     Running   0          16m          
my-app-5b4755fccf-wlpsj   1/1     Running   0          16m       

新增一个 v2 实例,正常运行后,销毁一个 v1 实例,同时创建新实例

Every 2.0s: kubectl get pods -l app=my-app
k01: Sat Oct 12 13:40:48 2019

NAME                      READY   STATUS              RESTARTS   AGE
my-app-5b4755fccf-2clg2   1/1     Running             0          166m
my-app-5b4755fccf-579cp   1/1     Running             0          166m
my-app-5b4755fccf-6p52j   1/1     Running             0          166m
my-app-5b4755fccf-dks9q   1/1     Running             0          166m
my-app-5b4755fccf-dlq74   1/1     Running             0          166m
my-app-5b4755fccf-kbf87   1/1     Running             0          166m
my-app-5b4755fccf-kpm8x   1/1     Running             0          166m
my-app-5b4755fccf-mjp6g   0/1     Terminating         0          166m
my-app-5b4755fccf-s4z6l   1/1     Running             0          166m
my-app-5b4755fccf-wlpsj   1/1     Running             0          166m
my-app-7555568f55-565c5   1/1     Running             0          30s
my-app-7555568f55-62f9r   0/1     ContainerCreating   0          2s

全部逐一完成替换

Every 2.0s: kubectl get pods -l app=my-app
k01: Sat Oct 12 14:07:48 2019

NAME                      READY   STATUS    RESTARTS   AGE          
my-app-7555568f55-565c5   1/1     Running   0          27m           
my-app-7555568f55-62f9r   1/1     Running   0          27m            
my-app-7555568f55-8nc6s   1/1     Running   0          25m            
my-app-7555568f55-9r8zv   1/1     Running   0          23m            
my-app-7555568f55-cv4qg   1/1     Running   0          26m            
my-app-7555568f55-gmfvb   1/1     Running   0          23m            
my-app-7555568f55-h65w9   1/1     Running   0          25m           
my-app-7555568f55-j2m44   1/1     Running   0          26m            
my-app-7555568f55-kps4p   1/1     Running   0          24m            
my-app-7555568f55-lv7h5   1/1     Running   0          24m       

流量全部迁至 v2 业务

# while sleep 1; do curl 10.110.122.235; done
Host: my-app-7555568f55-h65w9, Version: v2.0.0
Host: my-app-7555568f55-565c5, Version: v2.0.0
Host: my-app-7555568f55-9r8zv, Version: v2.0.0
Host: my-app-7555568f55-j2m44, Version: v2.0.0
Host: my-app-7555568f55-lv7h5, Version: v2.0.0
Host: my-app-7555568f55-j2m44, Version: v2.0.0
Host: my-app-7555568f55-gmfvb, Version: v2.0.0
...

回滚 & 暂停 & 发布

如果发现新版本有问题,可以回滚到原始版本

# kubectl rollout undo deploy my-app

开始自动替换 v2 实例

Every 2.0s: kubectl get pods -l app=my-app
k01: Sat Oct 12 14:53:54 2019

NAME                      READY   STATUS              RESTARTS   AGE
my-app-5b4755fccf-5jxdh   1/1     Running             0          29s
my-app-5b4755fccf-hrghv   0/1     ContainerCreating   0          2s   
my-app-5b4755fccf-zn7nd   1/1     Running             0          16s  
my-app-7555568f55-565c5   1/1     Running             0          73m  
my-app-7555568f55-62f9r   1/1     Running             0          73m  
my-app-7555568f55-8nc6s   1/1     Running             0          71m
my-app-7555568f55-cv4qg   1/1     Running             0          72m  
my-app-7555568f55-gmfvb   1/1     Terminating         0          69m  
my-app-7555568f55-h65w9   1/1     Running             0          71m
my-app-7555568f55-j2m44   1/1     Running             0          72m
my-app-7555568f55-kps4p   1/1     Running             0          70m
my-app-7555568f55-lv7h5   1/1     Running             0          70m

暂停发布,业务保持 v1 & v2 共存的 10 个实例状态

# kubectl rollout pause deploy my-app
deployment.apps/my-app paused

Every 2.0s: kubectl get pods -l app=my-app
k01: Sat Oct 12 16:13:10 2019

NAME                      READY   STATUS    RESTARTS   AGE          
my-app-5b4755fccf-2xs7k   1/1     Running   0          78m           
my-app-5b4755fccf-5jxdh   1/1     Running   0          79m            
my-app-5b4755fccf-874q9   1/1     Running   0          78m            
my-app-5b4755fccf-hrghv   1/1     Running   0          79m           
my-app-5b4755fccf-qnccz   1/1     Running   0          78m           
my-app-5b4755fccf-s68lq   1/1     Running   0          79m            
my-app-5b4755fccf-xlwb5   1/1     Running   0          78m           
my-app-5b4755fccf-zn7nd   1/1     Running   0          79m           
my-app-7555568f55-ddz84   1/1     Running   0          12m          
my-app-7555568f55-dp4w2   1/1     Running   0          11m          
my-app-7555568f55-z59jf   1/1     Running   0          12m

访问结果 v1 & v2 共存,效果类似 A/B 测试

# while sleep 1; do curl 10.110.122.235; done
Host: my-app-5b4755fccf-qnccz, Version: v1.0.0
Host: my-app-7555568f55-ddz84, Version: v2.0.0
Host: my-app-5b4755fccf-2xs7k, Version: v1.0.0
Host: my-app-7555568f55-ddz84, Version: v2.0.0
Host: my-app-5b4755fccf-s68lq, Version: v1.0.0
...

解除暂停,继续滚动发布

# kubectl rollout resume deploy my-app
deployment.apps/my-app resumed
Every 2.0s: kubectl get pods -l app=my-app                                                       k01: Sat Oct 12 16:54:18 2019

NAME                      READY   STATUS              RESTARTS   AGE
my-app-5b4755fccf-2xs7k   1/1     Running             0          119m
my-app-5b4755fccf-5jxdh   1/1     Running             0          120m
my-app-5b4755fccf-hrghv   1/1     Running             0          120m
my-app-5b4755fccf-qnccz   1/1     Running             0          119m
my-app-5b4755fccf-s68lq   1/1     Running             0          120m
my-app-5b4755fccf-xlwb5   1/1     Terminating         0          119m
my-app-5b4755fccf-zn7nd   1/1     Running             0          120m
my-app-7555568f55-cqzdc   1/1     Running             0          36s
my-app-7555568f55-ddz84   1/1     Running             0          53m
my-app-7555568f55-dp4w2   1/1     Running             0          52m
my-app-7555568f55-swfs7   0/1     ContainerCreating   0          3s
my-app-7555568f55-z59jf   1/1     Running             0          53

清除实验环境

# kubectl delete all -l app=my-app
pod "my-app-7555568f55-29lw2" deleted
pod "my-app-7555568f55-cqzdc" deleted
pod "my-app-7555568f55-ddz84" deleted
pod "my-app-7555568f55-dp4w2" deleted
pod "my-app-7555568f55-l7pdb" deleted
pod "my-app-7555568f55-sj72h" deleted
pod "my-app-7555568f55-swfs7" deleted
pod "my-app-7555568f55-sz758" deleted
pod "my-app-7555568f55-vtlkn" deleted
pod "my-app-7555568f55-z59jf" deleted
service "my-app" deleted
deployment.apps "my-app" deleted
replicaset.apps "my-app-5b4755fccf" deleted
replicaset.apps "my-app-7555568f55" deleted

分类:

更新时间: