Pod
Kubernetes の最小デプロイ単位で、1 つ以上のコンテナをまとめて管理するリソース
Pod とは
Pod は Kubernetes の最小デプロイ単位で、1 つ以上のコンテナをまとめて管理するリソースである。共有されるのは network namespace で、Pod にはアドレスファミリーごとに IP アドレスが 1 つ割り当てられ、中のコンテナは IP アドレスとポート空間まで共有する。だから互いを localhost で呼べる代わりに、2 つのコンテナが同じポートを listen することはできない。SystemV セマフォや POSIX 共有メモリといったプロセス間通信も、Pod 内では素通しで使える。ストレージの扱いは少し違い、Volume は Pod 側で宣言するが、使うコンテナが個別に volumeMounts で mount しない限り見えない。
この namespace を保持しているのは、アプリのコンテナより先に作られる基盤コンテナ (pause コンテナ) である。namespace と cgroup は、それを存続させるプロセスがいないと消えてしまうため、何もせず待つだけの pause がその役を担う。アプリのコンテナがクラッシュして入れ替わってもネットワーク設定が失われないのは、器である pause が生き続けているからだ。
Pod は使い捨ての単位でもある。いったんノードに割り当てられた Pod が別のノードへ移ることはなく、実行完了・Pod オブジェクトの削除・リソース不足による退避・ノード障害のいずれかで終わる。ノードが落ちたときに起きるのは Pod の移動ではなく、コントローラーによる別の Pod の作成で、名前も IP も UID も変わる。Pod 名や Pod IP を固定値と見なして設定を書くと、この入れ替わりで壊れる。構成は通常 1 Pod = 1 コンテナで、ログ収集やプロキシを足したいときにサイドカーで複数コンテナにする。
Pod の定義
定義で効いてくるのは resources と 2 種類の probe である。requests はスケジューラーがノードを選ぶときに使う見積もりで、limits は超えたときに絞られる (CPU) か kill される (メモリ) 上限である。probe は名前が似ているが役割が別で、readinessProbe が落ちても Service のエンドポイントから外れて新規トラフィックが止まるだけだが、livenessProbe が落ちるとコンテナが再起動される。起動に時間の掛かるアプリで livenessProbe の閾値だけを厳しくすると、起動しきる前に再起動を掛けられて延々と立ち上がらない。
apiVersion: v1
kind: Pod
metadata:
name: api-server
labels:
app: api-server
spec:
containers:
- name: app
image: myapp:1.0
ports:
- containerPort: 3000
resources:
requests: { cpu: 100m, memory: 128Mi }
limits: { cpu: 500m, memory: 512Mi }
readinessProbe:
httpGet: { path: /ready, port: 3000 }
livenessProbe:
httpGet: { path: /healthz, port: 3000 }
Pod のライフサイクル
Pod の status.phase が取る値は 5 つで、これ以外は存在しない。
Pending ──→ Running ──┬──→ Succeeded (全コンテナが正常終了)
└──→ Failed (少なくとも 1 つが失敗で終了)
Unknown ノードと通信できず状態が取得できない
| フェーズ | 説明 |
|---|---|
| Pending | API サーバーに受理されたが、まだ動き出していない (ノードへの割り当て待ち・イメージのダウンロード中) |
| Running | ノードに束縛され全コンテナが作成済みで、少なくとも 1 つが実行中か起動・再起動の途中 |
| Succeeded | 全コンテナが正常終了し、再起動されない (Job で到達する) |
| Failed | 全コンテナが終了し、少なくとも 1 つが非ゼロ終了かシステムによる停止で終わった |
| Unknown | 何らかの理由で Pod の状態が取得できない (ノードとの通信障害が典型) |
kubectl get pods の STATUS 列に出る CrashLoopBackOff や Terminating はフェーズではない。STATUS は人が読んで分かるようにした表示用の欄で、フェーズは Pod API のフィールドである。この 2 つを同じ軸だと思うと、存在しない状態遷移を探すことになる。
CrashLoopBackOff が指しているのは、コンテナの再起動に指数バックオフの待ちが掛かっている状態そのものである。kubelet は終了したコンテナを 10 秒・20 秒・40 秒と倍々の間隔で再起動し、待ち時間は 300 秒 (5 分) で上限に達する。コンテナが 10 分間問題なく動き続けるとこのタイマーはリセットされ、次のクラッシュは 1 回目として扱われる。逆に言えば、直ったように見えて 10 分持たずに再発する不具合では、待ち時間が伸び続けて復旧が遅く見える。
サイドカーパターン
従来のサイドカーは containers にアプリと並べて書く。
spec:
containers:
- name: app
image: myapp:1.0
- name: log-agent # サイドカー: ログ収集
image: fluent/fluent-bit:5.1.1
volumeMounts:
- name: logs
mountPath: /var/log/app
volumes:
- name: logs
emptyDir: {}
メインコンテナとサイドカーが同じ Volume を共有し、ログ収集・プロキシ・モニタリングといった横断的関心事を本体から分離する。イメージのタグを固定しているのは意図的で、latest のまま置くとノードによって違う版が動いたり、再起動しただけで版が変わったりする。
ただし containers に並べる書き方には起動順・終了順の保証がない。ログ収集より先にアプリが立ち上がって初期のログを取り逃す、Job でアプリが終わってもサイドカーが動き続けて Pod が完了しない、といった噛み合わせの悪さが出る。これに対して initContainers へ restartPolicy: Always を付ける書き方があり、こちらはアプリのコンテナより先に起動して後に終わる。Kubernetes v1.29 以降は既定で使える。
spec:
initContainers:
- name: log-agent
image: fluent/fluent-bit:5.1.1
restartPolicy: Always # これがサイドカーの指定 (init のまま終わらない)
volumeMounts:
- name: logs
mountPath: /var/log/app
containers:
- name: app
image: myapp:1.0
kubectl での操作
調査には順番がある。コンテナが一度も起動していない障害ではログが空なので、まず kubectl describe pod の Events を見る。ノードのリソース不足や taint でスケジューリングできない理由、イメージの取得失敗はログではなく Events に出る。起動した後で落ちているなら kubectl logs、既に再起動されて現世代のログが空なら --previous で 1 つ前のコンテナの出力を取る。
# Pod の一覧
kubectl get pods
# Pod の詳細 (イベント、状態)
kubectl describe pod api-server
# Pod のログ
kubectl logs api-server
kubectl logs api-server -c log-agent # サイドカーのログ
kubectl logs api-server --previous # 再起動前のコンテナのログ
# Pod に入る
kubectl exec -it api-server -- /bin/sh
# Pod の削除
kubectl delete pod api-server
Pod を直接作らない
本番環境では Pod を直接作成せず、Deployment 経由で管理する。Deployment が Pod の数を維持し、異常終了時に自動再作成する。
✅ Deployment → ReplicaSet → Pod (自動管理)
❌ Pod を直接作成 (異常終了しても再作成されない)
ECS タスクとの比較
複数コンテナの共同スケジューリング単位という位置づけで、ECS タスクは Pod に対応する。仕組みも近く、ECS の awsvpc モードはタスクに ENI を 1 枚割り当て、先に起動した pause コンテナのネットワークスタックを他のコンテナが共有する。結果としてタスク内のコンテナは ENI の IP で addressable になり、localhost で通信できる。違いが出るのは作り方で、ECS はタスク定義をリビジョンとして登録してから起動するのに対し、Pod は manifest をそのまま作成できる。手軽さの裏返しとして、前節の「直接作らない」規律が要る。
| 観点 | Kubernetes Pod | ECS タスク |
|---|---|---|
| 最小単位 | Pod (1+ コンテナ) | タスク (1+ コンテナ) |
| サイドカー | ネイティブ対応 | サポートあり |
| ネットワーク | Pod 内は localhost | タスク内は localhost |
| ストレージ共有 | Volume | Bind mount |
踏みやすい落とし穴は 2 つに集約される。1 つは Pod IP や Pod 名を固定と見なす設計で、Pod は入れ替わる前提のものなので参照は Service 名へ寄せる。もう 1 つは resources の未設定で、requests も limits も書かない Pod は QoS クラス BestEffort になり、ノードのメモリが枯渇したときの退避で最初に選ばれる側に回る (kubelet は使用量が requests を超えているか、Pod の優先度、requests に対する使用量の比で順位を付ける)。平時は差が出ないため、ノードが混み始めた日に落ちるのは resources を書いていない Pod からになる。
この記事は役に立ちましたか?
関連用語
Kubernetes
コンテナのデプロイ、スケーリング、管理を自動化するオープンソースのオーケストレーションプラットフォーム
Deployment
Kubernetes で Pod のレプリカ数、更新戦略、ロールバックを宣言的に管理するリソース
コンテナ
アプリケーションとその依存関係をパッケージ化し、環境に依存しない一貫した実行環境を提供する仮想化技術
サイドカーインジェクション
Kubernetes で Pod にサイドカーコンテナを自動的に注入し、横断的関心事を透過的に追加する仕組み
Init コンテナ
Kubernetes でメインコンテナの起動前に初期化処理を実行する特殊なコンテナ
Pod Disruption Budget (PDB) とは - Kubernetes の可用性を守る設定方法
PDB は Kubernetes でノードメンテナンス時に同時停止できる Pod 数を制限するリソース。maxUnavailable と minAvailable の使い分け / YAML 設定例を解説
関連する記事
OS / 低レイヤー本ガイド - コンピュータの仕組みを学ぶ技術書の選び方
OS、コンパイラ、ネットワークなど低レイヤーを学べる技術書の 4 ジャンルと、どこから始めるべきかの指針、賞味期限の見極め方を紹介します。
技術書の読書ノート術 - 付箋 / マーカー / デジタルの使い分け
技術書を読むときのノートの取り方を比較します。付箋派、マーカー派、デジタルノート派、それぞれの長所と短所を実体験をもとに紹介します。
Linux 本ガイド - コマンドライン / しくみ / 性能の 3 層で選ぶ技術書
Linux を学ぶ技術書の選び方を 3 層 (コマンドラインの操作 → カーネルのしくみ → 性能と運用) で整理。新しい Linux の教科書や [試して理解] Linux のしくみなどの定番書の使い分けと、学ぶ順番を解説します。