image-20211108215346196

目录

实验环境

实验环境:
1、win10,vmwrokstation虚机;
2、k8s集群:3台centos7.6 1810虚机,1个master节点,2个node节点
   k8s version:v1.22.2
   containerd://1.5.5

实验软件(无)

1、ReplicaSet 控制器

前面我们一起学习了 Pod 的原理和一些基本使用,但是在实际使用的时候并不会直接使用 Pod,而是会使用各种控制器来满足我们的需求Kubernetes 中运行了一系列控制器来确保集群的当前状态与期望状态保持一致,它们就是 Kubernetes 的大脑/心脏。例如,ReplicaSet 控制器负责维护集群中运行的 Pod 数量Node 控制器负责监控节点的状态,并在节点出现故障时及时做出响应总而言之,在 Kubernetes 中,每个控制器只负责某种类型的特定资源

2、控制器

注意理解下关于控制器的描述:

Kubernetes 控制器会监听资源的 创建/更新/删除 事件,并触发 Reconcile 调谐函数作为响应,整个调整过程被称作 “Reconcile Loop”(调谐循环) 或者 “Sync Loop”(同步循环)。**Reconcile 是一个使用资源对象的命名空间和资源对象名称来调用的函数,使得资源对象的实际状态与 资源清单中定义的状态保持一致。调用完成后,Reconcile 会将资源对象的状态更新为当前实际状态。**我们可以用下面的一段伪代码来表示这个过程:

for {
  desired := getDesiredState()  // 期望的状态
  current := getCurrentState()  // 当前实际状态
  if current == desired {  // 如果状态一致则什么都不做
    // nothing to do
  } else {  // 如果状态不一致则调整编排,到一致为止
    // change current to desired status
  }
}

这个编排模型就是 Kubernetes 项目中的一个通用编排模式,即:控制循环(control loop)

3、ReplicaSet

假如我们现在有一个 Pod 正在提供线上的服务,我们来想想一下我们可能会遇到的一些场景:

  • 某次运营活动非常成功,网站访问量突然暴增
  • 运行当前 Pod 的节点发生故障了,Pod 不能正常提供服务了

第一种情况,可能比较好应对,活动之前我们可以大概计算下会有多大的访问量,提前多启动几个 Pod 副本,活动结束后再把多余的 Pod 杀掉,虽然有点麻烦,但是还是能够应对这种情况的。

第二种情况,可能某天夜里收到大量报警说服务挂了,然后起来打开电脑在另外的节点上重新启动一个新的 Pod,问题可以解决。

但是如果我们都人工的去解决遇到的这些问题,似乎又回到了以前刀耕火种的时代了是吧?如果有一种工具能够来帮助我们自动管理 Pod 就好了,Pod 挂了自动帮我在合适的节点上重新启动一个 Pod,这样是不是遇到上面的问题我们都不需要手动去解决了。

而 ReplicaSet 这种资源对象就可以来帮助我们实现这个功能,ReplicaSet(RS) 的主要作用就是维持一组 Pod 副本的运行,保证一定数量的 Pod 在集群中正常运行,ReplicaSet 控制器会持续监听它所控制的这些 Pod 的运行状态,在 Pod 发送故障数量减少或者增加时会触发调谐过程,始终保持副本数量一定。


❤️实验测试:

实验日期:2021年11月8日21:25:39

和 Pod 一样我们仍然还是通过 YAML 文件来描述我们的 ReplicaSet 资源对象,如下 YAML 文件是一个常见的 ReplicaSet 定义:

[root@master1 ~]#vim nginx-rs.yaml

# nginx-rs.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name:  nginx-rs
  namespace: default
spec:
  replicas: 3  # 期望的 Pod 副本数量,默认值为1
  selector:  # Label Selector,必须匹配被管理的Pod的标签
    matchLabels:
      app: nginx
  template:  # Pod 模板
    metadata: #Pod名称会根据rs的name自动生成
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

上面的 YAML 文件结构和我们之前定义的 Pod 看上去没太大两样,有常见的 apiVersion、kind、metadata,在 spec 下面描述 ReplicaSet 的基本信息,其中包含3个重要内容:

  • replias:表示期望的 Pod 的副本数量
  • selector:Label Selector,用来匹配要控制的 Pod 标签,需要和下面的 Pod 模板中的标签一致
  • template:Pod 模板,实际上就是以前我们定义的 Pod 内容,相当于把一个 Pod 的描述以模板的形式嵌入到了 ReplicaSet 中来。

Pod 模板:

Pod 模板这个概念非常重要,因为后面我们讲解到的大多数控制器,都会使用 Pod 模板来统一定义它所要管理的 Pod。更有意思的是,我们还会看到其他类型的对象模板,比如Volume 的模板等。

上面就是我们定义的一个普通的 ReplicaSet 资源清单文件,ReplicaSet 控制器会通过定义的 Label Selector 标签去查找集群中的 Pod 对象:

replicaset top

我们直接来创建上面的资源对象:

[root@master1 ~]#kubectl apply -f nginx-rs.yaml
replicaset.apps/nginx-rs created
[root@master1 ~]#kubectl get rs
NAME       DESIRED   CURRENT   READY   AGE
nginx-rs   3         3         3       46s
[root@master1 ~]#

通过查看 RS 可以看到当前资源对象的描述信息,包括DESIREDCURRENTREADY的状态值,创建完成后,可以利用如下命令查看下 Pod 列表:

[root@master1 ~]#kubectl get po -l app=nginx
NAME             READY   STATUS    RESTARTS   AGE
nginx-rs-7btxg   1/1     Running   0          82s
nginx-rs-gfhzx   1/1     Running   0          82s
nginx-rs-v8rrb   1/1     Running   0          82s
[root@master1 ~]#

可以看到现在有 3 个 Pod,这 3 个 Pod 就是我们在 RS 中声明的 3 个副本,比如我们删除其中一个 Pod:

[root@master1 ~]#kubectl delete pod nginx-rs-v8rrb
pod "nginx-rs-v8rrb" deleted

然后再查看 Pod 列表:

[root@master1 ~]#kubectl get po -l app=nginx
NAME             READY   STATUS    RESTARTS   AGE
nginx-rs-7btxg   1/1     Running   0          2m28s
nginx-rs-gfhzx   1/1     Running   0          2m28s
nginx-rs-xxplf   1/1     Running   0          28s
[root@master1 ~]#

可以看到又重新出现了一个 Pod,这个就是上面我们所说的 ReplicaSet 控制器为我们做的工作,我们在 YAML 文件中声明了 3 个副本,然后现在我们删除了一个副本,就变成了两个,这个时候 ReplicaSet 控制器监控到控制的 Pod 数量和期望的 3 不一致,所以就需要启动一个新的 Pod 来保持 3 个副本,这个过程上面我们说了就是调谐的过程。同样可以查看 RS 的描述信息来查看到相关的事件信息:

[root@master1 ~]#kubectl describe rs nginx-rs
Name:         nginx-rs
Namespace:    default
Selector:     app=nginx
Labels:       <none>
Annotations:  <none>
Replicas:     3 current / 3 desired
Pods Status:  3 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
  Labels:  app=nginx
  Containers:
   nginx:
    Image:        nginx
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Events:
  Type    Reason            Age    From                   Message
  ----    ------            ----   ----                   -------
  Normal  SuccessfulCreate  3m31s  replicaset-controller  Created pod: nginx-rs-v8rrb
  Normal  SuccessfulCreate  3m31s  replicaset-controller  Created pod: nginx-rs-7btxg
  Normal  SuccessfulCreate  3m31s  replicaset-controller  Created pod: nginx-rs-gfhzx
  Normal  SuccessfulCreate  91s    replicaset-controller  Created pod: nginx-rs-xxplf
[root@master1 ~]#

可以发现最开始通过 ReplicaSet 控制器创建了 3 个 Pod,后面我们删除了 Pod 后, ReplicaSet 控制器又为我们创建了一个 Pod,和上面我们的描述是一致的。如果这个时候我们把 RS 资源对象的 Pod 副本更改为 2 spec.replicas=2,这个时候我们来更新下资源对象:

[root@master1 ~]#vim nginx-rs.yaml
……
spec:
  8   replicas: 2 #修改pod副本数为2
  9   selector:
 10     matchLabels:
 11       app: nginx
……
[root@master1 ~]#kubectl apply -f nginx-rs.yaml
replicaset.apps/nginx-rs configured
[root@master1 ~]#

[root@master1 ~]#kubectl get rs
NAME       DESIRED   CURRENT   READY   AGE
nginx-rs   2         2         2       5m38s
[root@master1 ~]#kubectl describe rs nginx-rs
Name:         nginx-rs
Namespace:    default
Selector:     app=nginx
Labels:       <none>
Annotations:  <none>
Replicas:     2 current / 2 desired
Pods Status:  2 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
  Labels:  app=nginx
  Containers:
   nginx:
    Image:        nginx
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Events:
  Type    Reason            Age    From                   Message
  ----    ------            ----   ----                   -------
  Normal  SuccessfulCreate  5m43s  replicaset-controller  Created pod: nginx-rs-v8rrb
  Normal  SuccessfulCreate  5m43s  replicaset-controller  Created pod: nginx-rs-7btxg
  Normal  SuccessfulCreate  5m43s  replicaset-controller  Created pod: nginx-rs-gfhzx
  Normal  SuccessfulCreate  3m43s  replicaset-controller  Created pod: nginx-rs-xxplf
  Normal  SuccessfulDelete  19s    replicaset-controller  Deleted pod: nginx-rs-xxplf
[root@master1 ~]#

可以看到 Replicaset 控制器在发现我们的资源声明中副本数变更为 2 后,就主动去删除了一个 Pod,这样副本数就和期望的始终保持一致了:

[root@master1 ~]#kubectl get po -l app=nginx
NAME             READY   STATUS    RESTARTS   AGE
nginx-rs-7btxg   1/1     Running   0          6m12s
nginx-rs-gfhzx   1/1     Running   0          6m12s
[root@master1 ~]#

我们可以随便查看一个 Pod 的描述信息可以看到这个 Pod 的所属控制器信息:

[root@master1 ~]#kubectl get po -l app=nginx
NAME             READY   STATUS    RESTARTS   AGE
nginx-rs-7btxg   1/1     Running   0          6m50s
nginx-rs-gfhzx   1/1     Running   0          6m50s
[root@master1 ~]#kubectl describe pod nginx-rs-gfhzx
Name:         nginx-rs-gfhzx
Namespace:    default
Priority:     0
Node:         node2/172.29.9.53
Start Time:   Mon, 08 Nov 2021 21:30:03 +0800
Labels:       app=nginx
Annotations:  <none>
Status:       Running
IP:           10.244.2.13
IPs:
  IP:           10.244.2.13
Controlled By:  ReplicaSet/nginx-rs #从这里可以看到,这个pod是被ReplicaSet/nginx-rs控制;
……
[root@master1 ~]#

注意:

**另外被 ReplicaSet 持有的 Pod 有一个 metadata.ownerReferences 指针指向当前的 ReplicaSet,表示当前 Pod 的所有者,这个引用主要会被集群中的垃圾收集器使用以清理失去所有者的 Pod 对象。**这个 ownerReferences 和数据库中的外键是不是非常类似。可以通过将 Pod 资源描述信息导出查看:

[root@master1 ~]#kubectl get po -l app=nginx
NAME             READY   STATUS    RESTARTS   AGE
nginx-rs-7btxg   1/1     Running   0          8m48s
nginx-rs-gfhzx   1/1     Running   0          8m48s

[root@master1 ~]#kubectl edit pod nginx-rs-gfhzx
或者
[root@master1 ~]#kubectl get po nginx-rs-gfhzx -oyaml
  ownerReferences:
  - apiVersion: apps/v1
    blockOwnerDeletion: true
    controller: true
    kind: ReplicaSet
    name: nginx-rs
    uid: e1b9d63b-6be5-4a9f-b565-1d8eea92c727

我们可以看到 Pod 中有一个 metadata.ownerReferences 的字段指向了 ReplicaSet 资源对象。如果要彻底删除 Pod,我们就只能删除 RS 对象:

[root@master1 ~]#kubectl delete rs nginx-rs
replicaset.apps "nginx-rs" deleted
[root@master1 ~]#kubectl get rs,pod
No resources found in default namespace.
[root@master1 ~]#

或者:执行 kubectl delete -f nginx-rs.yaml

或者:你如果想彻底删除pod,就需要把rs给删除掉或者把rs里的副本数改为0;

这就是 ReplicaSet 对象的基本使用。

实验到此结束。

4、Replication Controller(可以不看)

Replication Controller 简称 RC,实际上 RC 和 RS 的功能几乎一致,RS 算是对 RC 的改进,目前唯一的一个区别就是 RC 只支持基于等式的 selector(env=dev或environment!=qa),但 RS 还支持基于集合的 selector(version in (v1.0, v2.0)),这对复杂的运维管理就非常方便了。

比如上面资源对象如果我们要使用 RC 的话,对应的 selector 是这样的:

selector:
  app: nginx

RC 只支持单个 Label 的等式,而 RS 中的 Label Selector 支持 matchLabelsmatchExpressions 两种形式:

selector:
  matchLabels:
    app: nginx

---
selector:
  matchExpressions:  # 该选择器要求 Pod 包含名为 app 的标签
  - key: app
    operator: In
    values:  # 并且标签的值必须是 nginx
    - nginx

image-20211108222208783

总的来说 RS 是新一代的 RC,所以以后我们不使用 RC,直接使用 RS 即可,他们的功能都是一致的,但是实际上在实际使用中我们也不会直接使用 RS,而是使用更上层的类似于 Deployment 这样的资源对象。

注意,一般,还是matchLabels用的多一些。

关于我

我的博客主旨:我希望每一个人拿着我的博客都可以做出实验现象,先把实验做出来,然后再结合理论知识更深层次去理解技术点,这样学习起来才有乐趣和动力。并且,我的博客内容步骤是很完整的,也分享源码和实验用到的软件,希望能和大家一起共同进步!

各位小伙伴在实际操作过程中如有什么疑问,可随时联系本人免费帮您解决问题:

  1. 个人微信二维码:x2675263825 (舍得), qq:2675263825。

    image-20211002091450217

  2. 个人博客地址:www.onlyonexl.cn

    image-20211002092057988

  3. 个人微信公众号:云原生架构师实战

    image-20211002141739664

  4. 个人csdn

    https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421

    image-20211002092344616

最后

​ 好了,关于ReplicaSet实验就到这里了,感谢大家阅读,最后贴上我女神的photo,祝大家生活快乐,每天都过的有意义哦,我们下期见!

image-20211108215201479

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