kubernetes 之Replication Controller

原创
半兽人 发表于: 2018-11-20   最后更新时间: 2022-08-05 18:46:39  
{{totalSubscript}} 订阅, 12,173 游览

Replication Controller(简称RC)是Kubernetes系统中的核心概念之一,简单来说,它其实是定义了一个期望的场景,即声明某种Pod的副本数量在任意时刻都符合某个预期值,所以RC的定义包括如下几个部分。

  • Pod期待的副本数(replicas)。
  • 用于筛选目标Pod的Label Selector。
  • 当Pod的副本数量小于预期数量时,用于创建新Pod的Pod模版(template)。

下面是一个完整的RC定义的例子,即确保拥有tier=frontend标签的这个Pod(运行Tomcat容器)在整个Kubernetes集群中始终只有一个副本:

apiVersion: v1
kind: ReplicationController
metadata:
  name: frontend
spec:
  replicas: 1
  selector:
    tier: frontend
  template:
    metadata:
      labels:
        app: app-demo
        tier: frontend
    spec:
      containers:
       - name: tomcat-demo
         image: tomcat
         imagePullPolicy: IfNotPresent
         env:
         - name: GET_HOSTS_FROM
           value: dns
         ports:
         - containerPort: 80

当我们定义了一个RC并提交到Kubernetes集群中以后,Master节点上的Controller Manager组件就得到通知,定期巡检系统中当前存活的目标Pod,并确保目标Pod实例的数量刚好等于此RC的期望值,如果有过多的Pod副本在运行,系统就会停掉一些Pod,否则系统就会再自动创建一些Pod。可以说,通过RC,Kubernetes实现了用户应用集群的高可用性,并且大大减少了系统管理员在传统IT环境中需要完成的许多手工运维工作(如主机监控脚本、应用监控脚本、故障恢复脚本等)。

下面我们以3个Node节点的集群为例,说明Kubernetes如何通过RC来实现Pod副本数量自动控制的机制。假如我们的RC里定义redis-slave这个Pod需要保持2个副本,系统将可能在其中的两个Node上创建Pod。下图描述了在两个Node上创建redis-slave Pod的情形。

假设Node2上的Pod2意外终止,根据RC定义的replicas数量2,Kubernetes将会自动创建并启动一个新的Pod,以保住整个集群中始终有两个redis-slave Pod在运行。

如图所示,系统可能选择Node3或者Node1来创建一个新的Pod。

此外,在运行时,我们可以通过修改RC的副本数量,来实现Pod的动态缩放(Scaling)功能,还可以通过执行kubectl scale命令来一键完成:

$kubectl scale rc redis-slave --replicas=3
scaled

Scaling的执行结果如图所示。

需要注意的是,删除RC并不会影响通过该RC已创建好的Pod。为了删除所有Pod,可以设置replicas的值为0,然后更新该RC。另外,kubectl提供了stop和delete命令来一次性删除RC和RC控制的全部Pod。

当我们的应用升级时,通常会通过构建一个新的Docker镜像,并用新的镜像版本来替代旧的版本的方式达到目的,在系统升级的过程中,我们希望是平滑的方式,比如当前系统中10个对应的旧版本的Pod,最佳的方式是旧版本的Pod每次停止一个,同时创建一个新版本的Pod,在整个升级过程中,此消彼长,而运行中的Pod数量始终是10个,几分钟以后,当所有的Pod都已经是最新版本时,升级过程完成。通过RC的机制,Kubernetes很容易就实现了这种高级实用的特性,被称为滚动升级(Rolling Update)

由于Replication Controller与Kubernetes代码中的模块Replication Controller同名,同时这个词也无法准确表达它的本意,所以在Kubernetes v1.2时,它就升级成了另外一个新的概念 -- Replica Set,官方解释为“下一代的RC”,它与RC当前存在的唯一区别是:Replica Sets支持基于集合的Label selector(Set-based selector),而RC只支持基于等式的Label Selector(equality-based selector),这使得Replica Set的功能更强,下面是等价于之前RC例子的Replica Set的定义(省去了Pod模版部分的内容):

apiVersion: extensions/v1beta1
kind: ReplicaSet
metadataname: frontend
spec:
  selector:
    matchLabels:
      tier: frontend
    matchExpression:
      - {key: tier, operator: In, values: [frontend]}
  template:
  .......

kubectl命令工具适用于RC的绝大部分命令都同样适用于Replica Set。此外,当前我们很少单独使用Replica Set,它主要被Deployment这个更高层的资源对象所使用,从而形成一整套Pod创建、删除、更新的编排机制。当我们使用Deployment时,无须关心它是如何创建和维护Replica Set的,这一切都是自动发生的。

Replica Set与Deployment这两个重要资源对象逐步替换了之前的RC的作用,是Kubernetes v1.3里Pod自动扩容(伸缩)这个告警功能实现的基础,也将继续在Kubernetes未来的版本中发挥重要的作用。

最后我们总结一下关于RC(Replica Set)的一些特性与作用。

  • 在大多数情况下,我们通过定义一个RC实现Pod的创建过程及副本数量的自动控制。
  • RC里包括完整的Pod定义模版。
  • RC通过Label Selector机制实现对Pod副本的自动控制。
  • 通过改变RC里的Pod副本数量,可以实现Pod的扩容或缩容功能。
  • 通过改变RC里的Pod模版中的镜像版本,可以实现Pod的滚动升级功能。
更新于 2022-08-05

勿妄 2年前

以三个node节点为例中,假如我们的RC里定义redis-slave这个Pod需要保持3个副本的3应该是2吧

半兽人 -> 勿妄 2年前

是的,感谢,已更正。

Demo 2年前
 spec:
      containers:
       - name: tomcat-demo
         image: tomcat
         **ports:**
         imagePullPolicy: IfNotPresent
         env:
         - name: GET_HOSTS_FROM
           value: dns
         **ports:**
         - containerPort: 80

这里是该两个ports吗

半兽人 -> Demo 2年前

不该,感谢提醒。

骉騳马 2年前

小白请教:yaml中的apiVersion有固定值的吗,如果有的话这个值应该从哪里知道

半兽人 -> 骉騳马 2年前

可以通过

kubectl api-resources

查看对应版本。

我叫不生气 3年前

那个yaml示例文件有点问题,template不应该是spec.template这个字段吗,下面的对齐都有问题

感谢提醒,已更正,我之前是复制kubebiz的,可能在复制的时候格式错乱了。

感谢大佬百忙之中回复,文章梳理的很清晰,小弟初出茅庐,赐教了

多多交流,有任何问题随时留言

kind: ReplicationController,这个kind的值可以随便写吗?还是说只能是ReplicationController、Service和Pod中的其中一个?

kind是每个资源的类型,不能随便写的。

查看kubernetes更多相关的文章或提一个关于kubernetes的问题,也可以与我们一起分享文章