kubernetesのjobでsidecarのコンテナを終了させる方法
sidecar構成(1つのpodの中にメインのコンテナ+proxy等を担当するサブのコンテナを置く)をしている状態でjobやcronjobを走らせようとすると、メインのコンテナが終了してもサブのコンテナが終了しないとjobは完了扱いにならない
cronjobの場合、定期実行なので完了扱いにならないと次の実行で何かと困ったことが起きる
この解決法として、主に2つの解決法がある
- concurrencyPolicyをReplaceにする
- メインのコンテナからサブのコンテナにSIGTERMを送る
1.の方は、cronjobの設定で定期実行に前回の実行が終わってない時の挙動を設定できる。 これをReplaceにしておくと前回の実行が終了してるかどうかにかかわらず新しくjobを作り直すため、付け焼き刃的ではあるが一応解決はする。
ただ、1.の方法は正攻法ではないので、2.の方を検討する。
メインのコンテナでの処理が終わった時に、サブのコンテナのプロセスにSIGTERMを送ることで終了させる。 昔のkubernetesではpod内で名前空間を共有することができなかった(っぽい)が、今ではできるようになったのでこの方法が使える。
以下、実際の実装例を書く
構成
メインのコンテナ: python
サブのコンテナ: nginx
python
psutilを使ってサブコンテナのプロセスであるnginxのPIDを取得、SIGTERMを送る 実際に使うとしたらこのコードの前に目的の処理を書く、今回はnginxにSIGTERMを送るだけ
import psutil for proc in psutil.process_iter(): if "nginx" in proc.name(): print(proc.name()) print(proc.pid) proc.terminate()
Dockerfile
特筆することは無いが、nginxの起動を待ってから動くようにsleepを入れた
FROM python:3 ARG project_dir=/project/ WORKDIR $project_dir ADD . . RUN pip install -r requirements.txt CMD sleep 5 && python test.py
jobのyaml
shareProcessNamespace: true
を記述することで、pod内で名前空間が共有されるようになる
他は普通に書く
apiVersion: batch/v1 kind: Job metadata: name: sleep spec: completions: 1 parallelism: 1 template: spec: shareProcessNamespace: true containers: - name: sigterm-test-python image: sigterm-test-python:latest imagePullPolicy: Never - name: nginx image: nginx restartPolicy: Never
出力
起動直後
$kubectl get pods NAME READY STATUS RESTARTS AGE sleep-c9b8f 2/2 Running 0 6s
終了
&kubectl get pods NAME READY STATUS RESTARTS AGE sleep-c9b8f 0/2 Completed 0 29s
$kubectl get jobs NAME COMPLETIONS DURATION AGE sleep 1/1 7s 13s
サブコンテナのnginxも終了されており、jobが完了していることが確認できる