首页 > 其他分享 >29-Kubernete 中也有定时任务吗?

29-Kubernete 中也有定时任务吗?

时间:2024-01-11 13:56:30浏览次数:30  
标签:name job 29 Pod Job 定时 pi Kubernete spec

前面我们学习了 Deployment、Statefulset、Daemonset 这些工作负载,它们可以帮助我们在不同的场景下运行长伺型(Long Running)的服务。

但是有一类业务(一次性作业和定时任务)运行完就结束了,不需要长期运行,如果使用上述的那些工作负载就无法满足我们的要求。比如 Pod 运行结束后,会被 Deployment、Statefulset 控制器重启或者创建新的副本替换掉,而这并不是我们期望的行为。

所以说,对于这类作业任务,我们需要新的工作负载类型来描述。在 Kubernetes 中,我们分别用 Job 和 Cronjob 来描述一次性任务和定时任务。

我们先来看看 Job。

Job

我通过一个官方的例子来带你了解这个工作负载类型:

apiVersion: batch/v1beta1
kind: Job
metadata:
  name: pi
spec:
  template:
    spec:
      containers:
      - name: pi
        image: perl
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never
  backoffLimit: 4

这个 Job 负责计算 π 到小数点后的 2000 位,并将结果打印出来。

我们可以通过 kubectl create 命令将该 Job 创建出来:

$ kubectl create -f https://kubernetes.io/examples/controllers/job.yaml
job.batch/pi created

创建好了以后,我们来看下这个 Job:

kubectl describe jobs/pi
Name:           pi
Namespace:      default
Selector:       controller-uid=4f8027d0-cac1-42ea-b5f8-dbb4d9c9f67a
Labels:         controller-uid=4f8027d0-cac1-42ea-b5f8-dbb4d9c9f67a
                job-name=pi
Annotations:    <none>
Parallelism:    1
Completions:    1
Start Time:     Mon, 02 Dec 2020 15:04:52 +0200
Completed At:   Mon, 02 Dec 2020 15:06:39 +0200
Duration:       65s
Pods Statuses:  0 Running / 1 Succeeded / 0 Failed
Pod Template:
  Labels:  controller-uid=c9948307-e56d-4b5d-8302-ae2d7b7da67c
           job-name=pi
  Containers:
   pi:
    ...
Events:
  Type    Reason            Age   From            Message
  ----    ------            ----  ----            -------
  Normal  SuccessfulCreate  4m    job-controller  Created pod: pi-jk2k7

在这段代码中,有几点需要特别注意下。

  1. 系统自动给 Job 添加了 Selector,即 controller-uid=4f8027d0-cac1-42ea-b5f8-dbb4d9c9f67a,后面的这个 uid 就是指该 Job 自己的 uid。

  2. Job 上会自动被加上了 Label,即 controller-uid=4f8027d0-cac1-42ea-b5f8-dbb4d9c9f67a 和 job-name=pi。

  3. Job 中 spec.podTemplate 中也被加上了 Label,即 controller-uid=4f8027d0-cac1-42ea-b5f8-dbb4d9c9f67a 和 job-name=pi。这样 Job 就可以通过这些 Label 和 Pod 关联起来,从而控制 Pod 的创建、删除等操作。

我们可以通过这些 Label 来找到对应的 Pod。你可以直接使用 Job 的名字,这个最简洁最方便:

kubectl get pods --selector=job-name=pi

或者你也可以选择使用 Job 的 uid:

kubectl get pods --selector=controller-uid=4f8027d0-cac1-42ea-b5f8-dbb4d9c9f67a

我们可以看到,由 Job 创建出来的 Pod 已经运行结束,为 Completed 状态。

NAME       READY    STATUS       RESTARTS    AGE
pi-jk2k7   0/1      Completed    0           2m

如果说 Pod 运行过程中异常退出了,那就会根据的 Job 中 PodTemplate 定义的重启策略(restart policy)来操作。对于 Job 来说,我们当然不希望一直重启,因此这里的 restartPolicy 只能为 Never 或者 OnFailure。

如果说创建出来的 Pod 一直由于某些原因,导致运行不成功,怎么办呢?这个时候Job 控制器会根据 spec.backoffLimit 中定义的数值来限制 Pod 失败的次数。默认值是 6,我们在例子中设置为 4。达到这个次数以后,Job controller 便不会再新建 Pod,并直接停止运行这个 Job,将其标记为 Failure。

Job 还支持创建多个 Pod 并发地运行,我们来看另一个官方的例子“使用工作队列进行精细的并行处理”:

apiVersion: batch/v1
kind: Job
metadata:
  name: job-wq-2
