之前需要定期執行的任務:比如每天凌晨清理日誌、每週日凌晨備份數據庫、每小時同步一次數據。剛開始用Linux的crontab在集羣節點上跑,但節點故障後任務就中斷了,還不好統一管理。後來發現Kubernetes的CronJob完美解決了這些問題——它能在集羣中調度定時任務,自動容錯,還能通過資源配置控制任務資源佔用,比單機crontab靠譜多了。
一、CronJob與Job的核心區別
很多人會混淆CronJob和Job,其實兩者的定位很清晰:
- Job 是“一次性任務”,比如批量處理一批數據,執行完就結束,Pod也會隨之終止;
- CronJob 是“週期性任務”,基於crontab表達式循環創建Job,再由Job啓動Pod執行具體邏輯。
簡單説,CronJob是Job的“調度器”,每次觸發都會生成一個新的Job實例,即使某次任務失敗,下次還能正常執行,容錯性更強。
二、CronJob的工作原理
1. 調度機制
CronJob的調度完全遵循crontab格式(分 時 日 月 周),比如0 3 * * *表示每天凌晨3點執行。Kubernetes會通過控制器定期檢查調度規則,到達指定時間後,自動創建對應的Job資源。
2. 任務執行流程
- CronJob控制器按調度規則觸發Job創建;
- Job控制器根據
parallelism(併發數)和completions(完成數)啓動Pod; - Pod執行任務,成功後退出(退出碼0),Job標記為完成;
- CronJob會保留一定數量的歷史Job(由
successfulJobsHistoryLimit和failedJobsHistoryLimit控制),方便排查問題。
三、實戰:用CronJob實現日誌清理
1. 準備工作
先寫一個簡單的日誌清理腳本clean-logs.sh,用於刪除 /var/log/app 目錄下7天前的日誌文件:
#!/bin/bash
# 清理7天前的日誌文件
find /var/log/app -name "app-*.log" -mtime +7 -delete
echo "日誌清理完成,刪除了7天前的歷史日誌"
然後構建Docker鏡像,編寫Dockerfile:
FROM alpine:3.18
# 安裝find工具(alpine默認沒有)
RUN apk add --no-cache findutils
COPY clean-logs.sh /usr/local/bin/
# 增加執行權限
RUN chmod +x /usr/local/bin/clean-logs.sh
# 容器啓動時執行腳本
ENTRYPOINT ["/usr/local/bin/clean-logs.sh"]
構建並推送鏡像(假設私有倉庫地址為registry.company.com/tools/clean-logs:v1.0):
docker build -t registry.company.com/tools/clean-logs:v1.0 .
docker push registry.company.com/tools/clean-logs:v1.0
2. 創建CronJob配置文件
編寫clean-logs-cronjob.yaml,設置每天凌晨2點執行:
apiVersion: batch/v1
kind: CronJob
metadata:
name: clean-logs-cronjob
namespace: tools
spec:
# 調度規則:每天凌晨2點執行(分 時 日 月 周)
schedule: "0 2 * * *"
# 併發策略:禁止併發(避免多個清理任務同時執行)
concurrencyPolicy: Forbid
# 任務執行超時時間(10分鐘)
activeDeadlineSeconds: 600
# 保留3個成功的歷史Job
successfulJobsHistoryLimit: 3
# 保留1個失敗的歷史Job(方便排查)
failedJobsHistoryLimit: 1
# 觸發後1分鐘內未執行則視為失敗
startingDeadlineSeconds: 60
jobTemplate:
spec:
template:
spec:
# 任務完成後自動刪除Pod
restartPolicy: OnFailure
containers:
- name: clean-logs
image: registry.company.com/tools/clean-logs:v1.0
# 掛載需要清理的日誌目錄(根據實際場景調整)
volumeMounts:
- name: app-logs
mountPath: /var/log/app
volumes:
- name: app-logs
hostPath:
path: /data/app/logs
type: Directory
3. 應用配置並查看狀態
執行部署命令:
# 創建命名空間(如果不存在)
kubectl create namespace tools --dry-run=client -o yaml | kubectl apply -f -
# 部署CronJob
kubectl apply -f clean-logs-cronjob.yaml
查看CronJob狀態:
# 查看CronJob列表
kubectl get cronjob -n tools
# 查看具體信息(包括下次執行時間)
kubectl describe cronjob clean-logs-cronjob -n tools
# 查看已觸發的Job
kubectl get jobs -n tools
# 查看Pod日誌(驗證執行結果)
kubectl logs <pod-name> -n tools
四、常見問題與解決方案
1. 任務未按時執行
排查步驟:
- 先檢查調度表達式是否正確,比如把
0 2 * * *寫成0 2 * *(少了一位)會導致解析失敗; - 查看CronJob事件:
kubectl describe cronjob <name> -n <namespace>,如果有“Missed schedule”提示,可能是節點資源不足或startingDeadlineSeconds設置過短; - 確認集羣時間同步正常,節點時間不一致會導致調度紊亂。
2. Job和Pod堆積
原因:successfulJobsHistoryLimit和failedJobsHistoryLimit默認值為3和1,若未調整,長期運行後會堆積大量歷史資源。 解決:根據需求設置合理的保留數量,比如生產環境保留3個成功Job、1個失敗Job,測試環境可設為1和0。
3. 任務併發衝突
比如清理日誌時,前一次任務還沒結束,下一次又觸發了。 解決:設置concurrencyPolicy: Forbid(禁止併發)或Replace(替換正在運行的任務),根據業務場景選擇。
五、總結
CronJob是K8s集羣中定時任務的“得力助手”,相比單機crontab,它具備高可用、易管理、資源可控的優勢。使用時要注意三點:一是調度表達式要準確,二是合理配置併發策略和超時時間,三是及時清理歷史Job避免資源浪費。
實際場景中,除了日誌清理,還可以用它做數據庫備份、數據同步、定時報表生成等。比如我們團隊用CronJob每週日凌晨3點執行MySQL備份,同時將備份文件上傳到對象存儲,至今零故障運行。只要掌握好配置要點,CronJob就能成為集羣運維的“好幫手”,讓定時任務管理更省心、更可靠。