Pod升级和回滚
当集群中的某个服务需要升级时,我们需要停止目前与该服务相关的所有 Pod ,然后下载新版本镜像井创建新的 Pod 如果集群规模比较大,则这个工作就变成了一个挑战,而且先全部停止然后逐步升级的方式会导致较长时间的服务不可用 Kubernetes 提供了滚动升级功能来解决上述问题。
如果 Pod 是通过 Deployment
建的,则用户可以在运行时修改 Deployment的Pod 定义(spec.template
)或镜像名称 ,井应用到 Deployment
对象上,系统即可完成 Deployment 的自动更新操作。如果在更新过程中发生了错误, 则还可以通过回滚( Rollback )操作恢复 Pod的版本。
一、Deployment升级
Deployment nginx
1 | #nginx-deployment.yaml |
将nginx更新为1.9.1,通过kubectl set image
命令为Deployment设置新的镜像
1 | #通过命令行修改 |
升级会触发Pod的滚动升级操作
1 | kubectl rollout status deployment/nginx-deployment |
二、Deployment升级过程
更新过程
1 | kubectl describe deployments nginx-deployment |
初始创 Deployment 时, 系统创建了一 ReplicaSet
求创建了 Pod 副本,当更新 Deployment 系统 建了一个新 ReplicaSet
并将其副本数扩展 然后将旧的 ReplicaSet
缩减为 2。之后,系统按照相同策略对新旧两个RepilcaSet进行调整。
查看2个ReplicaSet
状态
1 | kubectl get rs |
升级过程中,系统会保证至少有两个 Pod 可用,并且最多同时运行4个 Pod,这是 Deployment
通过复杂的算法完成的。 Deployment
需要确保在整个更新过程中只有一定数量的 Pod 可能处于不可用状态,在默认情况下, Deployment 确保可用的 Pod 总数至少为所需的副本的数量( DESIRED )减1 ,也就是最多1个不可用( maxUnavailable=1
), Deployment还需要确保在整个更新过程中 Pod 的总数量不会超过所需的副本数太多,在默认情况下,Deployment 确保 Pod 的总数最 比所 Pod 数多1个,也就是最多1个浪涌值(maxSurge=1
)Kubenretes v1.6
版本开始, maxUnavailable
和maxSurge
默认值将从1,1更新为所需副本数的 25%、25%
更新策略
Deployment
的定义中,可以通过 spec.strategy
指定 Pod 更新的策略,目前支持两种策略RollingUpdate
(被动更新)和 Recreate
(重建) ,默认值为 RollingUpdate
Recreate
(重建):设置spec. strategy. type= Recreate
表示 Deployment 在更新 Pod 时,会先杀掉所有正在运行的 Pod ,然后创建新的 PodRollingUpdate
(滚动更新):设置spec.strategy.type=RollingUpdate
,表示 Deployment以滚动更新的方式来逐个更新 Pod 。同时,可以通过设置spec. strategy rollingUpdate
下的两个参数(maxUnavailable
、maxSurge
)来控制被动更新的过程。
滚动升级的参数:
spec.strategy.rollingUpdate.maxUnavailable
:指定 Deployment 在更新过程中不可用状态 Pod 的上限。可以是绝对值也可以是百分比spec.strategy.rollingUpdate.maxSurge
:Pod 总数超过Pod 期望副本数部分的最大值
多重更新:如果Deployment 上一次更新正在进行 ,此时用户再次发起 Deployment 更新操作,那 Deployment 每一次更新都创建一个ReplicaSet
而每次新的 ReplicaSet成功后,会逐 Pod 副本数 ,同时将之前正在扩容的 ReplicaSet
停止扩容(更新) 并将其加入旧版本 ReplicaSet
列表中,然后开始缩容至操作。
注意更新 Deployment 的标签选择器( Label selector )的情况。不鼓励更新Deployment
的标签选择器,因为这样会导致 Deployment选择的Pod列表发生变化,也能与其他控制器产生冲突。注意事项:
- 添加选择器标签时,必须同步修改 Deployment配置的Pod 的标签 ,为 Pod 添加新的标签,否则
Deployment
的更新会报验证错误而失败。添加标签选择器是无法向后兼容的,新的标签选择器不会匹配和使用旧选择器创建的ReplicaSet
和Pod ,因此添加选择器将会导致旧版ReplicaSet
和Pod
处于孤立状态 - 更新标签选择器,即更改选择器中标签的键或者值,也会产生与添加选择器标签类似的效果。
- 删除标签选择器, 即从 Deployment 标签选择器中删除一个或者多个标签,该
Deployment
的ReplicaSet
和Pod
不会受到任何影响,不是被删除的标签 仍会存在于现有Pod
和ReplicaSet
上。
二、Deployment的回滚
当我们更新一个镜像出现错误,这时需要用kubectl rollout history
查看Deployment部署的历史记录
1 | kubectl rollout history deployment/nginx-deployment |
创建Deployment时使用--record
参数,就可以在CHANGE-CAUSE
中看到每个版本的命令
Deployment 的更新操作是在 Deployment 进行部署( Rollout )时被触发的, 这意味着当且仅当 Deployment的Pod (即
spec.template
)被更改时才会创建新的修订版本,例如更新模板标签或容器镜像。其他更新操作(如扩展副本数〉将不会触发 Deployment的更新操作,这也意味着我 Deployment 回滚之前版本时, 只有 Deployment的Pod板部分会被修改。
1 | #查看特定版本的详细信息 ,可以加--revision=<N>参数 |
回滚到上一个版本:
1 | kubectl rollout undo deployment/nginx-deployment |
三、暂停和恢复Deployment的部署
对于一次复杂的 Deployment
配置修改,为了避免频繁触发 Deployment
更新操作,可以先暂停 Deployment 的更新操作,然后进行配置修改,再恢复 Deployment ,一次性触发完整的更新操作,就可以避免不必要的Deployment 更新操作了。
1 | #通过 kubectl rollout pause 命令暂停 Deployment 的更新操作: |
四、其他管理对象的更新策略
DaemonSet 的更新策略
包含2种升级策略
OnDelete
: 当使用OnDelete
作为升级策略时, 建好新DaemonSet
配置之后 Pod 并不会被自动创建,直到用户手动删除旧版本 Pod 发新建操。RollingUpdate
:旧版本的 Pod 将被自动杀掉, 然后自动创建新版本的DaemonSet
Pod整个过程与普通deployment
的滚动升级一样是可控 。不同于普通 Pod 滚动升级:- 不支持查看和管理
DaemonSet
更新历史记录 - DaemonSet 回滚并不能如同 Deployment 样直接通过
kubectl rollback
命令来实现, 而是必须通过再次提交旧版本配置的方式实现。
- 不支持查看和管理
StatefulSet更新
针对 StatefulSet
的更新策略正逐渐向 Deploymont
DaemonSet
的更新策略看齐 ,也将实 RollingUpdate
Paritioned
OnDelete
种策略 目标是保证StatefulSet
中各 Pod 有序 、逐个被更新,并且能够保留更新历史,也能回滚到某个历史版本。