📁GitHubにコード公開: GitHub: kubernetes_kind
シリーズ記事一覧
- 第1回:全体像と環境構築
- 第2回:Pod・ReplicaSet・Deployment
- 第3回:Service・Ingress
- 第4回:ConfigMap・Secret・Volume
- 第5回:Namespace・RBAC
- 第6回:トラブルシュートと運用
- 第7回:設計総合演習
📑 目次
1. この記事について
最終回です。
第1〜6回で整理してきた知識をすべて組み合わせて、
1つのアプリケーションをk8sで設計・デプロイしてみました。
🍽️ これまで調理技術(各リソース)を個別に練習してきました。
最終回は「コース料理を設計して、フルで提供する」総合演習です。
- 第1回:レストランの仕組みを理解した(k8sの世界観)
- 第2回:スタッフを配置した(Pod / Deployment)
- 第3回:お客さんが入れるようにした(Service)
- 第4回:メニュー表とレシピ帳を整備した(ConfigMap / Secret)
- 第5回:フロアを分けて入館証を発行した(Namespace / RBAC)
- 第6回:トラブル対応マニュアルを整備した(運用)
今回:全部を組み合わせて、レストランを完全開店する。
2. この記事のゴール
この記事で書いていること:
- 要件から必要なk8sリソースを洗い出す過程
- 全体構成図の設計
- 3層アプリをkindにデプロイして動作確認した話
- 第1〜6回の知識がどこで使われたかの振り返り
3. 前提条件
| 項目 | 要件 |
|---|---|
| 前回の完了 | 第1〜6回の知識 |
| クラスタ状態 | kindクラスタが起動中 |
# WSL2 Ubuntu で実行
kubectl get nodes
4. お題:要件の確認
4-1. シナリオ
このように依頼されました:
「シンプルなWebアプリ(フロントエンド + API + DB)をKubernetesで設計・デプロイしてください」
4-2. 要件
| 項目 | 内容 |
|---|---|
| アプリ構成 | フロントエンド + API + DB の3層 |
| フロントエンド | 静的HTML配信(nginx) |
| API | リバースプロキシ(nginx) → 将来的にアプリサーバーに差し替え可能 |
| DB | PostgreSQL |
| 環境 | 開発環境(development) |
| 非機能要件 | フロントエンド/APIは2台以上、DBは1台 |
| セキュリティ | DBパスワードはSecretで管理 |
4-3. 設計のゴール(成功条件)
| # | 条件 | テスト方法 |
|---|---|---|
| 1 | フロントエンドにブラウザからアクセスできる | port-forward → curl |
| 2 | フロントエンドからAPIに通信できる | nginx設定でプロキシ |
| 3 | APIからDBに接続できる | exec → psql |
| 4 | DBのパスワードがSecretで管理されている | kubectl get secret |
| 5 | フロントエンド/APIが2台で冗長化されている | kubectl get pods |
5. 設計フェーズ:要件 → リソース設計
5-1. 必要なリソースの洗い出し
🍽️ 設計は「何を作るか」を決めるフェーズ。
コードを書く前に、必要なリソースを全て書き出します。
| # | リソース | 用途 | 学んだ回 |
|---|---|---|---|
| 1 | Namespace | 開発環境を分離 | 第5回 |
| 2 | ConfigMap (frontend) | nginx設定ファイル | 第4回 |
| 3 | ConfigMap (api) | nginx設定ファイル | 第4回 |
| 4 | ConfigMap (db) | DB初期化設定 | 第4回 |
| 5 | Secret | DBパスワード | 第4回 |
| 6 | Deployment (frontend) | フロントエンド × 2台 | 第2回 |
| 7 | Deployment (api) | API × 2台 | 第2回 |
| 8 | Deployment (db) | PostgreSQL × 1台 | 第2回 |
| 9 | Service (frontend) | フロントエンドへのアクセス | 第3回 |
| 10 | Service (api) | APIへの内部アクセス | 第3回 |
| 11 | Service (db) | DBへの内部アクセス | 第3回 |
合計:11リソース
5-2. 全体構成図
凡例:
実線(→)= 通信フロー
点線(-.->)= ConfigMap・Secretの参照(マウント / 環境変数)
5-3. 通信の流れ
この3層アプリケーションの通信フローを、3つのフェーズに分けて見ていきます。
フェーズが進むにつれて経由する層が1つずつ増えていくことに注目してください。
5-3-1. フェーズ1:静的ページの取得(frontend層のみ)
5-3-2. フェーズ2:APIヘルスチェック(frontend → API)
5-3-3. フェーズ3:データ取得(frontend → API → DB)
5-4. デプロイ順序
依存関係があるため、デプロイには順序が重要です。
| 順序 | リソース | 理由 |
|---|---|---|
| ①最初 | Namespace | 全リソースの入れ物 |
| ②次 | ConfigMap / Secret | Deploymentが参照するため先に必要 |
| ③その次 | DB Deployment + Service | APIがDBに接続するため |
| ④その次 | API Deployment + Service | フロントがAPIに接続するため |
| ⑤最後 | Frontend Deployment + Service | 全ての依存先が揃ってから |
🍽️ レストラン開店の準備順序:
食材倉庫(DB)→ キッチン(API)→ ホール(Frontend)。
倉庫がないのにキッチンは開けない。
6. 実装フェーズ:マニフェスト作成 → デプロイ
6-1. ディレクトリ構成(11リソース:①~⑪)
# WSL2 Ubuntu で実行
mkdir -p ~/k8s-handson/design-exercise
cd ~/k8s-handson/design-exercise
最終的なファイル構成:
~/k8s-handson/design-exercise/
├── 01-namespace.yaml
├── 02-db-secret.yaml
├── 03-db-configmap.yaml
├── 04-api-configmap.yaml
├── 05-frontend-configmap.yaml
├── 06-db-deployment.yaml
├── 07-db-service.yaml
├── 08-api-deployment.yaml
├── 09-api-service.yaml
├── 10-frontend-deployment.yaml
└── 11-frontend-service.yaml
🔰 Memo:
ファイル名に番号を付けたのは、デプロイ順序を示すためです。
kubectl apply -f でディレクトリごと適用すると、
ファイル名のアルファベット順で処理されるので、番号を付けておくと依存関係の順序が守られます。
6-2. ① Namespace
# 01-namespace.yaml
# Namespace = 開発環境のフロア
apiVersion: v1
kind: Namespace
metadata:
name: k8s-web-app
💡ポイント:
Namespace は「フロアの仕切り」。
これ以降の全リソースにnamespace: k8s-web-appを指定することで、
default と完全に分離される。
6-3. ② Secret(DBパスワード)
📂 design-exercise/
├── 01-namespace.yaml ✅ ①
├── 02-db-secret.yaml ← ② 🆕
├── 03-db-configmap.yaml ← ③ 🆕
├── 04-api-configmap.yaml ← ④ 🆕
├── 05-frontend-configmap.yaml ← ⑤ 🆕
├── 06-db-deployment.yaml ⑥
├── 07-db-service.yaml ⑦
├── 08-api-deployment.yaml ⑧
├── 09-api-service.yaml ⑨
├── 10-frontend-deployment.yaml ⑩
└── 11-frontend-service.yaml ⑪
# 02-db-secret.yaml
# Secret = レシピ帳(金庫保管)
apiVersion: v1
kind: Secret
metadata:
name: db-secret
namespace: k8s-web-app
type: Opaque
stringData:
POSTGRES_PASSWORD: "k8s-demo-password"
# 本番では AWS Secrets Manager 等と連携が必須
🔑 ポイント:
stringDataは平文で書けて便利だが、
kubectl get secret -o yamlで見るとdata(base64)に自動変換されている。
本番では外部シークレットマネージャー連携が必須。
6-4. ③ ConfigMap(DB初期化)
# 03-db-configmap.yaml
# ConfigMap = DBの初期化設定
apiVersion: v1
kind: ConfigMap
metadata:
name: db-config
namespace: k8s-web-app
data:
POSTGRES_DB: "webapp"
POSTGRES_USER: "appuser"
# DB初期化SQL
init.sql: |
CREATE TABLE IF NOT EXISTS health_check (
id SERIAL PRIMARY KEY,
status VARCHAR(20) DEFAULT 'ok',
checked_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO health_check (status) VALUES ('ok');
💡ポイント:
この ConfigMap は2つの役割を兼ねている。
①POSTGRES_DB/POSTGRES_USERは環境変数として注入(envFrom)、
②init.sqlはファイルとしてマウント(volumeMounts)。
1つの ConfigMap でも注入方法が異なる点に注意。
6-5. ④ ConfigMap(API nginx設定)
# 04-api-configmap.yaml
# ConfigMap = APIのnginx設定
apiVersion: v1
kind: ConfigMap
metadata:
name: api-config
namespace: k8s-web-app
data:
default.conf: |
server {
listen 80;
server_name localhost;
# ヘルスチェック
location /health {
return 200 '{"status": "ok", "service": "api"}';
add_header Content-Type application/json;
}
# APIエンドポイント
location / {
return 200 '{"message": "Welcome to the API"}';
add_header Content-Type application/json;
}
}
💡ポイント:
/healthと/の2エンドポイントを定義。
将来アプリサーバー(Express, FastAPI等)に差し替える際は、
この ConfigMap を書き換えるだけで nginx 設定が切り替わる。
6-6. ⑤ ConfigMap(フロントエンド)
# 05-frontend-configmap.yaml
# ConfigMap = フロントエンドの設定(nginx設定 + HTML)
apiVersion: v1
kind: ConfigMap
metadata:
name: frontend-config
namespace: k8s-web-app
data:
# nginx設定(/api へのリクエストをAPIサービスに転送)
default.conf: |
server {
listen 80;
server_name localhost;
# 静的ファイルの配信
location / {
root /usr/share/nginx/html;
index index.html;
}
# /api へのリクエストを api-svc に転送
location /api/ {
proxy_pass http://api-svc/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
# ─────────────────────────────────────────────
# トップページのHTML(動作確認用の表示ページ)
# ※ 学習の本質はここではなく、上の nginx設定 と Deployment の連携部分です
# ※ HTML の中身をこのようにする必須性はありません
# ─────────────────────────────────────────────
index.html: |
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>k8s Web App</title>
<style>
body { font-family: sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; }
h1 { color: #326CE5; }
.status { padding: 15px; border-radius: 8px; margin: 10px 0; }
.ok { background: #e8f5e9; border: 1px solid #4CAF50; }
.info { background: #e3f2fd; border: 1px solid #2196F3; }
code { background: #f5f5f5; padding: 2px 6px; border-radius: 3px; }
</style>
</head>
<body>
<h1>☸️ k8s Web App</h1>
<p>Kubernetes設計・構築メモ — 第7回 総合演習</p>
<div class="status ok">
✅ フロントエンドは正常に動作しています
</div>
<div class="status info">
📡 APIの状態を確認するには:<br>
<code>curl http://localhost:8080/api/health</code>
</div>
<h2>構成</h2>
<ul>
<li>🏪 Frontend: nginx(このページ)</li>
<li>🍳 API: nginx(リバースプロキシ)</li>
<li>🗄️ DB: PostgreSQL</li>
</ul>
</body>
</html>
💡ポイント:
この ConfigMap は
default.conf(nginx設定)とindex.html(HTML)の2ファイルを持つ。
Deployment 側でitemsを使い、
それぞれ別ディレクトリにマウントする(6-11 参照)。
nginx設定のproxy_pass http://api-svc/が Service 名による名前解決の実例。
6-7. ⑥ DB Deployment
📂 design-exercise/
├── 01-namespace.yaml ✅ ①
├── 02-db-secret.yaml ✅ ②
├── 03-db-configmap.yaml ✅ ③
├── 04-api-configmap.yaml ✅ ④
├── 05-frontend-configmap.yaml ✅ ⑤
├── 06-db-deployment.yaml ← ⑥ 🆕
├── 07-db-service.yaml ← ⑦ 🆕
├── 08-api-deployment.yaml ⑧
├── 09-api-service.yaml ⑨
├── 10-frontend-deployment.yaml ⑩
└── 11-frontend-service.yaml ⑪
# 06-db-deployment.yaml
# DB Deployment = 食材倉庫のスタッフ配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: db
namespace: k8s-web-app
spec:
replicas: 1 # DBは1台(ステートフル)
selector:
matchLabels:
app: db
template:
metadata:
labels:
app: db
spec:
containers:
- name: postgres
image: postgres:16
ports:
- containerPort: 5432
# ConfigMapから一般設定を環境変数で注入
envFrom:
- configMapRef:
name: db-config
# Secretからパスワードを環境変数で注入
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: POSTGRES_PASSWORD
# 初期化SQLをマウント
volumeMounts:
- name: init-sql
mountPath: /docker-entrypoint-initdb.d
readOnly: true
volumes:
- name: init-sql
configMap:
name: db-config
items:
- key: init.sql
path: init.sql
ポイント解説:
| フィールド | 値 | なぜこの設定? | 学んだ回 |
|---|---|---|---|
replicas |
1 | DBはステートフル。複数台にするにはレプリケーション設計が必要 | 第2回 |
envFrom.configMapRef |
db-config | DB名・ユーザー名を ConfigMap から一括注入 | 第4回 |
env.secretKeyRef |
db-secret | パスワードだけ Secret 経由で分離(セキュリティ) | 第4回 |
volumeMounts |
/docker-entrypoint-initdb.d | PostgreSQL が初回起動時に init.sql を自動実行するパス | 第4回 |
volumes.configMap.items |
init.sql | ConfigMap の特定キーだけをファイルとして取り出す | 第4回 |
紐づけ図:
🍽️
DB Pod は「3方向から物資を受け取る調理場」。
ConfigMap から食材リスト(環境変数)と初期レシピ(init.sql)、
Secret から金庫の鍵(パスワード)を受け取り、Service が内線電話で繋ぐ。
6-8. ⑦ DB Service
# 07-db-service.yaml
# DB Service = 食材倉庫の内線電話(ClusterIP)
apiVersion: v1
kind: Service
metadata:
name: db-svc
namespace: k8s-web-app
spec:
type: ClusterIP # 内部からのみアクセス
selector:
app: db
ports:
- port: 5432
targetPort: 5432
🍽️ 食材倉庫(DB)の内線電話。外部のお客さんには番号を教えない(ClusterIP)。
| 設定 | 値 | 理由 |
|---|---|---|
type |
ClusterIP | DB は内部からのみアクセス。外部公開は不要 |
selector |
app: db |
DB Deployment の Pod を選択 |
port |
5432 | PostgreSQL のデフォルトポート |
6-9. ⑧ API Deployment
📂 design-exercise/
├── 01-namespace.yaml ✅ ①
├── 02-db-secret.yaml ✅ ②
├── 03-db-configmap.yaml ✅ ③
├── 04-api-configmap.yaml ✅ ④
├── 05-frontend-configmap.yaml ✅ ⑤
├── 06-db-deployment.yaml ✅ ⑥
├── 07-db-service.yaml ✅ ⑦
├── 08-api-deployment.yaml ← ⑧ 🆕
├── 09-api-service.yaml ← ⑨ 🆕
├── 10-frontend-deployment.yaml ⑩
└── 11-frontend-service.yaml ⑪
# 08-api-deployment.yaml
# API Deployment = キッチンのスタッフ配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
namespace: k8s-web-app
spec:
replicas: 2 # APIは2台で冗長化
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
# nginx設定をConfigMapからマウント
volumeMounts:
- name: api-conf
mountPath: /etc/nginx/conf.d
readOnly: true
volumes:
- name: api-conf
configMap:
name: api-config
ポイント解説:
| フィールド | 値 | なぜこの設定? | 学んだ回 |
|---|---|---|---|
replicas |
2 | APIは冗長化。1台が落ちてもServiceが残りに振り分ける | 第2回 |
image |
nginx:1.25 | 今回はnginxで代用。将来Express/FastAPI等に差し替え可能 | 第2回 |
volumeMounts |
/etc/nginx/conf.d | ConfigMap の nginx 設定をファイルとしてマウント | 第4回 |
💡DB Deployment との違い:
API にはenv/envFromがない。
設定はすべてファイルマウント(nginx.conf)で注入している。
紐づけ図:
🍽️
API Pod は「メニュー表(nginx設定)だけ受け取るシンプルなキッチン」。
DB Pod と比べると接続元が1つだけ。
— 設定の注入パターンが層によって異なる。
6-10. ⑨ API Service
# 09-api-service.yaml
# API Service = キッチンの内線電話(ClusterIP)
apiVersion: v1
kind: Service
metadata:
name: api-svc
namespace: k8s-web-app
spec:
type: ClusterIP # フロントエンドからの内部アクセス用
selector:
app: api
ports:
- port: 80
targetPort: 80
🍽️
キッチン(API)の内線電話。
フロントエンドの nginx がproxy_pass http://api-svc/でここに電話する。
| 設定 | 値 | 理由 |
|---|---|---|
type |
ClusterIP | API は外部公開不要。Frontend からの内部通信のみ |
selector |
app: api |
API Deployment の Pod(2台)にロードバランス |
port |
80 | nginx のデフォルトポート |
6-11. ⑩ Frontend Deployment
📂 design-exercise/
├── 01-namespace.yaml ✅ ①
├── 02-db-secret.yaml ✅ ②
├── 03-db-configmap.yaml ✅ ③
├── 04-api-configmap.yaml ✅ ④
├── 05-frontend-configmap.yaml ✅ ⑤
├── 06-db-deployment.yaml ✅ ⑥
├── 07-db-service.yaml ✅ ⑦
├── 08-api-deployment.yaml ✅ ⑧
├── 09-api-service.yaml ✅ ⑨
├── 10-frontend-deployment.yaml ← ⑩ 🆕
└── 11-frontend-service.yaml ← ⑪ 🆕
# 10-frontend-deployment.yaml
# Frontend Deployment = ホールのスタッフ配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
namespace: k8s-web-app
spec:
replicas: 2 # フロントエンドも2台で冗長化
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
# nginx設定とHTMLをConfigMapからマウント
volumeMounts:
- name: frontend-conf
mountPath: /etc/nginx/conf.d
readOnly: true
- name: frontend-html
mountPath: /usr/share/nginx/html
readOnly: true
volumes:
- name: frontend-conf
configMap:
name: frontend-config
items:
- key: default.conf
path: default.conf
- name: frontend-html
configMap:
name: frontend-config
items:
- key: index.html
path: index.html
ポイント解説:
| フィールド | 値 | なぜこの設定? | 学んだ回 |
|---|---|---|---|
replicas |
2 | フロントエンドも冗長化。Serviceが2台にロードバランス | 第2回 |
volumeMounts (1つ目) |
/etc/nginx/conf.d | nginx設定ファイル(proxy_pass含む)をマウント | 第4回 |
volumeMounts (2つ目) |
/usr/share/nginx/html | HTMLファイルをマウント(nginxのドキュメントルート) | 第4回 |
volumes.items |
key指定で分離 | 1つの ConfigMap から default.conf と index.html を別々のパスに配置 |
第4回 |
💡3つの Deployment の比較:
DB はenvFrom+env+volumeMounts、
API はvolumeMountsのみ、
Frontend はvolumeMounts× 2。
設定の注入パターンが層ごとに異なる点がポイント。
紐づけ図:
🍽️
Frontend Pod は「1つの引き出し(ConfigMap)から、
メニュー表(nginx設定)と看板(HTML)を別々に取り出して配置するホール」。
唯一の NodePort Service がお客さんの入口になる。
6-12. ⑪ Frontend Service
# 11-frontend-service.yaml
# Frontend Service = ホールの直通電話(NodePort)
apiVersion: v1
kind: Service
metadata:
name: frontend-svc
namespace: k8s-web-app
spec:
type: NodePort # 外部からアクセス可能
selector:
app: frontend
ports:
- port: 80
targetPort: 80
nodePort: 30080
🍽️
ホール(Frontend)の直通電話。
唯一の外部公開窓口(NodePort)。
お客さん(ブラウザ)はここに電話する。
| 設定 | 値 | 理由 |
|---|---|---|
type |
NodePort | 唯一の外部公開 Service。ブラウザから直接アクセス |
selector |
app: frontend |
Frontend Deployment の Pod(2台)にロードバランス |
nodePort |
30080 | Node の 30080 番ポートで外部公開 |
💡3つの Service の type 比較:
DB = ClusterIP(内部のみ)、
API = ClusterIP(内部のみ)、
Frontend = NodePort(外部公開)。
外部に公開するのは入口の1つだけ — これが多層防御の基本。
6-13. 一括デプロイ
# ~/k8s-handson/design-exercise/ で実行
# 全マニフェストを一括適用(ファイル名順に処理される)
kubectl apply -f .
期待される出力:
namespace/k8s-web-app created
secret/db-secret created
configmap/db-config created
configmap/api-config created
configmap/frontend-config created
deployment.apps/db created
service/db-svc created
deployment.apps/api created
service/api-svc created
deployment.apps/frontend created
service/frontend-svc created
11リソースが一括で作成されました。
# 全リソースの状態を確認
kubectl get all -n k8s-web-app
期待される出力:
NAME READY STATUS RESTARTS AGE
pod/api-xxxxxxxxx-xxxxx 1/1 Running 0 30s
pod/api-xxxxxxxxx-yyyyy 1/1 Running 0 30s
pod/db-xxxxxxxxx-zzzzz 1/1 Running 0 30s
pod/frontend-xxxxxxxxx-aaaaa 1/1 Running 0 30s
pod/frontend-xxxxxxxxx-bbbbb 1/1 Running 0 30s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/api-svc ClusterIP 10.96.x.x <none> 80/TCP 30s
service/db-svc ClusterIP 10.96.x.x <none> 5432/TCP 30s
service/frontend-svc NodePort 10.96.x.x <none> 80:30080/TCP 30s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/api 2/2 2 2 30s
deployment.apps/db 1/1 1 1 30s
deployment.apps/frontend 2/2 2 2 30s
🍽️
全フロアにスタッフが配置され、電話回線も繋がりました。
レストラン開店。
💡
kubectl get allは、
Pod / Service / Deployment / ReplicaSet を表示します。
ConfigMap・Secret・Namespace は表示されません。
確認するには個別コマンドが必要です。
# ConfigMap と Secret も確認
kubectl get configmap,secret -n k8s-web-app
7. 動作確認
7-1. フロントエンドにアクセス
# port-forward でフロントエンドにアクセス
kubectl port-forward service/frontend-svc 8080:80 -n k8s-web-app
別ターミナルで:
# トップページを確認
curl -s http://localhost:8080/
期待される出力: HTMLが返ってくれば成功です。
7-2. API経由でアクセス
# フロントエンドの /api/ がAPIに転送されるか確認
curl -s http://localhost:8080/api/health
期待される出力:
{"status": "ok", "service": "api"}
フロントエンド → API の通信が成功しました。
7-3. DBへの接続確認
# 別ターミナルで実行(port-forwardを止めない)
# DB Podに入ってpsqlで確認
kubectl exec -it deploy/db -n k8s-web-app -- psql -U appuser -d webapp -c "SELECT * FROM health_check;"
期待される出力:
id | status | checked_at
----+--------+----------------------------
1 | ok | 2026-xx-xx xx:xx:xx.xxxxxx
(1 row)
DBに初期データが入っています。
ConfigMapの init.sql が正しく実行されたようです。
7-4. Secret の確認
kubectl get secret db-secret -n k8s-web-app -o jsonpath='{.data.POSTGRES_PASSWORD}' | base64 --decode
期待される出力:
k8s-demo-password
7-5. 冗長性の確認(Self-healing)
# フロントエンドのPodを1つ削除
kubectl delete pod -l app=frontend \
-n k8s-web-app \
--field-selector=status.phase=Running \
--grace-period=0 \
--force 2>/dev/null | head -1
# すぐに確認
kubectl get pods -n k8s-web-app -l app=frontend --watch
2台体制が自動で復旧されることを確認したら Ctrl + C で終了。
7-6. 動作確認チェックリスト
| # | 確認項目 | コマンド | 結果 |
|---|---|---|---|
| 1 | フロントエンド にアクセス |
curl localhost:8080/ |
✅ HTML返却 |
| 2 | API通信 | curl localhost:8080/api/health |
✅ JSON返却 |
| 3 | DB接続 | kubectl exec ... psql |
✅ データ取得 |
| 4 | Secret管理 | kubectl get secret |
✅ base64エンコード済み |
| 5 | 冗長性 | Pod削除 → 自動復旧 | ✅ Self-healing |
7-7. 後片付け
# Namespace ごと全て削除
kubectl delete namespace k8s-web-app
# port-forward を Ctrl+C で停止
8. シリーズ総まとめ
8-1. 第1〜7回の知識マッピング
今回のハンズオンで、どの回の知識がどこで使われたかを振り返ります。
| 回 | 学んだこと | 今回の使用箇所 |
|---|---|---|
| 第1回 | k8sの世界観、kind構築 | kindクラスタで全体を動かした |
| 第2回 | Pod / Deployment | 3つのDeployment(frontend/api/db) |
| 第3回 | Service | ClusterIP × 2 + NodePort × 1 |
| 第4回 | ConfigMap / Secret | nginx設定、初期化SQL、DBパスワード |
| 第5回 | Namespace | k8s-web-app で環境分離 |
| 第6回 | トラブルシュート | 動作確認時の調査コマンド |
8-2. Docker Compose → k8s 最終対応表
| Docker Compose | Kubernetes | 設計思想の違い |
|---|---|---|
| 1ファイルで全管理 | 関心事ごとにリソースを分離 | 責任の分離 |
| 手動再起動 | Self-healing | 自律的な回復 |
| スケール手動 | Deployment + replicas | 宣言的なスケール |
| ポート直結 | Service(名前ベース) | 抽象化 |
| 環境変数ベタ書き | ConfigMap + Secret | 設定の外部化 |
| 権限管理なし | RBAC | 最小権限の原則 |
| 単一ファイル | Namespace | 環境の論理分離 |
8-3. k8sの設計思想(まとめ)
7回を通じて見えてきたk8sの設計思想を3つにまとめます。
🍽️ チェーンレストラン経営の3原則
| # | 設計思想 | 比喩 | 具体例 |
|---|---|---|---|
| 1 | 宣言的管理 | 「常に3人体制」と宣言すれば、本部が勝手に維持する | Deployment の replicas |
| 2 | 関心事の分離 | メニュー表、レシピ帳、食材倉庫は別々に管理する | ConfigMap / Secret / Volume |
| 3 | 疎結合 | スタッフ(Pod)が入れ替わっても、代表電話(Service)は変わらない | Service による抽象化 |
9. 次のステップ
9-1. このシリーズで学んだこと
✅ k8sの世界観(Docker Composeとの違い)
✅ コンテナ管理(Pod / ReplicaSet / Deployment)
✅ ネットワーク(Service / Ingress)
✅ 設定管理(ConfigMap / Secret / Volume)
✅ セキュリティ(Namespace / RBAC)
✅ 運用(ログ / 監視 / トラブルシュート)
✅ 総合設計(3層アプリのデプロイ)
9-2. 次の学習テーマ考察
| 優先度 | テーマ | 理由 |
|---|---|---|
| ⭐⭐⭐ | Helm | マニフェストのテンプレート化。実務では必須 |
| ⭐⭐⭐ | PersistentVolume / PVC | DBデータの永続化(今回は省略した部分) |
| ⭐⭐⭐ | Liveness / Readiness Probe | ヘルスチェックの自動化 |
| ⭐⭐ | HPA(Horizontal Pod Autoscaler) | 負荷に応じた自動スケール |
| ⭐⭐ | EKS(AWS) | クラウドでの本番k8s運用 |
| ⭐⭐ | CI/CD + k8s | GitOps(ArgoCD / Flux) |
| ⭐ | Istio / Service Mesh | マイクロサービス間の通信制御 |
| ⭐ | Operator パターン | カスタムコントローラー |
9-3. 最後に
🍽️ この7回のシリーズを通じて、
「個人経営の定食屋」の感覚から「チェーンレストランの設計」の視点に少しずつ変わってきた実感があります。
「なぜこう設計するのか」 という思考プロセスは、どんな技術が来ても応用できると思います。
このシリーズが、私と同じような立場の方のk8s学習の参考になればうれしいです。
(完結)