KEDA ScaledJob の Podが自動削除されなかった理由と対策

KEDA の ScaledJobで、`successfulJobsHistoryLimit` で指定した個数以上になると、完了した Jobが削除されるようになるのだが、なぜか、Job で作成されたPodが削除されない。

```go
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
}
```

いろいろ探してみると次の記事に行き当たった。ご丁寧に設定項目名まで同じや。そらそうや、わしこの設定項目考えたときにこれを参考にしたリソースやから、そら同じ名前やわ。

* [Orphaned pods after job is deleted via successfulJobsHistoryLimit](https://github.com/kubernetes/kubernetes/issues/71975)

ここに書かれていたことは主に二つ `ownerReference` のメタデータが存在するか？この[PR](https://github.com/kubernetes/kubernetes/pull/71801)で 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 とは

* [Garbage Collection](https://kubernetes.io/docs/concepts/workloads/controllers/garbage-collection/)

に書かれているが、自分の親リソースのリファレンスで、これを持っておくと、カスケードデリートのポリシーを設定すると、有効になる。ほかにも元ページには条件が載っていたので、これらをセットする必要があるのかもしれない。

# 現状の振る舞い

まず現状を確認しよう。Job がある。

```bash
$ 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があり、似たようなネーミングになっている。

```bash
$ 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` を使って中身を見てみよう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3470/58ec60a0-a4e4-3d10-0179-8076a638b778.png)

特に意識したつもりはないが、自動的に`ownerReferences` はセットされている。では、後はポリシーの設定

# PropagationPolicy

[Job v1 batch: Delete](https://v1-18.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#delete-job-v1-batch) を眺めていると、`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 の設定をデフォルトにすることにしました。 

```go
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 の定義を消すと、削除できるようになりました。

```bash
kubectl patch scaledjob -p '{"metadata":{"finalizers":[]}}' --type=merge
```

* [Custom resources with finalizers can "deadlock" customresourcecleanup.apiextensions.k8s.io finalizer
](https://github.com/kubernetes/kubernetes/issues/60538#issuecomment-369099998)

# おわりに

k8s のインターフェイスは素直でわかりやすくて楽しいですね！