5. 应用编排和管理:Deployment

本文由 CNCF + Alibaba 云原生技术公开课 整理而来

Deployment:管理部署发布

  • Pod 存在的问题:

Kubernetes 集群可以直接管理所有的 Pod 吗?如果这样做,会带来什么样的问题呢?

首先 Kubernetes 集群不可以直接管理所有的 Pod,也强烈不建议这么做,因为这么做会带来这些问题:

1. 如何保证集群内可用 Pod 的数量?

2. 如何为所有 Pod 更新镜像的版本?

3. 如何在更新过程中保证服务的可用性?

4. 如何在更新过程中发现问题并快速回滚?

正因为存在这些问题,所以 Kubernetes 引入了全新的资源对象——Deployment,它也是逻辑概念,用来作为 Pod 管理部署发布的控制器。

  • Deployment 介绍:

Deployment 作为 Pod 管理部署发布的控制器,每个 Deployment 其实是管理的一组相同的应用 PodDeployment 可以具体完成这些事情:

1. Deployment定义了 Pod 期望数量,Controller 始终会持续维持 Pod 数量为期望的数量。当 Pod 出现问题时,Controller也能够恢复

2. 配置 Pod 发布方式,Controller 会按照 Deployment 配置的策略来更新 Pod,而且在更新过程中可以设置不可用的 Pod 数量范围

3. 如果更新过程中发生问题,也可以针对 Deployment “一键回滚”,通过一条命令就可以将 Deployment 对应的所有 Pod 更新为之前的旧版本

Deployment 用法

下面简单介绍 Deployment 的用法。

  • Deployment 语法:

nginx Deployment yaml 文件示例:

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

文件解析:

apiVersion: apps/v1     表示 Deployment 当前所属的组是 apps,版本是 v1

kind        表示 Kubernetes 资源类型是 Deployment

metadata    表示 Deployment 的元数据,元数据通常包含 name、namespace、labels、annotations 等

spec    表示 Deployment 的期望状态,replicas 表示期望的 Pod 数量;selector 表示 Pod 选择器,选择带相同 label 的 Pod;
        template 表示 Pod 的模板,模板中也有 Pod 的 metadata 和 spec
  • 查看 Deployment 状态:

当创建出一个 Deployment,可以通过 kubectl get deployment 命令查看 Deployment 的状态。具体可以看到这些字段:

DESIRED     期望的 Pod 数量(replicas)

CURRENT     当前实际的 Pod 数量

UP-TO-DATE  到达期望版本的 Pod 数量

AVAILABLE   运行中可用的 Pod 数量

AGE         Deployment 创建的时长
  • 查看 Pod 状态:

当创建出一个 Deployment,可以通过 kubectl get pod 命令查看 Pod 的状态。通常可以看出 Pod 的名称分为三部分:

第一部分,是 Pod 所属的 Deployment 的名称,如果是上面示例中创建的 Deployment,则该名称是 nginx-deployment

第二部分,是 template-hash,同一个 Deployment 的 Pod 是一样的,因为 Pod 是同一个 template 中创建出来的

第三部分,是一个随机生成的字符串,每个 Pod 随机生成的字符串都不会相同
  • Deployment 更新镜像版本:

对一个给定的 Deployment 更新镜像版本,有三种方式。以上面示例为例:

1. kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1

2. kubectl edit deployment nginx-deployment             #修改镜像版本

3. 直接修改 yaml 文件(image: nginx:1.9.1),kubectl apply -f <yaml file>
  • Deployment 快速回滚:

如果在发布过程中遇到了问题,也支持快速回滚。以上面示例为例:

#回滚到上一版本

kubectl rollout undo deployment/nginx-deployment

#先查看版本列表,然后回滚到指定版本

kubectl rollout history deployment.v1.apps/nginx-deployment

kubectl rollout undo deployment.v1.apps/nginx-deployment --to-revision=2
  • Deployment Status

Kubernetes 的每一个资源都有它的 spec.StatusDeployment Status 中描述的三个其实是它的 conversion 状态,也就是 ProcessingComplete 以及 Failed

Processing 为例,Processing 指的是 Deployment 正在处于扩缩容或发布中。Processing 状态的 Deployment,它所有的 replicasPod 副本全部达到最新版本,而且是 Available,这样就可以进入 Complete 状态。而 Complete 状态如果再次发生了扩缩容,也会重新进入 Processing 这个状态。

如果在处理过程中遇到一些问题,比如拉取镜像失败或者 readiness probe 检查失败,就会进入 Failed 状态;如果在运行过程中,即 Complete 状态中发生 Pod readiness probe 检查失败,这个时候 Deployment 也会进入 Failed 状态。进入 Failed 状态之后,除非所有 replicas 均变成 Available,而且是 updated 最新版本,Deployment 才会重新进入 Complete 状态。


架构设计

  • 管理模式:

Deployment 只负责管理不同版本的 ReplicaSet,由 ReplicaSet 来管理具体的 Pod 副本数,每个 ReplicaSet 对应 Deployment template 的一个版本。每一次修改 template,都会生成一个新的 ReplicaSet,这个 ReplicaSet 下的 Pod 其实都是相同的版本。

