📋
Kubernetesマニフェスト読解ガイド
apiVersion/kind/metadata/specの構造からDeployment・Service・ラベル・セレクターの仕組みまで。マニフェストを読み書きするための基礎知識。
マニフェストの骨格:4つのトップレベルフィールド
すべてのK8sリソースは同じ骨格を持つ。
apiVersion: apps/v1 # ① どのAPIグループ・バージョンか
kind: Deployment # ② リソースの種類
metadata: # ③ リソースの識別情報
name: my-app
namespace: production
labels:
app: my-app
spec: # ④ リソース固有の仕様(kindによって全く異なる)
replicas: 3
...
apiVersion ─── どの「棚」に入っているリソースか
kind ─── 何のリソースか(設計図の名前)
metadata ─── 名札・住所(name, namespace, labels, annotations)
spec ─── 中身の仕様。ここだけ kind ごとに異なる
apiVersion の読み方
apps/v1
↑ ↑
グループ バージョン
v1(グループなし)= core group(最も基本的なリソース)
リソースとapiVersionの対応
| apiVersion | 含まれる主なリソース |
|---|---|
v1 | Pod, Service, ConfigMap, Secret, PersistentVolumeClaim, Namespace |
apps/v1 | Deployment, ReplicaSet, StatefulSet, DaemonSet |
batch/v1 | Job, CronJob |
networking.k8s.io/v1 | Ingress, NetworkPolicy |
rbac.authorization.k8s.io/v1 | Role, RoleBinding, ClusterRole |
autoscaling/v2 | HorizontalPodAutoscaler |
storage.k8s.io/v1 | StorageClass |
# 使えるAPIグループとバージョン一覧
kubectl api-versions
# リソース一覧(略称・namespaced かどうかも確認)
kubectl api-resources
よく使うリソース早見表
┌──────────────────┬─────────────────────────────────────────────────┐
│ リソース │ 役割・一言説明 │
├──────────────────┼─────────────────────────────────────────────────┤
│ Pod │ コンテナの最小実行単位。直接作ることは少ない │
│ Deployment │ Podのローリングアップデート・レプリカ管理 │
│ StatefulSet │ 順序・安定したIDが必要なPod(DB, Kafkaなど) │
│ DaemonSet │ 全Node(or 特定Node)に1つずつPodを置く │
│ Job │ 1回限りのバッチ処理 │
│ CronJob │ 定期実行のバッチ処理(cron式で指定) │
│ Service │ Podへの安定したエンドポイント(仮想IP) │
│ Ingress │ L7ルーティング(ホスト名・パスで振り分け) │
│ ConfigMap │ アプリの設定(平文)を外部化 │
│ Secret │ 機密情報(Base64エンコード) │
│ PVC │ ストレージの要求。PVと紐付く │
│ Namespace │ クラスター内の論理的な分離空間 │
│ ServiceAccount │ PodのIAM的なID。外部サービスへの認証に使う │
│ HPA │ CPU/メモリ等の指標でPod数を自動スケール │
└──────────────────┴─────────────────────────────────────────────────┘
Deployment を完全読解
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app # Deployment自体の名前
namespace: production
labels: # Deployment自身のラベル(セレクターとは別)
app: my-app
version: "1.2.0"
spec:
replicas: 3 # Pod数の目標値
selector: # 「このDeploymentが管理するPod」の条件
matchLabels:
app: my-app # ← spec.template.metadata.labels と一致させる
strategy:
type: RollingUpdate # 更新戦略(RollingUpdate or Recreate)
rollingUpdate:
maxSurge: 1 # 目標数を超えて同時に作れるPod数
maxUnavailable: 0 # 同時に停止できるPod数(0 = ダウンタイムなし)
template: # ここからがPodの設計図
metadata:
labels:
app: my-app # ← selector.matchLabels と必ず一致させる
spec:
containers:
- name: app
image: my-app:1.2.0
ports:
- containerPort: 8080
resources:
requests: # スケジューリング時の保証値(Nodeの割り当てに使用)
cpu: "250m" # 0.25 vCPU
memory: "256Mi"
limits: # 超えると OOM Kill / CPU スロットリング
cpu: "500m"
memory: "512Mi"
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: my-config # ConfigMapの名前
key: db_host
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: my-secret # Secretの名前
key: db_password
livenessProbe: # 失敗するとコンテナを再起動
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 10 # 起動後この秒数待ってからProbe開始
periodSeconds: 10
readinessProbe: # 失敗するとServiceのEndpointから除外(トラフィックを切る)
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
strategy の違い
RollingUpdate(デフォルト):
旧Pod を1つずつ停止 → 新Pod を起動 → 繰り返し
ダウンタイムゼロだがv1とv2が混在する瞬間がある
Recreate:
旧Pod を全部停止 → 新Pod を全部起動
ダウンタイムが発生するが、バージョン混在しない
DBマイグレーション等で使うケース
Service を完全読解
apiVersion: v1
kind: Service
metadata:
name: my-app-svc
namespace: production
spec:
type: ClusterIP # ClusterIP / NodePort / LoadBalancer
selector: # このServiceが転送先とするPodの条件
app: my-app # ← DeploymentのPod labelsと一致させる
ports:
- name: http
port: 80 # Serviceが受け付けるポート
targetPort: 8080 # 転送先PodのポートPort(containerPort)
protocol: TCP
port と targetPort の混乱を解消
クライアント
│ :80 でServiceに接続
▼
Service (port: 80)
│ targetPort: 8080 に転送
▼
Pod (containerPort: 8080)
port = Serviceが外(クラスター内)に公開するポート
targetPort = 転送先のPodが実際に待ち受けているポート
ラベルとセレクター:K8sの結合の仕組み
K8sリソース間の「紐付け」はラベルとセレクターだけで行われる。明示的な参照(ID等)は使わない。
【Deployment → Pod の管理関係】
Deployment の spec.selector.matchLabels: {app: my-app}
↓ 一致する
Pod の metadata.labels: {app: my-app}
→ このPodはこのDeploymentが管理する
【Service → Pod の転送関係】
Service の spec.selector: {app: my-app}
↓ 一致する
Pod の metadata.labels: {app: my-app}
→ このPodにトラフィックを転送する
よくある失敗パターン
# NG: selectorとtemplateのラベルが不一致
spec:
selector:
matchLabels:
app: my-app # ← "my-app"
template:
metadata:
labels:
app: myapp # ← "myapp"(ハイフンなし)
# エラー: `selector` does not match template `labels`
# NG: Serviceのselectorがtypo
# Service: selector: {app: my-apps} ← sがある
# Pod: labels: {app: my-app} ← sがない
# → Endpointsが空になり、トラフィックが届かない
# セレクター不一致のデバッグ
kubectl get endpoints my-app-svc
# ADDRESS が空なら Podが1つもマッチしていない
kubectl get pods -l app=my-app
# Serviceのselectorと同じラベルで手動確認
metadata の重要フィールド
labels と annotations の違い
metadata:
labels: # セレクターに使える(検索・フィルタの基準)
app: my-app # 短い・識別子として使う
env: production
annotations: # セレクターに使えない(メタデータの保存)
kubernetes.io/created-by: "terraform"
deployment.kubernetes.io/revision: "3"
# 長い文字列・URL・JSONなど自由に入れられる
# Ingressコントローラーの設定などもここに書く
namespace の影響範囲
同じ namespace 内:
Service は名前だけで参照できる
my-app-svc → my-app-svc.production.svc.cluster.local の短縮
別の namespace から:
FQDN で参照する必要がある
my-app-svc.production.svc.cluster.local
ClusterScope なリソース:
Node / PersistentVolume / ClusterRole / Namespace 自体
→ namespace に属さない(kubectl api-resources でNAMESPACED列を確認)
kubectl の読解支援コマンド
# フィールドの説明を確認(一番重要)
kubectl explain deployment
kubectl explain deployment.spec.strategy
kubectl explain pod.spec.containers.resources
# 既存リソースをYAMLで出力(構造の確認に)
kubectl get deployment my-app -o yaml
# 差分確認(適用前に変更内容を確認)
kubectl diff -f manifest.yaml
# ドライラン(実際には適用しない)
kubectl apply -f manifest.yaml --dry-run=client
kubectl apply -f manifest.yaml --dry-run=server # サーバー側でバリデーション
# リソースなしでPodのYAMLテンプレートを生成
kubectl run my-pod --image=nginx --dry-run=client -o yaml
# JSONPathで特定フィールドだけ取り出す
kubectl get pods -o jsonpath='{.items[*].metadata.name}'
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.phase}{"\n"}{end}'
# カスタムカラムで表示
kubectl get pods -o custom-columns=NAME:.metadata.name,STATUS:.status.phase,NODE:.spec.nodeName
よくある誤読パターン
誤読①:spec.template は「Podの設計図」であり「Pod自体」ではない
→ spec.replicas: 3 なら template から3つのPodが作られる
誤読②:containerPort は「開放宣言」であり「穴あけ」ではない
→ containerPort を書かなくても通信は通る(ドキュメント目的)
→ 実際のポート制御は NetworkPolicy で行う
誤読③:resources.requests はネットワーク帯域ではなくCPU/メモリ
→ "250m" は 0.25 vCPU(milli CPU)
→ "256Mi" は 256 メビバイト(1Mi = 1024 * 1024 bytes)
誤読④:Secret の value は暗号化ではなくBase64エンコード
→ echo -n "password" | base64 で作れる(誰でも復元可能)
→ 本当の秘密管理は Vault / AWS Secrets Manager / SOPS + GitOps
誤読⑤:Deployment を削除するとPodも消える
→ Deployment → ReplicaSet → Pod の親子関係
→ --cascade=orphan オプションで Pod を残すことも可能
複数マニフェストのまとめ方
# 単一ファイルに --- で区切って複数リソースを記述
cat <<EOF > app.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
name: my-config
data:
db_host: "postgres:5432"
---
apiVersion: apps/v1
kind: Deployment
...
---
apiVersion: v1
kind: Service
...
EOF
kubectl apply -f app.yaml # 全リソースを一括適用
kubectl apply -f ./manifests/ # ディレクトリ内の全yamlを適用
kubectl apply -f ./manifests/ --recursive # サブディレクトリも再帰的に - 1. 📡TCP/IPパケット通信の全過程
- 2. 🔌物理層・データリンク層詳解
- 3. 🌐ネットワーク層(IP)詳解
- 4. 🔄TCPの全機能詳解
- 5. ⚡UDP詳解とユースケース
- 6. 🌍アプリケーション層詳解(DNS・HTTP・TLS)
- 7. 🔧ソケットAPIとI/Oモデル詳解
- 8. ☁️コンテナ・クラウドネットワーキング詳解
- 9. ⚖️ロードバランサー・リバースプロキシ詳解
- 10. 🕸️Kubernetesネットワーク全体図
- 11. ⚔️K8s vs ECS:設計思想とアナロジーで理解する
- 12. 📋Kubernetesマニフェスト読解ガイド
- 13. 🏗️K8s・ECSのIaC管理(Terraform・Helm・GitOps)