2026年10月8日

2026年10月8日

KubernetesのInitContainer(initコンテナ)の使い方|起動前の準備処理の書き方と失敗時の調べ方

InitContainer(init コンテナ)は、Pod のメインのコンテナが起動する前に、準備のための処理を順番に実行して終了するコンテナです。依存するサービスの準備を待つ、設定ファイルを生成する、ボリュームに初期データを置く、といった処理を、アプリのイメージに手を加えずに分けて書けます。この記事では、基本の書き方、WordPress を例にした実用的な使い方、Pod が Init: の状態で止まったときの調べ方と、設計上の注意点を説明します。

内容は Kubernetes の現行のサポート対象の版を前提にしています(2026年10月現在)。後半で触れるネイティブサイドカーは比較的新しい機能なので、クラスタの版を kubectl version で確かめてください。

InitContainer の動き方

spec.initContainers に書いたコンテナは、次のように動きます。

  • 書いた順に1つずつ実行され、前のものが正常終了(終了コード0)してから次が始まる
  • すべての init コンテナが成功してから、spec.containers のメインのコンテナが起動する
  • 失敗した場合、Pod の restartPolicy が Always または OnFailure なら成功するまで再実行され、Never なら Pod は失敗として扱われる
  • 通常の init コンテナには livenessProbe・readinessProbe・startupProbe を設定できない(終了することが前提のため)

メインのコンテナとは別のイメージを使えるのが大きな利点です。たとえば、アプリのイメージに入れたくない git やデータベースのクライアントを、init コンテナ側だけに持たせることができます。

基本の書き方:依存サービスを待つ

最もよく使われるのは、データベースが接続を受け付けるまで待つ処理です。次の例では、WordPress の起動前に MySQL のサービスに mysqladmin ping が通るまで待ちます。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress
spec:
  replicas: 2
  selector:
    matchLabels:
      app: wordpress
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      initContainers:
        - name: wait-for-db
          image: mysql:8.4
          command:
            - sh
            - -c
            - |
              until mysqladmin ping -h mysql --silent; do
                echo "waiting for mysql..."
                sleep 3
              done
      containers:
        - name: wordpress
          image: wordpress:latest
          ports:
            - containerPort: 80
          env:
            - name: WORDPRESS_DB_HOST
              value: mysql
            - name: WORDPRESS_DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: wordpress-db
                  key: password

mysql は MySQL の Service 名です。init コンテナからも、通常のコンテナと同じように Service 名で名前解決できます。DB のクライアントを入れたくなければ、busybox イメージで nslookup を使い「Service の名前が引けるまで待つ」方法もありますが、名前が引けても DB が準備できているとは限らない点に注意してください。

待つ処理は、いつまでも終わらない可能性があります。DB の設定を誤っていると Pod は Init:0/1 のまま止まり続けるので、ログに待機中であることを出しておくと原因に早く気づけます。

よくある使い方

設定ファイルや初期データを用意する

init コンテナとメインのコンテナは、Pod 内の同じボリュームを共有できます。emptyDir を使えば、init コンテナで作ったファイルをメインのコンテナに渡せます。

spec:
  volumes:
    - name: shared
      emptyDir: {}
  initContainers:
    - name: render-config
      image: busybox:1.36
      command: ["sh", "-c", "echo \"site=$SITE_NAME\" > /work/app.conf"]
      env:
        - name: SITE_NAME
          value: example
      volumeMounts:
        - name: shared
          mountPath: /work
  containers:
    - name: app
      image: my-app:latest
      volumeMounts:
        - name: shared
          mountPath: /etc/my-app

テーマやプラグインのファイルを別のイメージから WordPress の wp-content 用ボリュームへコピーする、といった使い方も同じ考え方です。

ボリュームの権限を整える

永続ボリュームの所有者がアプリの実行ユーザーと合わず書き込めない場合に、init コンテナで chown する例をよく見かけます。ただし、この方法は init コンテナを root で動かす必要があります。多くの場合は Pod の securityContext.fsGroup を設定するほうが安全で簡単なので、先にそちらを検討してください。

Init で止まったときの調べ方

