一. 简介

Deployment是Kubernetes“控制器模式”的最基础的完整实现之一,但是却提供了Pod 的“水平扩展 / 收缩”(horizontal scaling out/in)的能力,这是非常核心的编排能力。

关于本文的代码,都在如下的地址中:Github资源

二. 核心

2.1 架构设计

Deployment 实际上是一个两层控制器。首先,它通过 ReplicaSet 的个数来描述应用的版本;然后,它再通过 ReplicaSet 的属性(比如 replicas 的值),来保证 Pod 的副本数量。

具体的deployment-replicaset-pod之间的关系可以如下图展示:

2.2 ReplicaSet

ReplicaSet 对象,其实就是由副本数目的定义和一个 Pod 模板组成的,其实就是是 Deployment 的一个子集。Deployment 的控制器,实际上控制的是 ReplicaSet 的数目,以及每个 ReplicaSet 的属性。

2.3 滚动更新

将一个集群中正在运行的多个 Pod 版本,交替地逐一升级的过程,就是“滚动更新”。这两个比例的值都是可以配置的,默认都是 DESIRED 值的 25%。

三. 创建Deployment流程

关于基于Deployment的自动扩容流程可以借助一个完整案例展示出来。

3.1 创建Depolyment YAML

定义一个 demo-deployment,它定义的 Pod 副本个数是 5 (spec.replicas=5)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-deployment
  labels:
    app: nginx
spec:
  replicas: 5
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.8.0
        ports:
        - containerPort: 80

3.2 水平扩展/收缩分析

ReplicaSet 负责通过“控制器模式”,保证系统中 Pod 的个数永远等于指定的个数(5 个)。 所以,Deployment 只允许容器的 restartPolicy=Always 的主要原因:只有在容器能保证自己始终是 Running 状态的前提下,ReplicaSet 调整 Pod 的个数才有意义。
Deployment 同样通过“控制器模式”,来操作 ReplicaSet 的个数和属性,进而实现“水平扩展 / 收缩”和“滚动更新”这两个编排动作。

  • 水平扩展

Deployment Controller 只需要修改它所控制的 ReplicaSet 的 Pod 副本个数就可以了。比如,把这个值从 5 改成 6,那么 Deployment 所对应的 ReplicaSet,就会根据修改后的值自动创建一个新的 Pod。

  • 水平收缩

按照上面流程按序反向删除即可。

3.3 创建

执行如下的创建指令即可:

kubectl apply -f demo-deployment.yaml --record

关于–record 参数,可与记录下每次操作所执行的命令,以方便后面查看。

3.4 检查Deployment状态

执行如下指令可以查看deployments的整体状态:

kubectl get deployments
# result
NAME              READY   UP-TO-DATE   AVAILABLE   AGE
demo-deployment   5/5     5            5           24s

关于图中的3种状态,详细含义如下:

  • READY:分子代表当前处于 Running 状态的 Pod 的个数,分母代表用户期望的 Pod 副本个数(spec.replicas 的值)。
  • UP-TO-DATE:当前处于最新版本的 Pod 的个数,所谓最新版本指的是 Pod 的 Spec 部分与 Deployment 里 Pod 模板里定义的完全一致。
  • AVAILABLE:当前已经可用的 Pod 的个数,即:既是 Running 状态,又是最新版本,并且已经处于 Ready(健康检查正确)状态的 Pod 的个数。

所以, AVAILABLE 字段,描述的才是用户所期望的最终状态。

3.5 实时滚动状态

实时查看 Deployment 对象的状态变化,执行如下指令:

kubectl rollout status deployment/demo-deployment

关于真实的滚动状态,手速要快,执行完apply后立即查看,结果如下:

3.6 查看ReplicaSet状态

执行如下指令:

kubectl get rs

在用户提交了一个 Deployment 对象后,Deployment Controller就会立即创建一个 Pod 副本个数为 5 的 ReplicaSet。这个 ReplicaSet 的名字,则是由 Deployment 的名字和一个随机字符串共同组成。
随机规则叫作pod-template-hash,ReplicaSet 会把这个随机字符串加在它所控制的所有 Pod 的标签里,从而保证这些 Pod 不会与集群里的其他 Pod 混淆。

