Kubernetes Pod Yamlファイル解説
Pod は Kubernetes における最小のスケジューリング単位であり、ほぼすべてのワークロードは最終的に Pod の YAML 定義に行き着きます。このノートでは Pod YAML の全フィールドの注釈を整理しました。正確な情報は kubectl explain のクエリ結果を基準にしてください。例:kubectl explain pod.spec.volumes。
なぜ Pod YAML を読み解く必要があるのか
普段 Deployment や StatefulSet でアプリケーションをデプロイしていますが、それらの spec.template 部分は本質的に Pod のテンプレートです。コンテナが起動しない、プローブが失敗する、マウントパスが間違っているといった問題のトラブルシューティングは、最終的に Pod 定義に立ち返ってフィールドを一つずつ確認することになります。毎回ドキュメントをめくるより、よく使うフィールドの意味を一度まとめて把握しておく方が効率的です。
フィールドに自信がないときは、API 自身に聞くのが最も確実です:
# あるフィールドのドキュメント説明を確認
kubectl explain pod.spec.containers.livenessProbe
# あるフィールド配下の全サブフィールドを再帰的に一覧表示
kubectl explain pod.spec.volumes --recursive
kubectl explain はクラスターの OpenAPI Schema を直接読み取るため、現在のクラスターバージョンと厳密に一致しており、どこかから書き写した注釈表よりもずっと正確です。
全フィールド注釈リファレンス
以下は注釈付きの完全なリファレンスです(注釈はクイックリファレンス用であり、正確には kubectl explain を基準にしてください):
apiVersion: v1 //バージョン
kind: pod //リソースタイプ、pod
metadata: //メタデータ
name: String //メタデータ、podの名前
namespace: String //メタデータ、podのネームスペース
labels: //メタデータ、ラベルのリスト
- name: String //メタデータ、ラベルの名前
annotations: //メタデータ、カスタムアノテーションのリスト
- name: String //メタデータ、カスタムアノテーションの名前
spec: //pod内のコンテナの詳細定義
containers: //pod内のコンテナのリスト、複数のコンテナを持てる
- name: String //コンテナ名
image: String //コンテナのイメージ名
imagesPullPolicy: [Always|Never|IfNotPresent]//イメージ取得のポリシー:常にプル、プルしない、ローカルにイメージがあればプルしない
command: [String] //コンテナの起動コマンドリスト(未設定の場合はイメージビルド時の起動コマンドを使用)
args: [String] //コンテナの起動引数リスト
workingDir: String //コンテナの作業ディレクトリ
volumeMounts: //コンテナ内部にマウントするストレージボリュームの設定
- name: String //Pod定義の共有ストレージボリューム名を利用。volumes[]部分で定義した共有ストレージボリューム名を使うこと
mountPath: String //ストレージボリュームをコンテナ内でMountする絶対パス。512文字未満にすること
readOnly: boolean //読み取り専用モードかどうか。デフォルトは読み書きモード
ports: //コンテナが公開するポート番号のリスト
- name: String //ポートの名前
containerPort: int //コンテナが公開するポート
hostPort: int //コンテナのあるホストがリッスンするポート(コンテナ公開ポートをホストのポートにマッピング)。デフォルトはcontainerPortと同じ。hostPortを設定すると、同一ホスト上でそのコンテナの2つ目のレプリカを起動できない
protocol: String //ポートのプロトコル。TCPとUDPをサポート、デフォルトはTCP
env: //コンテナ実行前に設定する環境変数のリスト
- name: String //環境変数の名前
value: String //環境変数の値
resources: //リソース制限とリソース要求の設定
limits: //リソース制限の設定
cpu: Srting //CPU制限。単位はcore数。docker run --cpu-sharesパラメータに使われる
memory: String //メモリ制限。単位はMiB、GiBなど。docker run --memoryパラメータに使われる
requeste: //リソース要求の設定
cpu: String //cpu要求。単位はcore数。コンテナ起動時の初期利用可能量
memory: String //メモリ要求。単位はMiBまたはGiB。コンテナ起動時の初期利用可能量
livenessProbe: //pod内コンテナのヘルスチェック設定。指定回数応答がなければ、そのコンテナを自動的に再起動する。プローブ方式はexec、httpGet、tcpSocket
exec: //execプローブ方式
command: [String] //exec方式で指定するコマンドまたはスクリプト
httpGet: //httpgetでヘルスチェック。pathとportの指定が必要
path: String //URLパス(対応するドメインまたはIPアドレスの部分を除いたもの)
port: number //対応するポート
host: String //ドメインまたはIPアドレス
scheme: Srtring //対応する検査プロトコル。httpなど
httpHeaders: //ヘッダー情報を指定
- name: Stirng //ヘッダー情報の名前
value: String //ヘッダー情報の値
tcpSocket: //tcpSocketでヘルスチェック
port: number //プローブ対象のポート番号
initialDelaySeconds: 0//コンテナ起動完了後、最初のプローブまでの時間。単位はs
timeoutSeconds: 0 //プローブの応答待ちタイムアウト時間。単位はs、デフォルトは1。タイムアウトするとコンテナは不健全と判断され再起動される
periodSeconds: 0 //定期プローブの間隔設定。単位はs、デフォルトは10
successThreshold: 0 //何回成功したら成功と見なすか
failureThreshold: 0 //何回失敗したら失敗と見なすか
securityContext: //セキュリティ設定
privileged: false //
restartPolicy: [Always|Never|OnFailure]//再起動ポリシー。終了したら必ず再起動 / 正常終了(終了コード0)以外の非0終了コードで終了した場合のみ再起動 / Pod終了後に終了コードをmasterへ報告しPodを再起動しない
nodeSelector: object //NodeのLabelを設定。key:value形式で指定し、PodはこれらのLabelを持つNodeにスケジューリングされる
imagePullSecrets: //イメージのpull時に使うSecrets名。name:sercretkey形式で指定
- name: String //参照名
hostNetwork: false //ホストネットワークモードを使うかどうか。デフォルトはfalse。trueにするとホストのネットワークを使用しdockerブリッジを使わない。このPodは同一マシン上で2つ目のレプリカを起動できない
volumes: //このpodに定義する共有ストレージボリュームのリスト
- name: String //共有ストレージボリューム名。1つのPod内で各ストレージボリュームに名前を定義し、spec[].containers[].volumeMounts[].nameから参照する。タイプは多数あり、emptyDir、hostPathなど
emptyDir: {} //emptyDirタイプのストレージボリューム。一時ディレクトリでPodとライフサイクルを共にする。空オブジェクト
hostPath: //hostPathタイプのストレージボリューム。Podのあるホストのディレクトリをマウントすることを表し、volumes[].hostNetwork.pathで指定する
path: string //Podのあるホストのディレクトリ。コンテナ内でmountされるディレクトリに使われる
secret: //secretタイプのストレージボリューム。クラスターで事前定義されたsecretオブジェクトをコンテナ内部にマウントすることを表す
secretName: String //ストレージボリューム名
items: //Secretオブジェクト内の特定のKeyのみをマウントしたい場合に使用
- key: String //keyの値
path: String //マッピングファイルの相対パス
configMap: //configMapタイプのストレージボリューム。クラスターで事前定義されたconfigMapオブジェクトをコンテナ内部にマウントすることを表す
name: String //使用するconfigMapの名前
items: //ConfigMapオブジェクト内の特定のKeyのみをマウントしたい場合に使用
- key: String //keyを定義
path: String //マッピングファイルの相対パス
いくつかの重要フィールドの詳しい説明
1) command と args
command はコンテナランタイムの entrypoint に対応し、args はそれに渡す引数に対応します。両方とも書かない場合はイメージ付属の ENTRYPOINT と CMD が使われ、args だけ書いた場合はイメージの ENTRYPOINT が保持されて CMD が上書きされ、command を書くとイメージ内の ENTRYPOINT と CMD はどちらも効かなくなります。「コンテナが起動直後に終了する」問題を調査するときは、まずこの 2 つのフィールドがイメージのデフォルト起動コマンドを意図せず上書きしていないかを確認しましょう。
2) resources:requests と limits
requests はスケジューリングの根拠です——スケジューラーはこれを基にノードの残リソースが足りるかを判断します。limits は実行時の上限です——メモリが limit を超えるとコンテナは OOMKill され、CPU が limit を超えるとスロットリングされます(コンテナは kill されません)。両方とも未設定の場合、Pod は BestEffort の QoS クラスで動作し、ノードのリソースが逼迫したときに真っ先に追い出されます。プロダクション環境では少なくとも requests は設定することをおすすめします。
3) ヘルスプローブ
livenessProbe はコンテナがまだ生きているかを判定し、失敗が failureThreshold 回に達すると kubelet がコンテナを再起動します。これ以外に readinessProbe(準備完了かを判定。失敗しても Pod が Service のエンドポイントから外されるだけで、コンテナは再起動されません)があり、フィールド構造は完全に同じです。initialDelaySeconds にはアプリケーションの起動時間を十分に確保してください。そうしないと、アプリが起動しきる前にプローブに「死んでいる」と判定され、再起動を繰り返すループに陥ります。
4) volumes と volumeMounts
ストレージは「2 段階」の宣言です。まず spec.volumes でボリューム(emptyDir、hostPath、secret、configMap などのタイプ)を定義し、次にコンテナの volumeMounts で name によって参照し、マウントパスを指定します。両側の name は完全に一致していなければならず、これは初心者が最もよく遭遇するエラーの原因のひとつです。emptyDir は Pod の削除とともに破棄されるため一時データにしか向きません。hostPath はホストのディレクトリを直接マウントするため、Pod が別ノードに移るとデータが「消えた」ように見えます。一般にログ収集のようなノードレベルのユースケースにのみ使います。
ハマりどころと注意点
上の注釈表は界隈で広く出回っていますが、書き写された版にはいくつかスペルの問題が混入しており、そのままコピーすると apply でエラーになるか、フィールドが静かに無視されます:
kind: podはkind: Podが正しく、リソースタイプは先頭が大文字です。imagesPullPolicyの正しいフィールド名はimagePullPolicyで、s は付きません。resources配下のrequesteの正しい書き方はrequestsです。- hostPath のパスフィールドは
volumes[].hostPath.pathであり、注釈に書かれているhostNetwork.pathは誤記です。
フィールド名のスペルを間違えた場合、クラスターの検証ポリシーによっては、そのまま拒否されることもあれば、未知のフィールドとして無視されることもあります——後者の方が厄介で、設定が効いているように見えて実際には効いていません。改めて強調しておきます。作業前に kubectl explain でフィールド名を確認するか、kubectl apply --dry-run=server -f pod.yaml で API Server に先に検証させましょう。
YAML のコメントには // ではなく # を使うべきです。上の表の // コメントはクイックリファレンス用の注記にすぎず、実際の YAML ファイルにコピーする前には削除するか # に書き換える必要があります。
まとめ
Pod YAML のフィールドは多いものの、よく使うものは実はいくつかの領域に集中しています。metadata の labels、containers のイメージと起動コマンド、resources、3 種類のプローブ、volumes のマウントです。注釈表はフィールドの位置を素早く特定するのに便利ですが、フィールド名とデフォルト値は必ず kubectl explain の出力を基準にしてください——現在のクラスターの Schema を読むため、古くなることも、書き写しのミスもありません。
COMMENTS