3.2 副本控制器(ReplicationController)
ReplicationController(在kubectl命令中经常缩写为rc
或rcs
)是实际确保特定数量的Pod副本在任意时刻的运行。如果Pod副本超过指定数量ReplicationController就会终止超出数量的Pod,如果太少就添加Pod。和手动创建Pod不同,ReplicationController操作的Pod在失败、删除、终止后会自动进行替换,因此还是推荐使用ReplicationController的,即使只有1个Pod(这也是依靠一个ReplicationController创建可靠运行的Pod简单场景)。
【运行一个ReplicationController】
下面是通过ReplicationController配置3个Nginx副本的栗子:
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx
spec:
replicas: 3
selector:
app: nginx
template:
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
可以通过kubectl apply -f xxx.yaml
的形式运行,然后可以查看ReplicationController的状态(上述是nginx
):kubectl describe replicationcontrollers/nginx
,可以看到Pod的具运行状态。如果要列出某个ReplicationController管理的所有的Pod,可以使用命令
pods=$(kubectl get pods --selector=app=nginx --output=jsonpath={.items..metadata.name})
echo $pods
选择器和ReplicationController的一样,其中--output=jsonpath
是指定了一个表达式,它只从返回列表中的每个Pod中获取名称。
【编写ReplicationController规约Spec】
和其他K8S的配置一样,一个ReplicationController需要apiVersion
和kind
以及metadata
字段,同样副本集控制器也需要.spec
进行规范指定:
1.Pod模板(Pod Template)
.spec.template
是.spec
唯一必需的字段,几乎和Pod的模式一样,除了它是嵌套的、没有apiVersion
和kind
。除此之外,ReplicationController必须指定合适的标签label(注意不要和其他控制器重叠)和重启策略(.spec.template.spec.restartPolicy
应该设为Always
,如果不指定这也是默认值)。
2.ReplicationController上的标签
副本控制器可以有自己的标签(.metadata.labels
),通常是将其设置为和.spec.template.metadata.labels
一样的值,如果.metadata.labels
没有指定,它默认会设置为.spec.template.metadata.labels
一样的值。当然它们的值也可以设置为不同,.metadata.labels
并不会影响ReplicationController的行为。
3.Pod选择器
.spec.selector
字段是标签选择器,一个ReplicationController将会管理所有带有和它标签选择器相匹配标签的Pod,它不区分它创建或删除的pods和另一个人或进程创建或删除的pods。这就允许ReplicationController可以在不影响运行的Pod的前提下进行替换。如果指定.spec.template.metadata.labels
,那它必须只能指定为.spec.selector
的值。如果.spec.selector
没有指定,那默认就是.spec.template.metadata.labels
的值。正常情况下,不应该创建任何带有和选择器相匹配标签的Pod,因为ReplicationController会认为它创建了其他的Pod。
4.多个副本
可以通过.spec.replicas
指定并行运行Pod的数量(默认为1)。运行时的副本数量可能忽高忽低,因为副本可能被增加、删除、替换的Pod提前被创建
【ReplicationController的行为】
1.删除ReplicationController和它所有的Pod
kubectl将会将ReplicationController规模缩减为0,然后在删除ReplicationController本身前删除每个Pod,如果kubectl命令被打断,它将会重启。在使用REST API操作时,需要明确按照上述的步骤执行(将副本缩减为0–>等待pod删除完成–>删除ReplicationController)。
2.仅仅删除ReplicationController
也可以在不影响任何Pod的情况下仅仅删除ReplicationController,需要在kubectl delete
时指定--cascade=false
,删除控制器后可以使用新的控制器替换,只要两者的.spec.selector
相同即可,新的ReplicationController将会接管之前控制器的Pod,但不会尝试去使用新的Pod模板创建已经存在的Pod,如果想升级老规范的Pod到新规范的Pod,需要使用rolling update。
【将Pod从ReplicationController中脱离】
只需要改变Pod的标签即可。
【常见使用模式】
- 重新调度Rescheduling;
- 规模伸缩:更新
replicas
字段即可; - 滚动升级(Rolling updates):ReplicationController被设计为通过挨个替换Pod的方式促进rolling update(可能名字也是由此而来)。推荐的方式是创建一个新的ReplicationController替换原来的控制器,并将它的副本数量设置为1,然后每次增加一个新的控制器、删除一个旧的控制器,然后在缩减到只有0个副本时直接删除旧的控制器,这可以预见性的更新pods副本集,而不考虑意外的失败。滚动更新控制器理论上可以确保在任何时刻都有足够数量的pod有效地提供服务。
- 多发布模式(Multiple release tracks):为了在滚动升级的进程中同时运行APP的多个版本,通常情况下,使用多个发布版本跟踪,长时间运行多个版本,甚至连续运行。比如一个Service的目标是
tier in (frontend), environment in (prod)
,现在满足这个条件的有10个,但想要某个组件的金丝雀(canary)版本,那可以搞个控制器:先将ReplicationController的replicas
设置为9,选择器为tier=frontend, environment=prod, track=stable
,再为金丝雀版本搞一个ReplicationController将replicas
设置为1,选择器为tier=frontend, environment=prod, track=canary
。 - 在Service中使用ReplicationController,一个Service中可以有多个ReplicationController,比如4中提到的场景。ReplicationController永远不会自行终止,一般和Service共死。Service可以由多个ReplicationController控制的Pod组成