kubernetes之Cronjob应用和踩坑

Cron Job 是什么?

Cron Job 管理基于时间的 job,即:

  • 在给定时间点只运行一次
  • 在给定时间点周期性地运行

一个 CronJob 对象类似于 crontab (cron table)文件中的一行。它根据指定的预定计划周期性地运行一个 Job,格式可以参考 Cron 。

注意: 在预定计划中,问号(?)和星号(*)的意义是相同的,表示给定字段的取值是任意可用值。

注意: 在 Kubernetes 1.4 版本引入了 ScheduledJob 资源,但从 1.5 版本开始改成了 CronJob。

典型的用法如下所示:

  • 在给定的时间点调度 Job 运行
  • 创建周期性运行的 Job,例如:数据库备份、发送邮件。

前提条件

当使用的 Kubernetes 集群,版本 >= 1.4(对 ScheduledJob),>= 1.5(对 CronJob),当启动 API Server(参考 为集群开启或关闭 API 版本 获取更多信息)时,通过传递选项 --runtime-config=batch/v2alpha1=true 可以开启 batch/v2alpha1 API。

Cron Job 限制

Cron Job 在每次调度运行时间内 大概 会创建一个 Job 对象。我们之所以说 大概 ,是因为在特定的环境下可能会创建两个 Job,或者一个 Job 都没创建。我们尝试少发生这种情况,但却不能完全避免。因此,创建 Job 操作应该是 _幂等的_。

Job 根据它所创建的 Pod 的并行度,负责重试创建 Pod,并就决定这一组 Pod 的成功或失败。Cron Job 根本不会去检查 Pod。

编写 Cron Job 规约

和其它 Kubernetes 配置一样,Cron Job 需要 apiVersion、 kind、和 metadata 这三个字段。 关于如何实现一个配置文件的更新信息,参考文档 部署应用、 配置容器 和 使用 kubectl 管理资源

Cron Job 也需要 .spec 段

注意: 对一个 Cron Job 的所有修改,尤其是对其 .spec 的修改,仅会在下一次运行的时候生效。

调度

.spec.schedule 是 .spec 中必需的字段,它的值是 Cron 格式字的符串,例如:0 * * * *,或者 @hourly,根据指定的调度时间 Job 会被创建和执行。

Job 模板

.spec.jobTemplate 是另一个 .spec 中必需的字段。它是 Job 的模板。 除了它可以是嵌套的,并且不具有 apiVersion 或 kind 字段之外,它和 Job 一样具有完全相同的模式(schema)。 参考 编写 Job 规格

启动 Job 的期限(秒级别)

.spec.startingDeadlineSeconds 字段是可选的。它表示启动 Job 的期限(秒级别),如果因为任何原因而错过了被调度的时间,那么错过执行时间的 Job 将被认为是失败的。如果没有指定,则没有期限。

并发策略

.spec.concurrencyPolicy 字段也是可选的。它指定了如何处理被 Cron Job 创建的 Job 的并发执行。只允许指定下面策略中的一种:

  • Allow(默认):允许并发运行 Job
  • Forbid:禁止并发运行,如果前一个还没有完成,则直接跳过下一个
  • Replace:取消当前正在运行的 Job,用一个新的来替换

注意,当前策略只能应用于同一个 Cron Job 创建的 Job。如果存在多个 Cron Job,它们创建的 Job 之间总是允许并发运行。

挂起

.spec.suspend 字段也是可选的。如果设置为 true,后续所有执行都将被挂起。它对已经开始执行的 Job 不起作用。默认值为 false

Job 历史限制

.spec.successfulJobsHistoryLimit 和 .spec.failedJobsHistoryLimit 这两个字段是可选的。它们指定了可以保留完成和失败 Job 数量的限制。

默认没有限制,所有成功和失败的 Job 都会被保留。然而,当运行一个 Cron Job 时,很快就会堆积很多 Job,推荐设置这两个字段的值。设置限制值为 0,相关类型的 Job 完成后将不会被保留。


 上面只是引用 https://kubernetes.io/zh/docs/concepts/workloads/controllers/cron-jobs/  k8s中文网的介绍  下面将介绍一下几个重要的配置和遇到的坑

  首先贴一个定时任务的配置

  

apiVersion: batch/v1beta1 #版本
kind: CronJob
metadata:
  name: xxxxxx  #名称
  namespace: xxxx #项目分组
spec:
  concurrencyPolicy: Replace   #重点  并发策略
  failedJobsHistoryLimit: 1     #重点   失败任务历史显示个数
  jobTemplate:
    metadata: {}
    spec:
      activeDeadlineSeconds: 600
      backoffLimit: 6
      completions: 1
      parallelism: 1
      template:
        metadata: {}
        spec:
          containers:
          - command:
            - curl
            - '-i'
            - >-
              www.baidu.com
            env:
            - name: MYPATH
              value: /usr/local
            image: >-
              registry-vpc.cn-shanghai.aliyuncs.com/jinlincentos/mycentos:1.4.1
            imagePullPolicy: IfNotPresent
            name: xxxxx  #应用名称
            ports:
            - containerPort: 80
              protocol: TCP
            resources:
              requests:
                cpu: 250m
                memory: 512Mi
            terminationMessagePath: /dev/termination-log
            terminationMessagePolicy: File
          dnsPolicy: ClusterFirst
          restartPolicy: Never    #重启策略
          schedulerName: default-scheduler
          securityContext: {}
          terminationGracePeriodSeconds: 30
  schedule: '*/1 * * * *'     #表达式 每分钟执行一次
  startingDeadlineSeconds: 60   #重点 job存活时间 默认不设置为永久
  successfulJobsHistoryLimit: 1  #重点 成功job历史显示个数
  suspend: true               #true 挂起 不运行  false 及运行

 下面说下 重点的几个配置:


  spec.concurrencyPolicy(并发策略):    Allow(默认):允许并发运行 ,会把停止后的job 和现在新创建的一起运行
                             JobForbid:禁止并发运行,如果一个新的Job创建时,正在运行一个旧Job,那么CronJob controller则不会创建这个新Job
                             Replace:如果一个新的Job创建时,正在运行一个旧Job,那么CronJob controller会使用这个新Job替代正在运行的旧Job
 
  restartPolicy(重启策略):            Always | Never | OnFailure]#Pod的重启策略(阿里只支持 Never 和 OnFailure)
                                                         Always:表示一旦不管以何种方式终止运行,kubelet都将重启,
                                                         OnFailure:表示只有Pod以非0退出码退出才重启, 
                                                         Nerver:表示不再重启该Pod
 
   .spec.successfulJobsHistoryLimit 和  .spec.failedJobsHistoryLimit 这两个字段是可选的。它们指定了可以保留完成和失败 Job 数量的限制。
 
  解释下几个参数和坑:
   以一个任务一分钟执行一次 , 17:00开始执行 为例:
   *   如果并发策略使用默认的Allow,那么手动停止及 suspend: true ,或者出现问题导致容器停止后下次开启或恢复,cronjob会根据  lastScheduleTime 和 你的cron表达式计算出中间错过多少个job,旧的job和新的job将一起运行,值得注意的是 如果旧的job 超过100个 k8s 将报错,启动或者回复容器后将不会运行,及17:05停止 等到18:00启动时 他会把 17:05-18:00应该运行的都执行一遍同时执行18:01的任务,如果你是19:00执行 这时17:05-17:00中间未执行的任务超过100个,将不会执行,这时你可以删除该应用重新新建或者 修改spec.startingDeadlineSeconds(下面会说到)参数后启动。
   
   *   如果并发策略使用的是 JobForbid,那么会先运行旧的job,新的job将不会执行 及先执行 17:05-18:00错过的任务
    
   *   如果并发策略使用 Replace,那么旧的job将不会运行,直接运行新的job 及不执行17:05-18:00错过的任务 直接执行18:01的任务
 
   *  不管使用以上那种策略 一定要设置  spec.startingDeadlineSeconds时间,这个参数指容器没有按时启动时,超过该时间就判断改job运行为失败,并且代表改job已经运行,时间设定应该大于cron表达式执行时间,只有设置了这个超时参数,旧的job才永远不会超过100个,不会影响我们停止应用的操作。
 
 * 设置.spec.successfulJobsHistoryLimit 和  .spec.failedJobsHistoryLimit限制后,该job会保存 但是因为一个job对应一个容器组,所以会有多个容器组存在(浪费资源)
 
   * cronjob运行流程为  创建job  ——> 然后job会创建pod ——> 然后执行调度 ——> 然后销毁pod   理解为 在高频率的定时任务就是不断的创建pod然后删除pod 个人觉得这样很占用资源
 
 
 
  以上为个人使用cronjob遇到的问题,做个记录方面后面学习使用。
  

猜你喜欢

转载自www.cnblogs.com/hgjit/p/10724925.html