シリーズ記事一覧
- 第1回:全体像と環境構築
- 第2回:Pod・ReplicaSet・Deployment
- 第3回:Service・Ingress
- 第4回:ConfigMap・Secret・PersistentVolume
- 第5回:模擬プロジェクト(Web+API+DB+Redis)
- 第6回:トラブルシュートと運用
- 第7回:総まとめと次のステップ
📑 目次
- この記事について
- この記事のゴール
- 全体の振り返り ― 第1回〜6回の知識マップ
- Docker Compose → k8s 対応マップ(総まとめ)
- YAMLの「つなぎ方」― リソース間の紐づけ総整理
- kubectlコマンド総まとめ
- 理解度セルフチェック ― 10の質問で振り返る
- Docker Compose → k8s マイグレーション戦略
- 次のステップ
- まとめ
1. この記事について
1-1. シリーズ概要
Docker Compose経験者が「素のKubernetes」を
1週間で実践レベルまで習得することを目指す学習記録です。
1-2. シリーズ構成
| 回 | テーマ | 内容 |
|---|---|---|
| 第1回 | 全体像と環境構築 | Docker Composeとの対比、minikube導入 |
| 第2回 | Pod と Deployment | コンテナ起動〜スケーリング〜ローリングアップデート |
| 第3回 | Service と Ingress | ネットワークと外部公開 |
| 第4回 | ConfigMap / Secret / PV | 設定管理と永続化 |
| 第5回 | 模擬プロジェクト | 全概念を組み合わせて実践 |
| 第6回 | トラブルシュートと運用 | エラー対応、ログ確認、運用テクニック |
| 第7回(本記事) | 総まとめ | 振り返り・次のステップ |
1-3. 対象読者
- 第1回〜第6回を読み終えた方
- 学んだ知識を整理して「語れる」状態にしたい方
2. この記事のゴール
| # | ゴール | 確認方法 |
|---|---|---|
| ① | 第1回〜6回の知識を構造的に整理できる | リソース全体像と相互関係を語れる |
| ② | Docker Compose → k8sの対応を網羅的に説明できる | 全対応マップを見ずに主要部分を語れる |
| ③ | k8sの主要概念を自分の言葉で説明できる | Q&A 10問に自分の言葉で答えられる |
| ④ | マイグレーション戦略を説明できる | 段階的移行の手順を語れる |
| ⑤ | 次の学習ステップが明確になる | Helm/ArgoCD等の位置づけを語れる |
3. 全体の振り返り ― 第1回〜6回の知識マップ
第1回〜6回で学んだリソースの全体像を図で整理します。
「何を・どの回で学んだか」を俯瞰することで、知識のつながりが見えてきます。
3-1. k8sリソース全体像
3-1-1. 図1:リクエストの流れ(通信経路)
外部からのリクエストがどのリソースを経由して Pod に届くかを示します。
| Service の type | 用途 | 学んだ回 |
|---|---|---|
| ClusterIP | クラスタ内部のみ(デフォルト) | 第3回 |
| NodePort | Nodeのポートで外部公開 | 第3回 |
| LoadBalancer | クラウドLB連携で外部公開 | 第3回 |
| Headless | StatefulSet用(個別Pod指定) | 第4回 |
3-1-2. 図2:Pod を支える設定・ストレージ
Pod に「何が注入されるか」を示します。
3-2. 回別の学習内容サマリー
| 回 | テーマ | 学んだリソース | キーコンセプト |
|---|---|---|---|
| 第1回 | 全体像 | — | k8sの存在意義、宣言的管理、Docker Compose対比 |
| 第2回 | Pod / Deployment | Pod, Deployment, ReplicaSet | labels/selector、ローリングアップデート |
| 第3回 | Service / Ingress | ClusterIP, NodePort, LB, Ingress | CoreDNS、kube-proxy、L4/L7、TLS終端 |
| 第4回 | ConfigMap / Secret / PV | ConfigMap, Secret, PV, PVC, StorageClass, StatefulSet | 責務分離、etcd暗号化、動的プロビジョニング、Headless Service |
| 第5回 | 模擬プロジェクト | Namespace + 全リソース統合 | 構築順序、Probe、resources、ファイルマウント |
| 第6回 | トラブルシュート | — | デバッグ5コマンド、エラーパターン7つ、ロールバック、dry-run |
3-3. k8sが解決する「Docker Composeの限界」
| Docker Composeの限界 | k8sの解決策 | 学んだ回 |
|---|---|---|
| 1台のホストでしか動かない | 複数Node + スケジューラ | 第1回 |
| スケーリングが手動 |
replicas + kubectl scale
|
第2回 |
| デプロイ = ダウンタイム | ローリングアップデート | 第2回 |
| サービスディスカバリが弱い | CoreDNS + Service | 第3回 |
| 外部公開が別途設定 | Ingress | 第3回 |
| 設定とコードが混在 | ConfigMap / Secret | 第4回 |
| データの永続化がNode固定 | PV / PVC / StorageClass | 第4回 |
| DBの順序制御が弱い | StatefulSet | 第4回 |
| ヘルスチェックがない | Probe | 第5回 |
| リソース制限がない | requests / limits | 第5回 |
| ロールバックが手動 | rollout undo |
第6回 |
4. Docker Compose → k8s 対応マップ(総まとめ)
Docker Composeの知識がk8sのどこに対応するかを一覧で確認します。「Composeではこう書いていたけど、k8sではどうなる?」という疑問をここで解消しましょう。
4-1. リソース対応
| Docker Compose | k8s | 学んだ回 |
|---|---|---|
services: |
Deployment / StatefulSet | 第2回 / 第4回 |
image: |
spec.containers[].image |
第2回 |
ports: |
Service | 第3回 |
environment: (一般) |
ConfigMap | 第4回 |
environment: (機密) |
Secret | 第4回 |
volumes: ./file:/path |
ConfigMap + volumeMount | 第4回 / 第5回 |
volumes: vol-name:/path |
PVC + volumeMount | 第4回 |
volumes: vol-name: (定義) |
PVC + StorageClass | 第4回 |
depends_on: |
構築順序 + readinessProbe | 第5回 |
docker-compose up |
kubectl apply -f |
第2回 |
docker-compose logs |
kubectl logs |
第6回 |
docker exec -it |
kubectl exec -it |
第6回 |
docker-compose down |
kubectl delete namespace |
第5回 |
4-2. k8sにしかないもの
| k8sリソース | Docker Composeでの代替 | 意味 |
|---|---|---|
| Ingress | なし(nginx等を別途構築) | L7ルーティング + TLS終端 |
| Namespace | なし | 環境分離、リソースクォータ |
| Probe |
healthcheck: (限定的) |
readiness/liveness/startup |
| resources |
deploy.resources: (Swarmのみ) |
CPU/メモリの保証と上限 |
| ロールバック | なし(手動で戻す) |
rollout undo で1コマンド |
| Headless Service | なし | Pod個別のDNS名 |
| StorageClass | なし | ストレージの動的プロビジョニング |
🍽️
Docker Compose = 「1人で切り盛りする小さなお店」。
k8s = 「大規模チェーン店の運営システム」。
やりたいことは同じだが、スケール・信頼性・運用性が桁違い。
5. YAMLの「つなぎ方」― リソース間の紐づけ総整理
k8sではリソース同士がYAMLで紐づいてはじめて動きます。
その紐づけ方は 2パターンしかありません。
| パターン | 仕組み | 対象 |
|---|---|---|
| ① ラベルセレクタ |
selector と labels が一致 |
Service→Pod, Deployment→Pod |
| ② 名前参照 | リソース名が文字列一致 | その他すべて |
5-1. パターン①:ラベルセレクタ方式
「labels(名札)と selector(条件)が一致すると繋がる」 方式です。
# ────────────────────────────────────
# 【①】Deployment:Pod に名札を貼り、自分も同じ名札で管理する
# ────────────────────────────────────
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
selector:
matchLabels:
app: web # ◆ この条件で Pod を管理する
template:
metadata:
labels:
app: web # ◆ Pod に貼る名札(ここが中心)
spec:
containers:
- name: nginx
image: nginx:1.25
---
# ────────────────────────────────────
# 【②】Service:同じ名札の Pod を探してトラフィックを送る
# ────────────────────────────────────
apiVersion: v1
kind: Service
metadata:
name: web-svc
spec:
selector:
app: web # ◆ 同じ名札 → この Pod にトラフィックを送る
ports:
- port: 80
3者の関係を整理すると:
Deployment Service
selector.matchLabels ──┐ ┌── spec.selector
▼ ▼
Pod の labels
app: web ← ◆ ここが全員の合流点
🍽️ Pod の名札(labels)は「ホール担当」。
Deployment は「ホール担当のシフトを管理する」(selector)。
Service は「ホール担当にお客さんを案内する」(selector)。
名札の文字が1文字でも違えば、管理もされず、お客さんも来ない。
5-2. パターン②:名前参照方式
「リソース名を文字列で直接指定する」 方式です。
# ────────────────────────────────────
# 【参照される側】ConfigMap の定義
# ────────────────────────────────────
apiVersion: v1
kind: ConfigMap
metadata:
name: db-config # ◆ この名前が
data:
POSTGRES_DB: "webapp"
---
# ────────────────────────────────────
# 【参照される側】Secret の定義
# ────────────────────────────────────
apiVersion: v1
kind: Secret
metadata:
name: db-secret # ◆ この名前が
stringData:
POSTGRES_PASSWORD: "mypassword"
---
# ────────────────────────────────────
# 【参照する側】Pod(Deployment の template)
# ────────────────────────────────────
spec:
containers:
- name: postgres
envFrom:
- configMapRef:
name: db-config # ◆ ここと一致 → 環境変数として注入
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret # ◆ ここと一致 → 環境変数として注入
key: POSTGRES_PASSWORD
🍽️
レストランで例えると、名前参照は「メニュー表の名前で注文する」方式。
「db-config ください」と書いたのに、
棚にあるのが「db-conf」だったら「そんなメニューありません」
(CreateContainerConfigError)になる。
| 誰が | 誰を | YAMLフィールド |
|---|---|---|
| Pod | ConfigMap | configMapRef.name |
| Pod | Secret | secretKeyRef.name |
| Pod | PVC | persistentVolumeClaim.claimName |
| PVC | StorageClass | storageClassName |
| Ingress | Service | backend.service.name |
| StatefulSet | Headless Service | spec.serviceName |
5-3. 参照関係の全体図
実線 = ①ラベルセレクタ方式 / 点線 = ②名前参照方式
5-4. タイプミス で壊れるとどうなるか
紐づけのどちらのパターンでタイプミスしたかで、症状と調査方法が変わります。
| パターン | よくあるミス | 症状 | 確認方法 |
|---|---|---|---|
| ①ラベル | selector と labels の不一致 | Service に疎通できない |
kubectl describe service で Endpoints が空 |
| ①ラベル | Ingress の Service名 タイプミス | 502 Bad Gateway |
kubectl describe ingress で確認 |
| ②名前 | ConfigMap名のタイプミス | CreateContainerConfigError |
kubectl get configmap -n NS で存在確認 |
| ②名前 | Secret キー名のタイプミス | CreateContainerConfigError |
kubectl describe secret でキー一覧確認 |
| ②名前 | PVC名のタイプミス | Pod が Pending |
kubectl get pvc -n NS で状態確認 |
各エラーの詳細な調査手順は第6回(セクション5) を参照してください。
6. kubectlコマンド総まとめ
「何をしたいか?」からコマンドを引く辞書です。
| やりたいこと | コマンド | 用途 |
|---|---|---|
| 状態を知りたい | kubectl get RESOURCE -n NS |
リソース一覧 |
kubectl describe RESOURCE NAME -n NS |
詳細情報(Events含む) | |
kubectl logs POD -n NS |
ログ確認 | |
| 問題を調べたい | kubectl logs POD --previous |
前回クラッシュのログ |
kubectl exec -it POD -- bash |
Pod内に入る | |
kubectl get events -n NS |
イベント一覧 | |
kubectl run debug --image=busybox--rm -it --restart=Never -- sh
|
一時デバッグPod | |
| 変更を適用したい | kubectl apply -f FILE |
リソース作成・更新 |
kubectl delete -f FILE |
リソース削除 | |
kubectl scale deployment/NAME --replicas=N |
スケーリング | |
| 元に戻したい | kubectl rollout undo deployment/NAME |
ロールバック |
kubectl rollout restart deployment/NAME |
安全な再起動 | |
kubectl rollout history deployment/NAME |
デプロイ履歴 | |
| 適用前に確認したい | kubectl apply --dry-run=server -f FILE |
事前検証 |
kubectl diff -f FILE |
差分確認 | |
| 監視したい | kubectl top pods / nodes |
CPU/メモリ使用量 |
7. 理解度セルフチェック ― 10の質問で振り返る
以下の質問に自分の言葉で答えられるかを試してみます。
7-1. Q1. KubernetesとDocker Composeの違いは?
回答例:
Docker Composeは単一ホスト上の複数コンテナを管理するツールです。
一方k8sは、複数ノードにまたがるコンテナオーケストレーションプラットフォームです。
k8sには自動スケーリング、ローリングアップデート、セルフヒーリング、サービスディスカバリなど、本番運用に必要な機能が組み込まれています。
Docker Composeは開発環境に適し、k8sは本番環境での大規模運用に適しています。
7-2. Q2. Podとは何ですか?
回答例:
Podはk8sの最小デプロイ単位で、1つ以上のコンテナをまとめたグループです。
同じPod内のコンテナはネットワーク(localhost)とストレージを共有します。
実務では1 Pod = 1コンテナが基本で、サイドカーパターン等の場合のみ複数コンテナを入れます。
Podは使い捨て(エフェメラル)で、直接作成せずDeployment経由で管理します。
7-3. Q3. DeploymentとStatefulSetの違いは?
回答例:
Deploymentはステートレスなアプリケーション向けで、Pod名はランダム、起動順序は保証されず、全PodがPVCを共有します。
StatefulSetはステートフルなアプリケーション(DB等)向けで、Pod名が連番、起動順序が保証され、各Podに専用PVCが割り当てられます。
StatefulSetはHeadless Serviceと組み合わせて各Podに固定DNS名を提供します。
7-4. Q4. ServiceのClusterIP / NodePort / LoadBalancerの違いは?
回答例:
ClusterIPはクラスタ内部専用の仮想IPで、Pod間通信に使います。
NodePortは各ノードのポートを開放して外部からアクセス可能にしますが、ポート番号が固定されるため本番には不向きです。
LoadBalancerはクラウドプロバイダーのロードバランサーを自動作成し、外部からのトラフィックを分散します。
実務ではIngressと組み合わせてL7ルーティングを行うのが一般的です。
7-5. Q5. ConfigMapとSecretの違いは?
回答例:
構造はほぼ同じですが、用途が違います。
ConfigMapは一般的な設定(環境名、ログレベル等)、Secretは機密情報(パスワード、APIキー等)に使います。
SecretはBase64エンコードされますが、これは暗号化ではありません。
Secretにはtmpfsマウント、RBAC制御、etcd暗号化などの追加保護レイヤーがあります。
本番ではExternal Secrets Operator等で外部シークレット管理サービスと連携するのがベストプラクティスです。
7-6. Q6. PersistentVolumeとPersistentVolumeClaimの関係は?
回答例:
PVはストレージの実体(「10GBのEBSボリュームがある」)、PVCは開発者からのストレージ要求(「10GBください」)です。
PVCを作成するとk8sが条件に合うPVを自動バインドします。
クラウド環境ではStorageClassによる動的プロビジョニングが主流で、PVCを作るだけで自動的にEBS等が作成されます。
ReclaimPolicyの設定(Retain/Delete)がデータ保護の鍵です。
7-7. Q7. Podが起動しない場合のトラブルシュート手順は?
回答例:
5つのコマンドを順番に使います。
まずkubectl get podsでSTATUSを確認。
CrashLoopBackOffならkubectl logs --previousで前回クラッシュのログを確認。
ImagePullBackOffやPendingならkubectl describe podのEventsで原因を特定。
Running だが READY 0/1 なら readinessProbe の設定を確認し、kubectl execでPod内から疎通テスト。
最後にkubectl get eventsでクラスタ全体の問題を確認します。
7-8. Q8. ローリングアップデートの仕組みは?
回答例:
Deploymentのイメージを更新すると、新しいPodを1台ずつ起動し、readinessProbeで正常確認後に古いPodを1台ずつ終了します。
これにより無停止でデプロイできます。
失敗した場合はkubectl rollout undoで1コマンドで前のバージョンに戻せます。
maxSurgeとmaxUnavailableで同時に何台まで入れ替えるかを制御できます。
7-9. Q9. readinessProbeとlivenessProbeの違いは?
回答例:
readinessProbeは「リクエストを受ける準備ができたか」をチェックし、失敗するとServiceの振り分けから外します。
Podは生き続けます。
livenessProbeは「生きているか」をチェックし、失敗するとPodを再起動します。
重要な設計ポイントとして、livenessProbeにDB接続チェックを入れてはいけません。
DB障害時にAPI Pod全台が再起動ループに陥るためです。
7-10. Q10. Ingressとは何ですか?なぜ必要?
回答例:
IngressはL7(HTTP/HTTPS)のルーティングルールを定義するリソースです。
ホスト名やパスに基づいて複数のServiceにトラフィックを振り分けます。
Serviceだけでは外部公開にNodePort(ポート固定)かLoadBalancer(各Serviceごとにロードバランサー)が必要ですが、Ingressなら1つのエントリーポイントで複数Serviceを管理でき、TLS終端も一元化できます。
実体はIngress Controller(nginx等)が処理します。
8. Docker Compose → k8s マイグレーション戦略
8-1. 段階的移行アプローチ
一気に移行するのではなく、段階的に進めるのが安全です。
Phase 2(設定分離)と Phase 3(ストレージ設計)は並行して進められます。両方完了後に Phase 4 へ。
8-2. Phase別の作業内容
8-2-1. Phase 1:YAML変換
| docker-compose.yml | k8s YAML |
|---|---|
services: api: |
Deployment + Service |
services: db: |
StatefulSet + Headless Service |
image: |
spec.containers[].image |
ports: |
Service の ports
|
🔰 この段階では「動くこと」が目標。最適化は後。
8-2-2. Phase 2:設定分離
| 作業 | 内容 |
|---|---|
| 環境変数を分類 | 一般設定 → ConfigMap、機密情報 → Secret |
| ハードコードを排除 | 接続先ホスト名をService名に変更 |
| 環境別ConfigMap | dev/staging/prod でConfigMapだけ差し替え |
8-2-3. Phase 3:ストレージ設計
| 判断 | 内容 |
|---|---|
| 永続化が必要なデータの特定 | DBデータ、アップロードファイル等 |
| StorageClass選定 | gp3/io2 等、ワークロードに応じて |
| ReclaimPolicy | 本番は Retain、開発は Delete |
| バックアップ戦略 | スナップショット、pg_dump 等 |
8-2-4. Phase 4:運用機能追加
| 機能 | 内容 |
|---|---|
| Probe | readiness/liveness の設計と設定 |
| resources | requests/limits のチューニング |
| Ingress | 外部公開 + TLS証明書 |
| Namespace | 環境分離 |
8-2-5. Phase 5:CI/CD統合
| ツール | 役割 |
|---|---|
| Helm | k8s YAMLのテンプレート化・パッケージ管理 |
| ArgoCD | GitOps(gitの変更を自動でクラスタに反映) |
| GitHub Actions | CI(テスト・ビルド・イメージ作成) |
8-3. よくある落とし穴
| 落とし穴 | 説明 | 対策 |
|---|---|---|
| 全サービスを一度に移行 | リスクが大きすぎる | 1サービスずつ段階的に |
| 開発環境なしで本番移行 | テストができない | minikubeで事前検証 |
| ConfigMap/Secret未分離 | パスワードがgitに入る | Phase 2を必ず実施 |
| PVのReclaimPolicy未確認 | Namespace削除でデータ消失 | 本番は必ずRetain |
| Probe未設定 | 障害Pod にリクエストが飛ぶ | Phase 4を必ず実施 |
9. 次のステップ
このシリーズで「素のk8s」を学びました。ここから先は、目的に応じてツールを選びます。
| 段階 | ツール | 何を解決するか | 比喩 | いつ必要か |
|---|---|---|---|---|
| すぐ学ぶ | Helm | YAML管理の複雑さ。 テンプレート変数で 環境差分を吸収 |
レシピのテンプレート。 分量だけ変えて同じ料理を作れる |
実務でほぼ必須 |
| ArgoCD | デプロイの自動化。 git push でクラスタに反映 |
自動発注システム。 メニュー更新で食材が届く |
CI/CD が必要になったら | |
| Prometheus + Grafana | 監視とアラート。 リソース使用量を ダッシュボードで可視化 |
厨房のモニタリングカメラ+温度計 | 本番運用開始時に | |
| 本番運用で | RBAC | 誰が何を操作できるかの制御 | スタッフの権限証。 アルバイトは金庫を開けられない |
チーム開発開始時に |
| NetworkPolicy | Pod間通信の制御。 不要な通信をブロック |
厨房の出入り口に セキュリティゲート |
セキュリティ要件が明確になったら | |
| HPA | 負荷に応じた 自動スケーリング |
混雑時に自動でスタッフを増員 | トラフィックが変動するサービスで | |
| エキスパート | Operator | カスタムリソースの 自動管理 |
専属マネージャー を雇って定型業務を自動化 |
独自リソース管理が必要な時 |
| Service Mesh | マイクロサービス間の 通信制御・可観測性 |
全通路に監視カメラ +自動ドアを設置 |
サービス数が増えた時 | |
| マルチクラスタ | 複数クラスタの 統合管理 |
複数店舗を 本部で一括管理 |
大規模運用・DR要件で |
10. まとめ
10-1. 本シリーズで学んだこと
| 回 | 学んだこと | 一言 | 該当セクション |
|---|---|---|---|
| 第1回 | k8sの全体像 | 「何のために存在するか」を理解 | 3-2, 3-3 |
| 第2回 | Pod / Deployment | 「コンテナの管理方法」を理解 | 3-2, 7-2〜7-3 |
| 第3回 | Service / Ingress | 「通信と外部公開」を理解 | 3-2, 7-4 |
| 第4回 | ConfigMap / Secret / PV | 「設定管理と永続化」を理解 | 3-2, 7-5〜7-6 |
| 第5回 | 模擬プロジェクト | 「全部組み合わせる」を体験 | 3-2, 5 |
| 第6回 | トラブルシュート | 「壊れた時の直し方」を理解 | 3-2, 7-7 |
| 第7回 | 総まとめ | 「語れる」状態に整理 | 7, 8, 9 |
10-2. シリーズを終えて
このシリーズでは、
Docker Compose経験をベースに「素のKubernetes」を全7回で学びました。
k8sのリソースは多く見えますが、
本質はDocker Composeの各要素を責務ごとに分離して、より堅牢に管理する仕組みだと感じました。
(完結)