5.2.4 更新 ReplicaSet 控制器

ReplicaSet 控制器的核心组成部分是标签选择器、副本数量及 Pod 模板,但更新操作一般是围绕 replicas 和 template 两个字段值进行的,毕竟改变标签选择器的需求几乎不存在。改动 Pod 模板的定义对已经创建完成的活动对象无效,但在用户逐个手动关闭其旧版本的 Pod 资源后就能以新代旧,实现控制器下应用版本的滚动升级。另外,修改副本的数量也就意味着应用规模的扩展(提升期望的副本数量)或收缩(降低期望的副本数量)。这两种操作也是系统运维人员日常维护工作的重要组成部分。

1. 更新 Pod 模板:升级应用

ReplicaSet 控制器的 Pod 模板可随时按需修改,但它仅影响这之后由其新建的 Pod 对象,对已有的副本不会产生作用。大多数情况下,用户需要改变的通常是模板中的容器镜像文件及其相关的配置以实现应用的版本升级。下面的示例清单文件片段(rs-example-v2.yaml)中的内容与之前版本(rs-example.yaml)的唯一不同之处也仅在于镜像文件的改动:

containers:
- name: nginx
  image: ikubernetes/myapp:v2
  ports:
  - name: http
    containerPort: 80

对新版本的清单文件执行 “kubectl apply” 或 “kubectl replace” 命令即可完成 rs-example 控制器资源的修改操作:

**[terminal]
**[delimiter $ ]**[command kubectl replace -f rs-example-v2.yaml]
replicaset.apps/rs-example replaced

不过,控制器 rs-example 管控的现存 Pod 对象使用的仍然是原来版本中定义的镜像:

**[terminal]
**[delimiter $ ]**[command kubectl get pods -l app=rs-demo -o custom-columns=Name:metadata.name,Image:spec.containers[0].image]
Name               Image
pod-example        ikubernetes/myapp:v1
rs-example-s47z9   ikubernetes/myapp:v1

此时,手动删除控制器现有的 Pod 对象(或修改与其匹配的控制器标签选择器的标签),并由控制器基于新的 Pod 模板自动创建出足额的 Pod 副本,即可完成一次应用的升级。新旧更替的过程支持如下两类操作方式。

  • 一次性删除控制器相关的所有 Pod 副本或更改相关的标签:剧烈更替,可能会导致 Pod 中的应用短时间不可访问(如图 5-5 所示);生产实践中,这种做法不可取。
直接更替所有 Pod 资源
图 1.7.2.4 - 直接更替所有 Pod 资源
  • 分批次删除旧有的 Pod 副本或更改其标签(待控制器补足后再删除另一批):滚动更替,更替期间新旧版本共存(如图 5-6 所示)。
滚动更替 Pod 资源
图 1.7.2.4 - 滚动更替 Pod 资源

例如,这里采用第一种方式进行操作,一次性删除 rs-example 相关的所有 Pod 副本:

**[terminal]
**[delimiter $ ]**[command kubectl delete pods -l app=rs-demo]
pod "pod-example" deleted
pod "rs-example-s47z9" deleted

再次列出 rc-example 控制器相关的 Pod 及其容器镜像版本时可以发现,使用新版本镜像的 Pod 已经创建完成:

**[terminal]
**[delimiter $ ]**[command kubectl get pods -l app=rs-demo -o custom-columns=Name:metadata.name,Image:spec.containers[0].image]
Name               Image
rs-example-rmmtp   ikubernetes/myapp:v2
rs-example-smmbv   ikubernetes/myapp:v2

必要时,用户还可以将 Pod 模板改回就的版本进行应用的 “降级” 或 “回滚”,它的操作过程与上述过程基本类似。事实上,修改 Pod 模板时,不仅仅能替换镜像文件的版本,甚至还可以将其替换成其他正在运行着的、完全不同应用的镜像,只不过此类需求并不多见。若同时改动的还有 Pod 模板中的其他字段,那么在新旧更替的过程中,它们也将随之被应用。

以上操作只为说明应用部署的方式,实际使用时还需要更为完善的机制。即便是仅执行了一到多次删除操作,手动执行更替操作也并非一项轻松的任务,幸运的是,更高级别的 Pod 控制器 Deployment 能够自动实现更完善的滚动更新和回滚,并为用户提供自定义更新策略的接口。而且,经过精心组织的更新操作还可以实现诸如蓝绿部署(Blue/Green Deployment)、金丝雀部署(Canary Deployment)和灰度部署等,这些内容将在后面章节中详细展开说明。

2. 扩容和缩容

改动 ReplicaSet 控制器对象配置中期望的 Pod 副本数量(replicas 字段)会由控制器实时做出响应,从而实现应用规模的水平伸缩。replicas 的修改及应用方式同 Pod 模板,不过,kubectl 还提供了一个专用的子命令 scale 用于实现应用规模的伸缩,它支持从资源清单文件中获取新的目标副本数量,也可以直接在命令行通过 “--replicas” 选项进行读取,例如将 rs-example 控制器的 Pod 副本数量提升至5个:

**[terminal]
**[delimiter $ ]**[command kubectl scale replicasets rs-example --replicas=5]
replicaset.extensions/rs-example scaled

由下面显示的 rs-example 资源的状态可以看出,将其 Pod 资源副本数量扩展至5个的操作已经成功完成:

**[terminal]
**[delimiter $ ]**[command kubectl get replicasets rs-example]
NAME         DESIRED   CURRENT   READY   AGE
rs-example   5         5         5       20h

收缩规模的方式与扩展相同,只需要明确指定目标副本数量即可。例如:

**[terminal]
**[delimiter $ ]**[command kubectl scale replicasets rs-example --replicas=3]
replicaset.extensions/rs-example scaled

另外,kubectl scale 命令还支持现有 Pod 副本数量符合指定的值时才执行扩展操作,这仅需要为命令使用 “--current-replicas” 选项即可。例如,下面的命令表示如果 rs-example 目前的 Pod 副本数量为 2,就将其扩展至 4 个:

**[terminal]
**[delimiter $ ]**[command kubectl scale replicasets rs-example --current-replicas=2 --replicas=4]
error: Expected replicas to be 2, was 3

但由于 rs-example 控制器现存的副本数量是 3 个,因此上面的扩展操作未执行并返回了错误提示。

如果 ReplicaSet 控制器管控的是有状态的应用,例如主从架构的 Redis 集群,那么上述这些升级、降级、扩展和收缩的操作都需要精心编排和参与才能进行,不过,这也在一定程度上降低了 Kubernetes 容器编排的价值和意义。好在,它提供了 StatufulSet 资源来应对这种需求,因此,ReplicaSet 通常仅用于管理无状态的应用,如 HTTP 服务程序等。

results matching ""

    No results matching ""