当集群中的某个服务需要升级时,我们需要停止目前与该服务相关的所有 Pod,然后重新拉取镜像并启动。如果集群规模比较大,则这个工作就变成了一个挑战,而且先全部停止然后逐步升级的方式会导致较长时间的服务不可用。kubernetes 提供了 rolling-update(滚动升级)功能来解决上述问题。
滚动升级通过执行 kubectl rolling-update 命令一键完成,该命令创建了一个新的RC,然后自动控制旧的 RC 中的 Pod 副本数量逐渐减少到 0,同时新的 RC 中的 Pod 副本数量从 0 逐步增加到目标值,最终 实现了 Pod 的升级。需要注意的是,系统要求新的 RC 需要与 旧的 RC 在相同的命名空间(Namespace)内,即不能把别人的资产偷偷转移到自家的名下。
以 redis-master 为例,假如当前运行的 redis-master Pod 是 1.0 版本,则现在需要升级到 2.0 版本。
创建 redis-master-controller-v2.yaml 的配置文件如下:
apiVersion: V1
kind: ReplicationController
metadata:
name: redis-master-v2
labels:
name: redis-master
version: v2
spec:
replicas: 1
selector:
name: redis-master
version:v2
template:
metadata:
lables:
name: redis-master
version: v2
spec:
containers:
- name: master
images: kubeguids/redis-master:2.0
ports:
- containerPort: 6379
在配置文件中有几处注意:
(1)RC 的名字(name)不能与旧的 RC 的名字相同。
(2)在 selector 中应至少有一个 Label 与旧的 RC 的 Label 不同,以标识其为新的 RC。本例中新增了一个名为 version 的 Label,以与旧的 RC 进行区分。
运行 kubectl rolling-update 命令完成 Pod 的滚动升级:
kubectl rolling-update redis-master -f redis-master-controller-v2.yaml
kubectl 的执行过程如下:
Creating redis-master-v2
.......................................................................................
Update successded. Deleting redis-master
redis-master-v2
等所有新的 Pod 启动完成后,旧的 Pod 也被全部销毁,这样就完成了容器集群的更新。
另一种方法是不使用配置文件,直接用 kubectl rolling-update 命令,加上 --image 参数指定新版镜像名称来完成 Pod 的滚动升级。
kubectl rolling-update redis-master --image=redis-master:2.0
与使用配置文件的方式不同,执行的结果是旧的 RC 被删除,新的 RC 仍将使用旧的 RC 的名字。
执行结果略.........................
更新完成后,查看 RC:
$ kubectl get rc
CONTROLLER CONTAINER(S) IMAGES(S) SELECTOR REPLICAS
redis0master master kubeguide/redis-master:2.0 deployment=XXXXX,name=redis-master,version=v1 3
可以看到,kubectl 给 RC 增加了 一个 key 为 “deployment” 的 Label(这个 key 的名字 可通过 --deployment-label-key参数进行修改),Label 的值是 RC 的内容进行 hash 计算后的值,相当于签名,这样就能很方便地比较 RC 里的 Image 名字 及其他信息是否发生了变化。
如果在更新过程中发现配置有错误,则用户可以中断更新操作,并通过执行 kubectl-rolling-update-rollback 完成 Pod 版本的回滚。
$ kubectl rolling-update redis-master --image=kubeguide/redis-master:2.0 --rollback