KEDA の ScaledJobで、successfulJobsHistoryLimit
で指定した個数以上になると、完了した Jobが削除されるようになるのだが、なぜか、Job で作成されたPodが削除されない。
func (e *scaleExecutor) deleteJobsWithHistoryLimit(logger logr.Logger, jobs []batchv1.Job, historyLimit int32) error {
if len(jobs) <= int(historyLimit) {
return nil
}
deleteJobLength := len(jobs) - int(historyLimit)
for _, j := range (jobs)[0:deleteJobLength] {
err := e.client.Delete(context.TODO(), j.DeepCopyObject())
if err != nil {
return err
}
logger.Info("Remove a job by reaching the historyLimit", "job.Name", j.ObjectMeta.Name, "historyLimit", historyLimit)
}
return nil
}
いろいろ探してみると次の記事に行き当たった。ご丁寧に設定項目名まで同じや。そらそうや、わしこの設定項目考えたときにこれを参考にしたリソースやから、そら同じ名前やわ。
ここに書かれていたことは主に二つ ownerReference
のメタデータが存在するか?このPRで issue が解決していることである。このPRは、Dec 6, 2018 no
v1.13 のマイルストーンに加えられているので、そこで修正されたらしい。kubernetes のバージョンがそれ以上であることは確認しないといけない。
ownerReferences:
- apiVersion: batch/v1
blockOwnerDeletion: true
controller: true
kind: Job
name: <job-name>
uid: 94ff084e-1a5b-11e9-b123-52540098c2e3
ownerReferences とは
に書かれているが、自分の親リソースのリファレンスで、これを持っておくと、カスケードデリートのポリシーを設定すると、有効になる。ほかにも元ページには条件が載っていたので、これらをセットする必要があるのかもしれない。
現状の振る舞い
まず現状を確認しよう。Job がある。
$ kubectl get jobs
NAME COMPLETIONS DURATION AGE
azure-servicebus-queue-consumer-7x629 1/1 8s 114s
azure-servicebus-queue-consumer-9m7v6 0/1 3s 3s
azure-servicebus-queue-consumer-lqftl 1/1 6s 66s
azure-servicebus-queue-consumer-qjfhr 1/1 10s 2m25s
azure-servicebus-queue-consumer-qs5rb 1/1 20s 49s
azure-servicebus-queue-consumer-v8n7m 1/1 8s 60s
Jobで作成されたPodがあり、似たようなネーミングになっている。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
azure-servicebus-queue-consumer-7x629-8kc2j 0/1 Completed 0 2m28s
azure-servicebus-queue-consumer-9m7v6-zgzsf 0/1 Completed 0 37s
azure-servicebus-queue-consumer-lqftl-67pnv 0/1 Completed 0 99s
azure-servicebus-queue-consumer-qjfhr-dhbgt 0/1 Completed 0 2m59s
azure-servicebus-queue-consumer-qs5rb-8qsr7 0/1 Error 0 83s
azure-servicebus-queue-consumer-qs5rb-v2d7d 0/1 Completed 0 70s
azure-servicebus-queue-consumer-v8n7m-dczp8 0/1 Completed 0 94s
kubectl edit pod
を使って中身を見てみよう。
特に意識したつもりはないが、自動的にownerReferences
はセットされている。では、後はポリシーの設定
PropagationPolicy
Job v1 batch: Delete を眺めていると、PropagationPolicy
といのが設定できるようだ。選べる値は三つ。デフォルトはどうなるかというと、リソースの finalizer の設定によるらしいが、私のはカスタムリソースで、定義されていない。background
か foreground
から選択すると良さげ。
- 'Orphan' - orphan the dependents;
- 'Background' - allow the garbage collector to delete the dependents in the background;
- 'Foreground' - a cascading policy that deletes all dependents in the foreground.
クライアントアプリケーションでの記述
修正のためには、ポリシーを設定すればいいだけなので、簡単でした。実際に試してみると、DeletePropagationBackground
でも DeletePropagationForeground
でも正しく動作しましたが、background の方でも十分早く削除がなされたので、Podの削除まで待ち受ける Foreground ではなく、Background の設定をデフォルトにすることにしました。
deletePolicy := metav1.DeletePropagationBackground
deleteOptions := &client.DeleteOptions{
PropagationPolicy: &deletePolicy,
}
err := e.client.Delete(context.TODO(), j.DeepCopyObject(), deleteOptions)
if err != nil {
return err
}
古いカスタムリソースが削除できない
さて、古い Keda の ScaledJob で、古いカスタムリソースが削除できない問題がありました。これは、finalizer
がセットされていて、それが、削除を妨げていたようです。何回削除しても消えないのでなんでだろうと思いましたが、こちらの issue どおりの方法で解決しました。finalizer の定義を消すと、削除できるようになりました。
kubectl patch scaledjob -p '{"metadata":{"finalizers":[]}}' --type=merge
- Custom resources with finalizers can "deadlock" customresourcecleanup.apiextensions.k8s.io finalizer
おわりに
k8s のインターフェイスは素直でわかりやすくて楽しいですね!