メインコンテンツへスキップ
  1. Blogs/

Kubernetes postStartフックの終了コード検証:exit 0とexit 1の実際の挙動を検証してみた

2 分
Kubernetes Minikube
0222-nnn
著者
0222-nnn
猫が好き
目次

はじめに
#

KubernetesのpostStartフックについて調べていたところ、公式ドキュメントに終了コードの詳細な記載がないことに気づきました。
実際にexit 0exit 1を返した場合の挙動がどう違うのか、minikube環境で検証してみました。

postStartフックとは?
#

postStartは、KubernetesのContainer Lifecycle Hookの一つで、コンテナが起動した直後に実行される処理を定義できます。

基本的な仕組み
#

  • コンテナのENTRYPOINT/CMDプロセスが開始された直後に実行される
  • 同期的に処理されるため、フックが終了するまでコンテナは「Running」状態にならない
  • 終了コードによってコンテナの運命が決まる:
    • exit 0(成功) → コンテナは正常に起動を続行
    • exit 1(失敗) → コンテナは即座に終了し、再起動ポリシーに従って再起動

検証環境
#

minikube   version: v1.36.0
Kubernetes version: Server Version: v1.33.1

実際の検証
#

成功パターン(exit 0)
#

apiVersion: v1
kind: Pod
metadata:
  name: poststart-exit0
spec:
  containers:
  - name: test
    image: busybox
    command: ["sh", "-c", "sleep 3600"]
    lifecycle:
      postStart:
        exec:
          command: ["sh", "-c", "echo 'postStart success'; exit 0"]

結果:

kubectl apply で成功パターンのYAMLをデプロイすると以下の結果になります。
コンテナは正常にRunning状態になり、postStartフックが成功したことが確認できます。

$ k get po poststart-exit0 
NAME              READY   STATUS    RESTARTS   AGE
poststart-exit0   1/1     Running   0          11s

失敗パターン(exit 1)
#

apiVersion: v1
kind: Pod
metadata:
  name: poststart-exit1
spec:
  containers:
  - name: test
    image: busybox
    command: ["sh", "-c", "sleep 3600"]
    lifecycle:
      postStart:
        exec:
          command: ["sh", "-c", "echo 'postStart will fail'; exit 1"]

結果:

kubectl apply で失敗パターンのYAMLをデプロイすると以下の結果になります。
コンテナはPostStartHookError状態になり、再起動を繰り返します。

tech-0222@MSI:root$ k get po poststart-exit1 -w
NAME              READY   STATUS              RESTARTS   AGE
poststart-exit1   0/1     ContainerCreating   0          2s
poststart-exit1   0/1     PostStartHookError   0          32s
poststart-exit1   0/1     PostStartHookError   1 (0s ago)   64s
poststart-exit1   0/1     CrashLoopBackOff     1 (1s ago)   65s
poststart-exit1   0/1     PostStartHookError   2 (0s ago)   112s
poststart-exit1   0/1     CrashLoopBackOff     2 (1s ago)   113s

イベントログの確認
#

失敗時のイベントログを見るとFailedPostStartHookKillingイベントが発生し、コンテナが強制終了されていることがわかります。

# poststart-exit1はPOD名
$ kubectl get events --field-selector involvedObject.name=poststart-exit1 --sort-by=.metadata.creationTimestamp

LAST SEEN   TYPE      REASON                OBJECT                MESSAGE
91s         Normal    Scheduled             pod/poststart-exit1   Successfully assigned default/poststart-exit1 to k8s-test
11s         Normal    Pulling               pod/poststart-exit1   Pulling image "busybox"
90s         Normal    Pulled                pod/poststart-exit1   Successfully pulled image "busybox" in 1.368s (1.368s including waiting). Image size: 2223685 bytes.     
10s         Normal    Created               pod/poststart-exit1   Created container: test
10s         Normal    Started               pod/poststart-exit1   Started container test
10s         Warning   FailedPostStartHook   pod/poststart-exit1   PostStartHook failed
10s         Normal    Killing               pod/poststart-exit1   FailedPostStartHook
58s         Normal    Pulled                pod/poststart-exit1   Successfully pulled image "busybox" in 1.397s (1.397s including waiting). Image size: 2223685 bytes.     
26s         Warning   BackOff               pod/poststart-exit1   Back-off restarting failed container test in pod poststart-exit1_default(2d08490a-d216-4995-856c-6f4617835f72)
10s         Normal    Pulled                pod/poststart-exit1   Successfully pulled image "busybox" in 1.342s (1.342s including waiting). Image size: 2223685 bytes.     

終了コード exit code 137
#

Podの詳細を確認すると、終了コードが137になっています。

$ kubectl get pod poststart-exit1 -o yaml | grep -A5 "lastState:"
    lastState:
      terminated:
        containerID: containerd://19b93fec260434f98f9dfbfe6f2f4518bef7507e5438115cc474f701f2654029
        exitCode: 137
        reason: Error

なぜ137なのか?
#

  • 137 = 128 + 9 (SIGKILL) → プロセスがkill -9された時の終了コード
  • postStartが失敗すると、Kubernetesがコンテナ全体を強制終了するため
  • 実際のpostStartフック自体はexit 1で失敗しているが、最終的にコンテナはSIGKILLで終了される

終了コードの仕組み
#

一般的に終了コードは以下のように分類されてるみたいです。

0:     正常終了
1-127: プログラムが自分で設定したエラーコード
128-255: シグナルによる終了(`終了コード = 128 + シグナル番号`)

主要なシグナル終了コード:

  • 130 = 128 + 2 → SIGINT(Ctrl+C)
  • 137 = 128 + 9 → SIGKILL(強制終了)
  • 143 = 128 + 15 → SIGTERM(終了要求)

この仕組みにより、終了コードを見るだけで「プログラムのエラー」「シグナルによる終了」なのかを判断できるようです。

まとめ
#

今回の検証で以下のことが確認できました。

  1. exit 0 → コンテナは正常に起動し続ける
  2. exit 1 → コンテナは即座に終了し、再起動を繰り返す
  3. 失敗時はPostStartHookErrorステータスになる
  4. 最終的な終了コードは137(SIGKILL)になる

公式ドキュメントには明記されていませんが、実際の挙動は明確に終了コードによって制御されていることがわかりました。 postStartフックを実装する際は、必ずexit 0で終了するように注意しましょう。

参考資料
#