5分ごとに動かしている処理が、たまに17分かかることがあります。次の起動が来ても、前がまだ終わっていません。
4時間ぶん48回を並べて測りました。何もしないと20回が前の実行と重なります。見送る方式なら10回が実行されず、待たせる方式なら最大16分遅れます。
3通りの扱い方を同じ条件で走らせました。どれを選んでも、何かを失います。
ジョブスケジューリングで起動が重なると何が起きるのかを、実際に走らせて測りました。5分ごとの起動を4時間ぶん、48回並べています。
処理にかかる時間はふだん1分から3分ですが、15%の割合で8分から17分に長引くようにしました。実際の業務処理に近い形です。
let ran = 0, skipped = 0, busyUntil = -1;
for (let i = 0; i < RUNS; i++) {
const start = i * EVERY;
if (start < busyUntil) { skipped++; continue; }
ran++; busyUntil = start + durations[i];
}
5分ごとに起動する処理を、4時間ぶん(48回)並べる やり方 実際に走った回数 重なった回数 取りこぼした回数 そのまま起動する 48回 20回 0回 前が動いていたら見送る 38回 0回 10回 順番に待たせる 48回 0回 0回 順番に待たせた場合、予定より最大 16分 遅れて始まった。 処理時間が起動の間隔(5分)を超えた回数: 7回 / 48回 処理時間の最大: 17分・最小: 1分
上の表を見てください。そのまま起動すると48回のうち20回が前の実行と重なりました。4割です。
処理時間が5分を超えたのは48回のうち7回です。それでも重なりは20回になりました。
1回17分かかると、その間に3回の起動が重なります。長引いた回数より、重なる回数のほうが多くなります。
見送る方式なら重なりは0回です。代わりに10回が実行されません。Kubernetesも、この方式では新しい実行を飛ばすと説明しています。
順番に待たせる方式なら48回すべて実行されます。代わりに予定より最大16分遅れて始まりました。
重なりを消すと、実行されない回か遅れが出る。
The CronJob does not allow concurrent runs; if it is time for a new Job run and the previous Job run hasn't finished yet, the CronJob skips the new Job run.原文Kubernetes ドキュメント「CronJob」 この内容の有効期限2027-02-18
起動する時刻だけでなく、前の実行が終わっていないときにどうするかを決めます。決めなければ既定の動きが出ます。
ジョブスケジューリングは、決まった時刻に処理を起動する仕組みです。決めるのは時刻だけではありません。
前の実行が終わっていないときの扱いは、選べるようになっていることが多いです。Kubernetesでは3通りから選びます。
3番目についてKubernetesは、新しい実行の時刻になったのに前の実行が終わっていない場合、動いている実行を新しい実行で置き換えると説明しています。前の処理は途中で止まります。
起動そのものが遅れることもあります。仕組みが止まっていた、負荷が高かった、といった理由です。
この場合の扱いも決められます。Kubernetesでは期限を過ぎると、その回の実行を飛ばす形です。以降の予定はそのまま続きます。
どの方式を選んでも、同じ処理が2回走る可能性は消えません。置き換える方式なら、途中まで進んだ処理がもう一度最初から走ります。
だからKubernetesも、定義する処理は冪等であるべきだとしています。何度実行しても結果が変わらない作りが前提です。詳しくは冪等性の記事で扱っています。
処理時間は種を固定した乱数で決めています。長引く割合を15%としましたが、実際の割合は処理の中身で変わります。まず自分の処理時間を記録して、最大値が起動の間隔を超えているかを見るところから始めてください。
If it is time for a new Job run and the previous Job run hasn't finished yet, the CronJob replaces the currently running Job run with a new Job run原文Kubernetes ドキュメント「CronJob」 この内容の有効期限2027-02-18
平均の処理時間を見て間隔を決めることです。重なりを決めるのは平均ではなく最大です。
ジョブスケジューリングでいちばん多い失敗は、ふだんの処理時間を見て間隔を決めることです。
前の節の計測では、処理時間の大半は1分から3分でした。5分ごとの起動なら余裕があるように見えます。
ところが最大は17分でした。この7回が20回の重なりを生んでいます。決めているのは平均ではなく最大です。
見送る方式にすると、10回が実行されません。これは失敗として記録されないことがあります。
Kubernetesも、期限を過ぎた場合についてその回の実行を飛ばし、以降の予定はそのまま続くとしています。飛ばしたことを数えていないと、処理されていない期間ができます。
4番目が抜けると、処理されていない期間が静かにできます。前の節では4時間で10回でした。
決めているのは平均ではなく最大。
After missing the deadline, the CronJob skips that instance of the Job (future occurrences are still scheduled).原文Kubernetes ドキュメント「CronJob」 この内容の有効期限2027-02-18
同じ課題を持つ会社にとって、動いている設定は「作る時間」を買えるということです。ServiceDockは自作のワークフローやテンプレートを出品できるマーケットプレイスです。手数料や出品の流れは出品者向けページにまとまっています。
出品の仕組みを見る