前面我们学习了pod,那我们在定义pod资源时,可以直接创建一个kind:Pod类型的自主式pod,但是这存在一个问题,假如pod被删除了,那这个pod就不能自我恢复,就会彻底被删除,线上这种情况非常危险,所以今天就给大家讲解下pod的控制器,所谓控制器就是能够管理pod,监测pod运行状况,当pod发生故障,可以自动恢复pod。也就是说能够代我们去管理pod中间层,并帮助我们确保每一个pod资源始终处于我们所定义或者我们所期望的目标状态,一旦pod资源出现故障,那么控制器会尝试重启pod或者里面的容器,如果一直重启有问题的话那么它可能会基于某种策略来进行重新布派或者重新编排;如果pod副本数量低于用户所定义的目标数量,它也会自动补全;这就是使用控制器的好处,下面我们就来介绍ReplicaSet控制器。

ReplicaSet是什么

ReplicaSet是kubernetes中的一种副本控制器,主要作用是控制由其管理的pod,使pod副本的数量始终维持在预设的个数。Kubernetes中还有一个类似功能的控制器:Replication Controller。ReplicaSet是Replication Controller的下一代副本控制器,目前两者只在标签选择器支持的查找方式有区别,ReplicaSet支持等式查找与集合查找两种方式,Replication Controller只支持等式查找。

kubectl命令同时支持ReplicaSet与Replication Controller两种副本控制器,但是kubectl rolling-update只支持Replication Controller类型的副本控制器,也就是说ReplicaSet无法通过kubectl rolling-update命令滚动升级。如果想要使用rolling-update功能的话,kubernetes官方推荐使用Deployments,并且因为Deployments是声明式的而rolling-update是命令式,所以推荐使用rollout命令实现滚动升级(kubectl管理对象的方式大体上分成两种,一种是命令式,另一种是声明式,声明式又细分成命令声明式与对角声明式,三种方式不能混用,所以才有此说)。

实现上kubernetes官方推荐不要直接使用ReplicaSet,用Deployments取而代之,Deployments是比ReplicaSet更高级的概念,它会管理ReplicaSet并提供很多其它有用的特性,最重要的是Deployments支持声明式更新,声明式更好相比于命令式更新的好处是不会丢失历史变更。总结起来就是:不要再直接使用ReplicaSet。

创建ReplicaSet

ReplicaSet的资源清单文件的编写可以通过kubectl explain rs查看详细的资源属性,下面的示例创建一个ReplicaSet资源文件:

apiVersion: apps/v1
kind: ReplicaSet		#创建的资源类型
metadata:
  name: nginx-rs		#控制器的名字
  labels:
    app: nginx
spec:
  replicas: 3			#管理的 pod 副本数量
  selector:
    matchLabels:
      app: nginx		#管理带有app=nginx标签的pod
  template:				#定义 pod 的模板
    metadata:
      labels:
        app: nginx		#pod标签,控制器根据这个标签找到它要管理的pod
    spec:
      containers:
      - name: nginx-pod		 #定义容器的名字
        image: nginx:1.21.5
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80

运行上面的ReplicaSet资源,查看ReplicaSet和pod状态如下,成功创建了3个副本。

NAME       DESIRED   CURRENT   READY   AGE    CONTAINERS   IMAGES         SELECTOR
nginx-rs   3         3         3       7m4s   nginx-pod    nginx:1.21.5   app=nginx
NAME             READY   STATUS    RESTARTS   AGE   IP             NODE         NOMINATED NODE   READINESS GATES
nginx-rs-4r4kc   1/1     Running   0          6s    10.81.58.225   k8s-node02   <none>           <none>
nginx-rs-7xdhf   1/1     Running   0          6s    10.81.85.237   k8s-node01   <none>           <none>
nginx-rs-nhjtk   1/1     Running   0          6s    10.81.58.224   k8s-node02   <none>           <none>

ReplicaSet管理pod

扩容、缩容

ReplicaSet最核心的功能是可以动态扩容和缩容,ReplicaSet的扩容和缩容很简单,有两种方式可以实现,一个是更新资源文件中的spec.replicas值就可实现;另外直接编辑控制器也能实现扩缩容。

更新资源文件

spec:
  replicas: 5			#管理的 pod 副本数量

修改spec.replicas的值为5个副本,重新执行kubectl apply -f nginx-rs.yaml命令更新,查看ReplicaSet和pod状态如下,pod副本数量更新为了5个。

NAME       DESIRED   CURRENT   READY   AGE   CONTAINERS   IMAGES         SELECTOR
nginx-rs   5         5         5       15m   nginx-pod    nginx:1.21.5   app=nginx
NAME             READY   STATUS    RESTARTS   AGE   IP             NODE         NOMINATED NODE   READINESS GATES
nginx-rs-4r4kc   1/1     Running   0          15m   10.81.58.225   k8s-node02   <none>           <none>
nginx-rs-7xdhf   1/1     Running   0          15m   10.81.85.237   k8s-node01   <none>           <none>
nginx-rs-8hn8g   1/1     Running   0          40s   10.81.85.238   k8s-node01   <none>           <none>
nginx-rs-mlrdj   1/1     Running   0          40s   10.81.58.226   k8s-node02   <none>           <none>
nginx-rs-nhjtk   1/1     Running   0          15m   10.81.58.224   k8s-node02   <none>           <none>

编辑控制器

kubectl edit rs nginx-rs

直接编辑控制器,修改spec.replicas的值为2个副本,保存退出会自动更新控制器和pod,再次查看ReplicaSet和pod状态如下,pod副本数量更新为了2个。

NAME       DESIRED   CURRENT   READY   AGE   CONTAINERS   IMAGES         SELECTOR
nginx-rs   2         2         2       18m   nginx-pod    nginx:1.21.5   app=nginx
NAME             READY   STATUS    RESTARTS   AGE   IP             NODE         NOMINATED NODE   READINESS GATES
nginx-rs-4r4kc   1/1     Running   0          18m   10.81.58.225   k8s-node02   <none>           <none>
nginx-rs-7xdhf   1/1     Running   0          18m   10.81.85.237   k8s-node01   <none>           <none>

更新、删除

更新pod

更新pod也是直接修改资源文件内容即可,跟上面的扩缩容一样,这里不再赘述,不过需要注意的是:更新资源文件并重新执行后,原来旧的pod使用的还是旧的资源文件创建的,新创建的pod才会使用新的资源文件创建。

删除pod

在ReplicaSet管理下的pod,如果单独删除pod后还会自动创建pod,已达到始终维持ReplicaSet需要的副本数量,如下所示,当删除nginx-rs-7xdhfpod后,会立刻重新创建一个名为nginx-rs-dbk9x的新的pod,已保证副本数量是2个。

#删除前的pod
NAME             READY   STATUS    RESTARTS   AGE   IP             NODE         NOMINATED NODE   READINESS GATES
nginx-rs-4r4kc   1/1     Running   0          28m   10.81.58.225   k8s-node02   <none>           <none>
nginx-rs-7xdhf   1/1     Running   0          28m   10.81.85.237   k8s-node01   <none>           <none>
#删除pod
kubectl delete pod nginx-rs-7xdhf
#删除后的pod
NAME             READY   STATUS    RESTARTS   AGE   IP             NODE         NOMINATED NODE   READINESS GATES
nginx-rs-4r4kc   1/1     Running   0          28m   10.81.58.225   k8s-node02   <none>           <none>
nginx-rs-dbk9x   1/1     Running   0          13s   10.81.85.239   k8s-node01   <none>           <none>

删除ReplicaSet

删除ReplicaSet可以通过执行对资源文件的删除操作,也可以通过名称删除控制器。

#通过资源文件进行删除
kubectl delete -f nginx-rs.yaml
#通过控制器名称删除
kubectl delete rs nginx-rs

上面的删除操作不仅会删除ReplicaSet,同时也会删除相关联的pod,如果只需要删除ReplicaSet,而保留pod的话,可以运行kubectl delete命令时加上--cascade=false选项,ReplicaSet被删除,其控制的pod不受影响。

kubectl delete -f nginx-rs.yaml --cascade=false
kubectl delete rs nginx-rs --cascade=false

水平自动扩缩容

通过HPA控制ReplicaSet根据负荷如cpu使用情况自动扩缩容(先初步了解,关注我后面会详细讲解HPA)。官网示例https://k8s.io/examples/controllers/hpa-rs.yaml,内容如下:

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: frontend-scaler
spec:
  scaleTargetRef:
    kind: ReplicaSet
    name: frontend
  minReplicas: 3
  maxReplicas: 10
  targetCPUUtilizationPercentage: 50

创建HPA对象,它将根据CPU使用情况,在3到10之间动态的调整副本数量。

kubectl create -f hpa-rs.yaml