Kubernetes(k8s)定時任務:CronJob

2023-06-02 18:00:47

一.系統環境

本文主要基於Kubernetes1.21.9和Linux作業系統CentOS7.4。

伺服器版本 docker軟體版本 Kubernetes(k8s)叢集版本 CPU架構
CentOS Linux release 7.4.1708 (Core) Docker version 20.10.12 v1.21.9 x86_64

Kubernetes叢集架構:k8scloude1作為master節點,k8scloude2,k8scloude3作為worker節點。

伺服器 作業系統版本 CPU架構 程序 功能描述
k8scloude1/192.168.110.130 CentOS Linux release 7.4.1708 (Core) x86_64 docker,kube-apiserver,etcd,kube-scheduler,kube-controller-manager,kubelet,kube-proxy,coredns,calico k8s master節點
k8scloude2/192.168.110.129 CentOS Linux release 7.4.1708 (Core) x86_64 docker,kubelet,kube-proxy,calico k8s worker節點
k8scloude3/192.168.110.128 CentOS Linux release 7.4.1708 (Core) x86_64 docker,kubelet,kube-proxy,calico k8s worker節點

二.前言

在現代的雲原生應用中,定時任務是一個非常重要的組成部分。Kubernetes提供了一種稱為CronJob的機制,可以讓我們方便地定義和管理定時任務。本文將介紹Kubernetes CronJob的基礎知識以及如何使用它來執行定時任務。

使用CronJob定時任務的前提是已經有一套可以正常執行的Kubernetes叢集,關於Kubernetes(k8s)叢集的安裝部署,可以檢視部落格《Centos7 安裝部署Kubernetes(k8s)叢集》https://www.cnblogs.com/renshengdezheli/p/16686769.html。

三.Kubernetes CronJob簡介

CronJob是Kubernetes中的一種控制器(其他控制器,比如deploymentDaemonSetReplicationControllerReplicaSet ),用於在指定時間間隔內執行一個或多個Pod。類似於Linux下的cron工具,可以幫助我們週期性地執行任務。Kubernetes CronJob使用Cron表示式來指定任務執行時間,這使得它非常靈活且易於使用。

除了CronJob定時任務,kubernetes還存在一次性任務job,詳情請檢視部落格《Kubernetes(k8s)一次性任務:Job》https://www.cnblogs.com/renshengdezheli/p/17450685.html。

四.kubernetes CronJob和Linux crontab對比

熟悉Linux系統的對crontab定時任務應該不陌生,下面看看kubernetes CronJob和Linux crontab兩者差異。

Linux 下的 crontab 和 Kubernetes 下的 CronJob 都是用於執行週期性任務的工具,但它們在實現方式和使用方式上有以下幾點不同:

  1. 排程精度:Linux 下的 crontab 支援分鐘級別的排程,而 Kubernetes 下的 CronJob 可以支援到秒級別的排程。
  2. 狀態管理:Linux 下的 crontab 只能通過檢視紀錄檔等方式來了解任務的執行情況,而 Kubernetes 下的 CronJob 可以通過 kubectl 工具檢視任務的執行狀態,並且可以對任務進行修改和刪除等操作。
  3. 並行控制:Linux 下的 crontab 沒有內建的並行控制機制,如果同一個任務同時被多次觸發,可能會導致資源搶佔。而 Kubernetes 下的 CronJob 可以通過 .spec.concurrencyPolicy 欄位指定任務的並行策略,從而避免資源搶佔的問題。
  4. 環境隔離:Linux 下的 crontab 所有任務都執行在同一個環境中,容易出現依賴衝突等問題。而 Kubernetes 下的 CronJob 可以定義多個 Pod 來執行不同的任務,從而實現了任務之間的環境隔離。
  5. 縮放性:Linux 下的 crontab 通常只能執行在單臺伺服器上,無法進行水平擴充套件。而 Kubernetes 下的 CronJob 可以執行在多節點的叢集上,並且可以通過水平擴充套件來提高任務的並行度和可用性。

綜上所述,Linux 下的 crontab 和 Kubernetes 下的 CronJob 在功能和使用方式上都有不同,具體使用哪種工具取決於具體的需求和場景。

五.CronJob表示式語法

cronjob類似於Linux 的crontab, cronjob簡寫為cj,檢視cronjob任務。

[root@k8scloude1 jobandcronjob]# kubectl get cj
No resources found in job namespace.

[root@k8scloude1 jobandcronjob]# kubectl get cronjob
No resources found in job namespace.

檢視建立cronjob的幫助

[root@k8scloude1 jobandcronjob]# kubectl create cj --help
Create a cronjob with the specified name.

Aliases:
cronjob, cj

