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遇到的問題,做個記錄方面后面學習使用。
  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM