VITANのブログ

Techなことをメモしていきます

kubernetesのjobでsidecarのコンテナを終了させる方法

sidecar構成(1つのpodの中にメインのコンテナ+proxy等を担当するサブのコンテナを置く)をしている状態でjobやcronjobを走らせようとすると、メインのコンテナが終了してもサブのコンテナが終了しないとjobは完了扱いにならない

cronjobの場合、定期実行なので完了扱いにならないと次の実行で何かと困ったことが起きる

この解決法として、主に2つの解決法がある

  1. concurrencyPolicyをReplaceにする
  2. メインのコンテナからサブのコンテナに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が完了していることが確認できる

参考

kubernetes.io