实战:DaemonSet 与 Job-2021.11.21

目录

实验环境

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

实验软件(无)

1、DaemonSet 控制器

哦,shift,我之前把static pod和Daemonset概念给弄混淆了。

通过该控制器的名称我们可以看出它的用法:Daemon,就是用来部署守护进程的DaemonSet用于在每个 Kubernetes 节点中将守护进程的副本作为后台进程运行说白了就是在每个节点部署一个 Pod副本当节点加入到 Kubernetes 集群中,Pod 会被调度到该节点上运行,当节点从集群够被移除后,该节点上的这个 Pod 也会被移除,当然,如果我们删除 DaemonSet,所有和这个对象相关的 Pods都会被删除。那么在哪种情况下我们会需要用到这种业务场景呢?其实这种场景还是比较普通的,比如:

  • 集群存储守护程序,如 glusterd、ceph 要部署在每个节点上以提供持久性存储;
  • 节点监控守护进程,如 Prometheus 监控集群,可以在每个节点上运行一个 node-exporter 进程来收集监控节点的信息;
  • 日志收集守护程序,如 fluentd 或 logstash,在每个节点上运行以收集容器的日志
  • 节点网络插件,比如 flannel、calico,在每个节点上运行为 Pod 提供网络服务。

这里需要特别说明的一个就是关于 DaemonSet 运行的 Pod 的调度问题,正常情况下,Pod 运行在哪个节点上是由 Kubernetes 的调度器策略来决定的,然而,由 DaemonSet 控制器创建的 Pod 实际上提前已经确定了在哪个节点上了(Pod创建时指定了.spec.nodeName,所以:

  • DaemonSet 并不关心一个节点的 unshedulable 字段,这个我们会在后面的调度章节和大家讲解的。
  • DaemonSet 可以创建 Pod,即使调度器还没有启动。

📍 注意:Daemonset的简写是ds

[root@nfs-server ~]#kubectl api-resources|head -1; kubectl api-resources |grep daemonsets
NAME                              SHORTNAMES   APIVERSION                             NAMESPACED   KIND
daemonsets                        ds           apps/v1                                true         DaemonSet
[root@nfs-server ~]#

❤️实战演示:

下面我们直接使用一个示例来演示下:
📍step1:在每个节点上部署一个 Nginx Pod:

[root@master1 ~]#vim nginx-ds.yaml
# nginx-ds.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nginx-ds
  namespace: default
spec:
  selector:
    matchLabels:
      k8s-app: nginx
  template:
    metadata:
      labels:
        k8s-app: nginx
    spec:
      containers:
      - image: nginx:1.7.9
        name: nginx
        ports:
        - name: http
          containerPort: 80

注意:我们可以看到,DaemonSet的yaml写法和Deployment非常类似,只是改变了下kind名称,注意下DaemonSet是没有副本数这一参数选项的。

📍step2:apply

[root@master1 ~]#kubectl apply -f nginx-ds.yaml
daemonset.apps/nginx-ds created

📍step3:创建完成后,我们查看 Pod 的状态:

[root@master1 ~]#kubectl get node
NAME      STATUS   ROLES                  AGE   VERSION
master1   Ready    control-plane,master   19d   v1.22.2
node1     Ready    <none>                 19d   v1.22.2
node2     Ready    <none>                 19d   v1.22.2
[root@master1 ~]#kubectl get po -l k8s-app=nginx -owide
NAME             READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
nginx-ds-g5jf4   1/1     Running   0          85s   10.244.1.82    node1   <none>           <none>
nginx-ds-hl7fx   1/1     Running   0          85s   10.244.2.106   node2   <none>           <none>

我们观察可以发现除了 master1 节点之外的2个节点上都有一个相应的 Pod 运行,因为 master1 节点上默认被打上了污点(taints),所以默认情况下不能调度普通的 Pod 上去,后面讲解调度器的时候会和大家学习如何调度上去。

📍step4:注意:我们这里先来提前看看master节点是如何打上污点的。

1、首先来看看这3个节点上是否打了污点呢?
[root@master1 ~]#kubectl describe node master1 |grep Taints
Taints:             node-role.kubernetes.io/master:NoSchedule
[root@master1 ~]#kubectl describe node node1 |grep Taints
Taints:             <none>
[root@master1 ~]#kubectl describe node node2 |grep Taints
Taints:             <none>
[root@master1 ~]#
我们可以看到只有master节点被打上了污点:`NoSchedule`;
某个节点上如果被打上了污点的话,那么普通pod是不会被调度到其上面的,除非添加了`容忍`才可以;

2、这个master1节点的`污点`是当时我们再搭建集群的时候就已经打上了的。我们可以看看当时搭建k8s集群的kubeadm.yaml文件内容。
  vim kubeadm.yaml
  1 apiVersion: kubeadm.k8s.io/v1beta3
  2 bootstrapTokens:
  3 - groups:
  4   - system:bootstrappers:kubeadm:default-node-token
  5   token: abcdef.0123456789abcdef
  6   ttl: 24h0m0s
  7   usages:
  8   - signing
  9   - authentication
 10 kind: InitConfiguration
 11 localAPIEndpoint:
 12   advertiseAddress: 172.29.9.51
 13   bindPort: 6443
 14 nodeRegistration:
 15   criSocket: /run/containerd/containerd.sock
 16   imagePullPolicy: IfNotPresent
 17   name: master1
 18   taints:
 19   - effect: "NoSchedule" #这里打了污点
 20     key: "node-role.kubernetes.io/master"

3、那么有的同学就会问:那么为什么你的`flannel和kubeproxy`pod都会在每个节点上创建1个pod呢?(包括master节点)

image-20211119225807852

这是因为flannel和kube-proxy配置清单里,daemonset那里有配置了容忍,所以才会在打了污点的master节点也调度一个pod。
vim kube-flannel.yml

image-20211119230218104

📍step5:注意:DaemonSetreplicaset是非常相似的,直接控制pod:

[root@master1 ~]#kubectl get po
NAME             READY   STATUS    RESTARTS   AGE
nginx-ds-g5jf4   1/1     Running   0          34m
nginx-ds-hl7fx   1/1     Running   0          34m
[root@master1 ~]#kubectl describe pod nginx-ds-g5jf4
……
Controlled By:  DaemonSet/nginx-ds
……

📍step6:我们再来把其中一个pod删除下,观察下这个pod是否会被立马重建?

[root@master1 ~]#kubectl get po -owide
NAME             READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
nginx-ds-g5jf4   1/1     Running   0          9h    10.244.1.82    node1   <none>           <none>
nginx-ds-hl7fx   1/1     Running   0          9h    10.244.2.106   node2   <none>           <none>
[root@master1 ~]#kubectl delete po nginx-ds-g5jf4
pod "nginx-ds-g5jf4" deleted
[root@master1 ~]#kubectl get po -owide
NAME             READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
nginx-ds-cg86w   1/1     Running   0          1s    10.244.1.83    node1   <none>           <none>
nginx-ds-hl7fx   1/1     Running   0          9h    10.244.2.106   node2   <none>           <none>
[root@master1 ~]#

我们可以发现,一旦某个节点的pod被删除后,它会立马被重建的。这个就是daemonset控制器的作用,它是一个loop,会一直监听节点上的pod是否满足副本数为1这个条件,如果不满足,会立即执行相应操作,使其符合期望的状态。

实验结束。

基本上我们可以用下图来描述 DaemonSet 的拓扑图:

集群中的 Pod 和 Node 是一一对应的,而 DaemonSet 会管理全部机器上的 Pod 副本,负责对它们进行更新和删除。

那么,DaemonSet 控制器是如何保证每个 Node 上有且只有一个被管理的 Pod 呢?

  • 首先控制器从 Etcd 获取到所有的 Node 列表,然后遍历所有的 Node。
  • 根据资源对象定义是否有调度相关的配置,然后分别检查 Node 是否符合要求。
  • 在可运行 Pod 的节点上检查是否已有对应的 Pod,如果没有,则在这个 Node 上创建该 Pod;如果有,并且数量大于 1,那就把多余的 Pod 从这个节点上删除;如果有且只有一个 Pod,那就说明是正常情况。

实际上当我们学习了资源调度后,我们也可以自己用 Deployment 来实现 DaemonSet 的效果,这里我们明白 DaemonSet 如何使用的即可,当然该资源对象也有对应的更新策略,有 OnDeleteRollingUpdate 两种方式,默认是滚动更新。

2、Job 与 CronJob

接下来给大家介绍另外一类资源对象:Job,我们在日常的工作中经常都会遇到一些需要进行批量数据处理和分析的需求,当然也会有按时间来进行调度的工作,在我们的 Kubernetes 集群中为我们提供了 JobCronJob 两种资源对象来应对我们的这种需求。

Job 负责处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个 Pod 成功结束。而CronJob 则就是在 Job 上加上了时间调度。

1.Job

首先我们可以使用kubectl explains job.spec来看下Job对象的可用字段。

📍step1:创建job-demo资源清单文件

我们用 Job 这个资源对象来创建一个任务,我们定义一个 Job 来执行一个倒计时的任务,对应的资源清单如下所示:

[root@master1 ~]#vim job-demo.yaml

# job-demo.yaml
apiVersion: batch/v1 #batch就是批处理
kind: Job
metadata:
  name: job-demo
spec:
  template:
    spec:
      restartPolicy: Never
      containers:
      - name: counter
        image: busybox
        command:
        - "bin/sh"
        - "-c"
        - "for i in 9 8 7 6 5 4 3 2 1; do echo $i; done"

注意:

这里的container要是一个任务才行,这里的image如果是nginx,那是不行的,因为nginx在前台,会一直运行下去的。

我们可以看到 Job 中也是一个 Pod 模板,和之前的 Deployment、StatefulSet 之类的是一致的,**只是 Pod 中的容器要求是一个任务,而不是一个常驻前台的进程了,因为需要退出。**另外值得注意的是 JobRestartPolicy 仅支持 NeverOnFailure 两种,不支持 Always,我们知道 Job 就相当于来执行一个批处理任务,执行完就结束了,如果支持 Always 的话是不是就陷入了死循环了?

📍step2:直接创建这个 Job 对象并查看

[root@master1 ~]#kubectl apply -f job-demo.yaml
job.batch/job-demo created

[root@master1 ~]#kubectl get job
NAME       COMPLETIONS   DURATION   AGE
job-demo   1/1           8s         2m40s
[root@master1 ~]#kubectl get po #注意下,这个就很奇怪了,0/1ready,证明目前0个job准备好了,也就是没有job正在运行了。
NAME                READY   STATUS      RESTARTS   AGE
job-demo--1-vwl74   0/1     Completed   0          2m42s
[root@master1 ~]#

📍step3:Job 对象创建成功后,我们可以查看下对象的详细描述信息:

[root@master1 ~]#kubectl describe job job-demo
Name:             job-demo
Namespace:        default
Selector:         controller-uid=3de30781-6de5-4264-b9c0-f39a8df772c3
Labels:           controller-uid=3de30781-6de5-4264-b9c0-f39a8df772c3
                  job-name=job-demo
Annotations:      <none>
Parallelism:      1
Completions:      1
Completion Mode:  NonIndexed
Start Time:       Sat, 20 Nov 2021 14:48:03 +0800
Completed At:     Sat, 20 Nov 2021 14:48:11 +0800
Duration:         8s
Pods Statuses:    0 Running / 1 Succeeded / 0 Failed
Pod Template:
  Labels:  controller-uid=3de30781-6de5-4264-b9c0-f39a8df772c3
           job-name=job-demo
  Containers:
   counter:
    Image:      busybox
    Port:       <none>
    Host Port:  <none>
    Command:
      bin/sh
      -c
      for i in 9 8 7 6 5 4 3 2 1;do echo $i;done
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Events:
  Type    Reason            Age    From            Message
  ----    ------            ----   ----            -------
  Normal  SuccessfulCreate  7m30s  job-controller  Created pod: job-demo--1-vwl74
  Normal  Completed         7m22s  job-controller  Job completed
[root@master1 ~]#

可以看到,Job 对象在创建后,它的 Pod 模板,被自动加上了一个 controller-uid=< 一个随机字符串 > 这样的 Label 标签,而这个 Job 对象本身,则被自动加上了这个 Label 对应的 Selector,从而 保证了 Job 与它所管理的 Pod 之间的匹配关系而 Job 控制器之所以要使用这种携带了 UID 的 Label,就是为了避免不同 Job 对象所管理的 Pod 发生重合。

📍step4:我们可以看到很快 Pod 变成了 Completed 状态,这是因为容器的任务执行完成正常退出了,我们可以查看对应的日志:

[root@master1 ~]#kubectl logs job-demo--1-vwl74
9
8
7
6
5
4
3
2
1
[root@master1 ~]#kubectl get po
NAME                READY   STATUS      RESTARTS   AGE
job-demo--1-vwl74   0/1     Completed   0          11m
[root@master1 ~]#

上面我们这里的 Job 任务对应的 Pod 在运行结束后,会变成 Completed 状态。

📍step5:在 Job 对象中通过设置字段 spec.activeDeadlineSeconds 来限制任务运行的最长时间

但是如果执行任务的 Pod 因为某种原因一直没有结束怎么办呢?同样我们可以在 Job 对象中通过设置字段 spec.activeDeadlineSeconds 来限制任务运行的最长时间,比如:

spec:
 activeDeadlineSeconds: 100

那么当我们的任务 Pod 运行超过了 100s 后,这个 Job 的所有 Pod 都会被终止,并且, Pod 的终止原因会变成 DeadlineExceeded

我们可以先看下这个字段的含义:

[root@master1 ~]#kubectl explain job.spec
……
     Specifies the duration in seconds relative to the startTime that the job
     may be continuously active before the system tries to terminate it; value
     must be positive integer. If a Job is suspended (at creation or through an
     update), this timer will effectively be stopped and reset when the Job is
     resumed again.
     
指定与作业的startTime相对的持续时间()  
可能在系统试图终止它之前一直处于活动状态; 价值  
必须是正整数。 如果Job被挂起(在创建时或通过  
更新),该计时器将有效地停止并重置时,作业  
再次恢复。  
……

📍step6:模拟job执行失败情况,验证pod重启策略Never和Onfailure

如果的任务执行失败了,会怎么处理呢,这个和定义的 restartPolicy 有关系,比如定义如下所示的 Job 任务,定义 restartPolicy: Never 的重启策略:

[root@master1 ~]#vim job-failedl-demo.yaml

# job-failed-demo.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: job-failed-demo
spec:
  template:
    spec:
      containers:
      - name: test-job
        image: busybox
        command: ["echo123", "test failed job!"]
      restartPolicy: Never

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

[root@master1 ~]#kubectl apply -f job-failed-demo.yaml
job.batch/job-failed-demo created

查看现象:

[root@master1 ~]#kubectl get po,job
NAME                           READY   STATUS       RESTARTS   AGE
pod/job-demo--1-vwl74          0/1     Completed    0          19h
pod/job-failed-demo--1-f5zw7   0/1     StartError   0          7m58s
pod/job-failed-demo--1-jfctk   0/1     StartError   0          8m17s
pod/job-failed-demo--1-k6szv   0/1     StartError   0          2m37s
pod/job-failed-demo--1-lsz8n   0/1     StartError   0          7m18s
pod/job-failed-demo--1-p9rm4   0/1     StartError   0          6m38s
pod/job-failed-demo--1-r4mbc   0/1     StartError   0          5m17s

NAME                        COMPLETIONS   DURATION   AGE
job.batch/job-demo          1/1           8s         19h
job.batch/job-failed-demo   0/1           8m17s      8m17s
[root@master1 ~]#

#我们可以再看一个pod里面的详细信息
[root@master1 ~]#kubectl describe po job-failed-demo--1-f5zw7
Name:         job-failed-demo--1-f5zw7
Namespace:    default
Priority:     0
Node:         node2/172.29.9.53
……
Events:
  Type     Reason       Age                 From               Message
  ----     ------       ----                ----               -------
  Normal   Scheduled    9m19s               default-scheduler  Successfully assigned default/job-failed-demo--1-f5zw7 to node2
  Normal   Pulling      9m18s               kubelet            Pulling image "busybox"
  Normal   Pulled       9m3s                kubelet            Successfully pulled image "busybox" in 15.250674145s
  Normal   Created      9m3s                kubelet            Created container test-job
  Warning  Failed       9m1s                kubelet            Error: failed to create containerd task: failed to create shim: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "echo123": executable file not found in $PATH: unknown
  Warning  FailedMount  8m56s (x4 over 9m)  kubelet            MountVolume.SetUp failed for volume "kube-api-access-x78p4" : object "default"/"kube-root-ca.crt" not registered
[root@master1 ~]#

可以看到当我们设置成 Never 重启策略的时候,Job 任务执行失败后会不断创建新的 Pod,但是不会一直创建下去,会根据 spec.backoffLimit 参数进行限制,默认为6,通过该字段可以定义重建 Pod 的次数,另外需要注意的是 Job 控制器重新创建 Pod 的间隔是呈指数增加的,即下一次重新创建 Pod 的动作会分别发生在 10s、20s、40s… 后。

[root@master1 ~]#kubectl explain job.spec
backoffLimit <integer>
     Specifies the number of retries before marking this job failed. Defaults to
     6

这里我们将上面这个job-failed-demo.yaml给删除掉:

[root@master1 ~]#kubectl delete -f job-failed-demo.yaml
job.batch "job-failed-demo" deleted
[root@master1 ~]#kubectl get po,job
NAME                    READY   STATUS      RESTARTS   AGE
pod/job-demo--1-vwl74   0/1     Completed   0          19h

NAME                 COMPLETIONS   DURATION   AGE
job.batch/job-demo   1/1           8s         19h
[root@master1 ~]#

但是如果我们设置的 restartPolicy: OnFailure 重启策略,则当 Job 任务执行失败后不会创建新的 Pod 出来,只会不断重启 Pod。这里,我们继续测试一下效果。

#创建资源清单
[root@master1 ~]#vim job-failedl-demo.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: job-failed-demo
  namespace: default
spec:
  template:
    spec:
      containers:
      - name: test-job
        image: busybox
        command: ["echo123", "test failed job"]
      restartPolicy: OnFailure

#apply
[root@master1 ~]#kubectl apply -f job-failed-demo.yaml
job.batch/job-failed-demo created

#查看:如果我们设置的 `restartPolicy: OnFailure` 重启策略,则当 Job 任务执行失败后不会创建新的 Pod 出来,只会不断重启 Pod。
[root@master1 ~]#kubectl get po
NAME                       READY   STATUS             RESTARTS      AGE
job-demo--1-vwl74          0/1     Completed          0             19h
job-failed-demo--1-n4mbz   0/1     CrashLoopBackOff   3 (24s ago)   2m22s
[root@master1 ~]#

#我们可以看一下这个pod的详细信息
[root@master1 ~]#kubectl describe pod job-failed-demo--1-n4mbz
……
Events:
  Type     Reason     Age                  From               Message
  ----     ------     ----                 ----               -------
  Normal   Scheduled  2m49s                default-scheduler  Successfully assigned default/job-failed-demo--1-n4mbz to node2
  Normal   Pulled     2m32s                kubelet            Successfully pulled image "busybox" in 15.244757032s
  Normal   Pulled     2m13s                kubelet            Successfully pulled image "busybox" in 15.231214243s
  Normal   Pulled     100s                 kubelet            Successfully pulled image "busybox" in 15.241950728s
  Normal   Created    55s (x4 over 2m31s)  kubelet            Created container test-job
  Normal   Pulled     55s                  kubelet            Successfully pulled image "busybox" in 15.210533743s
  Warning  Failed     52s (x4 over 2m28s)  kubelet            Error: failed to create containerd task: failed to create shim: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "echo123": executable file not found in $PATH: unknown
  Warning  BackOff    15s (x8 over 2m10s)  kubelet            Back-off restarting failed container
  Normal   Pulling    4s (x5 over 2m47s)   kubelet            Pulling image "busybox"
[root@master1 ~]#

#验证完之后,我们继续把这个job-failed-demo.yaml给删除掉
[root@master1 ~]#kubectl delete -f job-failed-demo.yaml
job.batch "job-failed-demo" deleted

注意:个人对这里有些不太明白。关于pod重启策略,到底是重启pod,还是重建pod呢?AlwaysOnFailureNever

image-20211121151546887

📍step6:测试parallelism和completions参数

除此之外,我们还可以通过设置 spec.parallelism 参数来进行并行控制,该参数定义了一个 Job 在任意时间最多可以有多少个 Pod 同时运行spec.completions 参数可以定义 Job 至少要完成的 Pod 数目。如下所示创建一个新的 Job 任务,设置允许并行数为2,至少要完成的 Pod 数为8:

我们先来看下这2个参数的官方定义:

[root@master1 ~]#kubectl explain job.spec
   completions  <integer>
     Specifies the desired number of successfully finished pods the job should
     be run with. Setting to nil means that the success of any pod signals the
     success of all pods, and allows parallelism to have any positive value.
     Setting to 1 means that parallelism is limited to 1 and the success of that
     pod signals the success of the job. More info:
     https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/


   parallelism  <integer>
     Specifies the maximum desired number of pods the job should run at any
     given time. The actual number of pods running in steady state will be less
     than this number when ((.spec.completions - .status.successful) <
     .spec.parallelism), i.e. when the work left to do is less than max
     parallelism. More info:
     https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/

1、创建资源清单
[root@master1 ~]#vim job-para-demo.yaml
# job-para-demo.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: job-para-test
spec:
  parallelism: 2
  completions: 8
  template:
    spec:
      containers:
      - name: test-job
        image: busybox
        command: ["echo", "test paralle job!"]
      restartPolicy: Never

2、apply
[root@master1 ~]#kubectl apply -f job-para-demo.yaml
job.batch/job-para-demo created

3、查看
[root@master1 ~]#kubectl get po,job
NAME                         READY   STATUS              RESTARTS   AGE
pod/job-demo--1-vwl74        0/1     Completed           0          19h
pod/job-para-demo--1-2zc7k   0/1     ContainerCreating   0          4s
pod/job-para-demo--1-ghnwh   0/1     Completed           0          24s
pod/job-para-demo--1-nkdz7   0/1     ContainerCreating   0          24s

NAME                      COMPLETIONS   DURATION   AGE
job.batch/job-demo        1/1           8s         19h
job.batch/job-para-demo   1/8           24s        24s


[root@master1 ~]#kubectl get po,job
NAME                         READY   STATUS      RESTARTS   AGE
pod/job-demo--1-vwl74        0/1     Completed   0          19h
pod/job-para-demo--1-2zc7k   0/1     Completed   0          109s
pod/job-para-demo--1-7zkg5   0/1     Completed   0          64s
pod/job-para-demo--1-968px   0/1     Completed   0          34s
pod/job-para-demo--1-9j497   0/1     Completed   0          80s
pod/job-para-demo--1-f8nf5   0/1     Completed   0          94s
pod/job-para-demo--1-ghnwh   0/1     Completed   0          2m9s
pod/job-para-demo--1-l8p7v   0/1     Completed   0          49s
pod/job-para-demo--1-nkdz7   0/1     Completed   0          2m9s

NAME                      COMPLETIONS   DURATION   AGE
job.batch/job-demo        1/1           8s         19h
job.batch/job-para-demo   8/8           2m7s       2m9s
[root@master1 ~]#

可以看到一次可以有2个 Pod 同时运行,需要8个 Pod 执行成功(默认是1个),如果不是8个成功,那么会根据 restartPolicy 的策略进行处理,可以认为是一种检查/重试机制(一般可能设置成2或者3)

实验结束。

2.CronJob

CronJob 其实就是在 Job 的基础上加上了时间调度,我们可以在给定的时间点运行一个任务,也可以周期性地在给定时间点运行。这个实际上和我们 Linux 中的 crontab 就非常类似了。

一个 CronJob 对象其实就对应中 crontab 文件中的一行,它根据配置的时间格式周期性地运行一个 Job,格式和 crontab 也是一样的。

crontab 的格式为:分 时 日 月 星期 要运行的命令

  • 第1列分钟 0~59
  • 第2列小时 0~23
  • 第3列日 1~31
  • 第4列月 1~12
  • 第5列星期 0~7(0和7表示星期天)
  • 第6列要运行的命令

❤️实验演示:

老样子,首先我们来看下CronJob的字段:

[root@master1 ~]#kubectl explain CronJob.spec
FIELDS:
   concurrencyPolicy    <string>
     Specifies how to treat concurrent executions of a Job. Valid values are: -
     "Allow" (default): allows CronJobs to run concurrently; - "Forbid": forbids
     concurrent runs, skipping next run if previous run hasn't finished yet; -
     "Replace": cancels currently running job and replaces it with a new one
#单词说明:concurrentcy 并发,并行  executions执行册数,运行次数

   failedJobsHistoryLimit       <integer>
     The number of failed finished jobs to retain. Value must be non-negative
     integer. Defaults to 1.
#单词说明:non-negative非负的,正的

   jobTemplate  <Object> -required->
     Specifies the job that will be created when executing a CronJob.

   schedule     <string> -required->
     The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron.

   startingDeadlineSeconds      <integer>
     Optional deadline in seconds for starting the job if it misses scheduled
     time for any reason. Missed jobs executions will be counted as failed ones.

   successfulJobsHistoryLimit   <integer>
     The number of successful finished jobs to retain. Value must be
     non-negative integer. Defaults to 3.

   suspend      <boolean>
     This flag tells the controller to suspend subsequent executions, it does
     not apply to already started executions. Defaults to false.
#单词说明:suspend v.悬挂;暂停,中止 subsequent 分布式
[root@master1 ~]#

📍step1:现在,我们用 CronJob 来管理我们上面的 Job 任务,定义如下所示的资源清单:

[root@master1 ~]#vim cronjob-demo.yaml
# cronjob-demo.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: cronjob-demo
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
          - name: hello
            image: busybox
            args:
            - "bin/sh"
            - "-c"
            - "for i in 9 8 7 6 5 4 3 2 1; do echo $i; done"

这里的 Kind 变成了 CronJob 了,要注意的是 .spec.schedule 字段是必须填写的,用来指定任务运行的周期,格式就和 crontab 一样。
另外一个字段是 .spec.jobTemplate, 用来指定需要运行的任务,格式当然和 Job 是一致的。
还有一些值得我们关注的字段 .spec.successfulJobsHistoryLimit(默认为3) 和 .spec.failedJobsHistoryLimit(默认为1),表示历史限制,是可选的字段,指定可以保留多少完成和失败的 Job。然而,当运行一个 CronJob 时,Job 可以很快就堆积很多,所以一般推荐设置这两个字段的值,如果设置限制的值为 0,那么相关类型的 Job 完成后将不会被保留。

📍step2:我们直接新建上面的资源对象:

[root@master1 ~]#kubectl apply -f cronjob-demo.yaml
cronjob.batch/cronjob-demo created

📍setp3:然后可以查看对应的 Cronjob 资源对象:

[root@master1 ~]#kubectl get cronjobs
NAME           SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob-demo   */1 * * * *   False     1        14s             16s
或者:
[root@master1 ~]#kubectl get cj
NAME           SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob-demo   */1 * * * *   False     1        18s             20s

📍setp4:稍微等一会儿查看可以发现多了几个 Job 资源对象,这个就是因为上面我们设置的 CronJob 资源对象,每1分钟执行一个新的 Job:

[root@master1 ~]#kubectl get po,job
NAME                                 READY   STATUS              RESTARTS   AGE
pod/cronjob-demo-27291254--1-m54nz   0/1     Completed           0          79s
pod/cronjob-demo-27291255--1-m8l8v   0/1     ContainerCreating   0          19s

NAME                              COMPLETIONS   DURATION   AGE
job.batch/cronjob-demo-27291254   1/1           22s        79s
job.batch/cronjob-demo-27291255   0/1           19s        19s
[root@master1 ~]#

再过一段时间查看:
[root@master1 ~]#kubectl get po,job
NAME                                 READY   STATUS              RESTARTS   AGE
pod/cronjob-demo-27291254--1-m54nz   0/1     Completed           0          2m10s
pod/cronjob-demo-27291255--1-m8l8v   0/1     Completed           0          70s
pod/cronjob-demo-27291256--1-d449d   0/1     ContainerCreating   0          10s

NAME                              COMPLETIONS   DURATION   AGE
job.batch/cronjob-demo-27291254   1/1           22s        2m10s
job.batch/cronjob-demo-27291255   1/1           21s        70s
job.batch/cronjob-demo-27291256   0/1           10s        10s
[root@master1 ~]#

📍setp5这个就是 CronJob 的基本用法,一旦不再需要 CronJob,我们可以使用 kubectl 命令删除它:

[root@master1 ~]#kubectl delete cronjob cronjob-demo
cronjob "cronjob-demo" deleted

不过需要注意的是这将会终止正在创建的 Job,但是运行中的 Job 将不会被终止,不会删除 Job 或 它们的 Pod。

思考:那如果我们想要在每个节点上去执行一个 Job 或者 Cronjob 又该怎么来实现呢?

关于我

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

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

  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

最后

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

image-20211121142536270

Logo

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

更多推荐