ReplicationController

ReplicationController顾名思义,可以用来创建Pod的多副本,并且被该Controller接管的Pod,当Node出现故障时,该Pod会随之挂掉,此时ReplicationController会检测到,并且重新调度到新的Node上创建。

ReplicationController的工作时确保Pod的数量始终与其标签选择器匹配,若不匹配,则其会根据所需,调整Pod的数量。

ReplicationController对于Pod数量的协调方式

从上面图可以看出,ReplicationController是根据Pod的标签进行匹配的,会根据标签决定当前被接管的Pod的数量。

Tips:ReplicationController的标签选择器,只能够匹配一个或多个包含特定标签的Pod,例如只匹配带有env=develenv=production的Pod(这两个标签的键都是env),而不能同时匹配env=develenv=production的Pod。这也是为什么现在被ReplicaSet取代的原因。

创建ReplicationController

使用YAML配置文件创建该资源,在该资源文件中,需要关注的主要有以下三个部分:

  • spec.replicas:Pod实例的副本数;

  • spec.selector:标签选择器,决定匹配的带有哪些标签的Pod。相同键的多组标签只能匹配其中一组,比如有env=testenv=prod,只能匹配其中一组;

  • spec.template:创建新Pod所用的模板;

下面展示一个具体的例子:

apiVersion: v1
kind: ReplicationController
metadata:
  name: kubia
spec:
  replicas: 3    # 副本数,Pod的个数
  selector:    # 标签选择器,用来决定RC管理的Pod(相同键的多组标签只能匹配其中一组)
    app: kubia
    env: test
  template:    # 创建新Pod的模板(为什么说新的,是因为如果RC是根据标签选择Pod的,如果当前已经有app: kubia的4个Pod,那么这个RC不会创建,反而会删掉1个,因为它的副本数是3)
    metadata:
      labels:
        app: kubia    # pod的标签一定要与RC的选择器一致,否则RC将无休止的创建新的容器
    spec:
      containers:
      - name: kubia
        image: luksa/kubia
        ports:
        - containerPort: 8080

通过kubectl get rc可以看到创建出来的RC资源的名字为kubia,再通过kubectl get pods可以看到创建出来的Pods的名字为kubia-xxxx(xxxx为自动生成的值)。

删除ReplicationController

同时删除接管的Pod

直接使用kubectl delete不仅仅会删除RC,同时会删除被其接管的Pod。例如删除名为kubia这个RC:

kubectl delete rc kubia

不删除接管的Pod

加上--cascade=false可以在删除RC的同时,不删除被其接管的Pod。例如删除名为kubia这个RC的同时,不删除被其接管的Pod:

kubectl delete rc kubia --cascase=false

将Pod移入或移出ReplicationController的作用域

由于ReplicationController是通过spec.selector即标签选择器决定接管的Pod的,因此可以通过更改Pod的metadata.labels的方式,将Pod移入或移出ReplicationController的作用域。

修改Pod的标签的方式,可以参考标签章节中的修改Pod标签一节中的方式。

水平缩放

可以通过三种方式更新:

  1. 修改RC的YAML配置文件中的spec.replicas字段:

    • 通过kubectl edit命令在线修改RC的YAML配置文件;

    • 直接修改RC的配置文件,然后通过kubectl apply -f使之生效;

  2. 通过kubectl scale命令修改。例如将kubia这个RC的副本数调整为10:

     kubectl scale rc kubia --replicas=10

水平缩放是声明式的,即告诉Kubernetes目标副本数为x,而不告诉它该如何做,只是指定期望状态。

滚动更新

可以使用kubectl rolling-update命令,令RC进行滚动升级。例如,需要升级的RC为kubia-v1,升级后的RC为kubia-v2,将容器镜像替换为luksa/kubia:v2

kubectl rolling-update kubia-v1 kubia-v2 --image=luksa/kubia:v2

Tips:

  1. 可以使用--help查看可更新的条目;

  2. 可以加上--v 6,提高日志级别,可以使得所有kubectl发起到API服务器的请求都会被输出;

输出结果为:

Command "rolling-update" is deprecated, use "rollout" instead
Created kubia-v2
Scaling up kubia-v2 from 0 to 3, scaling down kubia-v1 from 3 to 0 (keep 3 pods available, don't exceed 4 pods)
Scaling kubia-v2 up to 1
Scaling kubia-v1 down to 2
Scaling kubia-v2 up to 2
Scaling kubia-v1 down to 1
Scaling kubia-v2 up to 3
Scaling kubia-v1 down to 0
Update succeeded. Deleting kubia-v1
replicationcontroller/kubia-v2 rolling updated to "kubia-v2"

从输出可以看到滚动更新过程中,正在运行的Pod数量最大为4个,并且创建了一个新的RCkubia-v2来接管新的Pod,并且通过交替对kubia-v1缩容,对kubia-v2扩容的方式达成滚动升级的功能。在更新完成后,会删除旧的RCkubia-v1。可以用下图表示:

ReplicationController更新过程

从上图中也可以看到,在更新的过程中,rolling-update为区分新旧RC和它们接管的Pod,会为新旧Pod添加上键为deployment的标签,同时为新旧RC添加相应的标签选择器(这也是为什么这种更新方式会被废弃的原因之一)。由于新旧Pod都有app=kubia这个标签,而Service只匹配这个标签,所以在更新的过程中,客户端发起的请求会被无缝切换至新Pod上。

废弃原因

使用kubectl rolling-upgrade进行更新被废弃的原因有三个:

  1. 更新的过程中,会直接修改RC和Pod资源对象:为新旧RC添加新的标签选择器,为新旧Pod添加新的标签;

  2. 新旧RC的扩缩容的请求都是由kubectl客户端发起的,而不是Kubernetes的API服务器,因此若中途产生网络中断,会导致更新过程中断;

    使用--v 6可以看到kubectl的日志信息,从中可以发现针对下面两个路径的访问请求:

     /api/v1/namespaces/default/replicationcontrollers/kubia-v1/scale
     /api/v1/namespaces/default/replicationcontrollers/kubia-v2/scale

    即每次针对新旧RC扩缩容的操作,都是由kubectl向API服务器发起的,类似于平时写的脚本实现的自动化扩缩容。

  3. 需要创建新的RC来负责接管新的Pods;

Last updated

Was this helpful?