Kubernetes ReplicaSet和ReplicationController初学者指南
在本Kubernetes教程中,我们将探索ReplicaSet并使用不同的场景和示例将其与ReplicationController进行比较。
复制控制器概述
ReplicationController
是Kubernetes资源,可确保其pod始终保持运行状态。如果Pod由于某种原因而消失,例如在某个节点从集群中消失或者因为Pod被从节点上逐出而导致的消失,则ReplicationController会注意到丢失的Pod并创建一个替换Pod。
通常,
ReplicationController
用于创建和管理Pod的多个副本(副本)使用复制控制器或者副本集创建新Pod时,Node可能没有资源,在这种情况下,它将在另一个可用群集节点上自动创建新Pod
复制控制器如何工作
ReplicationController的工作是确保确切数量的Pod始终与其标签选择器匹配。
如果不是这样,ReplicationController将采取适当的措施以使实际值与所需的数字一致。
以下流程图显示了Replication Controller的操作:
ReplicationController具有三个基本部分:
标签选择器,用于确定ReplicationController范围内的哪些容器
副本数,该数量指定应运行的所需Pod数
Pod模板,在创建新的Pod副本时使用
一个ReplicationController的副本数量,标签选择器甚至是pod模板都可以随时修改,但是只有副本数量的更改会影响现有的pod。
创建复制控制器
为了获得复制控制器的种类和apiVersion,我们将检查api-resources的列表。
[root@controller ~]# kubectl api-resources | grep -iE 'KIND|replication' NAME SHORTNAMES APIGROUP NAMESPACED KIND replicationcontrollers rc true ReplicationController
因此,种类值将为ReplicationController,现在要获取这种apiVersion,我们将使用" kubectlexplain"命令:
[root@controller ~]# kubectl explain ReplicationController | head -n 2 KIND: ReplicationController VERSION: v1
现在,我们具有创建第一个复制控制器所需的" kind"和" apiVersion"值。
与pod和其他Kubernetes资源类似,我们可以通过将JSON或者YAML描述符发布到Kubernetes API服务器来创建ReplicationController。
[root@controller ~]# cat replication-controller.yml apiVersion: v1 kind: ReplicationController metadata: name: myapp-rc labels: app: myapp type: dev spec: replicas: 3 selector: app: myapp template: metadata: name: myapp-pod labels: app: myapp type: dev spec: containers: - name: nginx-container image: nginx
突出显示的部分是创建Pod的模板。
当我们将文件发布到API服务器时,Kubernetes将创建一个名为myapp-rc
的新Replication-Controller,以确保三个pod实例始终与标签选择器app = myapp
匹配。
如果没有足够的AD连播,则会从提供的AD连播模板中创建新的AD连播。
提示:
定义ReplicationController时不要指定pod选择器。
让Kubernetes从pod模板中提取它。
这将使YAML变得更短,更简单。
要创建ReplicationController,请使用kubectl create命令:
[root@controller ~]# kubectl create -f replication-controller.yml replicationcontroller/myapp-rc created
验证Replication Controller的操作
因为不存在带有app = myapp
标签的Pod,所以ReplicationController应该从Pod模板中旋转三个新Pod。
在默认名称空间中列出可用的Pod:
[root@controller ~]# kubectl get pods NAME READY STATUS RESTARTS AGE init-container-example-1 1/1 Running 0 112m myapp-rc-b2jtr 0/1 ContainerCreating 0 5s myapp-rc-c57qm 0/1 ContainerCreating 0 5s myapp-rc-hmj9g 0/1 ContainerCreating 0 5s
如预期的那样,ReplicationController已在默认名称空间中启动了3个Pod,以获取状态和可用复制控制器的列表:
[root@controller ~]# kubectl get rc NAME DESIRED CURRENT READY AGE myapp-rc 3 3 3 71s
这里的rc
是复制控制器的缩写。
为了确保RC将创建新的Pod,我们将删除标签为app = myapp
的现有Pod:
[root@controller ~]# kubectl delete pod myapp-rc-c57qm pod "myapp-rc-c57qm" deleted
如预期的那样,已删除的容器已从可用容器列表中删除,并创建了一个新容器:
[root@controller ~]# kubectl get pods NAME READY STATUS RESTARTS AGE init-container-example-1 1/1 Running 0 113m myapp-rc-2tcgx 1/1 Running 0 15s myapp-rc-b2jtr 1/1 Running 0 52s myapp-rc-hmj9g 1/1 Running 0 52s
要检查各个Pod的状态以及各个Pod正在运行的工作节点,可以将-o wide'与
kubectl get pods`命令配合使用:
[root@controller ~]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES init-container-example-1 1/1 Running 0 122m 10.36.0.2 worker-1.example.com <none> <none> myapp-rc-2tcgx 1/1 Running 0 9m58s 10.36.0.4 worker-1.example.com <none> <none> myapp-rc-b2jtr 1/1 Running 0 10m 10.36.0.3 worker-1.example.com <none> <none> myapp-rc-hmj9g 1/1 Running 0 10m 10.44.0.4 worker-2.example.com <none> <none>
我们可以使用kubectl describe
命令查看有关ReplicationController
的其他信息:
[root@controller ~]# kubectl describe rc myapp-rc Name: myapp-rc Namespace: default Selector: app=myapp Labels: app=myapp type=dev Annotations: <none> Replicas: 3 current/3 desired Pods Status: 3 Running/0 Waiting/0 Succeeded/0 Failed Pod Template: Labels: app=myapp type=dev Containers: nginx-container: Image: nginx Port: <none> Host Port: <none> Environment: <none> Mounts: <none> Volumes: <none> Events: Type Reason Age From Message ---- ------ ---- ---- ------ Normal SuccessfulCreate 91s replication-controller Created pod: myapp-rc-b2jtr Normal SuccessfulCreate 91s replication-controller Created pod: myapp-rc-c57qm Normal SuccessfulCreate 91s replication-controller Created pod: myapp-rc-hmj9g Normal SuccessfulCreate 54s replication-controller Created pod: myapp-rc-2tcgx
底部的事件列表显示了复制控制器执行的操作-到目前为止,它已创建了四个Pod。
更改吊舱模板
可以随时修改ReplicationController的pod模板。
更改吊舱模板只会影响新创建的吊舱,而不会影响处于运行状态的现有吊舱:
作为练习,我将通过编辑容器模板来更新副本的值,并将" replicas"的值更改为4并保存模板。
这将在默认的文本编辑器中打开ReplicationController的YAML定义:
[root@controller ~]# kubectl edit rc myapp-rc replicationcontroller/myapp-rc edited
现在,我们将列出Pod并验证副本数,如我们所见,现在我们有4个使用myapp
标签运行的Pod:
[root@controller ~]# kubectl get pods NAME READY STATUS RESTARTS AGE init-container-example-1 1/1 Running 0 130m myapp-rc-2tcgx 1/1 Running 0 17m myapp-rc-b2jtr 1/1 Running 0 17m myapp-rc-hmj9g 1/1 Running 0 17m myapp-rc-ksx4f 1/1 Running 0 3m7s
我们还可以检查复制控制器的状态,该状态现在显示它允许4个副本:
[root@controller ~]# kubectl get rc NAME DESIRED CURRENT READY AGE myapp-rc 4 4 4 18m
水平缩放吊舱
我们已经了解了ReplicationControllers如何确保一定数量的Pod实例始终处于运行状态。
因为更改所需的副本数非常简单,所以这也意味着水平缩放窗格很简单。
假设我们突然希望应用程序上的负载会增加,那么我们必须部署更多的Pod,直到负载减少为止,在这种情况下,我们可以轻松地扩展Pod的运行时间。
例如,其中我将副本数扩展到6:
[root@controller ~]# kubectl scale rc myapp-rc --replicas=6 replicationcontroller/myapp-rc scaled
然后验证带有" myapp"标签的Pod列表,因此又启动了两个Pod:
[root@controller ~]# kubectl get pods NAME READY STATUS RESTARTS AGE init-container-example-1 1/1 Running 0 132m myapp-rc-2tcgx 1/1 Running 0 19m myapp-rc-b2jtr 1/1 Running 0 20m myapp-rc-hmj9g 1/1 Running 0 20m myapp-rc-ksx4f 1/1 Running 0 5m41s myapp-rc-pvqk2 0/1 ContainerCreating 0 3s myapp-rc-zp972 0/1 ContainerCreating 0 3s
同样,一旦减少了负载,副本也可以按比例缩小,这里我现在将副本的数量减少到3. 此命令所做的只是修改ReplicationController定义的spec.replicas字段,就像我们更改时一样。
通过kubectl edit
。
:
[root@controller ~]# kubectl scale rc myapp-rc --replicas=3 replicationcontroller/myapp-rc scaled
在按比例缩小副本之后,我们可以看到新创建的Pod正在终止:
[root@controller ~]# kubectl get pods NAME READY STATUS RESTARTS AGE init-container-example-1 1/1 Running 0 134m myapp-rc-2tcgx 1/1 Running 0 21m myapp-rc-b2jtr 1/1 Running 0 21m myapp-rc-hmj9g 1/1 Running 0 21m myapp-rc-ksx4f 0/1 Terminating 0 7m13s myapp-rc-pvqk2 0/1 Terminating 0 95s myapp-rc-zp972 0/1 Terminating 0 95s
删除ReplicationController
当我们通过kubectl delete
删除ReplicationController
时,吊舱也会被删除。
但是,由于由ReplicationController
创建的容器不是ReplicationController不可或者缺的一部分,而是仅由其管理,因此我们只能删除ReplicationController并保持容器运行。
当使用kubectl delete删除ReplicationController
时,可以通过将--cascade = false
选项传递给命令来保持其pod运行。
[root@controller ~]# kubectl delete rc myapp-rc --cascade=false replicationcontroller "myapp-rc" deleted
因此,此复制控制器创建的Pod将继续处于运行状态(尽管不再受管理):
[root@controller ~]# kubectl get pods NAME READY STATUS RESTARTS AGE init-container-example-1 1/1 Running 0 136m myapp-rc-2tcgx 1/1 Running 0 23m myapp-rc-b2jtr 1/1 Running 0 24m myapp-rc-hmj9g 1/1 Running 0 24m
使用副本集代替复制控制器
最初," ReplicationControllers"是唯一的Kubernetes组件,用于在节点发生故障时复制Pod并重新计划它们的时间。
后来,引入了类似的资源" ReplicaSet"。
它是新一代的ReplicationController,并且将其完全替换(ReplicationControllers最终将被弃用)。
话虽如此,从现在开始,我们应该始终创建ReplicaSets
而不是ReplicationControllers
。
"它们几乎是相同的",因此使用它们应该没有任何麻烦。
比较ReplicaSet和ReplicationController
ReplicaSet
的行为与ReplicationController
完全一样,但是它具有更具表现力的pod选择器。尽管ReplicationController的标签选择器仅允许包含特定标签的匹配容器,而ReplicaSet的选择器也允许缺少特定标签的匹配容器或者包含特定标签键的容器,无论其值如何。
同样,例如,单个ReplicationController不能同时将标签为" env = production"的吊舱与标签为" env = devel"的吊舱进行匹配。
它只能与带有env = production标签的豆荚或者带有env = devel标签的豆荚匹配。
但是,单个ReplicaSet可以匹配两组Pod,并将它们视为一个组。同样,ReplicationController不能仅基于标签键的存在来匹配Pod,而不管其值如何,而ReplicaSet可以。
例如,ReplicaSet
可以匹配所有包含带有标签的标签的容器,无论其实际值是什么(我们可以将其视为env = *
)。
示例1:使用匹配标签创建副本集
我们将创建一个新的副本集,该副本集现在将映射复制控制器中的孤立吊舱。
但是在此之前,我们需要为副本集设置" KIND"和" apiVersion"值。
[root@controller ~]# kubectl api-resources | grep -iE 'KIND|replica' NAME SHORTNAMES APIGROUP NAMESPACED KIND replicationcontrollers rc true ReplicationController replicasets rs apps true ReplicaSet
现在我们有了KIND
的值,即ReplicaSet
,要得到这种apiVersion
,我们将使用kubectlexplain
:
[root@controller ~]# kubectl explain ReplicaSet | head -n 2 KIND: ReplicaSet VERSION: apps/v1
因此,ReplicaSet的apiVersion将为apps/v1. 我们将使用以下YAML文件来创建ReplicaSet
。
唯一的区别在于选择器,而不是在" selector"属性下直接列出吊舱所需的标签,而是在" selector.matchLabels"下指定了它们。
这是在ReplicaSet
中定义标签选择器的更简单(且表达较少)的方式。
[root@controller ~]# cat replica-set.yml apiVersion: apps/v1 kind: ReplicaSet metadata: name: myapp-replicaset labels: app: myapp type: dev spec: replicas: 3 selector: matchLabels: app: myapp template: metadata: name: myapp-pod labels: app: myapp type: dev spec: containers: - name: nginx-container image: nginx
现在,我们将此副本集应用于标签为" app:myapp"的现有吊舱,以便现在可以通过此副本集管理这些孤立的吊舱:
[root@controller ~]# kubectl apply -f replica-set.yml replicaset.apps/myapp-replicaset created
接下来验证Pod列表:
[root@controller ~]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES myapp-rc-6vjv4 1/1 Running 1 12h 10.36.0.4 worker-1.example.com <none> <none> myapp-rc-9fp5l 1/1 Running 1 12h 10.36.0.3 worker-1.example.com <none> <none> myapp-rc-cwwwh 1/1 Running 1 12h 10.44.0.4 worker-2.example.com <none> <none>
因此,没有创建新的Pod,让我们检查以下任何Pod的详细信息:
[root@controller ~]# kubectl describe pods myapp-rc-6vjv4 Name: myapp-rc-6vjv4 Namespace: default Priority: 0 Node: worker-1.example.com/192.168.43.49 Start Time: Mon, 30 Nov 2017 00:23:57 +0530 Labels: app=myapp type=dev Annotations: <none> Status: Running IP: 10.36.0.4 IPs: IP: 10.36.0.4 Controlled By: ReplicaSet/myapp-replicaset ...
如我们所见,此Pod是"由...控制:ReplicaSet/myapp-replicaset"。
之后,我们可以使用" kubectl get"命令检查" ReplicaSet":
[root@controller ~]# kubectl get rs NAME DESIRED CURRENT READY AGE myapp-replicaset 3 3 3 46s
要获取有关此副本集的更多详细信息,请执行以下操作:
[root@controller ~]# kubectl describe rs myapp-replicaset Name: myapp-replicaset Namespace: default Selector: app=myapp Labels: app=myapp type=dev Annotations: <none> Replicas: 3 current/3 desired Pods Status: 3 Running/0 Waiting/0 Succeeded/0 Failed Pod Template: Labels: app=myapp type=dev Containers: nginx-container: Image: nginx Port: <none> Host Port: <none> Environment: <none> Mounts: <none> Volumes: <none> Events: <none>
示例2:使用匹配表达式创建副本集
与ReplicationControllers相比,ReplicaSets的主要改进是其更具表现力的标签选择器。
我们在第一个ReplicaSet
示例中有意使用了更简单的matchLabels
选择器,以查看ReplicaSets与Replication-Controllers没有什么不同。
现在,我们将重写选择器以使用更强大的matchExpressions属性:
[root@controller ~]# cat replica-set.yml apiVersion: apps/v1 kind: ReplicaSet metadata: name: myapp-replicaset labels: app: myapp type: dev spec: replicas: 3 selector: matchExpressions: - key: app operator: In values: - myapp template: metadata: name: myapp-pod labels: app: myapp type: dev spec: containers: - name: nginx-container image: nginx
其中此"选择器"要求AD连播必须包含带有" app"键的标签,并且标签的值必须为" myapp"。
我们可以将其他表达式添加到选择器。
如示例中所示,每个表达式必须包含一个键,一个"操作符",并可能(取决于操作符)包含一个值列表。
我们会看到四个有效的运算符:
"输入":标签的值必须与指定的值之一匹配。
" NotIn":标签的值不得与任何指定值匹配。
Exists
:窗格必须包含带有指定键的标签(该值并不重要)。
使用此运算符时,我们不应指定值字段。DoesNotExist
:容器不得包含带有指定键的标签。
不得指定values属性。
如果我们指定多个表达式,则所有这些表达式必须取值为true才能使选择器与容器匹配。
如果同时指定matchLabels和matchExpressions,则所有标签都必须匹配,并且所有表达式的求值都必须为true,以使Pod匹配选择器。
我将删除现有的副本集,(我也可以更新现有的副本集,但为了正确演示这一点,我将删除现有的副本集)
[root@controller ~]# kubectl delete rs myapp-replicaset replicaset.apps "myapp-replicaset" deleted
现在,我们将使用新的matchmatchions值创建副本集:
[root@controller ~]# kubectl apply -f replica-set.yml replicaset.apps/myapp-replicaset created
验证Pod列表(此副本集未创建新Pod,因为我们已经运行了带有所需标签的Pod):
[root@controller ~]# kubectl get pods NAME READY STATUS RESTARTS AGE myapp-rc-s4ndd 1/1 Running 0 11m myapp-rc-svqcd 1/1 Running 0 11m myapp-rc-xr4bs 1/1 Running 0 11m
为了确保Pod由我们的副本集管理,我们可以使用kubectl describe
命令:
[root@controller ~]# kubectl describe pods myapp-rc-s4ndd Name: myapp-rc-s4ndd Namespace: default Priority: 0 Node: worker-1.example.com/192.168.43.49 Start Time: Mon, 30 Nov 2017 14:18:24 +0530 Labels: app=myapp type=dev Annotations: <none> Status: Running IP: 10.36.0.2 IPs: IP: 10.36.0.2 Controlled By: ReplicaSet/myapp-replicaset ...
因此,正如预期的那样,带有标签" app:myapp"的现有吊舱现在已映射到我们的" ReplicaSet"。
水平缩放Pod
现在类似于复制控制器,我们还可以缩放副本集容器。
在此示例中,我们会将Pod的数量增加到6:
[root@controller ~]# kubectl scale rs myapp-replicaset --replicas=6 replicaset.apps/myapp-replicaset scaled
现在验证Pod列表:
[root@controller ~]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES myapp-rc-6vjv4 1/1 Running 1 12h 10.36.0.4 worker-1.example.com <none> <none> myapp-rc-9fp5l 1/1 Running 1 12h 10.36.0.3 worker-1.example.com <none> <none> myapp-rc-cwwwh 1/1 Running 1 12h 10.44.0.4 worker-2.example.com <none> <none> myapp-replicaset-8r6kx 0/1 ContainerCreating 0 6s <none> worker-2.example.com <none> <none> myapp-replicaset-kp78z 0/1 ContainerCreating 0 6s <none> worker-1.example.com <none> <none> myapp-replicaset-svm45 0/1 ContainerCreating 0 6s <none> worker-1.example.com <none> <none>
如我们所见,新的虚拟机现在按照我们的模板以新名称启动,现在我们将按比例减少Pod的数量:
[root@controller ~]# kubectl scale rs myapp-replicaset --replicas=3 replicaset.apps/myapp-replicaset scaled
因此,新创建的Pod现在将终止:
[root@controller ~]# kubectl get pods NAME READY STATUS RESTARTS AGE myapp-rc-6vjv4 1/1 Running 1 12h myapp-rc-9fp5l 1/1 Running 1 12h myapp-rc-cwwwh 1/1 Running 1 12h myapp-replicaset-8r6kx 0/1 Terminating 0 11m myapp-replicaset-kp78z 0/1 Terminating 0 11m myapp-replicaset-svm45 0/1 Terminating 0 11m
删除副本集
这是对ReplicaSets的快速介绍,它是ReplicationControllers的替代方法。
请记住,请始终使用它们而不是ReplicationControllers,但是我们仍然可以在其他人的部署中找到ReplicationControllers。
现在,删除ReplicaSet
稍微清理一下集群。
我们可以按照删除ReplicationController
的相同方式删除ReplicaSet
:
[root@controller ~]# kubectl delete rs myapp-replicaset replicaset.apps "myapp-replicaset" deleted
这还将删除属于此副本集的所有Pod。
但是我们可以结合使用--cascade = false和此命令来保留副本集的所有pod部分。