@k2works/claude-code-booster 4.6.0 → 4.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/lib/assets/.claude/README.md +2 -0
  2. package/lib/assets/.claude/skills/creating-journal/SKILL.md +129 -0
  3. package/lib/assets/docs/article/getting-start-docker-kubernetes/01-container-and-docker-basics.md +332 -0
  4. package/lib/assets/docs/article/getting-start-docker-kubernetes/02-container-deployment.md +776 -0
  5. package/lib/assets/docs/article/getting-start-docker-kubernetes/03-practical-container-build-deploy.md +457 -0
  6. package/lib/assets/docs/article/getting-start-docker-kubernetes/04-multi-container-application.md +869 -0
  7. package/lib/assets/docs/article/getting-start-docker-kubernetes/05-kubernetes-introduction.md +576 -0
  8. package/lib/assets/docs/article/getting-start-docker-kubernetes/06-kubernetes-deploy-cluster.md +611 -0
  9. package/lib/assets/docs/article/getting-start-docker-kubernetes/07-kubernetes-advanced.md +612 -0
  10. package/lib/assets/docs/article/getting-start-docker-kubernetes/08-kubernetes-packaging.md +509 -0
  11. package/lib/assets/docs/article/getting-start-docker-kubernetes/09-container-operations.md +537 -0
  12. package/lib/assets/docs/article/getting-start-docker-kubernetes/10-optimal-container-image.md +631 -0
  13. package/lib/assets/docs/article/getting-start-docker-kubernetes/11-continuous-delivery.md +598 -0
  14. package/lib/assets/docs/article/getting-start-docker-kubernetes/12-container-use-cases.md +454 -0
  15. package/lib/assets/docs/article/getting-start-docker-kubernetes/13-case-monolith-compose-vs-kustomize.md +337 -0
  16. package/lib/assets/docs/article/getting-start-docker-kubernetes/14-case-event-driven-kustomize-vs-helm.md +315 -0
  17. package/lib/assets/docs/article/getting-start-docker-kubernetes/15-case-escqrs-axon-kustomize-vs-helm.md +288 -0
  18. package/lib/assets/docs/article/getting-start-docker-kubernetes/16-case-escqrs-kafka-kustomize-vs-helm.md +247 -0
  19. package/lib/assets/docs/article/getting-start-docker-kubernetes/17-case-comparison-summary.md +132 -0
  20. package/lib/assets/docs/article/getting-start-docker-kubernetes/18-case-load-testing.md +294 -0
  21. package/lib/assets/docs/article/getting-start-docker-kubernetes/appendix-a-dev-tools-setup.md +265 -0
  22. package/lib/assets/docs/article/getting-start-docker-kubernetes/appendix-b-orchestration-environments.md +521 -0
  23. package/lib/assets/docs/article/getting-start-docker-kubernetes/appendix-c-tips.md +510 -0
  24. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-01-comic.png +0 -0
  25. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-02-comic.png +0 -0
  26. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-03-comic.png +0 -0
  27. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-04-comic.png +0 -0
  28. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-05-comic.png +0 -0
  29. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-06-comic.png +0 -0
  30. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-07-comic.png +0 -0
  31. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-08-comic.png +0 -0
  32. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-09-comic.png +0 -0
  33. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-10-comic.png +0 -0
  34. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-11-comic.png +0 -0
  35. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-12-comic.png +0 -0
  36. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/overview-comic.png +0 -0
  37. package/lib/assets/docs/article/getting-start-docker-kubernetes/index.md +82 -0
  38. package/lib/assets/docs/article/getting-start-docker-kubernetes/outline.md +211 -0
  39. package/lib/assets/docs/article/index.md +3 -1
  40. package/lib/assets/mkdocs.yml +1 -0
  41. package/package.json +1 -1
