シリーズ記事一覧
- 第1回:全体像と環境構築
- 第2回:Pod・ReplicaSet・Deployment
- 第3回:Service・Ingress
- 第4回:ConfigMap・Secret・Volume
- 第5回:Namespace・RBAC
- 第6回:トラブルシュートと運用
- 第7回:設計総合演習
📑 目次
- この記事について
- この記事のゴール
- 前提条件
- Docker Composeではこうだった(Before)
- k8sではこうなる(After)
- ハンズオン:壊して学ぶ3層構造
- つまずきポイント(体験談)
- まとめ
- 次回予告
1. この記事について
前回、kindでKubernetesクラスタを構築しました。
チェーンレストランの「本部」を建てた状態です。
でもまだスタッフ(コンテナ)は配置していません。
今回はコンテナを動かしてみます。
ただし、k8sでは docker run のようにコンテナを直接動かすのではなく、3層の仕組みを使います。
「コンテナ動かすだけなのに、なぜ3つも概念がいるの?」
私もそう思いました。
実際に壊して体験してみたら、その理由がよくわかりました。
2. この記事のゴール
この記事で書いていること:
- Pod / ReplicaSet / Deployment の違いを整理
- マニフェストYAMLの読み方
- Podを削除して自動復旧を体験してみた話
- スケールアウト・ローリングアップデートを試してみた話
3. 前提条件
| 項目 | 要件 |
|---|---|
| 前回の完了 | 第1回でkindクラスタを構築済み |
| クラスタ状態 | 起動中であること |
# WSL2 Ubuntu で実行
# クラスタが動いているか確認
kubectl get nodes
期待される出力:
NAME STATUS ROLES AGE VERSION
my-first-cluster-control-plane Ready control-plane ... v1.xx.x
❌ クラスタがない場合は、再作成してください:
kind create cluster --name my-first-cluster
4. Docker Composeではこうだった(Before)
4-1. Docker Composeのコンテナ管理
Docker Composeでは、services に書いたものがそのままコンテナになります。
# docker-compose.yml
services:
web:
image: nginx:1.25
ports:
- "8080:80" # ホスト8080 → コンテナ80
シンプルで分かりやすい。
docker-compose up で起動、docker-compose down で停止。
4-2. でもこの壁がある
# コンテナが落ちたら…
docker-compose ps
# → web が Exit 1 になっている
# 手動で再起動するしかない
docker-compose restart web
| 困ること | Docker Composeの現実 |
|---|---|
| コンテナが落ちた | 手動で再起動 |
| 3台に増やしたい |
docker-compose up --scale web=3… でもロードバランスは? |
| 新バージョンに更新 | 止めて → 上げ直し(ダウンタイム発生) |
5. k8sではこうなる(After)
5-1. なぜ「3層」必要なのか?
🍽️ 比喩:チェーンレストランの人材管理
コンテナ1個だけ動かすなら、概念は1つで十分です。
でも本番運用では「常に3台動かしたい」「新バージョンに切り替えたい」が出てくる。これを人材管理に例えると…
層 k8s概念 比喩 責任 層1 Pod 調理スタッフ1人 実際に働く。倒れたらそれまで 層2 ReplicaSet シフト表 「常に3人体制」を保証。欠員が出たら補充 層3 Deployment 店長 シフト表の更新・メニュー切替を管理 スタッフ1人(Pod)だけだと、倒れたら終わり。
シフト表(ReplicaSet)があれば、自動で補充される。
店長(Deployment)がいれば、「来月から新メニュー」も段階的に切り替えてくれる。
5-2. 3層構造の関係図
この3層がどのような関係で動いているかを図で見てみましょう。
5-3. 各層の詳細
各層を詳しく見ていきます。
5-3-1. Pod(調理スタッフ1人)
| 項目 | 内容 |
|---|---|
| 定義 | k8sの最小デプロイ単位 |
| 中身 | 1つ以上のコンテナ(通常は1つ) |
| 特徴 | IPアドレスを持つ、壊れたら消える(使い捨て) |
| Docker比較 |
docker run で起動するコンテナ1個に近い |
🔰 Memo: 最初は「Pod ≒ コンテナ」と思っておけば大丈夫でした。
厳密には「コンテナを包む薄い箱」ですが、同じものとして扱って問題なかったです。
5-3-2. ReplicaSet(シフト表)
| 項目 | 内容 |
|---|---|
| 定義 | 「Podを常にN個維持する」ための仕組み |
| 特徴 | Podが減ったら自動補充、増えすぎたら削除 |
| Docker比較 |
docker-compose up --scale に近いが、自動維持する |
5-3-3. Deployment(店長)
| 項目 | 内容 |
|---|---|
| 定義 | ReplicaSetを管理し、バージョン更新を制御 |
| 特徴 | ローリングアップデート、ロールバック |
| Docker比較 | Docker Composeにはこの概念がない |
🔰 Note: 調べてみると、実務ではPodを直接作ることはほぼないそうです。
Deploymentを作れば、ReplicaSetとPodは自動で作られる。
つまり普段意識するのはDeploymentだけ、ということでした。
6. ハンズオン:壊して学ぶ3層構造
6-1. Step1:Podを直接作って、壊してみる(限界体験)
まず「Podだけだと何が困るか」を体験します。
# WSL2 Ubuntu で実行
# Pod を直接作成(nginx コンテナ)
kubectl run solo-pod --image=nginx:1.25
# Podが起動したか確認
kubectl get pods
期待される出力:
NAME READY STATUS RESTARTS AGE
solo-pod 1/1 Running 0 10s
では、このPodを意図的に壊します。
# Podを削除
kubectl delete pod solo-pod
# もう一度確認
kubectl get pods
期待される出力:
No resources found in default namespace.
🔰 ここが重要: Podは消えたまま、誰も復活させてくれません。
🍽️ 調理スタッフが倒れたのに、シフト表がないから誰も代わりを呼ばない状態です。
6-2. Step2:Deploymentで作って、壊してみる(自動復旧体験)
次に、Deploymentを使って同じことをします。
6-2-1. マニフェストYAMLの作成
💡 マニフェスト(manifest) とは、「こういうリソースを作ってほしい」と k8s に伝えるための定義ファイルです。レストランの比喩でいえば 指示書 そのもの。YAML形式で書くので、本シリーズでは「マニフェストYAML」と呼びます。
# WSL2 Ubuntu で実行
# 作業ディレクトリを作成
mkdir -p ~/k8s-handson/pod-deployment
cd ~/k8s-handson/pod-deployment
以下のファイルを作成します:
~/k8s-handson/pod-deployment/
└── nginx-deployment.yaml # ここに作成
# nginx-deployment.yaml
# Deployment = 店長への指示書
# API バージョンと種類の宣言
apiVersion: apps/v1
kind: Deployment
# Deploymentの名前
metadata:
name: nginx-deployment
# Deploymentの仕様(店長への指示内容)
spec:
# レプリカ数 = 「常に3人体制で」
replicas: 3
# どのPodを管理するか(ラベルで紐づけ)
selector:
matchLabels:
app: nginx
# Podのテンプレート(スタッフの募集要項)
template:
# Podに付けるラベル
metadata:
labels:
app: nginx
# Podの中身(コンテナの定義)
spec:
containers:
- name: nginx
image: nginx:1.25 # 使用するイメージ
ports:
- containerPort: 80 # コンテナ内のポート
6-2-2. マニフェストの構造解説
🍽️ このYAMLは「店長への指示書」です。
読み方を整理してみます。
| YAMLの項目 | 比喩 | 意味 |
|---|---|---|
kind: Deployment |
「これは店長への指示書です」 | リソースの種類 |
replicas: 3 |
「常に3人体制にしてください」 | 維持するPod数 |
selector |
「app: nginx のタグが付いたスタッフを管理して」 | 管理対象の特定 |
template |
「こういうスタッフを雇ってください」 | Pod のひな形 |
image: nginx:1.25 |
「スキル:nginx 1.25」 | 使用コンテナイメージ |
6-2-3. Deploymentを適用
# WSL2 Ubuntu で実行
# ~/k8s-handson/pod-deployment/ で実行
# マニフェストを適用(店長に指示書を渡す)
kubectl apply -f nginx-deployment.yaml
# Podの状態を確認
kubectl get pods
期待される出力:
NAME READY STATUS RESTARTS AGE
nginx-deployment-xxxxxxxxx-xxxxx 1/1 Running 0 10s
nginx-deployment-xxxxxxxxx-yyyyy 1/1 Running 0 10s
nginx-deployment-xxxxxxxxx-zzzzz 1/1 Running 0 10s
💡 エラーが出た場合 → セクション7-1(YAMLのインデントずれ)を確認
3つのPodが起動しました。
では1つ壊してみましょう。
# Podの名前を1つコピーして削除
# (出力に表示された名前を使ってください)
kubectl delete pod nginx-deployment-xxxxxxxxx-xxxxx
# すぐに確認(watchモードで監視)
kubectl get pods --watch
期待される出力:
NAME READY STATUS RESTARTS AGE
nginx-deployment-xxxxxxxxx-yyyyy 1/1 Running 0 1m
nginx-deployment-xxxxxxxxx-zzzzz 1/1 Running 0 1m
nginx-deployment-xxxxxxxxx-aaaaa 0/1 ContainerCreating 0 2s
nginx-deployment-xxxxxxxxx-aaaaa 1/1 Running 0 5s
自動復旧(Self-healing)しました。
1つ削除しても、すぐに新しいPodが作られて3台体制に戻ります。
これは実際に見ると「おお」となります。
Ctrl + C でwatchモードを終了してください。
🍽️ スタッフが1人倒れても、シフト表(ReplicaSet)が「3人体制」を守るために自動で補充してくれた、ということです。
6-3. Step3:スケールアウト体験
「3人体制」を「5人体制」に変更してみます。
# WSL2 Ubuntu で実行
# レプリカ数を5に変更
kubectl scale deployment nginx-deployment --replicas=5
# 確認
kubectl get pods
期待される出力:
NAME READY STATUS RESTARTS AGE
nginx-deployment-xxxxxxxxx-yyyyy 1/1 Running 0 3m
nginx-deployment-xxxxxxxxx-zzzzz 1/1 Running 0 3m
nginx-deployment-xxxxxxxxx-aaaaa 1/1 Running 0 2m
nginx-deployment-xxxxxxxxx-bbbbb 1/1 Running 0 5s
nginx-deployment-xxxxxxxxx-ccccc 1/1 Running 0 5s
5台に増えました。
逆に減らすこともできます。
# 2台に減らす
kubectl scale deployment nginx-deployment --replicas=2
# 確認
kubectl get pods
🍽️ 「今日は空いてるから2人体制で」と店長が判断。
余剰スタッフは帰宅(Pod削除)。
6-4. Step4:ローリングアップデート体験
nginx のバージョンを 1.25 → 1.26 に更新します。
# WSL2 Ubuntu で実行
# まず3台に戻す
kubectl scale deployment nginx-deployment --replicas=3
# 現在のイメージを確認
kubectl describe deployment nginx-deployment | grep Image
期待される出力:
Image: nginx:1.25
# イメージを更新(ローリングアップデート開始)
kubectl set image deployment/nginx-deployment nginx=nginx:1.26
# 更新の進行状況を監視
kubectl rollout status deployment/nginx-deployment
期待される出力:
Waiting for deployment "nginx-deployment" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "nginx-deployment" rollout to finish: 2 out of 3 new replicas have been updated...
deployment "nginx-deployment" successfully rolled out
# 更新後のイメージを確認
kubectl describe deployment nginx-deployment | grep Image
期待される出力:
Image: nginx:1.26
ゼロダウンタイムで更新完了。
古いPodを1つずつ新しいPodに入れ替えていく「ローリングアップデート」が行われました。
ダウンタイムなしで切り替わるのは、触ってみると想像以上にスムーズでした。
🍽️ 営業中のレストランで、スタッフを1人ずつ「旧メニュー担当 → 新メニュー担当」に切り替えていくイメージです。
お客さんには中断なし。
6-4-1. ローリングアップデートの流れ
6-4-2. おまけ:ロールバック
もし新バージョンに問題があったら、一瞬で元に戻せます。
# 直前のバージョンに戻す
kubectl rollout undo deployment/nginx-deployment
# 確認
kubectl describe deployment nginx-deployment | grep Image
期待される出力:
Image: nginx:1.25
🍽️ 「新メニュー不評だった!元に戻して!」→ 店長が即座にシフト表を元に戻す。
6-5. 後片付け
# Deployment を削除(Pod も一緒に消える)
kubectl delete deployment nginx-deployment
# 確認
kubectl get pods
期待される出力:
No resources found in default namespace.
7. つまずきポイント(体験談)
7-1. YAMLのインデントずれ
症状:
error: error validating "nginx-deployment.yaml": error validating data: ...
原因と対策: YAMLはインデント(スペース)が構文の一部です。
タブ文字は使えません。スペース2つで統一してください。
| ❌ NG | ✅ OK |
|---|---|
| タブ文字でインデント | スペース2つでインデント |
| インデントがバラバラ | 階層ごとにスペース2つずつ増やす |
7-2. 自動復旧が速すぎて見逃す
症状: kubectl delete pod → kubectl get pods したら、もう新しいPodが Running になっている。
対策: --watch フラグを先に付けてから別ターミナルで削除すると、復旧の過程が見えます。
# ターミナル1:監視
kubectl get pods --watch
# ターミナル2:削除
kubectl delete pod <Pod名>
7-3. Pod名の手打ちミス
症状:
Error from server (NotFound): pods "nginx-deployment-xxxxx" not found
対策: Pod名はランダム文字列を含むので、kubectl get pods で名前を確認してコピペするのが一番確実です。
# まず名前を確認 → 表示された名前をコピペして削除
kubectl get pods
kubectl delete pod <コピペしたPod名>
🔰 Memo: 慣れてきたらラベル指定で一括操作もできます:kubectl delete pod -l app=nginx
8. まとめ
8-1. この記事でやったこと
| # | 内容 | 状態 |
|---|---|---|
| 1 | Pod単体の限界を体験した(壊れたら終わり) | ✅ |
| 2 | Deploymentで自動復旧(Self-healing)を体験した | ✅ |
| 3 |
kubectl scale でスケーリングを体験した |
✅ |
| 4 | ローリングアップデート&ロールバックを体験した | ✅ |
8-2. 3層構造の対比(まとめ表)
| 観点 | Pod単体 | Deployment |
|---|---|---|
| 作成方法 | kubectl run |
kubectl apply -f |
| 障害時 | 消えたまま | 自動復旧 |
| スケール | できない | kubectl scale |
| バージョン更新 | 作り直し | ローリングアップデート |
| ロールバック | できない | kubectl rollout undo |
| 実務での使用 | ほぼ使わない | こちらが基本 |
8-3. Docker Compose → k8s 対応表
| Docker Compose | Kubernetes | 備考 |
|---|---|---|
services.web |
Deployment | 管理レベルが違う |
docker-compose up |
kubectl apply -f |
宣言的に適用 |
docker-compose up --scale web=3 |
kubectl scale --replicas=3 |
k8sは自動維持する |
| (該当なし) | ローリングアップデート | Docker Composeにはない |
| (該当なし) | Self-healing | Docker Composeにはない |
9. 次回予告
第3回:Service / Ingress — ネットワーキングの設計思想
今回、Podは動くようになりました。
でも「外からアクセスする方法」がまだありません。
🍽️ レストランは開店したけど、看板も入口もない状態。
お客さんがたどり着けない!
次回は:
- PodにはIPアドレスがあるのに、なぜ直接アクセスしないのか?
- Service の4つの種類(ClusterIP / NodePort / LoadBalancer / ExternalName)
- Ingressで「1つの入口から複数のサービスに振り分ける」方法
(つづく)