前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【重识云原生】第六章容器6.4.3节——ReplicationController

【重识云原生】第六章容器6.4.3节——ReplicationController

作者头像
江中散人_Jun
发布2022-10-04 20:00:26
8570
发布2022-10-04 20:00:26
举报

1 ReplicationController简介

1.1 Replication Controller简介

        Replication Controller简称RC,它能够保证Pod持续运行,并且在任何时候都有指定数量的Pod副本,在此基础上提供一些高级特性,其主要的功能如下:

  • 确保pod数量:它会确保Kubernetes中有指定数量的Pod在运行。如果少于指定数量的pod,Replication Controller会创建新的,反之则会删除掉多余的以保证Pod数量不变。
  • 确保pod健康:当pod不健康,运行出错或者无法提供服务时,Replication Controller也会杀死不健康的pod,重新创建新的。
  • 弹性伸缩 :在业务高峰或者低峰期的时候,可以通过Replication Controller动态的调整pod的数量来提高资源的利用率。同时,配置相应的
  • 监控功能(Hroizontal Pod Autoscaler),会定时自动从监控平台获取Replication Controller关联pod的整体资源使用情况,做到自动伸缩。
  • 滚动升级:滚动升级为一种平滑的升级方式,通过逐步替换的策略,保证整体系统的稳定,在初始化升级的时候就可以及时发现和解决问题,避免问题不断扩大。

        它在k8s中的架构如图:

        RC会在每个节点上创建Pod,Pod上如果有相应的Images可以直接创建,如果没有,则会拉取这个镜像再进行创建。

1.2 ReplicationController作用说明

        ReplicationController是一种Kubernetes资源对象,也是一类控制器,可确保它的pod始终保持运行状态。如果pod因任何原因消失(例如节点从集群中消失或由于该pod已从节点中逐出),则ReplicationController会注意到缺少了pod并创建替代pod。

        下图显示了当一个节点下线且带有两个pod时会发生什么。pod A是被直接创建的,因此是非托管的pod,而pod B由ReplicationController管理。节点异常退出后,ReplicationController会创建一个新的pod(pod B2)来替换缺少的pod B,而pod A完全丢失 —— 没有东西负责重建它。

        图中的ReplicationController只管理一个pod,但一般而言,ReplicationController旨在创建和管理一个pod的多个副本(replicas)。这就是ReplicationController名字的由来。

        节点故障时,只有ReplicationController管理的pod被重新创建。

1.3 ReplicationController工作原理解析

        ReplicationController会持续监控正在运行的pod列表,并保证相应“类型”的pod的数目与期望相符。如正在运行的pod太少,它会根据pod模板创建新的副本。如正在运行的pod太多,它将删除多余的副本。你可能会对有多余的副本感到奇怪。这可能有几个原因:

  • 有人会手动创建相同类型的pod。
  • 有人更改现有的pod的“类型”(标签?)。
  • 有人减少了所需的pod的数量,等等。

1.3.1 控制器的协调流程

        ReplicationController的工作是确保pod的数量始终与其标签选择器匹配。如果不匹配,则ReplicationController将根据所需,采取适当的操作来协调pod的数量。下图显示了ReplicationController的操作。

一个ReplicationController的协调流程

1.3.2 ReplicationController的三部分

        一个ReplicationController有三个主要部分(如下图所示):

  • label selector(标签选择器),对应spec.selector属性,用于确定ReplicationController作用域中有哪些pod;
  • replica count(副本个数),对应spec.replicas属性,指定应运行的pod数量;
  • pod template(pod模板),对应spec.template属性,用于创建新的pod副本;

ReplicationController的三个关键部分(pod选择器、副本个数和pod模板)

        ReplicationController的副本个数、标签选择器,甚至是pod模板都可以随时修改,但只有副本数目的变更会影响现有的pod。

