一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第10天,点击查看活动详情。
一、 前言
使用 Deployment 进行 Pod 的部署、升级与回滚。
Deployment为Pod和ReplicaSet提供了声明式定义方法,可以替代之前使用的ReplicationController(RC)来管理应用。
Deployment 资源对象为 Pod 和 ReplicaSet(ReplicationController 的升级版)提供了声明式定义,在 Deployment YAML 文件中描述期望达到的目标状态。
Deployment Controller会创建符合目标状态的ReplicaSet和Pod,如果更新Deployment,对应的ReplicaSet和Pod的状态也会改变以符合新的目标状态。
(1)典型应用场景
- 定义
Deployment来创建ReplicaSet和Pod
使用
Deployment来创建ReplicaSet,ReplicaSet又会在后台创建Pod。可以检查Pod的启动状态,观察是成功还是失败。也可以根据Deployment的状态判断上线是否hang住了。
- 滚动升级和回滚应用
通过更新
Deployment的PodTemplateSpec字段来声明Pod的新状态,更新Deployment后会创建一个新的ReplicaSet,Deployment会按照控制的速率删除由旧的ReplicaSet创建的Pod、并使用新的ReplicaSet创建新的Pod,当新生成的Pod达到要求的目标状态后,会清除旧的ReplicaSet。如果当前状态不稳定,可以回滚到之前的
Deployment revision,每次回滚都会更新Deployment的revision。
- 扩容和缩容
根据系统负载进行
Deployment的扩容和缩容。
- 暂停和继续
Deployment
暂停
Deployment并修改PodTemplateSpec字段,然后重新恢复上线。
(2)举个例子
- 定应
Deployment文件nginx-deployment.yaml
它可以创建一个
Replica Set来启动 3个nginx pod
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
- 执行创建
$ kubectl create -f nginx-deployment.yaml
deployment.apps/nginx-deployment created
- 查看
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
- 查看
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在运行中,可以修改Deployment的Pod定义或是镜像名称,并应用到Deployment 对象上,这样就完成了 Deployment的自动更新操作。
(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
- 修改了镜像名,就会触发系统完成
Deployment所有运行pod的滚动升级操作,查看rollout状态
Tips: 当且仅当
Deployment的.spec.template字段下的labels或是image更新时才会触发rollout,其它的更新并不会触发rollout。
$ kubectl rollout status deployment/nginx-deployment
deployment "nginx-deployment" successfully rolled out
- 查看更新后的
Deployment、RS、Pod:
# 可以看到 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
- 查看
nginx-deployment详细信息
$ kubectl describe deployments/nginx-deployment
# ReplicaSet 更新为 nginx-deployment-7448597cd5
(2)分析更新过程
Event事件,可以看到Pod的更新过程:
- 系统创建了一个新的
RS(nginx-deployment-7448597cd5),将其副本数量扩展到 1;将旧的RS(nginx-deployment-5754944d6c)副本数量缩减为 2 - 新的
RS副本数量扩展到了 2,旧的RS副本数量缩减为 1 - 新的
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下设置两个参数maxSurge和maxUnavailable来控制滚动更新的过程。
关于两个参数的详细说明:
-
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可以在滚动更新开始时立即进行副本数扩容,只要保证新旧RS的Pod副本总数之和不超过期望副本数的 125% 即可。一旦旧的 Pod 被 kill 掉,新的RS会进一步扩容。在整个过程中系统在任意时刻都能确保新旧RS的Pod副本总数之和不超过所需副本数的 125%。
(4)多重更新(Rollover)
“多重更新”也就是多个滚动更新(Rollout)同时进行。
每当 Deployment Controller 检测到有新的 Deployment 创建时,如果没有已存在的 ReplicaSet 来创建期望个数的Pod,Deployment Controller 就会创建一个新的 ReplicaSet 来执行改变,已存在的 ReplicaSet 控制 ``label匹配字段spec.selector但是template不匹配字段spec.template的Pod进行缩容,然后新的ReplicaSet将会扩容出匹配字段spec.replicas指定数目的Pod,旧的 ReplicaSet` 将会缩容到 0。
举个例子:比如创建了一个有 5 个 nginx:1.7.9 replica 的 Deployment,当刚刚创建到 3 个 nginx:1.7.9 replica 时,开始更新 Deployment 将其镜像修改为 nginx:1.9.1。在这种情况下,Deployment 会立即 kill 掉已创建的 3 个 nginx:1.7.9 的 Pod,并开始创建 nginx:1.9.1 的 Pod,它不会等到所有 5 个 nginx:1.7.9 的 Pod 都创建完成后才开始执行滚动更新。
更新 Deployment 的标签选择器(Label Selector)
通常情况下不建议更新
Deployment的标签选择器,因为这样会导致Deployment选择的Pod列表发生变化,可能与其他控制器发生冲突。
步骤如下:
- 添加标签选择器
在添加标签选择器时,注意要同步修改
Deployment配置的Pod标签,为Pod添加新的标签。
这里有点不同的是,添加标签选择器无法向后兼容,新的标签选择器不会匹配和使用旧选择器创建的 ReplicaSets 和 Pod,因此添加新的选择器会导致所有旧版本的 ReplicaSets 和由旧 ReplicaSets 创建的 Pod 处于孤立状态,即:不会被系统自动删除,也不受新的 ReplicaSet 控制。
向字段 spec.selector.matchLabels 和字段 spec.template.matedata.labels 同时添加标签 k8s: nginx-pod,使用如下命令进行修改:
$ kubectl edit deployment/nginx-deployment
deployment.extensions/nginx-deployment edited
查看更新后的 Deployment、RS、Pods:
# 可以看到更新完成
$ 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
- 更新标签选择器
比如更新选择器中标签的键或值,这种做法产生的效果与添加新选择器标签类似。
- 删除标签选择器
从
Deployment的标签选择器中删除一个或多个标签,该Deployment的ReplicaSet和Pod不会受到任何影响,只是被删除的标签依然会存在与现有的ReplicaSet和Pod上。