spec:
  parallelism: 2
  template:
    metadata:
      name: job-wq-2
    spec:
      containers:
      - name: c
        image: gcr.io/myproject/job-wq-2
      restartPolicy: OnFailure

在 Job 的定义中通过 spec.parallelism 字段,我们可以指定并发运行的 Pod 数目。我们这里指定为 2,也就是会创建 2 个同时运行的 Pod。

例子中的 2 个 Pod 都会不停地从队列中获取数据进行处理,直到队列为空后退出,运行结束。

Job 还支持其他的工作模式,比如通过模板渲染 Job 来支持批量任务的处理等等。你可以参照官方文档来解锁 Job 更多地使用场景,并动手学习实践。

通常来说,Job 运行结束,即状态为 Completed 或 Failure 时,我们并不需要在系统中继续保留该对象,尤其是这种对象较多的时候,会给 kube-apiserver 的 cache 以及系统访问带来很大的压力。

这个时候我们就可以使用TTL 控制器提供 的 TTL 能力了。

我们只需要在 Job 的 spec.ttlSecondsAfterFinished 字段设置一下,就可以让该控制器帮我们自动清理掉已经结束的资源,包括 Job 本身及其关联的 Pod 对象。

我们来看下面这个例子:

apiVersion: batch/v1
kind: Job
metadata:
  name: pi-with-ttl
spec:
  ttlSecondsAfterFinished: 100
  template:
    spec:
      containers:
      - name: pi
        image: perl
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never

该 Job 在运行结束 100 秒之后就被自动清理删除了,包括创建出来的 Pod。

目前这种 TTL 的能力还处于 Alpha 阶段,如果你要使用的话,需要手动开启 TTLAfterFinished 这个 feature gate,具体可以参考 TTL 控制器的文档学习如何打开和使用这个功能。

我们再来看看 CronJob。

CronJob

从名字就可以看出来,这个工作负载是用于定时任务的,比如每隔 1 分钟执行 1 次任务。

我们来看一个官方的 CronJob 的例子,这个例子比较简单明了:

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: hello # cronjob 名字
spec:
  schedule: "*/1 * * * *" # job执行的周期,通过 cron 格式来标明
  jobTemplate: # job模板
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            imagePullPolicy: IfNotPresent
            args:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure

CronJob 通过 spec.schedule 字段来标明 Job 被创建和执行的周期,该字段段用Cron格式编写。Cron 的基本格式为:

<分钟> <小时> <日> <月> <星期>

其中分钟的值从 0 到 59,小时的值从 0 到 23,日的值从 1 到 31,月的值从 1 到 12,星期的值从 0 到 6,0 表示星期日。

Cron 还支持“*,-/”等字符,其中 * 是个通配符,可以匹配任何值;/ 则表示起始时间触发,然后每隔一个固定时间触发一次。例如我们如果在分钟中设置 10/20,则表示第一次触发在第 10 分钟,接下来每隔 20 分钟触发一次,也就是第 30 分钟、第 50 分钟等依次往后的时间点触发一次。

所以我们例子中的"*/1 * * * *"表示每隔一分钟触发一次新 Job 的执行。

例子中的 spec.jobTemplate 指定了 Job 的模板,CronJob 控制器会根据 Cron 设置的时间触发新的 Job 创建。因此,我们修改 CronJob 的 spec,只会影响新 Job 的spec 配置,对于已经创建的 Job spec 不会有任何影响。

CronJob 会帮助我们管理 Job,比如自动清理运行完的 Job;也就是说,由 CronJob 管理的 Job,我们不需要去配置上文提到的 TTL 自动清理,CronJob 控制器会自动帮我们清理。CronJob 通过 spec.successfulJobsHistoryLimit 和 spec.failedJobsHistoryLimit 来限制保留已完成的 Job 数量,确保不会有大量的 Job 残留在系统中。默认值分别为 3 和 1。

当然在 CronJob 被触发,创建新的 Job 的时候,还会出现一种情形:上一次触发的 Job 还未执行完成。如果这个时候触发了另一个新 Job 的创建,势必会导致任务重叠。此时就需要你结合自己的业务来考虑这种行为对业务的影响了。

你可以在 spec.concurrentPolicy 中配置:

  • 设置为 Allow,这也是默认的值,允许并发任务的执行;

  • 设置为 Forbid,不允许并发任务执行;

  • 设置为 Replace,用新的 Job 来替换当前正在运行的老的 Job。

写在最后

这一讲,我带你了解了如何在 Kubernetes 中设置定时任务。所有 Cronjob 中的 schedule 字段中的时间都是基于 kube-controller-manager 的时区。我们在搭建环境的时候,最好将各个节点上的时间进行同步,这样可以避免很多奇奇怪怪的问题。