init コンテナが終わらないと、kubectl get pods の STATUS は次のように表示されます。

  • Init:0/2:2つある init コンテナのうち、完了したのが0個
  • Init:Error:init コンテナが失敗した
  • Init:CrashLoopBackOff:init コンテナが失敗と再実行を繰り返している
  • PodInitializing:init コンテナはすべて完了し、メインのコンテナを起動中

確かめる順番は次のとおりです。

kubectl describe pod <Pod名>                       # どの init コンテナで止まっているか、Events
kubectl logs <Pod名> -c wait-for-db                # init コンテナのログ(-c で名前を指定)
kubectl logs <Pod名> -c wait-for-db --previous     # 再実行前のログ

describe の「Init Containers」の欄に、各 init コンテナの State と終了コードが出ます。kubectl logs は -c でコンテナ名を指定しないとメインのコンテナを見に行くため、init コンテナのログが見つからないと感じたら名前の指定を確かめてください。

原因は、起こりやすい順に次のようなものです。

  1. 待ち先に届かない:Service 名や名前空間の誤り、DB 側が起動していない、NetworkPolicy で通信が止められている
  2. コマンドの誤り:イメージにそのコマンドが入っていない、シェルの書き方の誤り(終了コード 127 や 126)
  3. 権限・ボリュームの問題:マウント先に書き込めない、Secret や ConfigMap が存在しない
  4. イメージを取得できない:Init:ImagePullBackOff などと表示され、Events に理由が出る

設計で気をつけること

何度実行されても問題ない処理にする

init コンテナは、Pod が作り直されるたびに実行されます。ノードの再起動などで Pod のサンドボックスが作り直された場合にも再実行されることがあります。そのため、「すでにファイルがあれば何もしない」「すでに作られていればスキップする」のように、繰り返し実行しても結果が変わらない書き方にしておきます。

マイグレーションは Job も検討する

データベースのマイグレーションを init コンテナで行うと、レプリカ数の分だけ同時に実行されます。上の例のように replicas: 2 なら2つの Pod が同時にマイグレーションを始めるため、ロックを取る仕組みがないツールでは衝突のおそれがあります。一度だけ実行したい処理は Job に分けるか、Helm のフックなどデプロイの手順として実行するほうが扱いやすくなります。本番の DB に対する処理の前にはバックアップを取ってください。

起動時だけでなく運用中の切断にも備える

init コンテナが待つのは Pod の起動時だけです。運用中に DB が再起動しても init コンテナは動かないため、アプリ側に再接続の仕組みを持たせ、readinessProbe で「今はリクエストを受けられない」状態を表せるようにしておきます。

リソースの見積もり

Pod のリソース要求(requests)は、「init コンテナのうち最大のもの」と「メインのコンテナの合計」の大きい方で計算されます。init コンテナに大きな requests を書くと、その値でスケジュールされる点に注意してください。

ネイティブサイドカーとの違い

initContainers の中で restartPolicy: Always を指定したコンテナは、終了せずに動き続ける「サイドカー」として扱われます。ログ転送やプロキシのように、メインのコンテナより先に起動し、Pod が動いている間ずっと動いてほしいものに使う仕組みです。比較的新しい版で使えるようになった機能なので、クラスタが対応しているか確かめてから使ってください。

この記事で扱った通常の init コンテナは「終わってから次に進む」もの、ネイティブサイドカーは「起動したら次に進み、そのまま動き続ける」ものと区別しておくと混乱しません。サイドカーの詳しい書き方は、サイドカーパターンの記事で扱っています。

まとめ

  • init コンテナは spec.initContainers に書き、順番に実行されて全部成功してからメインのコンテナが起動する
  • 依存サービスを待つ、設定やデータを emptyDir で渡す、といった準備処理に向いている
  • 権限の調整は init コンテナでの chown より先に fsGroup を検討する
  • 止まったときは describe で止まっている init コンテナを特定し、logs -c <名前> でログを見る
  • 再実行されても問題ない処理にし、マイグレーションのような一度きりの処理は Job も検討する
  • 動き続ける補助コンテナにはネイティブサイドカー(restartPolicy: Always)を使う

お気軽にご相談ください

お見積りへ お問い合わせへ
▲