3.7 检查Events

为了产生事件,我在demo-deployment-v1.yaml里面调整了nginx的版本,并执行创建了。所以执行如下指令,可以看到这5个Pod的滚动更新状态。

kubectl describe deployment demo-deployment

通过查看 Deployment 的 Events,看到这个“滚动更新”的流程:

像这样,将一个集群中正在运行的多个 Pod 版本,交替地逐一升级的过程,就是“滚动更新”。

3.8 ReplicaSet最终状态

执行如下指令,获取ReplicaSet的最终状态:

kubectl get rs
# result
NAME                         DESIRED   CURRENT   READY   AGE
demo-deployment-5d59d67564   5         5         5       7m22s
demo-deployment-64c9d67564   0         0         0       13m

结果如下,旧 ReplicaSet(hash=64c9d67564)已经被“水平收缩”成了 0 个副本。

四. 拓展

4.1 历史回滚

我们可以通过kubectl rollout undo命令,就能把整个 Deployment 进行回滚。

检查历史版本

我需要使用 kubectl rollout history 命令,查看每次 Deployment 变更对应的版本。而由于我们在创建这个 Deployment 的时候,指定了–record 参数,所以我们创建这些版本时执行的 kubectl 命令,都会被记录下来。
指令如下:

kubectl rollout history deployment/demo-deployment
deployment.apps/demo-deployment
REVISION  CHANGE-CAUSE
1         kubectl apply --filename=demo-deployment.yaml --record=true
2         kubectl apply --filename=demo-deployment-v2.yaml --record=true

结果如下图:

注意:关于这个结果,是从上向下查看,版本号从Index 1开始。

查看指定版本内容
根据上图,我们打算回查看版本1内容,所以我们执行如下指令:

kubectl rollout history deployment/demo-deployment --revision=1

具体内容如下:

回滚到指定版本
执行如下的回滚指令:

kubectl rollout undo deployment/demo-deployment --to-revision=1

Deployment Controller 还会按照“滚动更新”的方式,完成对 Deployment 的降级操作。

  1. 设置历史版本数量
    spec.revisionHistoryLimit,就是 Kubernetes 为 Deployment 保留的“历史版本”个数。如果把它设置为 0,就不支持回滚操作。

4.2 发布方式区别

关于‘金丝雀发布’,‘蓝绿发布’和‘滚动发布’之间的区别,就以如下简单的总结。

  • 金丝雀部署

金丝雀发布的好处在于可以用真实环境测试新版本,当新版本存在问题时最多只影响部分用户,且支持安全快速的回滚策略(将路由到新版本上的流量切换到其它的老版本机器上即可)

  • 蓝绿发布

目的是减少因发布导致的服务中断时间,同时它也支持发布失败时的快速回滚。
蓝绿部署需要在发布过程中,同时运行两套程序。对硬件的要求也是当前所需的2倍,比如当前运行时,需要10台服务器支撑业务,那么使用蓝绿部署,你就需要购置20台服务器。

  • 滚动升级

滚动发布能够解决掉蓝绿部署时对硬件要求增倍的问题。
所谓滚动发布,就是在发布过程中,并不一下子启动所有新版本,而是先启动一台新版本,再停止一台老版本,然后再启动一台新版本,再停止一台老版本,直到全部发布完成,这样的话,如果当前需要10台服务器支撑服务,那么升级过程中一共只需要11台就行了。

五. 总结

Kubernetes 项目对 Deployment 的设计,实际上是代替我们完成了对“应用”的抽象,使得我们可以使用这个 Deployment 对象来描述应用,使用 kubectl rollout 命令控制应用的版本。
关于Deployment是日常无状态应用中最常见的组件,使用很简单,但是灵活使用很难。毕竟,工具始终是死的,主要还是看个人的符合场景的架构设计。

转自:https://blog.wyatt.plus/archives/150