1.3.3 更改控制器的标签选择器或pod模板的效果

        更改标签选择器和pod模板对现有pod没有影响。更改标签选择器会使现有的pod脱离ReplicationController的范围,因此控制器会停止关注它们。在创建pod后,ReplicationController也不关心其pod的实际“内容”(容器镜像、环境变量及其他)。因此,该模板仅影响由此ReplicationController创建的新pod。可以将其视为创建新pod的曲奇切模(cookie cutter)。

1.3.4 使用ReplicationController的好处

        像Kubernetes中的许多事物一样,ReplicationController尽管是一个令人难以置信的简单概念,却提供或启用了以下强大功能:

  • 确保一个pod(或多个pod副本)持续运行,方法是在现有pod丢失时启动一个新pod。
  • 集群节点发生故障时,它将为故障节点上运行的所有pod(即受ReplicationController控制的节点上的那些pod)创建替代副本。
  • 它能轻松实现pod的水平伸缩 —— 手动和自动都可以(参见第15章中的pod的水平自动伸缩)。

注意:pod实例永远不会重新安置到另一个节点。相反,ReplicationController会创建一个全新的pod实例,它与正在替换的实例无关。

2 RC常用管理

2.1 创建一个ReplicationController

        让我们了解一下如何创建一个ReplicationController,然后看看它如何让你的pod运行。就像pod和其他Kubernetes资源,可以通过上传JSON或YAML描述文件到Kubernetes API服务器来创建ReplicationController。

        你将为你的ReplicationController创建名为kubia-rc.yaml的YAML文件,如下面的代码清单所示。

代码清单2.1 ReplicationController的YAML定义:kubia-rc.yaml

        上传文件到API服务器时,Kubernetes会创建一个名为kubia的新ReplicationController,它确保符合标签选择器app=kubia的pod实例始终是三个。当没有足够的pod时,根据提供的pod模板创建新的pod。模板的内容与前一章中创建的pod定义几乎相同。

        模板中的pod标签显然必须和ReplicationController的标签选择器匹配,否则控制器将无休止地创建新的容器。因为启动新pod不会使实际的副本数量接近期望的副本数量。为了防止出现这种情况,API服务会校验ReplicationController的定义,不会接收错误配置。

        根本不指定选择器也是一种选择。在这种情况下,它会自动根据pod模板中的标签自动配置。

        提示 定义ReplicationController时不要指定pod选择器,让Kubernetes从pod模板中提取它。这样YAML更简短。

        要创建ReplicationController,请使用已知的kubectl create命令:

代码语言:javascript
复制
$ kubectl create -f kubia-rc.yaml

        一旦创建了ReplicationController,它就开始工作。让我们看看它都会做什么。

2.2 使用ReplicationController

        由于没有任何pod有app=kubia标签,ReplicationController会根据pod模板启动三个新的pod。列出pod以查看ReplicationController是否完成了它应该做的事情:

代码语言:javascript
复制
$ kubectl get pods

        它确实创建了三个pod。现在ReplicationController正在管理这三个pod。接下来,你将通过稍稍破坏它们来观察ReplicationController如何响应。

2.2.1 查看ReplicationController对已删除的pod的响应

        首先,你将手动删除其中一个pod,以查看ReplicationController如何立即启动新容器,从而将匹配容器的数量恢复为三:

代码语言:javascript
复制
$ kubectl delete pod kubia-53thy

        重新列出pod会显示四个,因为你删除的pod已终止,并且已创建一个新的pod:

代码语言:javascript
复制
$ kubectl get pods

        ReplicationController再次完成了它的工作。这是非常有用的。

2.2.2 获取有关ReplicationController的信息

        通过kubectl get命令显示的关于ReplicationController的信息:

代码语言:javascript
复制
$ kubectl get rc

注意:使用rc作为replicationcontroller的简写。

        你会看到三列显示了所需的pod数量,实际的pod数量,以及其中有多少pod已准备就绪(当我们在下一章谈论准备就绪探针时,你将了解这些含义)。可以通过kubectl describe命令看到ReplicationController的附加信息。