Deployment 创建 ReplicaSet,而 ReplicaSet 创建 Pod,它们的 OwnerRef 都对应了其控制器的资源。

  • Deployment 控制器:

首先,所有的控制器都是通过 Informer 中的事件做一些 HandlerWatch,这里 Deployment 控制器其实关注的是 DeploymentReplicaSet 中的事件,收到事件后会加入到队列中。而 Deployment 控制器从队列中取出来之后,它的逻辑会判断 Check Paused,这个 Paused 其实是 Deployment 是否需要进行新的发布,如果 Paused 设置为 true,就表示这个 Deployment 只会做一个数量上的维持,不会做新的发布。

如果 Check Paused 为 true,那么 Deployment 控制器只会做 Sync replicas,即把 replicas 同步到对应的 ReplicaSet 中,然后再更新 Deployment Status,这一次的过程就结束了。

如果 Paused 为 false,它就会做 Rollout,通过 CreateRolling 的方式来更新,更新的方式也是通过 Create/Update/Delete ReplicaSet 来做实现的。

  • ReplicaSet 控制器:

Deployment 分配 ReplicaSet 之后,ReplicaSet 控制器本身也是从 Informer 中 Wtach 一些事件,这些事件包含了 ReplicaSetPod 的事件。从队列中取出之后,ReplicaSet 控制器的逻辑很简单,就只管理 replicas。如果 replicas 比当前 Pod 数量大,就会扩容;反之则会缩容,删除 Pod,维持当前 Pod 数量与 replicas 一致。

Deployment 控制器其实做了更复杂的事情,包含了版本管理,只不过是把每一个版本下的 Pod 数量维持工作交给 ReplicaSet 来完成。

  • Spec 字段解析:

Deployment 中还有这些重要的 Spec 字段:

MinReadySeconds:Deployment 判断 Pod available 的最小时间。如果我们设置 MinReadySeconds 为 30 秒,那 Deployment 就一定会等到 Pod ready 超过 30 秒之后才认为 Pod 是 available 的。
                Pod available 的前提条件是 Pod ready,但是 ready 的 Pod 不一定是 available 的,它一定要超过 MinReadySeconds 之后,才会判断为 available;
 

revisionHistoryLimit:保留历史 revision(ReplicaSet)的数量,默认值为 10 个。可以设置为一个或两个,如果回滚可能性比较大的话,可以设置数量超过 10;
 

paused:用来标识 Deployment 只做数量维持、不做新的发布,这个字段在 Debug 场景可能会用到;
 

progressDeadlineSeconds:判断 Deployment Status 为 Failed 的最大时间。当 Deployment 处于扩缩容或者发布状态时,它的 condition 会处于 Processing 的状态。
                        可以为 Processing 设置一个超时时间。如果超过超时时间还处于 Processing 状态,那么控制器将认为这个 Pod 会进入 Failed 状态。
  • 升级策略字段解析:

DeploymentRollingUpdate 中主要提供了两个策略,分别是 MaxUnavailableMaxSurge

MaxUnavailable:滚动过程中最多有多少个 Pod 不可用

MaxSurge:滚动过程中最多存在多少个 Pod 超过预期 replicas 数量

举个例子,ReplicaSet 为 3 的 Deployment 在发布时可能存在一种情况:新版本的 ReplicaSet 和旧版本的 ReplicaSet 都可能有 2 个 replicas,加在一起就是 4 个,超过了期望的数量 3 个。这是因为默认的 MaxUnavailableMaxSurge 都是 25%,默认 Deployment 在发布的过程中,可能有 25% 的 replicas 是不可用的,也可能超过 replicas 数量 25% 是可用的,最高可以达到 125% 的 replicas 数量。

其实用户可以根据实际场景来做设置。当资源足够、且更注重发布过程中的可用性时,可设置 MaxUnavailable 较小、MaxSurge 较大。但如果资源比较紧张,可以设置 MaxSurge 较小,甚至设置为 0,但注意 MaxSurgeMaxUnavailable 不能同时为 0。

因为当 MaxSurge 为 0 的时候,必须要删除 Pod,才能扩容 Pod;如果不删除 Pod 是不能新扩 Pod 的,因为新扩出来的话,总的 Pod 数量就会超过期望数量。而两者同时为 0 的话,MaxSurge 保证不能新扩 Pod,但 MaxUnavailable 不能保证 ReplicaSet 中有 PodAvailable 的,这样就会产生问题。所以说这两个值不能同时为 0。

  • 总结:

Deployment 管理多版本的方式,是针对每个版本的 template 创建一个 ReplicaSet,由 ReplicaSet 维护期望数量的 Pod 副本,而 Deployment 只需要关心不同版本的 ReplicaSet 里要指定多少数量的 Pod。

因此,Deployment 部署发布的根本原理,就是 Deployment 调整不同版本 ReplicaSet 里的期望副本数,以此来达到多版本 Pod 的升级和回滚。


猜你喜欢

转载自blog.csdn.net/miss1181248983/article/details/110241163