LoginSignup
20
10

More than 3 years have passed since last update.

Kubernetes で Complete/Failed となった Job を自動削除する

Last updated at Posted at 2019-10-23

TL;DR

kube-apiserver に Feature Gates で以下を設定する。

--feature-gates=TTLAfterFinished=true

以下のように Job のマニフェストに .spec.ttlSecondsAfterFinished を追加する。

apiVersion: batch/v1
kind: Job
metadata:
  name: myjob
spec:
  ttlSecondsAfterFinished: 30 # こちらのフィールドを追加
  template:
    spec:
      containers:
      - name: busybox
        image: busybox
        command: ["date"]
        env:
        - name: TZ
          value: "JST-9"
      restartPolicy: Never

はじめに

Kubernetes でのバッチ処理などで Job を利用していて、以下のように実行が完了した Job とそれに依存する Pod が大量に残ってしまっているケースがあるかと思います。

$ kubectl get jobs,pods
NAME     COMPLETIONS   DURATION   AGE
myjob0   1/1           19s        112s
myjob1   1/1           23s        111s
myjob2   1/1           21s        111s
myjob3   1/1           26s        111s
myjob4   1/1           36s        111s
myjob5   1/1           33s        111s
myjob6   1/1           54s        111s
myjob7   1/1           59s        110s
myjob8   1/1           56s        110s
myjob9   1/1           30s        110s

NAME           READY   STATUS      RESTARTS   AGE
myjob0-lgx7h   0/1     Completed   0          90s
myjob1-sdbtg   0/1     Completed   0          89s
myjob2-ng5lb   0/1     Completed   0          89s
myjob3-fmmw4   0/1     Completed   0          89s
myjob4-z654m   0/1     Completed   0          89s
myjob5-4scjl   0/1     Completed   0          89s
myjob6-qg5xr   0/1     Completed   0          89s
myjob7-42s7r   0/1     Completed   0          88s
myjob8-7zzmg   0/1     Completed   0          88s
myjob9-hhrjw   0/1     Completed   0          88s

これを気付いた時に毎回手作業で削除するのは面倒なので、今回は Kubernetes で Complete/Failed となった Job を自動削除する方法を紹介します。

Feature Gates TTLAfterFinished について

TTLAfterFinished は Kubernetes 1.12 から Alpha で追加された Feature Gates で、これを有効化することで終了したリソースをクリーンアップするための TTL controller が機能するようになります。なお、この機能は Alpha ステージの実験段階のものなのでデフォルトでは有効化されていません。
https://v1-16.docs.kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/

こちらの機能が提供された背景を知るために Design Doc を見てみると Kubeflow, Prow, Apache Spark on Kubernetes, Jenkins Kubernetes plugin などから実行された Job をクリーンアップすることが具体的なユースケースとして挙げられていました。

TTL Controller について

TTL Controller は実行が完了したリソースに TTL の機構を提供するもので、現在は Job のみがサポートされています。
https://v1-16.docs.kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/

TTL Controller が有効な状態で Job Spec の .spec.ttlSecondsAfterFinished に値を設定する(設定例はこちら)ことで Complete/Failed となった Job を自動削除することが可能になります。リソースの実行が完了して .spec.ttlSecondsAfterFinished 秒後に、そのリソースが TTL Controller によって(依存するリソースと共に)自動削除されるイメージです。

Kubernetes クラスタ管理者向けな情報

Mutating Admission Webhook を使って、作成される Job にデフォルトで .spec.ttlSecondsAfterFinished を設定する運用も良いとのことでした。

また、TTL Controller はリソースに保存されている時間を元に制御を行うので、厳密な運用をしたければ Kubernetes クラスタの全ての Node で NTP を起動するのが望ましいとのことでした。詳細は #6159 を参照ください。

動作検証

TTLAfterFinished を有効化して minikube を起動します。

$ minikube version
minikube version: v1.4.0
commit: 7969c25a98a018b94ea87d949350f3271e9d64b6

$ minikube start --kubernetes-version=v1.16.0 --feature-gates=TTLAfterFinished=true

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.4", GitCommit:"c27b913fddd1a6c480c229191a087698aa92f0b1", GitTreeState:"clean", BuildDate:"2019-03-01T23:35:19Z", GoVersion:"go1.12", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"16", GitVersion:"v1.16.0", GitCommit:"2bd9643cee5b3b3a5ecbd3af49d09018f0773c77", GitTreeState:"clean", BuildDate:"2019-09-18T14:27:17Z", GoVersion:"go1.12.9", Compiler:"gc", Platform:"linux/amd64"}

$ kubectl get pods -n kube-system kube-apiserver-minikube -o yaml | grep feature-gates
    - --feature-gates=TTLAfterFinished=true

以下のスクリプトで .spec.ttlSecondsAfterFinished を設定した Job を複数作成します。今回は30秒で削除される設定を適用します。

for i in $(seq 0 4); do
cat << EOM | kubectl apply -f -
apiVersion: batch/v1
kind: Job
metadata:
  name: myjob${i}
spec:
  ttlSecondsAfterFinished: 30
  template:
    spec:
      containers:
      - name: busybox
        image: busybox
        command: ["date"]
        env:
        - name: TZ
          value: "JST-9"
      restartPolicy: Never
EOM
done

上記のスクリプトを実行すると5つの Job 及び、それに依存する Pod が作成されます。

$ kubectl get jobs,pods
NAME               COMPLETIONS   DURATION   AGE
job.batch/myjob0   1/1           8s         23s
job.batch/myjob1   1/1           11s        23s
job.batch/myjob2   1/1           21s        23s
job.batch/myjob3   1/1           13s        22s
job.batch/myjob4   1/1           16s        22s

NAME               READY   STATUS      RESTARTS   AGE
pod/myjob0-g9vjm   0/1     Completed   0          23s
pod/myjob1-pfcdt   0/1     Completed   0          23s
pod/myjob2-mf95m   0/1     Completed   0          23s
pod/myjob3-8xv7k   0/1     Completed   0          22s
pod/myjob4-4bfp5   0/1     Completed   0          22s

30秒が経過すると、Job とそれに紐づく Pod が削除されていることがわかると思います。

$ kubectl get jobs,pods
No resources found.

さいごに

今回は Kubernetes で Complete/Failed となった Job を自動削除する方法を紹介しました。CronJob を利用している方には不要かもしれませんが、Job 単体で利用されている方にとっては有効な設定かと思われます。

最近、個人的にカスタムコントローラーを学習していたのもあり、Kubernetes Way(client-go + code-generator)な実装である TTL Controller の実装を読めたことが非常に有意義でした。おしまい。

おまけ: TTL Controller の実装

Kubernetes 1.16.0 の実装を見ていきます。

Reconcile Loop の中で以下の processJob 関数を使って、Job の状態と TTL をチェックして削除するという処理が実行されています。シンプルな実装で自分でも普通に読めたので、ご興味ある方は是非参照ください。
https://github.com/kubernetes/kubernetes/blob/v1.16.0/pkg/controller/ttlafterfinished/ttlafterfinished_controller.go#L186-L238

備考: CronJob を利用している場合

CronJob を利用している場合には .spec.successfulJobsHistoryLimit (デフォルト:3).spec.failedJobsHistoryLimit (デフォルト:1) をマニフェストに定義することで、CronJob により定期実行される Job 及び、依存する Pod の履歴数を管理することができます。
https://v1-16.docs.kubernetes.io/docs/tasks/job/#jobs-history-limits

20
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
10