[{"data":1,"prerenderedAt":507},["ShallowReactive",2],{"blog-ja-k3s-cronjob-silent-failure-concurrencypolicy-missed-schedule":3,"blog-related-ja-k3s-cronjob-silent-failure-concurrencypolicy-missed-schedule":455,"blog-ja-k3s-cronjob-silent-failure-concurrencypolicy-missed-schedule-alt":443},{"id":4,"title":5,"author":6,"body":7,"date":437,"description":438,"extension":439,"image":440,"locale":441,"meta":442,"navigation":443,"path":444,"seo":445,"stem":446,"tags":447,"__hash__":454},"blog\u002Fblog\u002Fja\u002Fk3s-cronjob-silent-failure-concurrencypolicy-missed-schedule.md","CronJobは緑のまま、24日間何もしていなかった。K3sで実行が静かに止まる4つの罠","Kubo Team",{"type":8,"value":9,"toc":425},"minimark",[10,19,35,38,43,50,65,74,82,88,100,125,148,154,161,167,172,181,194,205,209,215,228,238,249,260,267,271,277,280,292,307,310,314,320,333,366,378,385,388,396,403,416],[11,12,13,14,18],"p",{},"ある朝、バックアップジョブの最終成功時刻を確認して青ざめたエンジニアがいた。ダッシュボード上のCronJobステータスはずっと「Succeeded」のまま。ところが実際には、そのバックアップは",[15,16,17],"strong",{},"24日間一度も実行されていなかった","。標準的な監視では、この種の障害はまったく健全に見える。",[11,20,21,22,26,27,30,31,34],{},"K3sやKubernetesのCronJobは、定期実行の仕組みとしては単純に見える。しかし",[23,24,25],"code",{},"concurrencyPolicy","、",[23,28,29],{},"startingDeadlineSeconds","、100回ミス上限、Exit Codeの意味という4つの要素が特定の組み合わせで重なると、",[15,32,33],{},"ステータスは正常なまま実行だけが止まる","という厄介な障害を引き起こす。単体で見れば公式ドキュメントに書いてある仕様通りの挙動なのに、組み合わさると誰にも気づかれない沈黙になる。",[11,36,37],{},"この記事では、実際に報告されているインシデント事例をもとに、K3s上のCronJobが静かに止まる4つの罠を1つずつ分解し、最後にKubernetesネイティブな監視だけでは不十分な理由と、気づける監視への変え方を整理する。",[39,40,42],"h2",{"id":41},"_1-cronjobのステータスは緑のままバックアップは24日間止まっていた","1. CronJobのステータスは緑のまま、バックアップは24日間止まっていた",[11,44,45],{},[46,47],"img",{"alt":48,"src":49},"section01","https:\u002F\u002Fcdn.kubo.hexabase.io\u002Fimages\u002Fblog\u002Fja\u002Fk3s-cronjob-silent-failure-concurrencypolicy-missed-schedule\u002Fsection01.webp",[11,51,52,53,56,57,64],{},"ある事例では、夜間バックアップ用のCronJobが",[15,54,55],{},"24日間にわたって実行されずに放置されていた","ことが報告されている。CronJobのステータス自体は「Succeeded」を示し続けており、外形的な異常は一切見られなかった。気づいたきっかけは、たまたま最終成功時刻を手動で確認したことだったという（",[58,59,63],"a",{"href":60,"rel":61},"https:\u002F\u002Fdev.to\u002Fkrissv\u002Fkubernetes-cronjobs-silently-fail-more-than-you-think-2nb9",[62],"nofollow","dev.to の分析記事","）。",[11,66,67,68,73],{},"この事例が示すのは、CronJobコントローラが「異常」だと自己申告してくれるとは限らないということだ。Kubernetesクラスタ自体が健全であっても、CronJobだけが静かに止まっているケースは十分にあり得る。この手の\"静かな失敗\"に気づけるかどうかは、CronJobの監視が最初から標準で組み込まれているかどうかで大きく変わる（",[58,69,72],{"href":70,"rel":71},"https:\u002F\u002Fkubo.hexabase.io\u002F",[62],"Kubo Cloud","のようにモニタリング基盤を標準搭載したK3s環境かどうかも、その分かれ目の一つだ）。以降の章では、この沈黙がどのような設定の組み合わせから生まれるのかを、公式ドキュメントの仕様に沿って分解していく。",[39,75,77,78,81],{"id":76},"_2-罠1-concurrencypolicy-forbid-は静かにスキップを選ぶ","2. 罠1: ",[23,79,80],{},"concurrencyPolicy: Forbid"," は「静かにスキップ」を選ぶ",[11,83,84],{},[46,85],{"alt":86,"src":87},"section02","https:\u002F\u002Fcdn.kubo.hexabase.io\u002Fimages\u002Fblog\u002Fja\u002Fk3s-cronjob-silent-failure-concurrencypolicy-missed-schedule\u002Fsection02.webp",[11,89,90,91,93,94,99],{},"CronJobの",[23,92,25],{},"には3つの選択肢がある。",[58,95,98],{"href":96,"rel":97},"https:\u002F\u002Fkubernetes.io\u002Fdocs\u002Fconcepts\u002Fworkloads\u002Fcontrollers\u002Fcron-jobs",[62],"Kubernetes公式ドキュメント","によれば、それぞれの挙動は次の通りだ。",[101,102,103,110,119],"ul",{},[104,105,106,109],"li",{},[15,107,108],{},"Allow","（デフォルト）: 前回のJobが実行中でも、新しいJobを並行して起動する",[104,111,112,115,116],{},[15,113,114],{},"Forbid",": 前回のJobが終わっていなければ、",[15,117,118],{},"新しいJobの起動自体をスキップする",[104,120,121,124],{},[15,122,123],{},"Replace",": 実行中のJobを打ち切り、新しいJobに置き換える",[11,126,127,128,130,131,136,137,139,140,143,144,147],{},"多くの現場では、バックアップやデータ同期のように「二重実行されると困る」処理に対して",[23,129,114],{},"を選ぶ。実際、",[58,132,135],{"href":133,"rel":134},"https:\u002F\u002Ftechblog.zozo.com\u002Fentry\u002Fkubernetes-cronjob-monitoring",[62],"ZOZO TECH BLOGのCronJob運用事例","でも、監視対象のCronJobに",[23,138,25],{},"と合わせて",[23,141,142],{},"activeDeadlineSeconds","・",[23,145,146],{},"backoffLimit","を組み合わせた設定例が紹介されている。",[11,149,150,151,153],{},"問題は、",[23,152,114],{},"が選んだ「スキップ」が、Job自体を作らない静かな挙動だという点にある。前段のJobがいつまでも終わらなければ、その間のスケジュールは記録も残らずに消えていく。ここに次の罠が重なる。",[39,155,157,158,160],{"id":156},"_3-罠2-startingdeadlineseconds-が守ってくれるとは限らない","3. 罠2: ",[23,159,29],{}," が「守ってくれる」とは限らない",[11,162,163],{},[46,164],{"alt":165,"src":166},"section03","https:\u002F\u002Fcdn.kubo.hexabase.io\u002Fimages\u002Fblog\u002Fja\u002Fk3s-cronjob-silent-failure-concurrencypolicy-missed-schedule\u002Fsection03.webp",[11,168,169,171],{},[23,170,29],{},"は、スケジュール時刻からJobの起動が何秒遅れたら諦めるかを定義するフィールドだ。公式ドキュメントには次のように明記されている。",[173,174,175],"blockquote",{},[11,176,177,178,180],{},"Jobが予定時刻に開始できず、",[23,179,29],{},"で指定した秒数を超えた場合、そのJobの実行はスキップされる。未指定の場合は期限なしとして扱われる。",[11,182,183,184,186,187,189,190,193],{},"一見単純な設定に見えるが、",[23,185,80],{},"と組み合わせると挙動が複雑になる。前回のJobが実行中の間はスキップされ続け、ようやく前回Jobが完了した時点で",[23,188,29],{},"が再評価される。",[15,191,192],{},"その時点ですでに期限を過ぎていれば、待たされていた実行はそのまま消える","。",[11,195,196,201,202,204],{},[58,197,200],{"href":198,"rel":199},"https:\u002F\u002Fengineering.mercari.com\u002Fblog\u002Fentry\u002Fk8s-cronjob-20200908\u002F",[62],"Mercari Engineeringのブログ","では、この",[23,203,29],{},"を「実質必須」の設定として扱うべきだと述べられている。未設定のまま長時間の障害やメンテナンスウィンドウが発生すると、次章で説明する上限に直結してしまうからだ。",[39,206,208],{"id":207},"_4-罠3-100回ミス上限とクロックスキューの罠","4. 罠3: 100回ミス上限とクロックスキューの罠",[11,210,211],{},[46,212],{"alt":213,"src":214},"section04","https:\u002F\u002Fcdn.kubo.hexabase.io\u002Fimages\u002Fblog\u002Fja\u002Fk3s-cronjob-silent-failure-concurrencypolicy-missed-schedule\u002Fsection04.webp",[11,216,217,218,221,222,227],{},"CronJobコントローラには、",[15,219,220],{},"連続100回のスケジュールミスでJob生成自体を止める","という仕様がある。",[58,223,226],{"href":224,"rel":225},"https:\u002F\u002Fplatform9.com\u002Fkb\u002Fpmk\u002Fsolutions\u002Fkubernetes-cronjobs-failed-with-error-too-many-missed-start-time",[62],"Platform9のナレッジベース","には、実際に出力されるエラーメッセージが記録されている。",[229,230,235],"pre",{"className":231,"code":233,"language":234},[232],"language-text","Cannot determine if job needs to be started: too many missed start time (> 100).\nSet or decrease .spec.startingDeadlineSeconds or check clock skew\n","text",[23,236,233],{"__ignoreMap":237},"",[11,239,240,244,245,248],{},[58,241,243],{"href":198,"rel":242},[62],"Mercari Engineeringの解説","によれば、この上限に到達する経路は必ずしも「本当に100回失敗した」場合だけではない。CronJobを",[23,246,247],{},"suspend: true","にして数日放置しただけでも、その間のスケジュールがミスとしてカウントされ、上限に達してしまうという。",[11,250,251,252,255,256,259],{},"さらにPlatform9の記録では、",[23,253,254],{},"status.lastScheduleTime","が未設定・null状態になっていると、コントローラは",[23,257,258],{},"metadata.creationTimestamp","という古い日時まで遡ってミス回数を計算してしまい、実際には正常に動いていたはずのCronJobでも100回超え扱いになるケースがあるとされている。ノード間のクロックスキュー（時刻ズレ）も同様の誤検知を誘発する要因だ。",[11,261,262,263,266],{},"一度この状態に陥ると、パッチ的な修正では復旧しないことが多い。両ブログとも、",[15,264,265],{},"CronJobリソースそのものを再作成する","ことを推奨している。",[39,268,270],{"id":269},"_5-罠4-exit-code-0-は仕事をしたことを保証しない","5. 罠4: Exit Code 0 は「仕事をした」ことを保証しない",[11,272,273],{},[46,274],{"alt":275,"src":276},"section05","https:\u002F\u002Fcdn.kubo.hexabase.io\u002Fimages\u002Fblog\u002Fja\u002Fk3s-cronjob-silent-failure-concurrencypolicy-missed-schedule\u002Fsection05.webp",[11,278,279],{},"ここまでの3つの罠は「Jobが起動すらされない」パターンだった。しかしJobが起動しても、まだ油断はできない。",[11,281,282,287,288,291],{},[58,283,286],{"href":284,"rel":285},"https:\u002F\u002Fkubernetes.io\u002Fdocs\u002Fconcepts\u002Fworkloads\u002Fcontrollers\u002Fjob\u002F",[62],"Kubernetes公式ドキュメントのJobリソースの説明","にある通り、KubernetesはUnixの慣習に従い、",[15,289,290],{},"コンテナがExit Code 0で終了すれば、それだけで「成功」と判定する","。処理対象が空だったのか、意図した件数を処理できたのかは、Kubernetes自身は関知しない。",[11,293,294,298,299,302,303,306],{},[58,295,297],{"href":60,"rel":296},[62],"dev.toの分析記事","では、この性質が「空のキューを処理しただけ」「0バイトのバックアップを作っただけ」でも成功扱いになってしまう問題として指摘されている。加えて、",[23,300,301],{},"successfulJobsHistoryLimit","（既定3）・",[23,304,305],{},"failedJobsHistoryLimit","（既定1）による自動ガベージコレクションで、障害調査に必要なログや実行履歴も早期に消えてしまう。",[11,308,309],{},"つまり「Job自体は起動されているのに、実質何もしていない」という4つ目の沈黙が、ここに存在する。",[39,311,313],{"id":312},"_6-気づける監視に変える-statusフィールドとメトリクス外形監視","6. 気づける監視に変える — statusフィールドとメトリクス、外形監視",[11,315,316],{},[46,317],{"alt":318,"src":319},"section06","https:\u002F\u002Fcdn.kubo.hexabase.io\u002Fimages\u002Fblog\u002Fja\u002Fk3s-cronjob-silent-failure-concurrencypolicy-missed-schedule\u002Fsection06.webp",[11,321,322,323,326,327,332],{},"ここまでの4つの罠に共通するのは、",[15,324,325],{},"Kubernetes内部の仕組みだけでは異常が自己申告されない","という点だ。",[58,328,331],{"href":329,"rel":330},"https:\u002F\u002Foneuptime.com\u002Fblog\u002Fpost\u002F2026-02-09-monitor-cronjob-missed-schedules\u002Fview",[62],"OneUptimeの監視ガイド","は、これに対する監視設計として次のポイントを挙げている。",[101,334,335,346,356,363],{},[104,336,90,337,143,339,143,342,345],{},[23,338,254],{},[23,340,341],{},"status.lastSuccessfulTime",[23,343,344],{},"status.active","を定期的に確認する",[104,347,348,349,143,352,355],{},"kube-state-metricsが公開する",[23,350,351],{},"kube_cronjob_status_last_schedule_time",[23,353,354],{},"kube_cronjob_status_last_successful_time","をPrometheusで収集する",[104,357,358,359,362],{},"アラート閾値は",[15,360,361],{},"想定実行間隔の2倍","を目安にする(日次ジョブなら約48時間、毎時ジョブなら約2時間が目安)",[104,364,365],{},"クラスタ内部の状態に依存せずに検知できる外形監視(dead man's switch)を併用する",[11,367,368,369,373,374,377],{},"ZOZO TECH BLOGの事例でも、Kubernetesネイティブな仕組みだけに頼らず、外部のダッシュボードやアラート基盤と組み合わせて閾値ベースの通知を行う構成が紹介されている（",[58,370,372],{"href":133,"rel":371},[62],"同記事","）。クラスタ内のコントローラが沈黙する可能性がある以上、",[15,375,376],{},"クラスタの外側から「最後に成功したのはいつか」を確認する仕組み","を持つことが、この4つの罠すべてに対する共通の防御線になる。",[11,379,380,381,384],{},"このあたりの監視基盤を自前で組むと、Prometheus・Grafanaの構築だけでも相応の工数がかかる。",[58,382,72],{"href":70,"rel":383},[62],"はK3sベースのマネージドKubernetes基盤で、Prometheus + Grafanaを標準搭載しているため、CronJobのstatusメトリクスを可視化するダッシュボードをゼロから組む必要がない。",[39,386,387],{"id":387},"まとめ",[11,389,390,391,143,393,395],{},"CronJobが静かに止まる背景には、単一の設定ミスではなく、",[23,392,25],{},[23,394,29],{},"・100回ミス上限・Exit Code 0という4つの仕様が組み合わさった結果としての沈黙がある。それぞれは公式ドキュメント通りの正しい挙動であり、だからこそ気づきにくい。",[11,397,398,399,402],{},"対策の本質は「Kubernetesが異常を教えてくれる」という前提を捨て、",[23,400,401],{},"lastScheduleTime","のようなstatusフィールドとメトリクスを外部から監視する仕組みを最初から組み込んでおくことにある。",[11,404,405,406,409,410,415],{},"K3sクラスタでこうした監視をどこまで自前で運用し続けるか、あるいは標準搭載の監視基盤に任せるかは、チームのリソース次第だ。",[58,407,72],{"href":70,"rel":408},[62],"ならPrometheus + Grafanaが最初から組まれた状態でK3sクラスタを立ち上げられるため、この記事で挙げたようなCronJobの監視設計を、構築フェーズからやり直さずに済む。まずは",[58,411,414],{"href":412,"rel":413},"https:\u002F\u002Fwww.hexabase.com\u002Fpricing\u002F",[62],"料金プラン","で、今のCronJob運用にかかっているコストと比較してみてほしい。",[11,417,418,419,424],{},"もしオンプレミス環境や閉域網でCronJobを運用していて、外形監視の経路確保自体が課題になっているなら、",[58,420,423],{"href":421,"rel":422},"https:\u002F\u002Fwww.hexabase.com\u002Fproduct\u002Fkubo\u002Fon-premise",[62],"Kubo On-Premise","という選択肢もある。データを外に出さずに、同様の監視設計を組み込むことができる。",{"title":237,"searchDepth":426,"depth":426,"links":427},2,[428,429,431,433,434,435,436],{"id":41,"depth":426,"text":42},{"id":76,"depth":426,"text":430},"2. 罠1: concurrencyPolicy: Forbid は「静かにスキップ」を選ぶ",{"id":156,"depth":426,"text":432},"3. 罠2: startingDeadlineSeconds が「守ってくれる」とは限らない",{"id":207,"depth":426,"text":208},{"id":269,"depth":426,"text":270},{"id":312,"depth":426,"text":313},{"id":387,"depth":426,"text":387},"2026-09-16","K3s\u002FKubernetesのCronJobは「Succeeded」表示のまま実行されないことがある。concurrencyPolicy・startingDeadlineSeconds・100回ミス上限・Exit Code 0が重なって起きる静かな失敗の仕組みと監視での防ぎ方を解説する。","md","https:\u002F\u002Fcdn.kubo.hexabase.io\u002Fimages\u002Fblog\u002Fja\u002Fk3s-cronjob-silent-failure-concurrencypolicy-missed-schedule\u002Ftitle.webp","ja",{},true,"\u002Fblog\u002Fja\u002Fk3s-cronjob-silent-failure-concurrencypolicy-missed-schedule",{"title":5,"description":438},"blog\u002Fja\u002Fk3s-cronjob-silent-failure-concurrencypolicy-missed-schedule",[448,449,450,451,452,453],"k3s","kubernetes","cronjob","concurrencypolicy","monitoring","sre","zVcuJh5cbGb1Fr-cAJ9GwWuLbDj9d4xb00daF1OO0YQ",[456,465,474,482,490,497],{"path":457,"title":458,"description":459,"date":460,"tags":461},"\u002Fblog\u002Fja\u002Fk3s-litmuschaos-chaos-engineering-blast-radius","「本番のK3sを、自分でわざと壊す。」LitmusChaosで始めるカオスエンジニアリング、最初に壊していいワークロードの見極め方","K3s本番環境の耐障害性は、実際に壊れてからでないと分からない。監視やアラートは「壊れた後」を検知する仕組みに過ぎない。CNCFのLitmusChaosを使ったカオスエンジニアリングの始め方と、最初に壊していいワークロード・壊してはいけないワークロードの見極め方をK3s環境の実例で解説する。","2026-09-04",[448,449,462,463,464,453],"chaos-engineering","litmuschaos","resilience",{"path":466,"title":467,"description":468,"date":469,"tags":470},"\u002Fblog\u002Fja\u002Fk3s-servicemonitor-prometheus-not-scraping-connection-points","ServiceMonitorのYAMLは合ってる。K3sでPrometheusにターゲットが出てこない『接続点』の診断手順","K3sでkubernetes service monitorを設定したのにPrometheusのTargetsに何も出てこない。原因の9割はラベルセレクタ・ポート名・RBAC・namespaceSelectorという4つの接続点にある。1段ずつ疑って直す診断手順を解説する。","2026-08-30",[448,449,471,472,452,473],"prometheus","service-monitor","observability",{"path":475,"title":476,"description":477,"date":478,"tags":479},"\u002Fblog\u002Fja\u002Fkubernetes-high-availability-broadcast-seamless-switching","「同じ映像を2回送って、早く着いた方を使う。」放送業界の非常識がKubernetesの高可用性設計そのものだった件","ワールドカップ放送は同じ映像を2つの経路で二重送信し、早く着いた方だけを使う。この一見無駄な冗長化がKubernetesの高可用性設計・マルチAZ構成と同じ思想である理由を解説する。","2026-08-05",[448,449,480,481,453],"high-availability","multi-az",{"path":483,"title":484,"description":485,"date":486,"tags":487},"\u002Fblog\u002Fja\u002Fedge-k3s-observability-homelab-dashboard","壁に貼っただけで「安心」に変わる。ホームラボの壁掛けダッシュボードが教えてくれた、エッジK3sクラスタの観測性設計","自宅の壁掛けダッシュボード作りで起きた総当たりのトラブルシューティングは、工場や店舗に分散したエッジKubernetesクラスタの運用でも同じ罠になる。K3s・Prometheus・Grafanaの公式ドキュメントを引きながら、観測性を後回しにしないための設計原則を解説する。","2026-07-26",[448,449,488,473,452,489],"edge-computing","managed-kubernetes",{"path":491,"title":492,"description":493,"date":494,"tags":495},"\u002Fblog\u002Fja\u002Fbroadcast-redundancy-kubernetes-high-availability-design","FIFAワールドカップの中継は、なぜ絶対に途切れないのか。放送業界の二重伝送に学ぶKubernetesの本当の高可用性設計","Kubernetesの高可用性は「レプリカを増やす」だけでは実現しない。放送業界のSMPTE ST 2022-7二重伝送技術を手がかりに、Topology Spread ConstraintsとマルチAZ設計の本質を解説する。","2026-07-20",[449,448,480,496,453,489],"topology-spread-constraints",{"path":498,"title":499,"description":500,"date":501,"tags":502},"\u002Fblog\u002Fja\u002Fk3s-hpa-containerresource-sidecar-utilization-dilution","HPAがサイドカーの分まで合算してスケールしていた。KubernetesのContainerResourceという盲点","KubernetesのHPAはPod内の全コンテナの使用量を合算して利用率を計算するため、Istioサイドカーやログエージェントの負荷が判定を薄める。ContainerResourceメトリクスで解決する方法をK3s\u002FKubo文脈で解説する。","2026-10-21",[448,449,503,504,505,506],"hpa","containerresource","autoscaling","service-mesh",1792592603952]