Kubernetes的部署策略以下几种:

  • 重建(recreate):停止旧版本部署新版本
  • 滚动更新(rolling-update):一个接一个地以滚动更新方式发布新版本
  • 蓝绿(blue/green):新版本与旧版本一起存在,然后切换流量
  • 金丝雀(canary):将新版本面向一部分用户发布,然后继续全量发布

重建(Recreate)

  • 特点 : 停止旧版本部署新版本

  • 使用场景 : 最好在开发环境

  • yaml(版本A)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    #deploy
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: web-recreate
    namespace: dev
    spec:
    selector:
    matchLabels:
    app: web-recreate
    replicas: 2 # 部署两个pod
    template:
    metadata:
    labels:
    app: web-recreate
    spec:
    containers:
    - name: web-recreate
    image: tomcat:8-slim
    ports:
    - containerPort: 8080
    livenessProbe:
    tcpSocket:
    port: 8080
    initialDelaySeconds: 20
    periodSeconds: 10
    failureThreshold: 2
    successThreshold: 1
    ---
    #service
    apiVersion: v1
    kind: Service
    metadata:
    name: web-recreate
    namespace: dev
    spec:
    ports:
    - port: 80
    protocol: TCP
    targetPort: 8080
    selector:
    app: web-recreate
    type: ClusterIP

    ---
    #ingress
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
    name: web-recreate
    namespace: dev
    spec:
    rules:
    - host: web-recreate.chc.com
    http:
    paths:
    - path: /
    backend:
    serviceName: web-recreate
    servicePort: 80

    在访问服务的机器上配置hosts:192.168.43.113 web-recreate.chc.com,然后通过web-recreate.chc.com域名访问

  • yaml(版本B)使用Recreate策略更新

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    #deploy
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: web-recreate
    namespace: dev
    spec:
    strategy: # 部署策略声明
    type: Recreate # 使用Recreate策略
    selector:
    matchLabels:
    app: web-recreate
    replicas: 2 # 部署两个pod
    template:
    metadata:
    labels:
    app: web-recreate
    type: web-app # 更新内容为:加多一个标签type
    spec:
    containers:
    - name: web-recreate
    image: tomcat:8-slim
    ports:
    - containerPort: 8080
    livenessProbe:
    tcpSocket:
    port: 8080
    initialDelaySeconds: 20
    periodSeconds: 10
    failureThreshold: 2
    successThreshold: 1
    ---
    #service
    apiVersion: v1
    kind: Service
    metadata:
    name: web-recreate
    namespace: dev
    spec:
    ports:
    - port: 80
    protocol: TCP
    targetPort: 8080
    selector:
    app: web-recreate
    type: ClusterIP

    ---
    #ingress
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
    name: web-recreate
    namespace: dev
    spec:
    rules:
    - host: web-recreate.chc.com
    http:
    paths:
    - path: /
    backend:
    serviceName: web-recreate
    servicePort: 80

    重新创建策略是一个虚拟部署,包括关闭版本A,然后在关闭版本A后部署版本B. 此技术意味着服务的停机时间取决于应用程序的关闭和启动持续时间。

滚动更新(rolling-update)

  • 特点 : 滚动更新通过逐个替换实例来逐步部署新版本的应用,直到所有实例都被替换完成为止.更新过程中新旧服务同时可以访问

  • 更新的过程 : 在负载均衡器后面使用版本 A 的实例池,然后部署版本 B 的一个实例,当服务准备好接收流量时(Readiness Probe 正常),将该实例添加到实例池中,然后从实例池中删除一个版本 A 的实例并关闭

  • yaml(版本A)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    #deploy
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: web-rollingupdate
    namespace: dev
    spec:
    selector:
    matchLabels:
    app: web-rollingupdate
    replicas: 2
    template:
    metadata:
    labels:
    app: web-rollingupdate
    spec:
    containers:
    - name: web-rollingupdate
    image: tomcat:8-slim
    ports:
    - containerPort: 8080
    livenessProbe:
    tcpSocket:
    port: 8080
    initialDelaySeconds: 20
    periodSeconds: 10
    failureThreshold: 3
    successThreshold: 1
    timeoutSeconds: 5
    ---
    #service
    apiVersion: v1
    kind: Service
    metadata:
    name: web-rollingupdate
    namespace: dev
    spec:
    ports:
    - port: 80
    protocol: TCP
    targetPort: 8080
    selector:
    app: web-rollingupdate
    type: ClusterIP

    ---
    #ingress
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
    name: web-rollingupdate
    namespace: dev
    spec:
    rules:
    - host: web-rollingupdate.chc.com
    http:
    paths:
    - path: /
    backend:
    serviceName: web-rollingupdate
    servicePort: 80

    在访问服务的机器上配置hosts:192.168.43.113 web-rollingupdate.chc.com,然后通过web-recreate.chc.com域名访问

  • yaml(版本B)使用rolling-update策略更新

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    #deploy
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: web-rollingupdate
    namespace: dev
    spec:
    strategy: # 声明使用部署策略
    type: RollingUpdate # 使用RollingUpdate策略来更新pod
    rollingUpdate: # RollingUpdate策略配置
    maxSurge: 50% # 一次可以添加50%个Pod
    maxUnavailable: 50% # 滚动更新期间最大50%个Pod不可用
    selector:
    matchLabels:
    app: web-rollingupdate
    replicas: 2
    template:
    metadata:
    labels:
    app: web-rollingupdate
    type: web-app2 # 更新内容为:加多一个标签type
    spec:
    containers:
    - name: web-rollingupdate
    image: tomcat:9-slim # 更新tomcat版本
    ports:
    - containerPort: 8080
    livenessProbe:
    tcpSocket:
    port: 8080
    initialDelaySeconds: 20
    periodSeconds: 10
    failureThreshold: 3
    successThreshold: 1
    timeoutSeconds: 5
    ---
    #service
    apiVersion: v1
    kind: Service
    metadata:
    name: web-rollingupdate
    namespace: dev
    spec:
    ports:
    - port: 80
    protocol: TCP
    targetPort: 8080
    selector:
    app: web-rollingupdate
    type: ClusterIP

    ---
    #ingress
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
    name: web-rollingupdate
    namespace: dev
    spec:
    rules:
    - host: web-rollingupdate.chc.com
    http:
    paths:
    - path: /
    backend:
    serviceName: web-rollingupdate
    servicePort: 80

    可以使用kuectl rollout pause deploy [deployments] -n [namespaces]命令暂停滚动从而让新旧服务同时存在,来进行测试

    然后使用kuectl rollout resume deploy [deployments] -n [namespaces]恢复滚动操作

    回滚到上个版本: kuectl rollout undo deploy [deployments] -n [namespaces]

  • rollingUpdate配置说明

    参数 说明
    maxSurge 一次更新pod的数量可以使用百分比%,也可以使用数量
    maxUnavailable 滚动更新期间最大不可用Pod数量,可以用百分比%,也可以使用数量
  • 资源部署操作kuectl rollout

    kuectl rollout文档

    命令 作用
    history 查看历史版本
    pause 暂停资源(可以暂停滚动更新)
    resume 恢复暂停资源
    status 查看资源状态
    undo 回滚版本

