TOC

DaemonSet控制器

    ReplicaSet是一个Pod直接控制器,它能控制Pod满足用户所期望的基本数量,但是ReplicaSet自身在更新这个功能上可能不是表现特别良好,因此在ReplicaSet之上我们又抽象出来的Deployment,去扩展ReplicaSet能够拥有滚动部署、金丝雀部署等功能,这也是Deployment之所谓称之为Deployment的核心原因之一,但是要注意的是,在一个拥有三个Kubernetes工作节点的之上,我们把一个Deployment运行为6个Pod副本,甚至运维为9个Pod副本也是没有问题的,那也就是意味着在这种场景当中,一个节点上,有可能需要把同一个Pod副本运行多个,但是有些系统级任务,它并不需要在每一个节点上运行多分,有一个就行了,但是Deployment做不到,Deployment之能说在整个集群中运行你所期望数量的Pod,至于这些Pod能够运行在哪些节点上,我们无法控制,那是由调度器根据所谓的数量按需调度的;
    因此,我们期望在每一个节点上只运行一个Pod,Pod的数量我们就不能定义了,Pod数量取决你的节点数,并不是由用户决定定义的,因此DaemonSet,它的一个最大特点在于,我们在定义时只需要给定Pod模版和标签选择器即可,至于要运行多少个副本,则取决于我们的集群规模,你有三个节点,那么三个节点上各运行一个副本,后来加入一个新的节点会自动被添加出对应的守护进程,如果我们减了2个节点,它也不会把这两个节点上面的DaemonSet控制器所控制的Pod在其他节点上运行起来,因此DaemonSet只需要标签选择器,和Pod模版就能完成任务,;
    但是有些场景中,我们也可能存在这样的需求,比如,整个集群有五个节点,但是只有三个几点有显卡,其他都没有显卡,我们需要做一些AI计算,这些都需要用到显卡,或者说一些挖矿程序,也需要依赖我们的显卡,所以向这种情况下,我们期望添加一个守护进程,这个守护进程只添加在有显卡的节点上,那么就说明我们只需要运行这三台节点上运行我们的这个守护进程,因此在这种场景当中如果只有部分节点满足我们运行一个特有系统级守护进程的需求的话,我们甚至于DaemonSet控制器控制下的守护进程不需要在集群上的每一个节点上运行,而是只需要在部分节点上运行,那么这个时候,我们就需要用标签的节点选择器,是节点选择器,来选择节点,所谓节点就是我们告诉我们的调度器,只把这些Pod调度到哪些节点运行,所以我们需要给节点打上标签,然后让调度器根据节点选择器,选择把这些Pod调度到哪些节点上,那么我们就可以只在三台有显卡的节点上运行一个系统级的Pod,而且只跑一个,而且,DaemonSet也支持滚动更新,比如我们日志收集查看filebeat,从5.6要升级到5.7,那么我们的DaemonSet也可以先加后减,也可以先减后加,也可以加的比减的少,但是对于DaemonSet来讲,它能够唯一采取的策略是先减后加,因为每一个节点只有一个,当然它也可以滚动更新,具体更新方式和Pod差不多;
[root@node1 cce]# cat ds.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: daemonsetbusybox
  namespace: cce
spec:
  selector:
    matchLabels:
      app: busybox
  template:
    metadata:
      namespace: cce
      name: busybox
      labels:
        app: busybox
    spec:
      restartPolicy: Always
      containers:
      - name: busybox
        imagePullPolicy: IfNotPresent
        image: busybox:latest
        command:
        - '/bin/sh'
        - '-c'
        - 'sleep 100000'
# 可以看到每一个节点都运行了一个daemonSet控制器的Pod
[root@node1 cce]# kubectl get pods -n cce -l app=busybox -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
daemonsetbusybox-hvq27 1/1 Running 0 3m14s 10.244.1.69 node2.cce.com <none> <none>
daemonsetbusybox-l6fjb 1/1 Running 0 3m14s 10.244.2.68 node3.cce.com <none> <none>
滚动更新
[root@node3 ~]# kubectl explain daemonset.spec.updateStrategy
    OnDelete:删一个更新一个,先删除,后创建,只有当你手动删除老的DaemonSet pods时,新的DaemonSet pods 才会被自动创建;
    RollingUpdate:可以选择一次更新几个节点,先删除后创建;
示例
# DaemonSet模版文件
[root@node1 cce]# cat test.yml 
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: daemonsetbusybox
  namespace: cce
spec:
  selector:
    matchLabels:
      app: busybox
  template:
    metadata:
      namespace: cce
      name: busybox
      labels:
        app: busybox
    spec:
      restartPolicy: Always
      containers:
      - name: busybox
        imagePullPolicy: IfNotPresent
        image: busybox:1.31
        command:
        - '/bin/sh'
        - '-c'
        - 'sleep 100000'