Examples:
  # Create a cronjob
  kubectl create cronjob my-job --image=busybox --schedule="*/1 * * * *"
  
  # Create a cronjob with command
  kubectl create cronjob my-job --image=busybox --schedule="*/1 * * * *" -- date
......
Usage:
  kubectl create cronjob NAME --image=image --schedule='0/5 * * * ?' -- [COMMAND] [args...] [flags] [options]

Use "kubectl options" for a list of global command-line options (applies to all commands).

CronJob表示式由五個欄位組成,分別代表分鐘、小時、日、月、周幾。每個欄位可以是以下任何值:

  • 單個數位:例如5表示第5分鐘或5月份。
  • 逗號分隔的數位列表:例如5,15,25表示第5、15和25分鐘。
  • 連續的數位範圍:例如10-15表示從第10分鐘到第15分鐘。
  • 星號(*):表示匹配該欄位的所有值。例如在分鐘欄位上使用星號表示每分鐘執行任務。
  • 斜槓(/):表示步長值。例如在分鐘欄位上使用"*/3"表示每隔3分鐘執行一次任務。

CronJob表示式範例:

  • 每小時執行:0 * * * *
  • 每天晚上10點執行:0 22 * * *
  • 每週一早上6點執行:0 6 * * 1
  • 每2分鐘執行一次任務 : */2 * * * *

六.建立CronJob定時任務

生成cronjob的yaml檔案,--schedule="*/1 * * * *" 表示每分鐘執行一次,執行的命令為:-- sh -c "date;sleep 10"列印當前日期和休眠10秒鐘。

[root@k8scloude1 jobandcronjob]# kubectl create cronjob my-cronjob --image=busybox --schedule="*/1 * * * *" --dry-run=client -o yaml -- sh -c "date;sleep 10" >cronjob.yaml

[root@k8scloude1 jobandcronjob]# cat cronjob.yaml 
apiVersion: batch/v1
kind: CronJob
metadata:
  creationTimestamp: null
  name: my-cronjob
spec:
  jobTemplate:
    metadata:
      creationTimestamp: null
      name: my-cronjob
    spec:
      template:
        metadata:
          creationTimestamp: null
        spec:
          containers:
          - command:
            - sh
            - -c
            - date;sleep 10
            image: busybox
            name: my-cronjob
            resources: {}
          restartPolicy: OnFailure
  schedule: '*/1 * * * *'
status: {}

修改yaml檔案,功能為:建立一個 名為my-cronjob的Kubernetes CronJob定時任務,使用 busybox 映象作為容器映象,執行每分鐘一次的定時任務,任務是date;sleep 10列印當前日期和休眠10秒鐘。

schedule:*/1 * * * *:表示每分鐘執行一次作業。

restartPolicy: OnFailure:在容器執行失敗時重新啟動容器。

[root@k8scloude1 jobandcronjob]# vim cronjob.yaml 

[root@k8scloude1 jobandcronjob]# cat cronjob.yaml 
apiVersion: batch/v1
kind: CronJob
metadata:
  creationTimestamp: null
  name: my-cronjob
spec:
  jobTemplate:
    metadata:
      creationTimestamp: null
      name: my-cronjob
    spec:
      template:
        metadata:
          creationTimestamp: null
        spec:
          #當需要關閉容器時,立即殺死容器而不等待預設的30秒優雅停機時長。
          terminationGracePeriodSeconds: 0
          containers:
          - command:
            - sh
            - -c
            - date;sleep 10
            image: busybox
            #imagePullPolicy: IfNotPresent:表示如果本地已經存在該映象,則不重新下載;否則從遠端 Docker Hub 下載該映象
            imagePullPolicy: IfNotPresent
            name: my-cronjob
            resources: {}
          #restartPolicy: OnFailure:在容器執行失敗時重新啟動容器。  
          restartPolicy: OnFailure
  #表示每分鐘執行一次作業。        
  schedule: '*/1 * * * *'
status: {}

建立cronjob並檢視

[root@k8scloude1 jobandcronjob]# kubectl apply -f cronjob.yaml 
cronjob.batch/my-cronjob created

[root@k8scloude1 jobandcronjob]# kubectl get cj
NAME         SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
my-cronjob   */1 * * * *   False     0        <none>          4s

[root@k8scloude1 jobandcronjob]# kubectl get pod
No resources found in job namespace.

現在開始觀察pod狀態,使用watch每 0.5 秒執行一次 kubectl get pod 命令,實時檢視 Kubernetes 叢集中 Pod 的狀態資訊。可以發現由於sleep 10,所以每個pod執行10秒之後status由running變為Completed。

#每 0.5 秒執行一次 `kubectl get pod` 命令
[root@k8scloude1 jobandcronjob]# watch -n .5 'kubectl get pod'