代码清单2.2 显示使用kubectl describe的ReplicationController的详细信息

代码语言:javascript
复制
# kubectl describe rc kubia-rc 
Name: kubia-rc 
Namespace: test 
Selector: app=kubia 
Labels: app=kubia 
Annotations: <none> 
Replicas: 3 current / 3 desired Pods 
Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed Pod 
Template: 
  Labels: app=kubia 
  Containers: 
    kubia: 
      Image: luksa/kubia 
      Port: 8080/TCP 
      Host Port: 0/TCP 
  Environment: <none> 
  Mounts: <none> 
  Volumes: <none> 
  Events: Type Reason Age From Message 
---- ------ ---- ---- ------- 
Normal SuccessfulCreate 6m24s 
replication-controller Created pod: kubia-rc-hvx2m Normal SuccessfulCreate 6m24s replication-controller Created pod: kubia-rc-6zkpd Normal SuccessfulCreate 6m24s replication-controller Created pod: kubia-rc-x97fm Normal SuccessfulCreate 3m56s replication-controller Created pod: kubia-rc-kkpzv

        当前的副本数与所需的数量相符,因为控制器已经创建了一个新的pod。它显示了四个正在运行的pod,因为被终止的pod仍在运行中,尽管它并未计入当前的副本个数中。底部的事件列表显示了ReplicationController的行为—— 它到目前为止创建了四个pod。

2.3 控制器如何创建新的pod

        控制器通过创建一个新的替代pod来响应pod的删除操作(见下图)。从技术上讲,它并没有对删除本身做出反应,而是针对由此产生的状态 —— pod数量不足。

        虽然ReplicationController会立即收到删除pod的通知(API服务器允许客户端监听资源和资源列表的更改),但这不是它创建替代pod的原因。该通知会触发控制器检查实际的pod数量并采取适当的措施。

        如果一个pod消失,ReplicationController将发现pod数目更少并创建一个新的替代pod。

2.4 应对节点故障

        看着ReplicationController对手动删除pod做出响应没什么意思,所以我们来看一个更好的示例。如果使用Google Kubernetes Engine来运行这些示例,那么已经有一个三节点Kubernetes集群。你将从网络中断开其中一个节点来模拟节点故障。

注意:如果使用Minikube,则无法做这个练习,因为只有一个节点同时充当主节点和工作节点。

        如果节点在没有Kubernetes的场景中发生故障,运维人员需要手动将节点上运行的应用程序迁移到其他机器。而现在,Kubernetes会自动执行此操作。在ReplicationController检测到它的pod已关闭后不久,它将启动新的pod以替换它们。

        让我们在实践中看看这个行为。需要使用gcloud compute ssh命令ssh进入其中一个节点,然后使用sudo ifconfig eth0 down关闭其网络接口,如下面的代码清单所示。

注意:通过使用-o wide选项列出pod,选择至少运行一个pod的节点。

代码清单2.3 通过关闭网络接口来模拟节点故障

代码语言:javascript
复制
$ gcloud compute ssh gke-kubia-default-pool-b46381f1-xwko

        当你关闭网络接口时,ssh会话将停止响应,所以需要打开另一个终端或强行退出ssh会话。在新终端中,可以列出节点以查看Kubernetes是否检测到节点下线。这需要一分钟左右的时间。然后,该节点的状态显示为NotReady:

代码语言:javascript
复制
$ kubectl get node

        如果你现在列出pod,那么你仍然会看到三个与之前相同的pod,因为Kubernetes在重新调度pod之前会等待一段时间(如果节点因临时网络故障或Kubelet重新启动而无法访问)。如果节点在几分钟内无法访问,则调度到该节点的pod的状态将变为Unknown。此时,ReplicationController将立即启动一个新的pod。可以通过再次列出pod来看到这一点:

注意:pod的存活时间,你会发现kubia-dmdck pod是新的。你再次拥有三个运行的pod实例,这意味着ReplicationController再次开始它的工作,将系统的实际状态置于所需状态。

        如果一个节点不可用(发生故障或无法访问),会发生同样的情况。立即进行人为干预就没有必要了。系统会自我修复。要恢复节点,需要使用以下命令重置它:

代码语言:javascript
复制
$ gcloud compute instances reset gke-kubia-default-pool-b46381f1-xwko

        当节点再次启动时,其状态应该返回到Ready,并且状态为Unknown的pod将被删除。

2.5 将pod移入或移出ReplicationController的作用域

        由ReplicationController创建的pod并不是绑定到ReplicationController。在任何时刻,ReplicationController管理与标签选择器匹配的pod。通过更改pod的标签,可以将它从ReplicationController的作用域中添加或删除。它甚至可以从一个ReplicationController移动到另一个。

提示:尽管一个pod没有绑定到一个ReplicationController,但该pod在metadata.ownerReferences字段中引用它,可以轻松使用它来找到一个pod属于哪个ReplicationController。

        如果你更改了一个pod的标签,使它不再与ReplicationController的标签选择器相匹配,那么该pod就变得和其他手动创建的pod一样了。它不再被任何东西管理。如果运行该节点的pod异常终止,它显然不会被重新调度。但请记住,当你更改pod的标签时,ReplicationController发现一个pod丢失了,并启动一个新的pod替换它。

        让我们通过你的pod试试看。由于你的ReplicationController管理具有app=kubia标签的pod,因此需要删除这个标签或修改其值以将该pod移出ReplicationController的管理范围。添加另一个标签并没有用,因为ReplicationController不关心该pod是否有任何附加标签,它只关心该pod是否具有标签选择器中引用的所有标签。

1. 给ReplicationController管理的pod加标签

        需要确认的是,如果你向ReplicationController管理的pod添加其他标签,它并不关心:

代码语言:javascript
复制
$ kubectl label pod kubia-dmdck type=special $ kubectl get pods --show-labels

        给其中一个pod添加了type=special标签,再次列出所有pod会显示和以前一样的三个pod。因为从ReplicationController角度而言,没发生任何更改。

2. 更改已托管的pod的标签

        现在,更改app=kubia标签。这将使该pod不再与ReplicationController的标签选择器相匹配,只剩下两个匹配的pod。因此,ReplicationController会启动一个新的pod,将数目恢复为三:

代码语言:javascript
复制
$ kubectl label pod kubia-dmdck app=foo --overwrite

        --overwrite参数是必要的,否则kubectl将只打印出警告,并不会更改标签。这样是为了防止你想要添加新标签时无意中更改现有标签的值。再次列出所有pod时会显示四个pod:

注意:使用-L app选项在列中显示app标签。

        你现在有四个pod:一个不是由你的ReplicationController管理的,其他三个是。其中包括新建的pod。

        下图说明了当你更改pod的标签,使得它们不再与ReplicationController的pod选择器匹配时,发生的事情。可以看到三个pod和ReplicationController。在将pod的标签从app=kubia更改为app=foo之后,ReplicationController就不管这个pod了。由于控制器的副本个数设置为3,并且只有两个pod与标签选择器匹配,所以ReplicationController启动kubia-2qneh pod,使总数回到了三。kubiadmdck pod现在是完全独立的,并且会一直运行直到你手动删除它(现在可以这样做,因为你不再需要它)。

通过更改标签从ReplicationController的作用域中删除一个pod

3. 从控制器删除pod

        当你想操作特定的pod时,从ReplicationController管理范围中移除pod的操作很管用。例如,你可能有一个bug导致你的pod在特定时间或特定事件后开始出问题。如果你知道某个pod发生了故障,就可以将它从Replication-Controller的管理范围中移除,让控制器将它替换为新pod,接着这个pod就任你处置了。完成后删除该pod即可。