# 第一次版本发布1.31版本
[root@node3 ~]# kubectl get ds -n cce -o wide --show-labels 
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE CONTAINERS IMAGES SELECTOR LABELS
daemonsetbusybox 2 2 2 2 2 <none> 113s busybox busybox:1.31 app=busybox <none>
# 第二次版本发布
[root@node1 cce]# kubectl set image -f test.yml busybox=busybox:latest
# 监控版本更新
[root@node2 ~]# kubectl rollout status -n cce daemonset daemonsetbusybox 
daemon set "daemonsetbusybox" successfully rolled out
[root@node2 ~]# kubectl rollout status -n cce daemonset daemonsetbusybox 
Waiting for daemon set "daemonsetbusybox" rollout to finish: 0 out of 2 new pods have been updated...
Waiting for daemon set "daemonsetbusybox" rollout to finish: 0 out of 2 new pods have been updated...
Waiting for daemon set "daemonsetbusybox" rollout to finish: 1 out of 2 new pods have been updated...
Waiting for daemon set "daemonsetbusybox" rollout to finish: 1 out of 2 new pods have been updated...
Waiting for daemon set "daemonsetbusybox" rollout to finish: 1 out of 2 new pods have been updated...
Waiting for daemon set "daemonsetbusybox" rollout to finish: 1 of 2 updated pods are available...
daemon set "daemonsetbusybox" successfully rolled out
# 查看最新版本
[root@node3 ~]# kubectl get ds -n cce -o wide --show-labels 
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE CONTAINERS IMAGES SELECTOR LABELS
daemonsetbusybox 2 2 2 0 2 <none> 3m34s busybox busybox:latest app=busybox <none>
使用标签选择器来指定node
[root@node1 ~]# cat cce.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: daemonsetbusybox
  namespace: cce
spec:
  selector:
    matchLabels:
      app: busybox
  template:
    metadata:
      namespace: cce
      name: busybox
      labels:
        app: busybox
    spec:
      restartPolicy: Always
      nodeSelector: # 添加标签选择器
        daemon: "true"
      containers:
      - name: busybox
        imagePullPolicy: IfNotPresent
        image: busybox:latest
        command:
        - '/bin/sh'
        - '-c'
        - 'sleep 100000'
[root@node1 ~]# kubectl apply -f cce.yaml
daemonset.apps/daemonsetbusybox created
# 创建之前查看daemonset的node
[root@node1 ~]# kubectl get pods -n cce
No resources found in cce namespace.
# 给我们的node增加标签
[root@node1 ~]# kubectl label nodes node2.cce.com daemon=true
node/node2.cce.com labeled
# 增加标签之后自动立即创建
[root@node1 ~]# kubectl get pods -n cce
NAME READY STATUS RESTARTS AGE
daemonsetbusybox-g4t2v 0/1 ContainerCreating 0 0s
# 可以看到已经在node2上面创建一个新的daemonset的Pod
[root@node1 ~]# kubectl get pods -n cce -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
daemonsetbusybox-g4t2v 0/1 ContainerCreating 0 40s <none> node2.cce.com <none> <none>

Job控制器

    Job控制器的主要作用是,一次性就业,非守护进程,它需要在后台运行,任务执行完成之后,就退出,我们正常Pod控制器控制的Pod一旦宕,会自动重建,这是我们的Deployment、ReplicaSet或者DaeonSet的特性,但是有些任务,比如像备份,我们只执行一次备份任务就行了,那这个时候可以使用我们的Job控制器,所以Job控制器就是用来创建一个或多个Pod,这个Pod就是执行相应的任务,完成之后终止就完了,如果要删除Job,我们会删除这个Pod所做的所有操作;

注意:Job控制器下面的Pod不是一定不会重建,如果任务执行失败(通过退出码判断)就会重建,如果执行成功就不会进程重建,所以需要关注一下restartPolicy,如果是Never表示重新创建一个Never

Job控制器参数
template:Pod模版;
selector:标签选择器;
Parallel Jobs:如果任务可以被切分,那么通过多进程的方式并行处理,Parallel Jobs主要的作用就是如果有多个备份脚本可以并行处理;
    completions:定义任务总量;
    parallelism:并行总量,如果任务总量为1那么并行总量之能唯一,如果任务总量为多个并行总量可以随意;
apiVersion: batch/v1
kind: Job
metadata:
  name: jobs
  namespace: cce
spec:
  completions: 5 # 一共五个任务
  parallelism: 2 # 并行2个,
  template:
    spec:
      containers:
      - name: myjob
        image: busybox:latest
        command:
        - '/bin/sh'
        - '-c'
        - 'sleep 5'
      restartPolicy: Never
CronJob
    Job负责处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个Pod成功结束。而CronJob则就是在Job上加上了时间调度;
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: jobs
  namespace: cce
spec:
  schedule: "0/1 * * * *" # 和crontab的语法一样
  jobTemplate: # 这是job的template
    spec:
      template:
        spec:
          containers:
          - name: myjob
            image: busybox:latest
            command:
            - '/bin/sh'
            - '-c'
            - 'sleep 5'
            restartPolicy: Never

Garbage Collction 垃圾收集器

    一个Pod控制器终止的时候会把这个控制器下面的Pod全部回收,这个过程我们把它叫做垃圾收集,每一个依赖性的Object在他的metadata中都有一个ownerReferences字段,你没定义它也会自动填充,比如由控制器创建的Pod,那么Pod的ownerReferences就属于它的控制器,所以任何一个Object终止的时候,一般都由它的ownerReferences所指定的那个对象负责给他进行GC垃圾收集,大多数情况下会自动设置,当然用于也可以自己指定垃圾收集器,而收集的方式一般是通过级联的方式进行的,一个叫做后台一个叫前台,通常情况下我们删除Pod控制器,那么这个控制器下面的Pod会自动删除,这种我们叫做级联,当然我们也可以设置不联机删除,Pod控制器删除之后下面的Pod不会删除,会转为自助式Pod,没有控制器了。
    基本上有引用者的时候,删除了引用者,那么被引用的资源会一起删除,而这个级联操作,可以工作为两种模型,就是前台和后台,后台就是删除一个资源的过程不用管,全部会在后台执行,所谓前台就是用户需要等待资源以及被引用的资源一起删除之后再进行下一步的操作,会占用终端;
[root@node1 ~]# kubectl explain cj.metadata.ownerReferences

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注