参考书籍:[基于 Kubernetes 的容器云平台实战]
Replication Controller
Kubernetes 提供 Replication Controller(简称 “RC”)来管理 Pod,Replication Controller 确保任何时候 Kubernetes 集群中有指定数量的 Pod 副本在运行。如果少于指定数量的 Pod 副本,Replication Controller 会启动新的 Pod,反之会杀死多余的以保证数量不变。当 Pod 失败,被删除或被终结时,RC 会自动创建新的 Pod 来保证副本数量,所以即使只有一个 Pod,也应该使用 RC 来进行管理。除此之外,RC 还提供了一些更高级的特性,比如滚动升级,升级回滚等。
RC 定义文件详解
我们通过 Replication Controller(RC)来创建持续运行的 Pod,Replication Controller 的定义文件 my-testpod-rc.yaml 如下:
1 | apiVersion: v1 |
提示:Kubernetes 通过 template 来生成 Pod,创建完成后,模板和 Pod 就没有任何关系了。RC 通过 Label 查找对应的 Pod 并控制副本。
通过定义文件创建 Replication Controller:
1 | # kubectl create -f my-testpod-rc.yaml |
查询 Replication Controller
1 | # kubectl get rc my-testpod |
查询 Pod 容器
1 | # kubectl get pod --selector app=testpod |
因为 Replication Controller 设置 Pod 的副本数目(replicas)为 2,所以创建出两个 Pod,并且可以看出 Pod 的名称前缀是 Replication Controller 的名称,后缀则是 5 位随机字符串。
删除一个 Pod 后,Replication Controller 会立刻再创建一个 Pod:
1 | # kubectl delete pod my-testpod-f8bp6 |
使用 kubectl delete
命令删除 Replication Controller,默认会删除 Replication Controller 关联的所有 Pod 副本。如果要保留 Pod 运行,删除 Replication Controller 的时候可以设置参数 --cascade=false
。
在实际的操作中,相比直接创建 Pod,一般都是先在 Replication Controller 中预定义 Pod 模板,然后通过 Replication Controller 来创建 Pod,Pod 模板是在 Replication Controller 的定义中通过 .spec.template
设置的。Pod 模板的定义方法与 Pod 的定义一致,但是有一些需要注意的内容:
- 在 Pod 模板中无需指定 Pod 名称,即使指定了也不起作用。通过 Pod 模板创建 Pod 时,会设置 Pod 的 .metadata.generateName,Pod 的名称就是 “.metadata.generateName + 5位随机码”。目的时确保 Pod 模板创建出来的 Pod 名称是唯一的;
- Pod 模板中的重启策略必须是 Always,因为 Replication Controller 要保证 Pod 持续运行,确保 Pod 总是重启容器;
- Pod 模板中的 Label 不能位空,否则 Replication Controller 无法同 Pod 模板创建出来的 Pod 进行关联。
Pod 模板实例:
1 | apiVersion: v1 |
通过定义文件创建 PodTemplate
1 | # kubectl create -f my-testpod-temp.yaml |
RC 与 Pod 的关联 – Label
RC 与 Pod 的关联是通过 Label 来实现的。Label 机制是 Kubernetes 中的一个核心概念,通过 Label 定义这些对象的可识别属性,可以灵活地进行分类和选择。对于 Pod,需要设置其自身的 Label 来进行标识,Label 是一系列的键值对,用户可以在 Pod.metadata.labels
中对其进行设置。Labels 键值对可以使多个:
1 | Labels: |
Label 虽然是用户任意定义的,但是 Label 必须具有可标识性,比如设置 Pod 的应用名称和版本号等。另外 Label 是不具有唯一性的,为了更准确的标识一个 Pod,应该为 Pod 设置多个维度的 Label。如下:
1 | "release": "v1", "release": "v2" |
例如,当用户在 RC 的 yaml 文件中定义了该 RC 的 Selector 中的 Label 为 “app: my-web”,那么这个 RC 就会去关注 Pod.metadata.labels
中 Label 为 “app: my-web” 的 Pod。
修改了对应 Pod 的 Label,就会使 Pod 脱离 RC 的控制。同样,在 RC 运行正常的时候,若试图继续创建同样 Label 的 Pod,是无法创建的。因为 RC 人为副本数已经正常了,再多的话会被 RC 删掉。
对于 Replication Controller 来说就是通过 Label Selector 来匹配 Pod 的 Label,从而实现关联关系。在 Replication Controller 的定义中通过 .spec.selector
来设置 Label Selector。
Replication Controller 的定义文件 my-test-rc.yaml 如下
1 | apiVersion: v1 |
通过定义文件创建 Replication Controller
1 | # kubectl create -f my-test-rc.yaml |
查询 Replication Controller
1 | # kubectl get rc my-test |
通过 Label 查询 Replication Controller 创建的 Pod
1 | # kubectl get pod --label-columns=app --selector app=my-test |
可以将该 Pod 的标签 app=my-test 修改为
1 | # kubectl label pod my-test-dg6f4 app=debug --overwrite |
通过查询可以看到有新的 Pod 被创建,因为 Replication Controller 只是通过 Label 关联 Pod,对 Replication Controller 而言,Pod 的 Label 被修改相当于减少一个关联的 Pod,自然会触发创建的新的 Pod
1 | # kubectl get pod --selector app --label-columns=app |
弹性伸缩
弹性伸缩是为了适应应用负载变化,以弹性可伸缩的方式提供资源。反映到 Kubernetes 中,指的是可根据负载的高低动态调整 Pod 的副本数,目前 Kubernetes 提供了 API 接口实现 Pod 的弹性伸缩。当然,Pod 的副本数本来就是通过 Replication Controller 进行控制,所以 Pod 的弹性伸缩就是修改 Replication Controller 的 Pod 副本数,可以通过 kubectl scale 命令来完成。
首先,创建 Replication Controller,设置的 Pod 副本数为 1,Replication Controller 的定义文件 my-test-rc.yaml 文件如下:
1 | apiVersion: v1 |
通过定义文件创建 Replication Controller
1 | # kubectl create -f my-test-rc.yaml |
查询 Replication Controller
1 | # kubectl get rc my-test |
通过 Label 查询 Replication Controller 创建的 Pod
1 | # kubectl get pod --selector app=my-test --label-columns=app |
调整 Pod 的副本数是通过修改 RC 中 Pod 的副本来实现的,示例如下:
扩容 Pod 的副本数目到 5
1
2
3
4
5
6# kubectl scale replicationcontroller my-test --replicas=5
replicationcontroller/my-test scaled
# kubectl get rc --selector app=my-test
NAME DESIRED CURRENT READY AGE
my-test 5 5 5 3m59s缩容 Pod 的副本数目到 1
1
2
3
4
5
6# kubectl scale replicationcontroller my-test --replicas=1
replicationcontroller/my-test scaled
# kubectl get rc --selector app=my-test -owide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
my-test 1 1 1 6m22s nginx nginx app=my-test
滚动升级
滚动升级是一种平滑过渡的升级方式,在升级过程中,服务仍然可用,通过逐步替换的策略保证整体系统的稳定,在初步升级的过程中还可以及时发现,调整问题,以保证问题影响度不会扩大。
对于在 Kubernetes 中支持滚动升级,现在通过举例演示应用从 v1 版本滚动升级到 v2 版本。首先创建 v1 版本的 Replication Controller,v1 版本的 Replication Controller 的定义文件 my-test-v1-rc.yaml 如下:
1 | apiVersion: v1 |
通过定义文件创建 Replication Controller
1 | # kubectl create -f my-test-v1-rc.yaml |
查询 Replication Controller
1 | # kubectl get rc my-test-v1 -owide |
扩容 Pod 的副本数目到 4
1 | # kubectl scale replicationcontroller my-test-v1 --replicas=4 |
现在需要应用从 v1 版本升级到 v2 版本,v2 版本的 Replication Controller 定义文件 my-test-v2-rc.yaml 文件如下
1 | apiVersion: v1 |
Kubernetes 中滚动升级的命令如下:
1 | kubectl rolling-update my-test-vl -f my-test-v2-rc.y出nl --update-period=lOs |
升级开始后,首先根据定义文件创建 v2 版本的 RC,然后每隔 10s(–update-period=10s) 逐步增加 v2 版本的 Pod 副本数,并逐步减少 v1 版本 Pod 的副本数。升级完成之后,删除 v1 版本的 RC,保留 v2 版本的 RC,从而实现滚动升级。
升级过程中如发生错误而导致中途退出,可以选择继续升级。Kubernetes 能够智能的判断升级中断之前的状态,然后紧接着继续执行升级。当然也可以进行回退,命令如下
1 | kubectl rolling-update my-test-v1 -f my-test-v2-rc.yaml --update-period=10s --rollback |
回退的方式实际就是升级的逆操作,即逐步增加 v1 版本 Pod 的副本数,逐步减少 v2 版本 Pod 的副本数。
注意:新版本中
rolling-update
命令已被移除,新版本中滚动升级的命令为 set,如下
1 | # kubectl set image rc my-test-v1 my-test-v1=nginx:latest --record |
Replica Set
Replica Set 是升级版的 Replication Controller,用于确保与 Label Selector 匹配的 Pod 数量维持在期望值。不同于 Replication Controller,Replica Set 引入了基于子集的 Selector 查询条件,而 Replication Controller 仅支持基于值相等的 Selector 条件查询。社区引入 Replica Set 的初衷是:当 v1 版本被废弃时,Replication Controller 完成其历史使命,而由 Replica Set 来接管其工作。虽然 Replica Set 可以独立使用,但它主要被 Deployment 用作 Pod 机制的创建,删除和更新。当使用 Deployment 时,用户不必担心创建 Pod 的 Replica Set,因为可以通过 Deployment 管理 Replica Set,除非需要自定义更新编排。这意味着可能永远不需要操作 Replica Set 对象,而是使用 Deployment 替代管理。
大多数支持 Replication Controller 命令的 Kubectl 也支持 Replica Set,rolling-update 命令除外。如果要使用 rolling-update,请使用 Deployment 来实现。
定义 frontend.yaml 文件,内容如下:
1 | apiVersion: extensions/v1beta1 |
使用定义文件创建 ReplicaSet
1 | kubectl create -f frontend.yaml |