[root@k8scloude1 jobandcronjob]# kubectl get pod
NAME                        READY   STATUS    RESTARTS   AGE
my-cronjob-27406765-xk2v7   1/1     Running   0          9s

[root@k8scloude1 jobandcronjob]# watch -n .5 'kubectl get pod'

[root@k8scloude1 jobandcronjob]# kubectl get pod

NAME                        READY   STATUS      RESTARTS   AGE
my-cronjob-27406765-xk2v7   0/1     Completed   0          70s
my-cronjob-27406766-7gbjc   1/1     Running     0          10s

[root@k8scloude1 jobandcronjob]# kubectl get pod
NAME                        READY   STATUS      RESTARTS   AGE
my-cronjob-27406765-xk2v7   0/1     Completed   0          76s
my-cronjob-27406766-7gbjc   0/1     Completed   0          16s

刪除cronjob

[root@k8scloude1 jobandcronjob]# kubectl delete cj my-cronjob 
cronjob.batch "my-cronjob" deleted

[root@k8scloude1 jobandcronjob]# kubectl get pod
No resources found in job namespace.

[root@k8scloude1 jobandcronjob]# kubectl get cj
No resources found in job namespace.

七.建立具有超時時間的CronJob定時任務

剛才建立的cronjob,每個pod會執行10s(sleep 10),有的pod可能會執行很長時間,我們可以使用activeDeadlineSeconds引數限制pod最多執行多長時間。activeDeadlineSeconds 用於指定 Pod 最大的執行時間。如果一個 Pod 已經執行了超過這個時間,Kubernetes 會強制將其終止刪除。

修改yaml檔案,新增activeDeadlineSeconds: 5:設定了 Pod 最大執行時間為 5 秒,如果超過這個時間就會被 Kubernetes 強制刪除。

[root@k8scloude1 jobandcronjob]# vim cronjob.yaml 

[root@k8scloude1 jobandcronjob]# cat cronjob.yaml 
apiVersion: batch/v1
kind: CronJob
metadata:
  creationTimestamp: null
  name: my-cronjob
spec:
  jobTemplate:
    metadata:
      creationTimestamp: null
      name: my-cronjob
    spec:
      #activeDeadlineSeconds: 5:設定了 Pod 最大執行時間為 5 秒,如果超過這個時間就會被 Kubernetes 強制刪除。
      activeDeadlineSeconds: 5
      template:
        metadata:
          creationTimestamp: null
        spec:
          #當需要關閉容器時,立即殺死容器而不等待預設的30秒優雅停機時長。
          terminationGracePeriodSeconds: 0
          containers:
          - command:
            - sh
            - -c
            - date;sleep 10
            image: busybox
            imagePullPolicy: IfNotPresent
            name: my-cronjob
            resources: {}
          #restartPolicy: OnFailure:在容器執行失敗時重新啟動容器。  
          restartPolicy: OnFailure
  #表示每分鐘執行一次作業。        
  schedule: '*/1 * * * *'
status: {}

建立cronjob

[root@k8scloude1 jobandcronjob]# kubectl apply -f cronjob.yaml 
cronjob.batch/my-cronjob created

[root@k8scloude1 jobandcronjob]# kubectl get cj
NAME         SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
my-cronjob   */1 * * * *   False     0        <none>          6s

[root@k8scloude1 jobandcronjob]# kubectl get pod
No resources found in job namespace.

現在開始觀察pod狀態,使用watch每 0.5 秒執行一次 kubectl get pod 命令,實時檢視 Kubernetes 叢集中 Pod 的狀態資訊。可以發現每一分鐘執行一次定時任務「*/1 * * * *」 ,sleep 10超過5秒,pod執行5秒之後被強制刪除。

[root@k8scloude1 jobandcronjob]# watch -n .5 'kubectl get pod'

[root@k8scloude1 jobandcronjob]# kubectl get pod
NAME                        READY   STATUS    RESTARTS   AGE
my-cronjob-27406771-vskpb   1/1     Running   0          3s

[root@k8scloude1 jobandcronjob]# kubectl get pod
No resources found in job namespace.

[root@k8scloude1 jobandcronjob]# kubectl get pod
No resources found in job namespace.

刪除cronjob

[root@k8scloude1 jobandcronjob]# kubectl delete cj my-cronjob 
cronjob.batch "my-cronjob" deleted

[root@k8scloude1 jobandcronjob]# kubectl get cj
No resources found in job namespace.

[root@k8scloude1 jobandcronjob]# kubectl get pod
No resources found in job namespace.

八.總結

本文介紹了Kubernetes CronJob定時任務的語法,如何建立cronjob定時任務,以及建立具有超時時間的cronjob。

Kubernetes CronJob為容器化環境提供了非常便利的任務排程功能,可以幫助我們自動化許多常見的週期性任務。