【Kubernetes】Pod 之 Deployment 管理

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第10天,点击查看活动详情

一、 前言

使用 Deployment 进行 Pod 的部署、升级与回滚。

DeploymentPodReplicaSet 提供了声明式定义方法,可以替代之前使用的 ReplicationController(RC)来管理应用。

Deployment 资源对象为 PodReplicaSetReplicationController 的升级版)提供了声明式定义,在 Deployment YAML 文件中描述期望达到的目标状态。

Deployment Controller 会创建符合目标状态的 ReplicaSetPod,如果更新 Deployment,对应的 ReplicaSetPod 的状态也会改变以符合新的目标状态。

(1)典型应用场景

  1. 定义 Deployment 来创建 ReplicaSetPod

使用 Deployment 来创建 ReplicaSetReplicaSet 又会在后台创建 Pod。可以检查 Pod 的启动状态,观察是成功还是失败。也可以根据 Deployment 的状态判断上线是否 hang 住了。

  1. 滚动升级和回滚应用

通过更新 DeploymentPodTemplateSpec 字段来声明 Pod 的新状态,更新 Deployment 后会创建一个新的 ReplicaSetDeployment 会按照控制的速率删除由旧的 ReplicaSet 创建的 Pod、并使用新的 ReplicaSet 创建新的 Pod,当新生成的 Pod 达到要求的目标状态后,会清除旧的 ReplicaSet

如果当前状态不稳定,可以回滚到之前的 Deployment revision,每次回滚都会更新 Deploymentrevision

  1. 扩容和缩容

根据系统负载进行 Deployment 的扩容和缩容。

  1. 暂停和继续 Deployment

暂停 Deployment 并修改 PodTemplateSpec 字段,然后重新恢复上线。

(2)举个例子

  1. 定应Deployment文件 nginx-deployment.yaml

它可以创建一个 Replica Set 来启动 3个 nginx pod

扫描二维码关注公众号,回复: 13779827 查看本文章
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.7.9
          ports:
            - containerPort: 80
复制代码
  1. 执行创建
$ kubectl create -f nginx-deployment.yaml
deployment.apps/nginx-deployment created
复制代码
  1. 查看Deployment的状态、RS的状态,以及运行的 Pod 副本数量
# 可以看到已经创建了 3 个符合要求的 Pod,这 3 个 Pod 都是最新的、都处于可用状态
$ kubectl get deployments
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           39s

# 该 RS 需要 3 个 Pod,当前符合要求的有 3 个 Pod 并且已经创建好,RS 名字的组成:<Deployment 的名字>-<Pod template 的 hash 值>
$ kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-5754944d6c   3         3         3       6m18s

# 使用 nginx-deployment-5754944d6c RS 创建的 3 个 Pod
$ kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-5754944d6c-gv8x8   1/1     Running   0          6m36s
nginx-deployment-5754944d6c-hsp99   1/1     Running   0          6m36s
nginx-deployment-5754944d6c-qqh42   1/1     Running   0          6m36s
复制代码
  1. 查看nginx-deployment的详细信息
$ kubectl describe deployment nginx-deployment
# 在 Annotations 记录了版本 revision: 1
# 默认更新策略使用的是 RollingUpdate
# max unavailable 和 max surge 的默认值都为 25%
# ReplicaSet 为 nginx-deployment-5754944d6c
复制代码



二、Deployment 升级

Kubernetes 提供滚动升级,就不用暂停与该服务相关的所有pod

通常使用 Deployment 来创建 Pod 资源对象,当Pod 在运行中,可以修改 DeploymentPod 定义或是镜像名称,并应用到 Deployment 对象上,这样就完成了 Deployment 的自动更新操作。

(1)举个栗子

  1. pod的镜像更新为 nginx:1.9.1
$ kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
deployment.extensions/nginx-deployment image updated

# 也可以使用 kubectl edit 命令进行更新,把 image 字段下的 nginx:1.7.9 更改为 nginx:1.9.1
$ kubectl edit deployment/nginx-deployment
deployment.extensions/nginx-deployment edited
复制代码
  1. 修改了镜像名,就会触发系统完成Deployment所有运行pod的滚动升级操作,查看rollout状态

Tips: 当且仅当 Deployment.spec.template 字段下的 labels 或是 image 更新时才会触发 rollout,其它的更新并不会触发 rollout

$ kubectl rollout status deployment/nginx-deployment
deployment "nginx-deployment" successfully rolled out
复制代码
  1. 查看更新后的 DeploymentRSPod
# 可以看到 UP-TO-DATE 的数量已经变成了 3,说明已经全部更新完成
$ kubectl get deployment
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           143m

# 查看两个 RS 的最终状态,可以看到旧的 RS 已经没有 Pod 在运行了,新的 RS 创建好了 3 个新的 Pod
$ kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-5754944d6c   0         0         0       143m
nginx-deployment-7448597cd5   3         3         3       6m11s

# 由新 nginx-deployment-7448597cd5 RS 创建出来的 3 个 Pod
$ kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-7448597cd5-7c9ms   1/1     Running   0          6m19s
nginx-deployment-7448597cd5-h6k89   1/1     Running   0          5m58s
nginx-deployment-7448597cd5-m8dnk   1/1     Running   0          5m25s
复制代码
  1. 查看nginx-deployment详细信息
$ kubectl describe deployments/nginx-deployment
# ReplicaSet 更新为 nginx-deployment-7448597cd5
复制代码

(2)分析更新过程

Event事件,可以看到Pod的更新过程:

  1. 系统创建了一个新的 RS(nginx-deployment-7448597cd5),将其副本数量扩展到 1;将旧的 RS(nginx-deployment-5754944d6c)副本数量缩减为 2
  2. 新的 RS 副本数量扩展到了 2,旧的 RS 副本数量缩减为 1
  3. 新的 RS 副本数量扩展到了 3,旧的 RS 副本数量缩减为 0

(3)更新策略

Deployment 通过字段 spec.strategy 设置 Pod 更新策略。

上面创建的 Deployment 的相关默认设置如下:

spec:
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
复制代码

Deployment 的更新策略有两种:

  • Recreat(重建): 先 kill 掉所有正在运行的 Pod,然后创建新的 Pod
  • RollingUpdate(滚动更新): 逐个更新 Pod。可以在字段 spec.strategy.rollingUpdate 下设置两个参数 maxSurgemaxUnavailable 来控制滚动更新的过程。

关于两个参数的详细说明:

  • maxUnavailable

指定更新过程中不可用状态的 Pod 数量上限。默认值 25% 指的是:Pod 期望副本数的 25%,然后系统会以向下取整的方式计算出绝对值(整数)。对于这里而言,当开始滚动更新时,旧的 RS 立即将副本数缩小到所需副本总数的 75%(3 * 75% = 2.25,然后向下取整,绝对值为 2),一旦新的 Pod 创建并准备好,旧的 RS 会进一步缩容,新的 RS 会进一步扩容,整个过程中系统在任意时刻都可以确保可用状态的 Pod 总数至少占 Pod 期望副本总数的 75%。

  • maxSurge:指定更新过程中 Pod 总数超过 Pod 期望副本数部分的最大值。默认值 25% 指的是:Pod 期望副本数的 25%,然后系统会以向上取整的方式计算出绝对值(整数)。对于这里而言,新的 RS 可以在滚动更新开始时立即进行副本数扩容,只要保证新旧 RSPod 副本总数之和不超过期望副本数的 125% 即可。一旦旧的 Pod 被 kill 掉,新的 RS 会进一步扩容。在整个过程中系统在任意时刻都能确保新旧 RSPod 副本总数之和不超过所需副本数的 125%。

(4)多重更新(Rollover)

“多重更新”也就是多个滚动更新(Rollout)同时进行。

每当 Deployment Controller 检测到有新的 Deployment 创建时,如果没有已存在的 ReplicaSet 来创建期望个数的PodDeployment Controller 就会创建一个新的 ReplicaSet 来执行改变,已存在的 ReplicaSet 控制 ``label匹配字段spec.selector但是template不匹配字段spec.templatePod进行缩容,然后新的ReplicaSet将会扩容出匹配字段spec.replicas指定数目的Pod,旧的 ReplicaSet` 将会缩容到 0。

举个例子:比如创建了一个有 5 个 nginx:1.7.9 replicaDeployment,当刚刚创建到 3 个 nginx:1.7.9 replica 时,开始更新 Deployment 将其镜像修改为 nginx:1.9.1。在这种情况下,Deployment 会立即 kill 掉已创建的 3 个 nginx:1.7.9Pod,并开始创建 nginx:1.9.1Pod,它不会等到所有 5 个 nginx:1.7.9Pod 都创建完成后才开始执行滚动更新。

更新 Deployment 的标签选择器(Label Selector

通常情况下不建议更新 Deployment 的标签选择器,因为这样会导致 Deployment 选择的 Pod 列表发生变化,可能与其他控制器发生冲突。

步骤如下:

  1. 添加标签选择器

在添加标签选择器时,注意要同步修改 Deployment 配置的 Pod 标签,为 Pod 添加新的标签。

这里有点不同的是,添加标签选择器无法向后兼容,新的标签选择器不会匹配和使用旧选择器创建的 ReplicaSetsPod,因此添加新的选择器会导致所有旧版本的 ReplicaSets 和由旧 ReplicaSets 创建的 Pod 处于孤立状态,即:不会被系统自动删除,也不受新的 ReplicaSet 控制。

向字段 spec.selector.matchLabels 和字段 spec.template.matedata.labels 同时添加标签 k8s: nginx-pod,使用如下命令进行修改:

$ kubectl edit deployment/nginx-deployment
deployment.extensions/nginx-deployment edited
复制代码

查看更新后的 DeploymentRSPods

# 可以看到更新完成
$ kubectl get deployment/nginx-deployment
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           3h58m

# 创建了新的 RS:
$ kubectl get rs nginx-deployment-8ff4cd577
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-5754944d6c   0         0         0       3h58m
nginx-deployment-7448597cd5   3         3         3       101m
nginx-deployment-8ff4cd577    3         3         3       88s

# 使用新的 RS nginx-deployment-8ff4cd577 创建了 3 个 Pod,可以发现之前的 3 个 Pod 依然存在着,没有被删除
$ kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-7448597cd5-7c9ms   1/1     Running   0          101m
nginx-deployment-7448597cd5-h6k89   1/1     Running   0          100m
nginx-deployment-7448597cd5-m8dnk   1/1     Running   0          100m
nginx-deployment-8ff4cd577-8gxw2    1/1     Running   0          95s
nginx-deployment-8ff4cd577-8plkw    1/1     Running   0          95s
nginx-deployment-8ff4cd577-g7bc2    1/1     Running   0          95s
复制代码
  1. 更新标签选择器

比如更新选择器中标签的键或值,这种做法产生的效果与添加新选择器标签类似。

  1. 删除标签选择器

Deployment 的标签选择器中删除一个或多个标签,该 DeploymentReplicaSetPod 不会受到任何影响,只是被删除的标签依然会存在与现有的 ReplicaSetPod 上。

猜你喜欢

转载自juejin.im/post/7084670154344235038