@@ -0,0 +1,294 @@
1
+ # 第 18 章 ケーススタディの負荷テスト
2
+
3
+ ## はじめに
4
+
5
+ 第 12 章「12.3 負荷テスト」では、Python 製の負荷テストツール **Locust** をコンテナで動かす考え方を学びました。負荷生成ツール・シナリオ・テスト対象をすべてコンテナとして扱うことで、負荷テスト環境を「コードから一括で構築し、終わったら破棄する」ことができます。
6
+
7
+ この章では、その考え方を第 13〜16 章の 4 ケース(同一ドメイン = Cargo Tracker の 4 アーキテクチャ)に適用します。各ケースに Locust の負荷テスト一式を用意し、**Docker Compose 版**と **Kubernetes 版**の 2 通りで実行できるようにしました。
8
+
9
+ 実装はすべて各ケースの [`loadtest/`](https://github.com/k2works/getting-started-docker-kubernetes/tree/main/apps/case-studies) ディレクトリにあります。
10
+
11
+ | ケース | アーキテクチャ | loadtest ディレクトリ |
12
+ |--------|--------------|----------------------|
13
+ | case-1 | モノリス | `apps/case-studies/case-1-monolith/loadtest/` |
14
+ | case-2 | イベント駆動 MS | `apps/case-studies/case-2-event-driven/loadtest/` |
15
+ | case-3 | ES/CQRS(Axon) | `apps/case-studies/case-3-escqrs-axon/loadtest/` |
16
+ | case-4 | ES/CQRS(Kafka) | `apps/case-studies/case-4-escqrs-kafka/loadtest/` |
17
+
18
+ ---
19
+
20
+ ## 18.1 構成
21
+
22
+ 各ケースの `loadtest/` には次のファイルが入っています。シナリオ(`locustfile.py`)は Compose 版・Kubernetes 版で共有します。
23
+
24
+ | ファイル | 役割 |
25
+ |---------|------|
26
+ | `locustfile.py` | 負荷シナリオ(仮想ユーザーの振る舞い) |
27
+ | `compose.loadtest.yaml` | Docker Compose 版 Locust の起動定義(Web UI: 8089) |
28
+ | `kustomization.yaml` | Kubernetes 版 Locust の Kustomize 定義 |
29
+ | `k8s-locust.yaml` | Kubernetes 版 Locust の Deployment / Service |
30
+ | `README.md` | 実行手順・対象エンドポイント |
31
+
32
+ ### 現行 Locust API を使う
33
+
34
+ 第 12 章で引用したサンプル(`senario.py`)は、Locust 旧 API(`HttpLocust` / `TaskSet`)で書かれていました。これらは現行の Locust では廃止されているため、本章のシナリオは**現行 API(`HttpUser` / `@task` / `between`)**と公式イメージ `locustio/locust` で記述しています。
35
+
36
+ ```python
37
+ from locust import HttpUser, between, task
38
+
39
+
40
+ class CargoTrackerUser(HttpUser):
41
+ # 各タスクの実行間隔(記事の min_wait / max_wait に相当)
42
+ wait_time = between(1, 3)
43
+
44
+ @task(5)
45
+ def bookings(self):
46
+ self.client.get("/api/v1/bookings", name="/api/v1/bookings")
47
+ ```
48
+
49
+ 旧 API の `min_wait` / `max_wait`(ミリ秒)は、現行では `wait_time = between(min, max)`(秒)に置き換わっています。`HttpLocust` は `HttpUser`、`task_set` を持つ `TaskSet` は `HttpUser` に直接 `@task` を書く形になりました。
50
+
51
+ ---
52
+
53
+ ## 18.2 ケースごとの対象エンドポイントと認証
54
+
55
+ 負荷テストで重要なのは「**副作用のない読み取り系(GET)に、認証を通して負荷をかける**」ことです。4 ケースは認証方式が異なるため、シナリオもそれに合わせています。
56
+
57
+ | ケース | 公開ポート(Compose) | 認証方式 | シナリオの方針 |
58
+ |--------|---------------------|---------|--------------|
59
+ | case-1 | 18080(app) | セッション + フォームログイン | 認証不要の GET のみ(`/actuator/health`、`/login`、`/public/tracking`) |
60
+ | case-2 | 9080(gateway) | JWT(gateway で強制) | ログインで JWT を取得し、Read 系 GET に付与 |
61
+ | case-3 | 9081(gateway) | JWT(gateway で強制) | ログインで JWT を取得し、CQRS Query 側へ |
62
+ | case-4 | 9082(gateway) | `local` では認可無効 | 匿名で Read Model を GET |
63
+
64
+ ### case-1: 認証不要の GET(セッション認証のため)
65
+
66
+ モノリス版は Spring Security のフォームログイン(セッション + CSRF)で保護されています。負荷テストでは、確実に匿名アクセスできる GET だけを対象にしています。
67
+
68
+ | メソッド | パス | 説明 |
69
+ |---------|------|------|
70
+ | GET | `/actuator/health` | ヘルスチェック |
71
+ | GET | `/login` | ログイン画面(HTML) |
72
+ | GET | `/public/tracking` | 公開追跡の検索画面 |
73
+
74
+ ### case-2 / case-3: JWT ログインしてから GET
75
+
76
+ 両ケースとも gatewayms が JWT 認証を強制します。Locust の `on_start`(仮想ユーザー開始時に 1 回呼ばれる)でログインしてトークンを取得し、以降の GET に `Authorization: Bearer <token>` を付けます。
77
+
78
+ ```python
79
+ def on_start(self):
80
+ """ログインして JWT を取得する。失敗時はトークンなしで続行する。"""
81
+ self.token = None
82
+ with self.client.post(
83
+ "/api/v1/auth/login",
84
+ json={"username": USERNAME, "password": PASSWORD},
85
+ name="/api/v1/auth/login",
86
+ catch_response=True,
87
+ ) as res:
88
+ if res.status_code == 200:
89
+ data = res.json() if res.text else {}
90
+ self.token = data.get("token") or data.get("accessToken")
91
+ if self.token:
92
+ res.success()
93
+ else:
94
+ res.failure("token がレスポンスに含まれていません")
95
+ else:
96
+ res.failure(f"ログイン失敗: HTTP {res.status_code}")
97
+ ```
98
+
99
+ 既定ユーザーはシード済みの `admin` / `password` です。case-3 は CQRS の Query 側(`/api/v1/bookings`、`/api/v1/voyages`、`/api/v1/billing/invoices` など)の Read Model 読み取りに負荷をかけます。
100
+
101
+ ### case-4: 認証なしで Read Model を GET
102
+
103
+ case-4 は `local`(`local-docker`)プロファイルで起動するため、gateway / 各サービスの Spring Security 認可が無効になります。そのためログイン処理なしで、ページング付きの一覧 API に直接負荷をかけられます。
104
+
105
+ ```python
106
+ @task(5)
107
+ def bookings(self):
108
+ """予約一覧(Read Model、ページング)。"""
109
+ self.client.get("/api/v1/bookings?page=0&size=20", name="/api/v1/bookings")
110
+ ```
111
+
112
+ `name=` を明示しているのは、`?page=0&size=20` のようなクエリ違いを Locust の統計上で同じエンドポイントとして集計するためです。
113
+
114
+ ---
115
+
116
+ ## 18.3 Docker Compose 版
117
+
118
+ Compose 版は、第 12 章のサンプルと同様に「負荷生成側(Locust)を独立した Compose として用意する」方式です。ただし本ケーススタディは `dev:<case>` でアプリ本体を起動し、gateway/app を**ホストポートに公開**します。そこで Locust 側は、`host.docker.internal` 経由でそのホスト公開ポートへ負荷をかけます(どの Compose ネットワークからでも到達できます)。
119
+
120
+ 出典: `apps/case-studies/case-4-escqrs-kafka/loadtest/compose.loadtest.yaml`
121
+
122
+ ```yaml
123
+ name: loadtest-case4
124
+
125
+ services:
126
+ locust:
127
+ image: locustio/locust:2.32.5
128
+ ports:
129
+ - "8089:8089"
130
+ volumes:
131
+ - ./locustfile.py:/mnt/locust/locustfile.py:ro
132
+ environment:
133
+ LOCUST_LOCUSTFILE: /mnt/locust/locustfile.py
134
+ # 負荷対象。ホストに公開された 9082 番(gatewayms: 9082:8080)へ向ける。
135
+ LOCUST_HOST: ${TARGET_URL:-http://host.docker.internal:9082}
136
+ extra_hosts:
137
+ - "host.docker.internal:host-gateway"
138
+ ```
139
+
140
+ ポイントは次のとおりです。
141
+
142
+ - `image` に公式イメージ `locustio/locust` を使い、`volumes` でシナリオファイルをマウントします。イメージを再ビルドせずにシナリオを差し替えられます。
143
+ - `LOCUST_LOCUSTFILE` / `LOCUST_HOST` は、Locust の CLI オプション(`-f` / `--host`)に対応する環境変数です。
144
+ - `extra_hosts` で `host.docker.internal` を `host-gateway` に解決し、Linux でもホスト公開ポートへ到達できるようにしています。
145
+
146
+ ### 実行手順(Compose 版)
147
+
148
+ ```bash
149
+ # 1. アプリ本体を起動(gateway をホスト 9082 に公開)
150
+ npx gulp dev:case4
151
+
152
+ # 2. Locust を起動(Web UI: http://localhost:8089)
153
+ npx gulp loadtest:case4
154
+
155
+ # 3. ブラウザで同時ユーザー数・増加レートを指定してテスト開始
156
+
157
+ # 4. 終了
158
+ npx gulp loadtest:case4:down
159
+ ```
160
+
161
+ CI 向けに、UI なしで一定時間だけ実行して終了するヘッドレス実行も用意しています。
162
+
163
+ ```bash
164
+ # 既定: 50 ユーザー / 毎秒 5 ユーザー増 / 1 分間
165
+ npx gulp loadtest:case4:headless
166
+
167
+ # パラメータを環境変数で上書き
168
+ USERS=100 SPAWN=10 DURATION=3m npx gulp loadtest:case4:headless
169
+ ```
170
+
171
+ ---
172
+
173
+ ## 18.4 Kubernetes 版
174
+
175
+ Kubernetes 版は、第 12 章の「負荷生成側とテスト対象を同一オーケストレータに載せる」考え方をそのまま適用します。**アプリと同じ名前空間に Locust をデプロイ**し、クラスタ内のサービス(`gatewayms` など)へ DNS 名で直接負荷をかけます。`host.docker.internal` やポートフォワードを介さず、より本番に近い経路で計測できます。
176
+
177
+ シナリオ(`locustfile.py`)は Kustomize の `configMapGenerator` で ConfigMap として配布し、Compose 版と同じファイルを共有します。
178
+
179
+ 出典: `apps/case-studies/case-4-escqrs-kafka/loadtest/kustomization.yaml`
180
+
181
+ ```yaml
182
+ apiVersion: kustomize.config.k8s.io/v1beta1
183
+ kind: Kustomization
184
+
185
+ namespace: cargo-tracker
186
+
187
+ configMapGenerator:
188
+ - name: locust-scenario
189
+ files:
190
+ - locustfile.py
191
+
192
+ resources:
193
+ - k8s-locust.yaml
194
+ ```
195
+
196
+ 出典: `apps/case-studies/case-4-escqrs-kafka/loadtest/k8s-locust.yaml`(抜粋)
197
+
198
+ ```yaml
199
+ apiVersion: apps/v1
200
+ kind: Deployment
201
+ metadata:
202
+ name: locust
203
+ spec:
204
+ replicas: 1
205
+ selector:
206
+ matchLabels:
207
+ app: locust
208
+ template:
209
+ metadata:
210
+ labels:
211
+ app: locust
212
+ spec:
213
+ containers:
214
+ - name: locust
215
+ image: locustio/locust:2.32.5
216
+ args:
217
+ - "-f"
218
+ - "/mnt/locust/locustfile.py"
219
+ - "--host"
220
+ - "http://gatewayms:8080" # クラスタ内サービスへ直接
221
+ ports:
222
+ - name: web
223
+ containerPort: 8089
224
+ volumeMounts:
225
+ - name: scenario
226
+ mountPath: /mnt/locust
227
+ volumes:
228
+ - name: scenario
229
+ configMap:
230
+ name: locust-scenario
231
+ ```
232
+
233
+ ポイントは次のとおりです。
234
+
235
+ - `namespace` をアプリと同じにすることで、`--host http://gatewayms:8080` のように**サービス名だけ**で負荷対象を指定できます(同一名前空間内の DNS 解決)。
236
+ - `configMapGenerator` は ConfigMap 名にハッシュ(`locust-scenario-xxxx`)を付けます。Volume の `configMap.name` への参照は Kustomize が自動で書き換えるため、シナリオを変更すると新しいハッシュになり、Pod が確実に最新シナリオで再起動します。
237
+ - 負荷対象は、case-1 は `cargo-tracker:80`、case-2〜4 は `gatewayms:8080` です(各サービスのクラスタ内ポート)。
238
+
239
+ ### 実行手順(Kubernetes 版)
240
+
241
+ ```bash
242
+ # 1. アプリ本体を Kubernetes にデプロイ
243
+ npx gulp k8s:case4
244
+
245
+ # 2. Locust をデプロイ(同じ名前空間 cargo-tracker へ)
246
+ npx gulp loadtest:case4:k8s
247
+
248
+ # 3. Web UI を port-forward して開く(http://localhost:8089、Ctrl+C で終了)
249
+ npx gulp loadtest:case4:k8s:open
250
+
251
+ # 4. 削除
252
+ npx gulp loadtest:case4:k8s:delete
253
+ ```
254
+
255
+ なお、アプリの `k8s:<case>:open` タスクは、Locust をデプロイ済みであれば負荷テストの Web UI(`http://localhost:8089`)も Kibana などと一緒に自動で開きます(未デプロイのときは `svc/locust` が見つからずスキップされます)。アプリ・ログ可視化・負荷テスト UI を 1 コマンドでまとめて開けます。
256
+
257
+ ```bash
258
+ npx gulp k8s:case4 # アプリをデプロイ
259
+ npx gulp loadtest:case4:k8s # 負荷テストをデプロイ
260
+ npx gulp k8s:case4:open # アプリ + Kibana + Locust(8089) をまとめて開く
261
+ ```
262
+
263
+ ---
264
+
265
+ ## 18.5 運用タスクとして統合する
266
+
267
+ これらの負荷テストは、本プロジェクトの運用タスク(Gulp)に `loadtest:<case>` として統合されています。`dev:<case>`(Compose 起動)・`k8s:<case>`(Kubernetes デプロイ)と同じ命名規約で扱えます。
268
+
269
+ | タスク | 説明 |
270
+ |--------|------|
271
+ | `loadtest:<case>` | Compose 版 Locust の Web UI を起動 |
272
+ | `loadtest:<case>:headless` | Compose 版を UI なしで実行(`USERS` / `SPAWN` / `DURATION` で調整) |
273
+ | `loadtest:<case>:down` | Compose 版を停止・破棄 |
274
+ | `loadtest:<case>:k8s` | Kubernetes 版をデプロイ |
275
+ | `loadtest:<case>:k8s:open` | Kubernetes 版の Web UI を port-forward して開く |
276
+ | `loadtest:<case>:k8s:delete` | Kubernetes 版を削除 |
277
+ | `loadtest:help` | 一覧とヘルプを表示 |
278
+
279
+ ES/CQRS のケース(case-3 / case-4)では、書き込み(コマンド)から Read Model への投影が非同期です。シード直後は一覧が空のことがあるため、デプロイ後しばらく待ってから負荷テストを実行してください。
280
+
281
+ ---
282
+
283
+ ## まとめ
284
+
285
+ - 第 12 章で学んだ Locust の負荷テストを、4 ケース(モノリス / イベント駆動 / ES・CQRS Axon / ES・CQRS Kafka)に適用しました
286
+ - シナリオは現行 Locust API(`HttpUser` / `@task` / `between`)で記述し、Compose 版・Kubernetes 版で共有します
287
+ - 認証方式の違い(セッション / JWT / 認可無効)に合わせ、副作用のない読み取り系 GET に負荷をかけるシナリオにしました
288
+ - Compose 版は `host.docker.internal` 経由でホスト公開ポートへ、Kubernetes 版は同一名前空間からクラスタ内サービスへ、それぞれ負荷をかけます
289
+ - 運用タスク(`loadtest:<case>`)として統合し、`dev:<case>` / `k8s:<case>` と同じ流れで「構築 → 負荷テスト → 破棄」を繰り返せます
290
+
291
+ ---
292
+
293
+ - 前の章: [第 17 章 ケーススタディ実装比較まとめ](17-case-comparison-summary.md)
294
+ - シリーズ目次: [Docker/Kubernetes 実践コンテナ解説](index.md)
@@ -0,0 +1,265 @@
1
+ # 付録 A 開発ツールのセットアップ
2
+
3
+ ## はじめに
4
+
5
+ 本編で扱った Docker や Kubernetes を快適に学習・開発するには、いくつかの周辺ツールをそろえておくと便利です。この付録では、書籍『Docker/Kubernetes 実践コンテナ開発入門(第 2 版)』の付録に沿って、次の 4 つの開発ツールのセットアップ方法を解説します。
6
+
7
+ - A.1 WSL2 — Windows 上で Linux 環境を動かす基盤
8
+ - A.2 asdf — 複数言語・ツールのバージョンを統一管理する
9
+ - A.3 kind — Docker の中に Kubernetes クラスタを立ち上げる
10
+ - A.4 Rancher Desktop — Docker Desktop の代替となるローカル開発環境
11
+
12
+ それぞれのツールは「何を解決するのか」という観点から整理します。ツールを導入する目的が明確であれば、自分の環境に合わせて取捨選択できるからです。
13
+
14
+ なお、本付録には 2 種類の情報が含まれます。1 つは本リポジトリ(`getting-started-docker-kubernetes`)に実在する設定ファイルやスクリプトを引用した内容で、もう 1 つは各ツールの一般的な利用手順です。前者には出典を明示し、後者は「一般的な手順」と区別して記載します。コマンドの実行結果は環境やバージョンによって変わるため、確実でないものは「例」と明記するか省略しています。
15
+
16
+ ---
17
+
18
+ ## A.1 WSL2
19
+
20
+ ### WSL2 は何を解決するか
21
+
22
+ Docker や Kubernetes のツールチェーンは Linux を前提に作られているものが多く、Windows でそのまま動かそうとすると差異に悩まされがちです。WSL2(Windows Subsystem for Linux 2)は、Windows 上で本物の Linux カーネルを動かす仕組みで、この「Windows と Linux の隔たり」を解決します。
23
+
24
+ WSL の初代(WSL1)が Linux システムコールを翻訳する方式だったのに対し、WSL2 は軽量な仮想マシン上で実際の Linux カーネルを動作させます。これにより、ファイルシステムの互換性やネットワーク、Docker のようなコンテナ技術との相性が大きく改善されました。
25
+
26
+ ### WSL2 の導入
27
+
28
+ 最近の Windows 10/11 では、管理者権限の PowerShell またはコマンドプロンプトから次のコマンド 1 つで WSL2 と既定のディストリビューション(通常は Ubuntu)をまとめて導入できます。
29
+
30
+ ```bash
31
+ wsl --install
32
+ ```
33
+
34
+ 実行後は再起動を求められることがあります。再起動後、初回起動時に Linux ユーザー名とパスワードの設定を求められます。
35
+
36
+ インストール済みの状態を確認したい場合は、次のコマンドでバージョンや稼働状態を確認できます。
37
+
38
+ ```bash
39
+ # WSL のバージョンと状態を確認する
40
+ wsl --status
41
+
42
+ # インストール済みディストリビューションを一覧表示する
43
+ wsl --list --verbose
44
+ ```
45
+
46
+ `wsl --list --verbose` の `VERSION` 列が `2` になっていれば WSL2 で動作しています。
47
+
48
+ ### ディストリビューションの導入
49
+
50
+ 既定以外のディストリビューションを使いたい場合は、導入可能な一覧を確認してから指定してインストールします。
51
+
52
+ ```bash
53
+ # インストール可能なディストリビューションの一覧を表示する
54
+ wsl --list --online
55
+
56
+ # ディストリビューションを指定してインストールする(例: Ubuntu-22.04)
57
+ wsl --install -d Ubuntu-22.04
58
+ ```
59
+
60
+ 既存のディストリビューションを WSL2 に変換したい場合は、バージョンを明示的に設定します。
61
+
62
+ ```bash
63
+ # 既定のバージョンを WSL2 にする
64
+ wsl --set-default-version 2
65
+
66
+ # 個別のディストリビューションを WSL2 に変換する(例)
67
+ wsl --set-version Ubuntu-22.04 2
68
+ ```
69
+
70
+ ### Docker との連携
71
+
72
+ WSL2 は、コンテナ開発環境との連携において中心的な役割を果たします。代表的な連携方法は次の 2 つです。
73
+
74
+ 1. Docker Desktop の WSL2 バックエンドを利用する方法。Docker Desktop の設定で WSL2 ベースのエンジンを有効化すると、Windows 側にインストールした Docker を WSL2 のディストリビューションから透過的に利用できます。
75
+ 2. WSL2 のディストリビューション内に直接 Docker Engine をインストールする方法。Docker Desktop を使わず、Linux と同じ手順で Docker をセットアップします。後述の Rancher Desktop も WSL2 を基盤として利用します。
76
+
77
+ 開発時のポイントとして、ソースコードは Windows 側(`/mnt/c/...`)ではなく WSL2 のファイルシステム上(例: `~/projects`)に置くと、ファイル I/O が高速になり、ファイル変更検知(ホットリロード)も安定します。
78
+
79
+ > 注: 上記コマンドは Windows 環境で一般的に有効なものです。利用可能なディストリビューションや既定の挙動は Windows のバージョン・更新状況によって異なります。
80
+
81
+ ---
82
+
83
+ ## A.2 asdf
84
+
85
+ ### asdf は何を解決するか
86
+
87
+ 開発を進めると、Go や Node.js といった言語ランタイムに加えて、`kustomize`、`helm`、`tilt` などの CLI ツールを多数使うことになります。これらは「プロジェクトごとに必要なバージョンが違う」「チームメンバー間でバージョンがそろわず、手元では動くのに他の環境で動かない」といった問題を起こしがちです。
88
+
89
+ asdf は、複数の言語・ツールのバージョンを 1 つの仕組みでまとめて管理するバージョンマネージャです。プロジェクトのルートに置いた `.tool-versions` ファイルでツールとバージョンを宣言しておくことで、チーム全体で同じバージョンを再現できます。
90
+
91
+ ### `.tool-versions` でバージョンを固定する
92
+
93
+ 本リポジトリのサンプルアプリ `taskapp` では、`apps/taskapp/.tool-versions`(出典: `getting-started-docker-kubernetes` リポジトリ)で次のようにツールとバージョンを固定しています。
94
+
95
+ ```text
96
+ golang 1.21.6
97
+ tilt 0.33.10
98
+ kustomize 5.3.0
99
+ kubectx 0.9.5
100
+ helm 3.13.3
101
+ ```
102
+
103
+ このファイルが示すとおり、`taskapp` の開発には Go 本体に加えて、Kubernetes 開発で頻出する次のツール群が必要です。
104
+
105
+ - `golang` — アプリケーション本体の実装に使う言語ランタイム
106
+ - `tilt` — Kubernetes 上での開発を高速化する開発ツール
107
+ - `kustomize` — Kubernetes マニフェストを環境差分込みで管理するツール
108
+ - `kubectx` — `kubectl` のコンテキスト・名前空間を素早く切り替えるツール
109
+ - `helm` — Kubernetes アプリケーションのパッケージマネージャ
110
+
111
+ 別のサンプルである `echo` アプリでは、`apps/echo/.tool-versions`(出典: 同リポジトリ)でより最小限の構成になっており、`kustomize` のみを固定しています。
112
+
113
+ ```text
114
+ kustomize 5.3.0
115
+ ```
116
+
117
+ このように、`.tool-versions` をプロジェクトごとに置くことで、「そのプロジェクトに必要なツールとバージョン」が明文化され、リポジトリをクローンした人は同じ環境を再現できます。
118
+
119
+ ### asdf のインストールとプラグイン追加
120
+
121
+ asdf は本体を導入したあと、ツールごとに「プラグイン」を追加して使います。一般的な利用の流れは次のとおりです。
122
+
123
+ ```bash
124
+ # プラグインを追加する(例: golang と kustomize)
125
+ asdf plugin add golang
126
+ asdf plugin add kustomize
127
+
128
+ # .tool-versions に書かれたバージョンを一括インストールする
129
+ asdf install
130
+
131
+ # ツールのバージョンをグローバルに設定する(例)
132
+ asdf global golang 1.21.6
133
+ ```
134
+
135
+ `asdf plugin add` で対象ツールのプラグインを登録し、`asdf install` で `.tool-versions` の内容に従ってバージョンをインストールします。`asdf global` は、カレントディレクトリに `.tool-versions` がない場面でのデフォルトバージョンを設定するためのコマンドです(プロジェクト単位で固定したい場合は `asdf local` を使い、`.tool-versions` を更新します)。
136
+
137
+ ### `.tool-versions` から一括セットアップするスクリプト
138
+
139
+ `taskapp` には、`.tool-versions` を読み取ってプラグイン追加とインストールをまとめて実行するセットアップスクリプトが用意されています。出典は `apps/taskapp/hack/install-tools.sh`(`getting-started-docker-kubernetes` リポジトリ)です。
140
+
141
+ ```bash
142
+ #!/usr/bin/env bash
143
+
144
+ cat .tool-versions | while read line
145
+ do
146
+ echo $line | awk '{print $1}' | xargs -I{} asdf plugin add {}
147
+ if [ $? -ne 0 ]; then
148
+ continue
149
+ fi
150
+ done
151
+
152
+ asdf install
153
+ ```
154
+
155
+ このスクリプトが行っていることは次のとおりです。
156
+
157
+ 1. `.tool-versions` を 1 行ずつ読み込む。
158
+ 2. 各行の先頭フィールド(ツール名)を `awk` で取り出し、`asdf plugin add` に渡してプラグインを追加する。
159
+ 3. プラグイン追加に失敗した行(`$? -ne 0`)はスキップして次の行へ進む。
160
+ 4. すべてのプラグイン追加が終わったら、最後に `asdf install` で `.tool-versions` に書かれたバージョンを一括インストールする。
161
+
162
+ つまり、`.tool-versions` を更新してこのスクリプトを実行するだけで、必要なツール群を宣言どおりにそろえられます。バージョン管理の「単一の情報源(Single Source of Truth)」を `.tool-versions` に集約し、手作業のばらつきを排除する典型的なパターンです。
163
+
164
+ > 注: `.tool-versions` の内容(ツール名・バージョン)は上記のとおり実ファイルからの引用ですが、`asdf plugin add` / `asdf install` / `asdf global` の使い方は asdf の一般的な利用手順です。
165
+
166
+ ---
167
+
168
+ ## A.3 kind
169
+
170
+ ### kind は何を解決するか
171
+
172
+ kind(Kubernetes IN Docker)は、その名のとおり Docker コンテナをノードに見立てて Kubernetes クラスタを立ち上げるツールです。本来 Kubernetes クラスタの構築には複数のマシンや仮想マシンが必要ですが、kind を使えば Docker さえあれば手元のマシン 1 台でクラスタを起動・破棄できます。
173
+
174
+ これにより「Kubernetes を学習・検証したいが、本格的なクラスタを用意するのは大変」という問題を解決できます。起動も破棄も速く、CI 環境での Kubernetes テストにも広く使われています。
175
+
176
+ ### クラスタの作成と削除
177
+
178
+ 最も基本的な使い方は次のとおりです(一般的な手順)。
179
+
180
+ ```bash
181
+ # 既定設定でクラスタを作成する
182
+ kind create cluster
183
+
184
+ # 名前を付けてクラスタを作成する(例)
185
+ kind create cluster --name dev
186
+
187
+ # 作成済みクラスタの一覧を表示する
188
+ kind get clusters
189
+
190
+ # クラスタを削除する(名前を付けた場合は --name で指定)
191
+ kind delete cluster --name dev
192
+ ```
193
+
194
+ `kind create cluster` を実行すると、kind が Docker コンテナとしてノードを起動し、`kubectl` の接続先(kubeconfig のコンテキスト)も自動的に設定します。作成後はそのまま `kubectl get nodes` などでクラスタを操作できます。
195
+
196
+ ### kind-config.yaml によるマルチノード構成
197
+
198
+ 既定では単一ノード(コントロールプレーン兼ワーカー)のクラスタになりますが、設定ファイルを渡すことで複数ノードのクラスタを構成できます。次は 1 つのコントロールプレーンと 2 つのワーカーノードを持つ構成の例です(一般的な例)。
199
+
200
+ ```text
201
+ # kind-config.yaml
202
+ kind: Cluster
203
+ apiVersion: kind.x-k8s.io/v1alpha4
204
+ nodes:
205
+ - role: control-plane
206
+ - role: worker
207
+ - role: worker
208
+ ```
209
+
210
+ この設定ファイルを指定してクラスタを作成します。
211
+
212
+ ```bash
213
+ # 設定ファイルを指定してマルチノードクラスタを作成する
214
+ kind create cluster --name multi --config kind-config.yaml
215
+ ```
216
+
217
+ 複数ノード構成にすると、Pod のスケジューリングやノード間の挙動を、本番に近い形でローカル検証できます。Kubernetes の基本概念については本編の第 5 章も参照してください。
218
+
219
+ > 注: 上記の kind-config.yaml と各コマンドは kind の一般的な使い方を示した例です。実際の `apiVersion` やノード設定は kind のバージョンによって異なる場合があります。
220
+
221
+ ---
222
+
223
+ ## A.4 Rancher Desktop
224
+
225
+ ### Rancher Desktop は何を解決するか
226
+
227
+ Rancher Desktop は、ローカルでコンテナと Kubernetes をまとめて動かせるデスクトップアプリケーションです。Docker Desktop の代替として利用でき、ライセンス面や軽量さを理由に選ばれることがあります。Windows・macOS・Linux に対応し、GUI からバージョンやランタイムを切り替えられます。
228
+
229
+ 「Docker Desktop に依存せずに、ローカルでコンテナと Kubernetes の両方を手軽に扱いたい」というニーズを解決するのが Rancher Desktop です。
230
+
231
+ ### コンテナランタイムの切り替え(containerd / dockerd)
232
+
233
+ Rancher Desktop の特徴の 1 つは、コンテナランタイムを切り替えられる点です。設定画面から次の 2 種類を選択できます。
234
+
235
+ - containerd — Kubernetes が標準的に利用するコンテナランタイム。Rancher Desktop では `nerdctl` という Docker 互換 CLI を通じてイメージのビルドやコンテナの実行を行います。
236
+ - dockerd(Moby) — 従来の Docker と同じランタイム。`docker` コマンドや `docker-compose` をそのまま使いたい場合に選択します。
237
+
238
+ 既存の `docker` コマンドや本編で扱った操作をそのまま使いたい場合は dockerd を、Kubernetes 寄りの運用に合わせたい場合は containerd を選ぶ、といった使い分けができます。
239
+
240
+ ### 内蔵 Kubernetes(k3s)
241
+
242
+ Rancher Desktop には軽量な Kubernetes ディストリビューションである k3s が内蔵されています。アプリの設定で Kubernetes を有効化すると、追加のインストールなしでローカル Kubernetes クラスタが起動し、`kubectl` で操作できるようになります。利用する Kubernetes のバージョンも GUI から選択できます。
243
+
244
+ Windows では、Rancher Desktop は WSL2 を基盤として動作します(A.1 を参照)。そのため、WSL2 が有効になっていることが前提になります。kind がクラスタを都度作成・破棄するのに対し、Rancher Desktop の k3s は「常駐するローカルクラスタ」として使える点が異なります。用途に応じて、kind と Rancher Desktop を使い分けるとよいでしょう。
245
+
246
+ > 注: ランタイムの切り替えや Kubernetes 有効化は Rancher Desktop の GUI から行う操作であり、画面構成はバージョンによって異なります。ここではコマンド出力の掲載は省略します。
247
+
248
+ ---
249
+
250
+ ## まとめ
251
+
252
+ 本付録では、Docker / Kubernetes を学習・開発するための周辺ツールを 4 つ紹介しました。それぞれが解決する課題を整理すると次のとおりです。
253
+
254
+ - WSL2 — Windows 上で Linux 環境を動かし、Linux 前提のツールチェーンや Docker をスムーズに利用できるようにする。
255
+ - asdf — `.tool-versions` で言語・ツールのバージョンを宣言的に固定し、チーム全体で同じ環境を再現する。本リポジトリの `apps/taskapp/.tool-versions` と `apps/taskapp/hack/install-tools.sh` がその実例である。
256
+ - kind — Docker さえあれば手元でマルチノードの Kubernetes クラスタを起動・破棄でき、学習や CI に適する。
257
+ - Rancher Desktop — Docker Desktop の代替として、containerd/dockerd の切り替えと内蔵 k3s により、ローカルでコンテナと Kubernetes をまとめて扱える。
258
+
259
+ これらのツールは排他的なものではなく、目的に応じて組み合わせて使えます。たとえば「Windows で WSL2 を基盤に Rancher Desktop を動かし、プロジェクトのツールは asdf で固定し、検証用クラスタは kind で立てる」といった構成も成り立ちます。自分の開発スタイルと、本編で学んだコンテナ・Kubernetes の知識に合わせて、必要なツールを選んでください。
260
+
261
+ ### 関連リンク
262
+
263
+ - [付録 B さまざまなコンテナオーケストレーション環境](appendix-b-orchestration-environments.md)
264
+ - [第 1 章 コンテナと Docker の基礎](01-container-and-docker-basics.md)
265
+ - [第 5 章 Kubernetes 入門](05-kubernetes-introduction.md)