4. 更改ReplicationController的标签选择器

        这里有个练习,看看你是否完全理解了ReplicationController:如果不是更改某个pod的标签而是修改了ReplicationController的标签选择器,你认为会发生什么?

        如果你的答案是“它会让所有的pod脱离ReplicationController的管理,导致它创建三个新的pod”,那么恭喜你,答对了。这表明你了解了ReplicationController的工作方式。Kubernetes确实允许你更改ReplicationController的标签选择器,但这不适用于本章后面介绍的其他资源(也是用来管理pod的)。

        你永远不会修改控制器的标签选择器,但你会时不时会更改它的pod模板。就让我们来了解一下吧。

2.6 修改pod模板

        ReplicationController的pod模板可以随时修改。更改pod模板就像用一个曲奇刀替换另一个。它只会影响你之后切出的曲奇,并且不会影响你已经剪切的曲奇(见下图)。要修改旧的pod,你需要删除它们,并让ReplicationController根据新模板将其替换为新的pod。

更改ReplicationController的pod模板只影响之后创建的pod,并且不会影响现有的pod

        可以试着编辑ReplicationController并向pod模板添加标签。使用以下命令编辑ReplicationController:

代码语言:javascript
复制
$ kubectl edit rc kubia

        这将在你的默认文本编辑器中打开ReplicationController的YAML配置。找到pod模板部分并向元数据添加一个新的标签。保存更改并退出编辑器后,kubectl将更新ReplicationController并打印以下消息:

代码语言:javascript
复制
replicationcontroller "kubia" edited

        现在可以再次列出pod及其标签,并确认它们未发生变化。但是如果你删除了这个pod并等待其替代pod创建,你会看到新的标签。

        像这样编辑一个ReplicationController,来更改容器模板中的容器图像,删除现有的容器,并让它们替换为新模板中的新容器,可以用于升级pod,但你将在第9章学到更好的方法。

        配置kubectl edit使用不同的文本编辑器

        可以通过设置KUBE_EDITOR环境变量来告诉kubectl使用你期望的文本编辑器。例如,如果你想使用nano编辑Kubernetes资源,请执行以下命令(或将其放入~/.bashrc或等效文件中):

代码语言:javascript
复制
export KUBE_EDITOR="/usr/bin/nano"

        如果未设置KUBE_EDITOR环境变量,则kubectl edit会回退到使用默认编辑器(通常通过EDITOR环境变量进行配置)。

2.7 水平缩放pod

        你已经看到了ReplicationController如何确保持续运行的pod实例数量保持不变。因为改变副本的所需数量非常简单,所以这也意味着水平缩放pod很简单。

        放大或者缩小pod的数量规模就和在ReplicationController资源中更改Replicas字段的值一样简单。更改之后,ReplicationController将会看到存在太多的pod并删除其中的一部分(缩容时),或者看到它们数目太少并创建pod(扩容时)。

2.7.1 命令行方式实现Pod扩容

        ReplicationController一直保持三个pod实例在运行的状态。现在要把这个数字提高到10。你可能还记得,已经在第2章中扩容了ReplicationController。可以使用和之前相同的命令:

代码语言:javascript
复制
$ kubectl scale rc kubia --replicas=10

2.7.2 通过编辑定义文件实现缩放Pod

        不使用kubectl scale命令,而是通过以声明的形式编辑ReplicationController的定义对其进行缩放:

代码语言:javascript
复制
$ kubectl edit rc kubia

        当文本编辑器打开时,找到spec.replicas字段并将其值更改为10,如下面的代码清单所示。

代码清单2.4 运行kubectl edit在文本编辑器中编辑RC

        保存该文件并关闭编辑器,ReplicationController会更新并立即将pod的数量增加到10:

代码语言:javascript
复制
$ kubectl get rc

        就是这样。如果 kubectl scale 命令看起来好像是你在告诉Kubernetes要做什么,现在就更清晰了,你是在声明对ReplicationController的目标状态的更改,而不是告诉Kubernetes它要做的事情。

2.7.3 用kubectl scale命令缩容

        现在将副本数目减小到3。可以使用 kubectl scale 命令:

代码语言:javascript
复制
$ kubectl scale rc kubia --replicas=3

        所有这些命令都会修改ReplicationController定义的spec.replicas字段,就像通过 kubectl edit 进行更改一样。

2.7.4 伸缩集群的声明式方法

        在Kubernetes中水平伸缩pod是陈述式的:“我想要运行x个实例。”你不是告诉Kubernetes做什么或如何去做,只是指定了期望的状态。

        这种声明式的方法使得与Kubernetes集群的交互变得容易。设想一下,如果你必须手动确定当前运行的实例数量,然后明确告诉Kubernetes需要再多运行多少个实例的话,工作更多且更容易出错,改变一个简单的数字要容易得多。在第15章中,你会发现如果启用pod水平自动缩放,那么即使是Kubernetes本身也可以完成。

2.8 删除一个ReplicationController

        当你通过 kubectl delete 删除ReplicationController时,pod也会被删除。但是由于由ReplicationController创建的pod不是ReplicationController的组成部分,只是由其进行管理,因此可以只删除ReplicationController并保持pod运行,如下图所示。

        当你最初拥有一组由ReplicationController管理的pod,然后决定用ReplicaSet( 你接下来会知道)替换ReplicationController时,这就很有用。可以在不影响pod的情况下执行此操作,并在替换管理它们的ReplicationController时保持pod不中断运行。

使用--cascade=false删除ReplicationController使托架不受管理

        当使用kubectl delete删除ReplicationController时,可以通过给命令增加--cascade=false选项来保持pod的运行。马上试试看:

代码语言:javascript
复制
$ kubectl delete rc kubia --cascade=false

        你已经删除了ReplicationController,所以这些pod独立了,它们不再被管理。但是你始终可以使用适当的标签选择器创建新的ReplicationController,并再次将它们管理起来。

参考链接

replication controller_fightingwy的博客-CSDN博客

Kubernetes核心概念之Replication Controller详解_linux运维技术的技术博客_51CTO博客

ReplicationController

如何理解ReplicationController及其配置 - 云计算 - 亿速云

kubernetes概念之四:Replication Controller&Replica Sets&Deployments_ITPUB博客

4.2 了解ReplicationController - 知乎

K8s控制器ReplicationController(RC)_bjgaocp的博客-CSDN博客

k8s入门-Replication Controller控制器_wc1695040842的博客-CSDN博客

3.2 控制器——副本控制器(ReplicationController)_jacksonary的博客-CSDN博客_replicationcontroller

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-09-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 ReplicationController简介
    • 1.1 Replication Controller简介
      • 1.2 ReplicationController作用说明
        • 1.3 ReplicationController工作原理解析
          • 1.3.1 控制器的协调流程
          • 1.3.2 ReplicationController的三部分
          • 1.3.3 更改控制器的标签选择器或pod模板的效果
          • 1.3.4 使用ReplicationController的好处
      • 2 RC常用管理
        • 2.1 创建一个ReplicationController
          • 2.2 使用ReplicationController
            • 2.2.1 查看ReplicationController对已删除的pod的响应
            • 2.2.2 获取有关ReplicationController的信息
          • 2.3 控制器如何创建新的pod
            • 2.4 应对节点故障
              • 2.5 将pod移入或移出ReplicationController的作用域
                • 2.6 修改pod模板
                  • 2.7 水平缩放pod
                    • 2.7.1 命令行方式实现Pod扩容
                    • 2.7.2 通过编辑定义文件实现缩放Pod
                    • 2.7.3 用kubectl scale命令缩容
                    • 2.7.4 伸缩集群的声明式方法
                  • 2.8 删除一个ReplicationController
                  • 参考链接
                  相关产品与服务
                  容器服务
                  腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档