蓝绿(blue/green)

  • 特点 :版本2(绿) 与版本1()一起部署,在测试新版本满足要求后,然后更新更新 Kubernetes 中扮演负载均衡器角色的 Service 对象,通过替换 label selector 中的版本标签来将流量发送到新版本

  • web-bluegreen.yaml(版本 1)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    #deploy
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: web-bluegreen
    namespace: dev
    spec:
    strategy: # 声明使用部署策略
    type: RollingUpdate # 使用RollingUpdate策略来更新pod
    rollingUpdate: # RollingUpdate策略配置
    maxSurge: 50% # 一次可以添加50%个Pod
    maxUnavailable: 50% # 滚动更新期间最大50%个Pod不可用
    selector:
    matchLabels:
    app: web-bluegreen
    replicas: 2
    template:
    metadata:
    labels:
    # 这里标签注明app名字和版本号
    app: web-bluegreen
    version: v1.0
    spec:
    containers:
    - name: web-bluegreen
    image: tomcat:8-slim
    ports:
    - containerPort: 8080
    livenessProbe:
    tcpSocket:
    port: 8080
    initialDelaySeconds: 20
    periodSeconds: 10
    failureThreshold: 3
    successThreshold: 1
    timeoutSeconds: 5
  • bluegreen-service.yaml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    ---
    #service
    apiVersion: v1
    kind: Service
    metadata:
    name: web-bluegreen
    namespace: dev
    spec:
    ports:
    - port: 80
    protocol: TCP
    targetPort: 8080
    selector:
    # 这里匹配 app 和 version 标签,当要切换流量的时候,我们更新 version 标签的值,比如:v2.0
    app: web-bluegreen
    version: v1.0
    type: ClusterIP

    ---
    #ingress
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
    name: web-bluegreen
    namespace: dev
    spec:
    rules:
    - host: web-bluegreen.chc.com
    http:
    paths:
    - path: /
    backend:
    serviceName: web-bluegreen
    servicePort: 80
  • web-bluegreen2.yaml(版本2)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    #deploy
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: web-bluegreen-v2 # 新版本的名称
    namespace: dev
    spec:
    strategy: # 声明使用部署策略
    type: RollingUpdate # 使用RollingUpdate策略来更新pod
    rollingUpdate: # RollingUpdate策略配置
    maxSurge: 50% # 一次可以添加50%个Pod
    maxUnavailable: 50% # 滚动更新期间最大50%个Pod不可用
    selector:
    matchLabels:
    app: web-bluegreen
    replicas: 2
    template:
    metadata:
    labels:
    app: web-bluegreen
    version: v2.0 #标签的version变为v2.0
    spec:
    containers:
    - name: web-bluegreen
    image: tomcat:9-slim # 升级tomcat
    ports:
    - containerPort: 8080
    livenessProbe:
    tcpSocket:
    port: 8080
    initialDelaySeconds: 20
    periodSeconds: 10
    failureThreshold: 3
    successThreshold: 1
    timeoutSeconds: 5
  • bluegreen-service.yaml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    ---
    #service
    apiVersion: v1
    kind: Service
    metadata:
    name: web-bluegreen
    namespace: dev
    spec:
    ports:
    - port: 80
    protocol: TCP
    targetPort: 8080
    selector:
    # 这里匹配 app 和 version 标签,当要切换流量的时候,我们更新 version 标签的值
    app: web-bluegreen
    version: v2.0 # 切换流量到v2.0版本
    type: ClusterIP

    ---
    #ingress
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
    name: web-bluegreen
    namespace: dev
    spec:
    rules:
    - host: web-bluegreen.chc.com
    http:
    paths:
    - path: /
    backend:
    serviceName: web-bluegreen
    servicePort: 80
  • 蓝/绿部署步骤:

    1. 部署版本1的yaml:kubectl apply -f web-bluegreen.yaml
    2. 部署service的yaml: kubectl apply -f bluegreen-service.yaml
    3. 部署版本2的yaml : kubectl apply -f web-bluegreen2.yaml
    4. 等待版本2的全部部署完成
    5. 切换流量入口从版本1到版本2 (这里就是将service的yaml的version标签改成v2.0): kubectl apply -f bluegreen-service.yaml
    6. 关闭版本1的应用 : kubectl delete deployments -n dev web-bluegreen
  • 优缺点:

    1. 实时部署/回滚
    2. 避免版本问题,因为一次更改是整个应用的改变
    3. 需要两倍的资源
    4. 在发布到生产之前,应该对整个应用进行适当的测试

金丝雀(Canary)

  • 特点:金丝雀部署是让部分用户访问到新版本应用,在一段时间后如果没有检测到错误,则可以扩展新版本的副本数量并删除旧版本的应用。

  • 部署方式参照蓝/绿部署的yaml文件

    1. 部署版本1web-bluegreen.yaml
    2. 部署版本2web-bluegreen2.yaml
    3. bluegreen-service.yaml中的version标签去掉
    4. 部署service服务bluegreen-service.yaml
    5. 如果版本2的pod没问题,逐步替换版本1为版本2
  • 优缺点

    1. 部分用户获取新版本
    2. 方便错误发现和性能监控
    3. 快速回滚
    4. 发布较慢
    5. 流量精准控制很浪费
  • 建议:使用服务网格(如 Istio)来构建金丝雀部署,拥有更精准的流量控制