如果你对本节课有什么想法或者疑问,欢迎你在留言区留言,我们一起讨论。


标签:name,job,29,Pod,Job,定时,pi,Kubernete,spec
From: https://www.cnblogs.com/huangjiale/p/17958435

相关文章

  • 28-面向 K8 编程:如何通过 Operator 扩展 Kubernete API?
    你好,我是正范。在上一讲,我们学习了如何通过一个YAML文件来定义一个CRD,即扩展API。这种扩展API跟Kubernetes内置的其他API同等地位,都可以通过kubectl或者REST接口访问,在使用过程中不会有任何差异。但只是定义一个CRD并没有什么作用。虽说kube-apiserver会将其数......
  • 08-配置管理:Kubernete 管理业务配置方式有哪些?配置管理:Kubernete 管理业务配置方式有
    通过前面几节课的学习,我们已经对Kubernetes中的Pod以及一些业务负载有所了解。你可以根据课程中提供的示例,自己动手尝试在集群中实践起来。在使用过程中,我们常常需要对Pod进行一些配置管理,比如参数配置文件怎么使用,敏感数据怎么保存传递,等等。有些人可能会觉得,为什么不把这......
  • 14-日志采集:如何在 Kubernete 中做日志收集与管理?
    说到日志,你应该不陌生。日志中不仅记录了代码运行的实时轨迹,往往还包含着一些关键的数据、错误信息,等等。日志方便我们进行分析统计及监控告警,尤其是在后期问题排查的时候,我们通过日志可以很方便地定位问题、现场复现及问题修复。日志也是做可观测性(Observability)必不可少的一部分......
  • 13-服务守护进程:如何在 Kubernete 中运行 DaemonSet 守护进程?
    通过前面课程的学习,我们对Kubernetes中一些常见工作负载已经有所了解。比如无状态工作负载Dployment可以帮助我们运行指定数目的服务副本,并维护其状态,而对于有状态服务来说,我们同样可以采用StatefulSet来做到这一点。但是,在实际使用的时候,有些场景,比如监控各个节点的状态,使......
  • 15-Prometheu:Kubernete 怎样实现自动化服务监控告警?
    通过之前的学习,我们已经对Kubernetes有了一定的理解,也知道如何在Kubernetes中部署自己的业务系统。Kubernetes强大的能力让我们非常方便地使用容器部署业务。Kubernetes自带的副本保持能力,可以避免部署的业务系统出现单点故障,提高可用性。各种探针也可以帮助我们对运行中的......
  • 17-案例实战:教你快速搭建 Kubernete 监控平台
    Prometheus和Grafana可以说是Kubernetes监控解决方案中最知名的两个。Prometheus负责收集、存储、查询数据,而Grafana负责将Prometheus中的数据进行可视化展示,当然Grafana还支持其他平台,比如ElasticSearch、InfluxDB、Graphite等。CNCF博客也将这两者称为黄金组合,目......
  • 16-迎战流量峰值:Kubernete 怎样控制业务的资源水位?
    通过前面的学习,相信你已经见识到了Kubernetes的强大能力,它能帮你轻松管理大规模的容器服务,尤其是面对复杂的环境时,比如节点异常、容器异常退出等,Kubernetes内部的Service、Deployment会动态地进行调整,比如增加新的副本、关联新的Pod等。当然Kubernetes的这种自动伸缩能......
  • 18-权限分析:Kubernete 集群权限管理那些事儿
    你好,我是正范。通过前面的课程学习,你已经学会了使用kubectl命令行,或者直接发送REST请求,以及使用各种语言的client库来跟APIServer进行交互。那么你是否知道在这其中Kubernetes是如何对这些请求进行认证、授权的呢?这节课,我们就来一探究竟。任何请求访问Kubernetes的kub......
  • 19-资源限制:如何保障你的 Kubernete 集群资源不会被打爆
    前面的课时中,我们曾提到通过HPA控制业务的资源水位,通过ClusterAutoscaler自动扩充集群的资源。但如果集群资源本身就是受限的情况下,或者一时无法短时间内扩容,那么我们该如何控制集群的整体资源水位,保障集群资源不会被“打爆”?今天我们就来看看Kubernetes中都有哪些能力可以......
  • 20-资源优化:Kubernete 中有 GC(垃圾回收)吗?
    GarbageCollector即垃圾回收,通常简称GC,和你之前在其他编程语言中了解到的GC基本上是一样的,用来清理一些不用的资源。Kubernetes中有各种各样的资源,当然需要GC啦,今天我们就一起来了解下Kubernetes中的GC。你可能最先想到的就是容器的清理,即Kubelet侧的GC,清理许多处于......