プログラミング

Kubernetes CronJob 失敗 対処法|EKSでも止まらない定期バッチ

記事内に商品プロモーションを含む場合があります

Amazon EKS で Kubernetes CronJob を運用していると「ジョブが走らない」「失敗して止まった」などのトラブルに遭遇しがちです。

本記事では Kubernetes CronJob 失敗 対処法 を軸に、EKS ユーザーが押さえるべき原因分析と最新ベストプラクティスをまとめます。

CronJob が失敗・動かない主な4パターン

同時実行ポリシーでジョブがスキップされる

concurrencyPolicy: Forbid を指定すると前回ジョブ完了まで次のジョブをスキップします。これは仕様であり失敗ではないものの、実行漏れと誤認しやすいので注意しましょう (出典: https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/)。

  • 処理時間が読めない場合は Replace を検討

  • リソース不足が原因なら Pod の CPU / メモリを増強

正直、最初は「なぜ動かないのか分からない」と戸惑いましたが、ログを追えばスキップ理由が分かり安心しました。

一時停止と “100 回ルール”

.spec.suspend: true で CronJob を停止し、数日後に再開したら動かない…。これは 100 回連続で実行機会を逃すと CronJob が停止 する安全装置によるものです (出典: https://github.com/kubernetes/kubernetes/blob/master/pkg/controller/cronjob/)。毎分ジョブなら約1.5時間で上限到達。

  • 長期停止前にスケジュールを毎時へ変更し失敗カウントを抑制

  • 再開後に startingDeadlineSeconds を適切に設定しておく

わたしも週末メンテで suspend しっぱなしにしてしまい、月曜朝に慌てて再デプロイした苦い体験があります。

startingDeadlineSeconds 未設定

未設定だと「遅れてでも全部実行する」挙動になり、逃しカウントが増えて 100 回停止に直結します。

毎時バッチなら 360000 秒(約100時間)以内に収めると安心です。

Cron 式とタイムゾーンの誤り

Kubernetes 1.27 以降は .spec.timeZone が Stable になり、timeZone: "Asia/Tokyo" で日本時間指定が可能です (出典: https://github.com/kubernetes/kubernetes/pull/113845)。以前の UTC ずれ問題を根本解消できます。

  • cron 式はオンライン validator で確認

  • EKS クラスタバージョンが 1.27 以上かチェック

失敗を防ぐ設定ベストプラクティス

ConcurrencyPolicy 設計

  • Allow : 重複許可、簡単だが二重処理に要注意

  • Forbid : 重複禁止、処理ロック的に使える

  • Replace : 長時間ジョブを中断し最新ジョブへ置換

ジョブ実行時間が読めない場合は Replace が安全でした。実際にわたしのバックアップ処理は Replace で安定稼働しています。

startingDeadlineSeconds の設定ガイド

実行間隔 推奨値の目安
毎分 600–900 秒
5 分ごと 3 000–4 000 秒
毎時 7 200–10 800 秒

Job 再試行 (backoffLimit) と履歴

  • 失敗時に再試行不要なら backoffLimit: 0

  • ttlSecondsAfterFinished で完了後に Job を自動削除し、メトリクスをクリーンに保つ

  • successfulJobsHistoryLimit / failedJobsHistoryLimit で履歴を絞りクラスターを軽量化

監視とアラート設計

  • CloudWatch Container Insights で異常終了 Pod を可視化

  • Prometheus + Alertmanagerkube_job_failed をトリガに通知

  • EventBridge → SNS でメール・Slack 連携

CronJob 失敗 監視 EKS をキーワードに検索すると、実装例が多数見つかります。アラートは「早朝の定期バッチが止まった」瞬間に気付ける一番の保険です。

Amazon EKS ならではの運用Tips

ノードオートスケーリング

CronJob が作成されても Pod が Pending のままなら、ノードグループに該当インスタンスタイプが無い可能性があります。Cluster Autoscaler を有効化し、必要な taint / label を設定しましょう。

CloudWatch ログの活用

CronJob Pod 標準出力を CloudWatch Logs に送れば、フィルタで errorpanic を検知可能。わたしは Logs Insights で「status=error AND cronjob=my-batch」クエリを実行し、失敗パターンを洗い出しています。

GitOps で Manifest を管理

手動 kubectl apply はヒューマンエラーの温床。Argo CDFlux で Git リポジトリと同期し、PR レビューで startingDeadlineSecondsconcurrencyPolicy の差分を可視化すると運用が楽になります。

よくある Q&A

  • Q. suspend せずに安全に止めたい
    → スケジュールを未来日時に変更し、停止後に元へ戻す方法がおすすめ。

  • Q. 100 回制限を無効化できる?
    → できません。設計段階で startingDeadlineSeconds やスケジュール変更で回避しましょう。

  • Q. UTC ずれ以外で実行時刻がおかしい
    → コントロールプレーンの時計とノードの NTP 同期を確認。EKS は自動同期ですが独自 AMI では要チェック。

まとめ

  • Kubernetes CronJob 失敗 対処法 の核心は ConcurrencyPolicy と startingDeadlineSeconds

  • suspend × 長期停止は “100 回ルール” で停止するため要注意。

  • EKS 環境では CloudWatch・Prometheus 監視と GitOps を組み合わせ、止まらない定期バッチを実現しよう。