如何在CronJob容器结束后标记含常驻容器的Pod为成功并避免重复执行?
问题解决方案
问题1:CronJob任务容器完成后Pod无法标记为成功
当前Pod因常驻容器webapp1持续运行,导致任务容器hello执行完毕后Pod仍处于活跃状态。由于无法修改常驻容器代码,可通过共享进程命名空间+任务容器结束后终止常驻容器的方案解决:
- 在Pod spec中开启
shareProcessNamespace: true,让容器间可互相访问进程 - 修改
hello容器的命令,在任务执行完成后,杀死常驻容器的进程
修改后的Pod配置片段:
spec: shareProcessNamespace: true containers: - name: webapp1 image: katacoda/docker-http-server:latest ports: - containerPort: 80 - name: hello image: quarkus-test imagePullPolicy: Never command: ["/bin/sh", "-c", "./application -Dquarkus.http.host=0.0.0.0 && pkill -f 'docker-http-server'"] restartPolicy: OnFailure
当hello容器的任务执行完成后,会通过pkill终止webapp1的进程,此时Pod内所有容器均已结束,Pod会被标记为成功状态。
问题2:节点故障重启后CronJob同一天重复执行
要避免同一天重复执行,可结合两种策略实现:
策略1:利用CronJob并发限制
将concurrencyPolicy设置为Forbid,同时配置startingDeadlineSeconds:
spec: schedule: "*/1 * * * *" concurrencyPolicy: Forbid startingDeadlineSeconds: 300
concurrencyPolicy: Forbid:禁止并发执行,若前一个Job仍在运行,新Job不会被创建startingDeadlineSeconds:设置任务启动超时窗口,若节点故障导致任务错过调度窗口超过该时间,不会重新触发
策略2:通过ConfigMap记录执行日期(更可靠)
若节点重启后旧Job已被清理,上述策略可能失效,可添加init容器校验当天是否已执行:
- 先创建存储执行记录的ConfigMap:
apiVersion: v1 kind: ConfigMap metadata: name: cronjob-exec-record data: last-exec-date: ""
- 修改CronJob的Job模板,添加init容器做日期校验:
jobTemplate: spec: template: spec: initContainers: - name: check-exec-date image: busybox:latest command: ["/bin/sh", "-c"] args: - | TODAY=$(date +%Y-%m-%d) LAST_EXEC=$(cat /record/last-exec-date) if [ "$TODAY" = "$LAST_EXEC" ]; then echo "今日已执行过,退出" exit 1 else echo "$TODAY" > /record/last-exec-date fi volumeMounts: - name: exec-record mountPath: /record volumes: - name: exec-record configMap: name: cronjob-exec-record
init容器会先检查ConfigMap中的日期,若当天已执行过则退出(Pod失败,Job不会重复执行),否则更新日期并启动主容器。
完整配置示例
整合上述方案后的完整CronJob配置:
apiVersion: batch/v1 kind: CronJob metadata: name: hello spec: schedule: "*/1 * * * *" concurrencyPolicy: Forbid startingDeadlineSeconds: 300 jobTemplate: spec: ttlSecondsAfterFinished: 30 template: spec: shareProcessNamespace: true hostAliases: - ip: "192.168.59.1" hostnames: - "host.minikube.internal" initContainers: - name: check-exec-date image: busybox:latest command: ["/bin/sh", "-c"] args: - | TODAY=$(date +%Y-%m-%d) LAST_EXEC=$(cat /record/last-exec-date) if [ "$TODAY" = "$LAST_EXEC" ]; then echo "今日已执行过,退出" exit 1 else echo "$TODAY" > /record/last-exec-date fi volumeMounts: - name: exec-record mountPath: /record volumes: - name: exec-record configMap: name: cronjob-exec-record containers: - name: webapp1 image: katacoda/docker-http-server:latest ports: - containerPort: 80 - name: hello image: quarkus-test imagePullPolicy: Never command: ["/bin/sh", "-c", "./application -Dquarkus.http.host=0.0.0.0 && pkill -f 'docker-http-server'"] restartPolicy: OnFailure
内容的提问来源于stack exchange,提问作者Pp88
相关产品推荐
相关产品推荐

