Kubernetes ReplicaSet和ReplicationController初学者指南

时间:2020-01-09 10:41:07  来源:igfitidea点击:

在本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部分。