Kubernetes工作负载之控制器(2):Replication Controller

注意:建议使用Deployment配置ReplicaSet的方法控制pod副本数。

1. 什么是Replication Controller ?

Replication Controller保证了在所有时间内,都有特定数量的Pod副本在运行:如果太多了,Replication Controller就杀死几个;如果太少了,Replication Controller会新建几个。与直接创建pod不同的是,Replication Controller会替换掉那些删除的或者被终止的pod,不管删除的原因是什么(维护阿,更新啊,Replication Controller都不关心)。

基于这个理由,我们建议:即使只创建一个pod,我们也要使用Replication Controller。Replication Controller就像一个进程管理器,监管着不同node上的多个pod,而不是单单监控一个node上的pod,Replication Controller会委派本地容器来启动一些节点上服务(如kubelet,docker)。

  • Replication Controller只对含有RestartPolicy = Always的Pod的生效

正如我们在pod的生命周期中讨论的,Replication Controller只会对RestartPolicy = Always的Pod的生效(RestartPolicy的默认值就是Always),Replication Controller 不会管理有不同启动策略的pod。

如我们在issue #503讨论的,我们希望在将来别的控制器被加入到Kubernete中来管理一些例如负载阿,测试等相关功能

Replication Controller永远不会自己关闭,但是我们并不希望Replication Controller成为一个长久存在的服务。服务可能会由多个Pod组成,这些Pod又被多个Replication Controller控制着,我们希望Replication Controller会在服务的生命周期中被删除和新建(例如在这些pod中发布一个更新)。对于服务和用户来说,Replication Controller是通过一种无形的方式来维持着服务的状态。

2. ReplicationController工作原理

2.1 template

一个Replication Controller通过模版来创建pod,这个是Replication Controller内置的功能,但是我们计划要把这个功能从Replication Controller中剥离出来。

Pod模版是一个Pod副本的期望状态,它更像是一个制作饼干的模具:一旦从这个模具中出来之后,饼干就和饼干模具没有任何关联。Pod模版的改变和更改对已经存在的pod没有任何影响:在创建pod之后,我们可以直接修改Replication Controller的yaml文件。这对Pod来说非常重要:这样就定制了Pod中所有容器的期望状态。这从根本上简化系统复杂度,增加了灵活性,正如使用实例。

无状态服务

尽管Pod的rc配置文件可能会随着时间变化而不一样,但Replication Controller创建的Pod可以相互替代和保持语义上相同,这非常适合无状态服务。

动态分配机制(高可用,共享,work-pool类应用程序)
Replication Controller也可以被用在保持主从的高可用,共享,work-pool类应用程序,这样的程序应该使用的是动态分配机制,例如etcd的lock module和RabbitMQ队列。相对于静态或一次性定制的Pod配置文件,任何定制化的Pod(例如垂直的自动伸缩资源(cpu,内存)),应该被其它的线上Controller管理,而不是Replication Controller。

2.2 labels

由Replication Controller监控的Pod数量是由label selector(标签选择器)决定的。在Replication Controller和被控制的Pod之间,label selector创建了一个松耦合的关系(Pod与其定义文件的关系密切)。我们不使用固定长度的数组来存储被管理的Pod,因为根据我们的经验,不论是系统还是客户,这样都会增加管理的复杂度。

replication controller需要确认从特定模版创建出来的pod拥有label selector所要求的标签,尽管,它还没有这么作,我们需要通过确认replication controllers的label selectors 没有覆盖设置来确定仅有一个Replication Controller控制所指定的Pod(这段话有点怪)

记住这个:replication controller自己也可以由标签,would generally carry the labels their corresponding pods have in common,但是这些标签并不影响replication controller的行为

Pod会被replication controller删除,如果修改那些pod的标签,这个功能可能会被应用在从服务中删除pod来作测试,数据恢复等。Pod如果是以这种方式被删除的话,那么那个pod会被自动的替换(前提是宗的副本数量未修改)

类似的,删除一个replication controller不会影响它创建的pod,如果向删除那些它那些控制的pod,需要首先拔replcas的值设置为0(注意,用户端工具kubectl 提供了一个命令stop,来删除replication controller以及它控制的pod,但是,这个功能在现在的api中不存在)

3. replication controller的职责

replication controller的任务就是保证预计数量的pod并保证其可用性。目前,只有那些被终止的Pod是从总数量中排除的,在将来,可读性以及其它系统信息可能会被纳入统计,我们可能会增加更多的替代策略,并且我们计划可以执行其它外部程序可以使使用并实现复杂的替换或者策略。

replication controller的任务永远都只会是单一的。它自身不会进行是否可读和是否可用的检测,相比与自动进行缩放和放大,replication controller更倾向与使用外部的自动平衡工具,这些外部工具要作的仅仅是修改replicas的值来实现Pod数量的变化,我们不会增加replication controller的调度策率,也不会让replication controller来验证受控的Pod是否符合特定的模版,因为这些都会阻碍自动调整和其它的自动的进程。类似的,完成时限,需求依赖,配置扩展,等等都属于其它的部分。

replication controller的目的是成为一个原始的积木,我们希望在replication controller上层的api或者工具来为用户提供方便,现在kubectl支持的宏观操作,比如run,stop,scale,rolling-update就是这个概念的例子。举例来说,我们可以想象和“天庭”管理着replication controller,auto-scalers, services, scheduling policies, canaries等等。

4. RC常见的使用方式

4.1 Rescheduling(重新规划)

无论你有1个还是1000个Pod需要运行,Replication Controller会确保指定数量的Pod存在,即使发生节点故障或Pod终止(由于其他控制代理的操作)也是如此。

4.2 Scaling(伸缩)

Replication Controller让我们更容易地控制Pod副本数量,不管是手动修改yaml文件还是通过其它的自动管理的工具,都需要修改replicas值

无论手动修改还是用自动伸缩控制代理,通过更新字段replicas的值,ReplicationController可以轻松地增加或减少Pod副本数量。

4.3 Rolling updates(滚动更新)

Replication Controller支持动态更新。当我们更新一个service时,RC允许我们一个个的替换Pod:推荐的方法是创建一个新的只有1个Pod副本(replicas值为1)的Replication Controller,然后新的RC每次加1,旧的RC每次减1,直到旧RC的replicas值变成0,然后我们删除旧的RC。这样就可以规避升级过程中出现的未知错误。

理论上,动态更新控制器要考虑应用服务的可用性,确保足够数量的Pod提供服务,并在任何时间都能正常访问服务。

两个Replication Controller创建的Pod至少要有一个不同的标签(镜像的tag,因为一般镜像的更新都会带来一个新的镜像tag)。我们需要通过# kubectl rolling-update来实现动态更新。

4.4 Multiple release tracks(多版本发布追踪)

在程序更新过程中,我们可以通过多版本的追踪,让多个版本额外运行一段时间,也可以在一段时间内持续地运行多个版本(新旧共存)(版本追踪是通过label实现)

例如:一个服务可能绑定的Pod是tier in (frontend), environment in (prod)。现在假设由10个Pod副本组成这个tier,现在我们要发布一个新的镜像版本canary(金丝雀)。这时,我们应该创建一个Replication Controller,并且设置replcas值为9,标签为tier=frontend, environment=prod, track=stable;再另外设置一个Replication Controller,设置replacas值为1,标签为tier=frontend, environment=prod, track=canary。

现在,该服务就可以同时使用canary(金丝雀)和非金丝雀版本的Pod了,这时我们可以通过不同的Replication Controller进行一些测试,监控。

4.5 Using ReplicationControllers with Services(使用ReplicationControllers与关联的Services)


5. RC的替代方法

5.1 ReplicaSet

ReplicaSet是支持基于集合的label selector的下一代ReplicationController 。它主要用于Deployment协调pod创建、删除和更新。请注意,除非需要自定义更新编排或根本不需要更新,否则建议使用Deployment而不是直接使用ReplicaSet。

5.2 Deployment(推荐)

Deployment是一个高级的API对象,以类似的方式# kubectl rolling-update,更新其底层的ReplicaSets和RS的Pods。如果你希望使用滚动更新功能,建议使用Deployment进行部署。因为使用# kubectl rolling-update部署Deployment,是声明式的,服务器端的,并具有其他功能。

5.3 Bare Pods(用户直接创建的Pod,不使用控制器)

与用户直接创建Pod的情况不同,ReplicationController会替换由于任何原因而被删除或终止的Pod,例如在节点故障或节点破坏(例如内核升级)的情况下。 出于这个原因,即使您的应用程序只需要一个Pod,我们也建议您使用ReplicationController。 与流程管理器类似,ReplicationController可以监控多个节点上的多个Pod,而不是单个节点上的单个进程。ReplicationController会将本地容器重新启动,再委托给节点上的某个代理(如kubelet或docker)。

5.4 Job

对于预期会自行终止的Pod(即批处理作业),使用Job而不是ReplicationController。

5.5 DaemonSet

对于提供主机级别功能(如主机监控或主机日志记录)的Pod,请使用DaemonSet而不是ReplicationController进行管理。使用DaemonSet管理的Pod寿命与主机生命周期相关:DaemonSet管理的Pod需要在其他Pod启动之前在主机上运行,并且在主机准备好重启/关机时,可以安全终止。

6. 使用实例

此ReplicationController配置运行三个副本的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       # 如果镜像不指定tag,默认是latest
        ports:
        - containerPort: 10001

然后我们运行以下命令,k8s会自动下载所需镜像:

# kubectl create -f replication.yaml

检查ReplicationController的状态

# kubectl describe replicationcontroller/nginx

一段时间过后,k8s创建了三个pod,并显示:3 Running / 0 Waiting / 0 Succeeded / 0 Failed

以机器可读的形式,列出属于ReplicationController的所有Pod

//定义环境变量pods,其值封装了关于pod的查询命令
# pods=$(kubectl get pods --selector=app=nginx --output=jsonpath={.items..metadata.name})                 

# echo $pods            // 输出nginx-cjf74 nginx-ck2cv nginx-vml6q

在这里,上述的selector与ReplicationController的selector相同(在kubectl describe replicationcontrollers/nginx的输出中可以看到;也可在replication.yaml中看到)。--output = jsonpath选项指定一个表达式,它以返回列表的形式,从每个pod中获取名称。

你可能感兴趣的:(K8S)