@k2works/claude-code-booster 4.5.0 → 4.7.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.
- package/lib/assets/.claude/skills/creating-slides/SKILL.md +86 -0
- package/lib/assets/.claude/skills/creating-slides/agents/openai.yaml +4 -0
- package/lib/assets/.claude/skills/creating-slides/references/manga-css.md +45 -0
- package/lib/assets/.claude/skills/creating-slides/scripts/slide_tools.py +239 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/01-container-and-docker-basics.md +332 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/02-container-deployment.md +776 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/03-practical-container-build-deploy.md +457 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/04-multi-container-application.md +869 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/05-kubernetes-introduction.md +576 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/06-kubernetes-deploy-cluster.md +611 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/07-kubernetes-advanced.md +612 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/08-kubernetes-packaging.md +509 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/09-container-operations.md +537 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/10-optimal-container-image.md +631 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/11-continuous-delivery.md +598 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/12-container-use-cases.md +454 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/13-case-monolith-compose-vs-kustomize.md +337 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/14-case-event-driven-kustomize-vs-helm.md +315 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/15-case-escqrs-axon-kustomize-vs-helm.md +288 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/16-case-escqrs-kafka-kustomize-vs-helm.md +247 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/17-case-comparison-summary.md +132 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/18-case-load-testing.md +294 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/appendix-a-dev-tools-setup.md +265 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/appendix-b-orchestration-environments.md +521 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/appendix-c-tips.md +510 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-01-comic.png +0 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-02-comic.png +0 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-03-comic.png +0 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-04-comic.png +0 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-05-comic.png +0 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-06-comic.png +0 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-07-comic.png +0 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-08-comic.png +0 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-09-comic.png +0 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-10-comic.png +0 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-11-comic.png +0 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-12-comic.png +0 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/images/overview-comic.png +0 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/index.md +82 -0
- package/lib/assets/docs/article/getting-start-docker-kubernetes/outline.md +211 -0
- package/lib/assets/docs/article/index.md +3 -1
- package/lib/assets/mkdocs.yml +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
# 第 8 章 Kubernetes アプリケーションのパッケージング
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
*マニフェストを整理し、テンプレートと環境別の値で再利用できるリリース単位にまとめます。*
|
|
6
|
+
|
|
7
|
+
## はじめに
|
|
8
|
+
|
|
9
|
+
前章までで、Pod、Deployment、Service、Ingress、StatefulSet、Job といった Kubernetes のリソースを、素の YAML マニフェストとして記述しデプロイしてきました。小さなアプリケーションであれば、これらのマニフェストを `kubectl apply -f` で適用するだけで十分に運用できます。
|
|
10
|
+
|
|
11
|
+
しかし、アプリケーションが成長し、開発・ステージング・本番といった複数の環境で運用するようになると、素の YAML だけでは次のような問題に直面します。
|
|
12
|
+
|
|
13
|
+
- **マニフェストの重複**:環境ごとにマニフェスト一式をコピーすると、ほとんど同じ内容のファイルが何セットも生まれます。共通部分を修正するたびに、すべてのコピーに同じ変更を反映しなければなりません。
|
|
14
|
+
- **差分管理の難しさ**:環境間で本当に違うのは「レプリカ数」「イメージタグ」「ホスト名」「Service の種別」といったごく一部です。にもかかわらず、ファイル全体を複製してしまうと、どこが意図的な差分でどこが修正漏れなのかが見分けにくくなります。
|
|
15
|
+
- **再利用性の低さ**:同じ構成のアプリケーションを別のプロジェクトで使い回したいとき、素の YAML には「外から値を差し替える」仕組みがないため、結局コピーして書き換える作業を繰り返すことになります。
|
|
16
|
+
|
|
17
|
+
これらの問題を解決するのが、Kubernetes アプリケーションの **パッケージング** という考え方です。本章では、代表的な 2 つのツールを扱います。
|
|
18
|
+
|
|
19
|
+
- **Kustomize**:素の YAML を「base(共通の土台)」と「overlay(環境ごとの差分)」に分け、テンプレート言語を使わずに YAML をオーバーレイ(重ね合わせ)で合成します。`kubectl` に同梱されているため、追加インストールなしで使えます。
|
|
20
|
+
- **Helm**:マニフェストを Go テンプレートで記述し、`values.yaml` で値を差し替えながら 1 つの「チャート」としてパッケージ化します。バージョン管理されたアプリケーションの配布・インストールに強みがあります。
|
|
21
|
+
|
|
22
|
+
それでは、まず Kustomize から見ていきましょう。
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 8.1 Kustomize
|
|
27
|
+
|
|
28
|
+
Kustomize は、素の YAML マニフェストを **テンプレート化せずに** カスタマイズするためのツールです。Go テンプレートのような特別な構文を覚える必要はなく、有効な Kubernetes マニフェストをそのまま材料として扱います。中心となるのは `kustomization.yaml` というファイルで、ここに「どのマニフェストを集めるか」「どんな変換を加えるか」を宣言します。
|
|
29
|
+
|
|
30
|
+
### base 構造 — 共通の土台をまとめる
|
|
31
|
+
|
|
32
|
+
本書のサンプルアプリケーション taskapp では、`k8s/kustomize/base` ディレクトリにアプリケーション全体の土台となるマニフェストを配置しています(出典: `apps/taskapp/k8s/kustomize/base`)。
|
|
33
|
+
|
|
34
|
+
ルートの `kustomization.yaml` は、コンポーネントごとのサブディレクトリを `resources` として束ねます。
|
|
35
|
+
|
|
36
|
+
```yaml
|
|
37
|
+
# apps/taskapp/k8s/kustomize/base/kustomization.yaml
|
|
38
|
+
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
39
|
+
kind: Kustomization
|
|
40
|
+
|
|
41
|
+
namespace: taskapp
|
|
42
|
+
|
|
43
|
+
resources:
|
|
44
|
+
- ./mysql
|
|
45
|
+
- ./migrator
|
|
46
|
+
- ./api
|
|
47
|
+
- ./web
|
|
48
|
+
|
|
49
|
+
commonLabels:
|
|
50
|
+
app.kubernetes.io/name: taskapp
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
ここで使われているフィールドの意味は次のとおりです。
|
|
54
|
+
|
|
55
|
+
- **`namespace`**:このセットに含まれるすべてのリソースを、指定した名前空間(ここでは `taskapp`)に配置します。マニフェスト 1 枚ごとに `metadata.namespace` を書く必要がありません。
|
|
56
|
+
- **`resources`**:合成の対象とするマニフェスト、または別の `kustomization.yaml` を持つディレクトリを列挙します。この例では `mysql`・`migrator`・`api`・`web` という 4 つのコンポーネントを参照しています。
|
|
57
|
+
- **`commonLabels`**:列挙したすべてのリソースに共通のラベル(`app.kubernetes.io/name: taskapp`)を付与します。selector やラベルの付け忘れを防げます。
|
|
58
|
+
|
|
59
|
+
### コンポーネントごとの kustomization
|
|
60
|
+
|
|
61
|
+
`resources` で参照される各コンポーネントも、それぞれ `kustomization.yaml` を持ちます。たとえば API コンポーネントは次のようになっています。
|
|
62
|
+
|
|
63
|
+
```yaml
|
|
64
|
+
# apps/taskapp/k8s/kustomize/base/api/kustomization.yaml
|
|
65
|
+
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
66
|
+
kind: Kustomization
|
|
67
|
+
|
|
68
|
+
secretGenerator:
|
|
69
|
+
- name: api-config
|
|
70
|
+
files:
|
|
71
|
+
- api-config.yaml=./api-config.yaml
|
|
72
|
+
type: Opaque
|
|
73
|
+
|
|
74
|
+
resources:
|
|
75
|
+
- deployment.yaml
|
|
76
|
+
- service.yaml
|
|
77
|
+
|
|
78
|
+
commonLabels:
|
|
79
|
+
app.kubernetes.io/component: api
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
ここでは Deployment と Service という素の YAML を `resources` で束ねつつ、`app.kubernetes.io/component: api` というコンポーネント固有のラベルを追加しています。ルートとコンポーネントの両方で `commonLabels` を使うことで、`app.kubernetes.io/name`(アプリケーション全体)と `app.kubernetes.io/component`(構成要素)が階層的に付与される仕組みです。
|
|
83
|
+
|
|
84
|
+
さらに注目したいのが **`secretGenerator`** です。これは Secret マニフェストを手書きするのではなく、ファイルの中身から Secret を自動生成する機能です。`files` に指定したファイル(`api-config.yaml`)を読み込み、`api-config` という名前の `Opaque` 型 Secret を作り出します。
|
|
85
|
+
|
|
86
|
+
データベース系のコンポーネントでも同じ仕組みが使われています。
|
|
87
|
+
|
|
88
|
+
```yaml
|
|
89
|
+
# apps/taskapp/k8s/kustomize/base/mysql/kustomization.yaml
|
|
90
|
+
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
91
|
+
kind: Kustomization
|
|
92
|
+
|
|
93
|
+
secretGenerator:
|
|
94
|
+
- name: mysql
|
|
95
|
+
files:
|
|
96
|
+
- root_password=./secrets/mysql_root_password
|
|
97
|
+
- user_password=./secrets/mysql_user_password
|
|
98
|
+
type: Opaque
|
|
99
|
+
|
|
100
|
+
resources:
|
|
101
|
+
- service.yaml
|
|
102
|
+
- statefulset.yaml
|
|
103
|
+
|
|
104
|
+
commonLabels:
|
|
105
|
+
app.kubernetes.io/component: mysql
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
`root_password=./secrets/mysql_root_password` のように `キー=ファイルパス` の形で書くと、Secret 内のキー名とファイルを対応づけられます。パスワードのような秘匿情報を YAML に直書きせず、別ファイルとして管理できるのが利点です。
|
|
109
|
+
|
|
110
|
+
なお `secretGenerator` で生成される Secret には、内容のハッシュ値が名前のサフィックスとして付与されます。中身が変わると Secret 名も変わるため、Secret を参照する Deployment が自動的に再起動され、設定変更が確実に反映されます。
|
|
111
|
+
|
|
112
|
+
migrator コンポーネントは、データベースのマイグレーションを実行する Job をまとめています。
|
|
113
|
+
|
|
114
|
+
```yaml
|
|
115
|
+
# apps/taskapp/k8s/kustomize/base/migrator/kustomization.yaml
|
|
116
|
+
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
117
|
+
kind: Kustomization
|
|
118
|
+
|
|
119
|
+
secretGenerator:
|
|
120
|
+
- name: migrator
|
|
121
|
+
files:
|
|
122
|
+
- root_password=./secrets/mysql_root_password
|
|
123
|
+
- user_password=./secrets/mysql_user_password
|
|
124
|
+
type: Opaque
|
|
125
|
+
|
|
126
|
+
resources:
|
|
127
|
+
- job.yaml
|
|
128
|
+
|
|
129
|
+
commonLabels:
|
|
130
|
+
app.kubernetes.io/component: migrator
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
このように Kustomize では、アプリケーションを「コンポーネント単位の小さな `kustomization.yaml`」に分解し、それらをルートの `kustomization.yaml` が束ねる、という入れ子の構造を作れます。各コンポーネントは独立して理解・修正でき、全体は 1 コマンドで合成できます。
|
|
134
|
+
|
|
135
|
+
### kubectl kustomize で合成結果を確認する
|
|
136
|
+
|
|
137
|
+
`kustomization.yaml` がどんなマニフェストに展開されるかは、`kubectl kustomize` で確認できます。このコマンドはクラスタには何も適用せず、合成結果を標準出力に表示するだけなので安全です。
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
# base 全体を合成して結果を表示する(クラスタには適用しない)
|
|
141
|
+
kubectl kustomize apps/taskapp/k8s/kustomize/base
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
出力には、`namespace: taskapp` が各リソースに設定され、`commonLabels` が反映され、`secretGenerator` から生成された Secret が含まれた、完成形のマニフェストが並びます。適用前にこのコマンドで差分を目視確認することを習慣にすると、意図しない変更を防げます。
|
|
145
|
+
|
|
146
|
+
### kubectl apply -k でデプロイする
|
|
147
|
+
|
|
148
|
+
合成結果に問題がなければ、`-k` オプションでそのままクラスタへ適用します。`-k` は「kustomize ディレクトリを対象にする」という意味で、`-f`(単一ファイル)と対になるオプションです。
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
# kustomization.yaml を解釈してクラスタに適用する
|
|
152
|
+
kubectl apply -k apps/taskapp/k8s/kustomize/base
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
内部的には `kubectl kustomize` で合成した結果を `kubectl apply` に渡すのと同じ動作になります。削除したい場合は `kubectl delete -k` を使います。
|
|
156
|
+
|
|
157
|
+
### overlay — 環境ごとの差分を重ねる
|
|
158
|
+
|
|
159
|
+
「はじめに」で述べた重複の問題は、Kustomize の **base / overlay** という考え方で解決します。共通部分を `base` に置き、環境固有の差分だけを `overlay` 側の `kustomization.yaml` に記述します。overlay は `resources`(または `bases`)で base を参照し、その上に変換を重ねます。
|
|
160
|
+
|
|
161
|
+
GitOps のブートストラップ用に用意された echo-bootstrap は、overlay 的に base を参照して上書きする良い例です(出典: `apps/cd/echo-bootstrap/kustomization.yaml`)。
|
|
162
|
+
|
|
163
|
+
```yaml
|
|
164
|
+
# echo-bootstrap/kustomization.yaml
|
|
165
|
+
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
166
|
+
kind: Kustomization
|
|
167
|
+
namespace: gitops-echo
|
|
168
|
+
resources:
|
|
169
|
+
- namespace.yaml
|
|
170
|
+
- deployment.yaml
|
|
171
|
+
- ingress.yaml
|
|
172
|
+
- service.yaml
|
|
173
|
+
commonLabels:
|
|
174
|
+
app.kubernetes.io/name: echo
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
ここでは `namespace: gitops-echo` を指定することで、同じ deployment.yaml・service.yaml を別の名前空間向けに展開できます。base のマニフェストを一切書き換えずに、overlay の `kustomization.yaml` だけで配置先を切り替えられる点が、複製とは決定的に異なります。
|
|
178
|
+
|
|
179
|
+
### namePrefix と images — 名前とイメージを変換する
|
|
180
|
+
|
|
181
|
+
overlay でよく使われる変換に、`namePrefix` と `images` があります。argocd のサンプルにある kustomize-guestbook は、`namePrefix` の最小例です(出典: `apps/cd/argocd-example-apps/kustomize-guestbook`)。
|
|
182
|
+
|
|
183
|
+
```yaml
|
|
184
|
+
# argocd-example-apps/kustomize-guestbook/kustomization.yaml
|
|
185
|
+
namePrefix: kustomize-
|
|
186
|
+
|
|
187
|
+
resources:
|
|
188
|
+
- guestbook-ui-deployment.yaml
|
|
189
|
+
- guestbook-ui-svc.yaml
|
|
190
|
+
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
191
|
+
kind: Kustomization
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
`namePrefix: kustomize-` を指定すると、参照したすべてのリソース名の先頭に `kustomize-` が付きます。対象の Deployment は次のように `guestbook-ui` という名前を持っていますが、
|
|
195
|
+
|
|
196
|
+
```yaml
|
|
197
|
+
# argocd-example-apps/kustomize-guestbook/guestbook-ui-deployment.yaml
|
|
198
|
+
apiVersion: apps/v1
|
|
199
|
+
kind: Deployment
|
|
200
|
+
metadata:
|
|
201
|
+
name: guestbook-ui
|
|
202
|
+
spec:
|
|
203
|
+
replicas: 1
|
|
204
|
+
revisionHistoryLimit: 3
|
|
205
|
+
selector:
|
|
206
|
+
matchLabels:
|
|
207
|
+
app: guestbook-ui
|
|
208
|
+
template:
|
|
209
|
+
metadata:
|
|
210
|
+
labels:
|
|
211
|
+
app: guestbook-ui
|
|
212
|
+
spec:
|
|
213
|
+
containers:
|
|
214
|
+
- image: gcr.io/heptio-images/ks-guestbook-demo:0.1
|
|
215
|
+
name: guestbook-ui
|
|
216
|
+
ports:
|
|
217
|
+
- containerPort: 80
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
`namePrefix` を適用すると、`guestbook-ui` は `kustomize-guestbook-ui` という名前で生成されます。selector のラベルとの整合性も Kustomize が自動で面倒を見てくれるため、同じ base を複数 overlay で並行デプロイしても名前が衝突しません。
|
|
221
|
+
|
|
222
|
+
実運用の overlay では、これに加えてコンテナイメージのタグを差し替える `images` フィールドがよく使われます。`images` を使うと、マニフェスト本体の `image:` 行を書き換えずに、overlay 側でタグやリポジトリを上書きできます(例)。
|
|
223
|
+
|
|
224
|
+
```yaml
|
|
225
|
+
# overlay 側の kustomization.yaml でイメージタグを差し替える例
|
|
226
|
+
images:
|
|
227
|
+
- name: gcr.io/heptio-images/ks-guestbook-demo
|
|
228
|
+
newTag: "0.2"
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
このように `namespace`・`namePrefix`・`commonLabels`・`images` といった変換を overlay に集約することで、「base は触らず、環境差分だけを宣言する」という運用が成立します。これが Kustomize による重複・差分管理問題の解決策です。
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## 8.2 Helm
|
|
236
|
+
|
|
237
|
+
Helm は、Kubernetes アプリケーションを **チャート(Chart)** という単位でパッケージ化するためのツールです。Kustomize がテンプレートを使わずに YAML を重ね合わせるのに対し、Helm は **Go テンプレート** でマニフェストを記述し、`values.yaml` で与えた値を埋め込んで最終的なマニフェストを生成します。バージョン管理されたアプリケーションを配布・インストール・アップグレードする用途に適しています。
|
|
238
|
+
|
|
239
|
+
ここでは argocd のサンプルにある helm-guestbook を題材に、チャートの構造を見ていきます(出典: `apps/cd/argocd-example-apps/helm-guestbook`)。チャートは次のようなファイル構成です。
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
helm-guestbook/
|
|
243
|
+
├── Chart.yaml # チャートのメタデータ
|
|
244
|
+
├── values.yaml # デフォルトの値
|
|
245
|
+
├── values-production.yaml # 本番環境向けに差し替える値
|
|
246
|
+
└── templates/ # Go テンプレート化したマニフェスト群
|
|
247
|
+
├── deployment.yaml
|
|
248
|
+
├── service.yaml
|
|
249
|
+
├── _helpers.tpl
|
|
250
|
+
└── NOTES.txt
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Chart.yaml — チャートのメタデータ
|
|
254
|
+
|
|
255
|
+
`Chart.yaml` には、チャートの名前やバージョンといったメタデータを記述します。
|
|
256
|
+
|
|
257
|
+
```yaml
|
|
258
|
+
# argocd-example-apps/helm-guestbook/Chart.yaml
|
|
259
|
+
apiVersion: v2
|
|
260
|
+
name: helm-guestbook
|
|
261
|
+
description: A Helm chart for Kubernetes
|
|
262
|
+
type: application
|
|
263
|
+
version: 0.1.0
|
|
264
|
+
appVersion: "1.0"
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
各フィールドの意味は次のとおりです。
|
|
268
|
+
|
|
269
|
+
- **`apiVersion: v2`**:Helm 3 系のチャート形式であることを示します。
|
|
270
|
+
- **`name`**:チャートの名前です。
|
|
271
|
+
- **`type: application`**:デプロイ可能なアプリケーションチャートであることを示します(再利用ライブラリの場合は `library`)。
|
|
272
|
+
- **`version`**:チャート自体のバージョンです。テンプレートや構成を変更するたびにインクリメントします。セマンティックバージョニングに従います。
|
|
273
|
+
- **`appVersion`**:パッケージされているアプリケーション本体のバージョンです。チャートのバージョンとは独立して管理されます。
|
|
274
|
+
|
|
275
|
+
なお、チャートは `helm package` コマンドで `名前-バージョン.tgz` という単一のアーカイブにまとめられます。本書のサンプルにある `gihyo-docker-kuberbetes/ch07/echo-0.1.0.tgz` は、まさにこの形式でパッケージ化された echo チャートです(出典: `gihyo-docker-kuberbetes/ch07`)。`.tgz` 1 つでチャートを配布・共有できるのが Helm の特徴です。
|
|
276
|
+
|
|
277
|
+
### values.yaml — デフォルトの値
|
|
278
|
+
|
|
279
|
+
`values.yaml` には、テンプレートに埋め込むデフォルト値を定義します。
|
|
280
|
+
|
|
281
|
+
```yaml
|
|
282
|
+
# argocd-example-apps/helm-guestbook/values.yaml
|
|
283
|
+
replicaCount: 1
|
|
284
|
+
|
|
285
|
+
image:
|
|
286
|
+
repository: gcr.io/heptio-images/ks-guestbook-demo
|
|
287
|
+
tag: 0.1
|
|
288
|
+
pullPolicy: IfNotPresent
|
|
289
|
+
|
|
290
|
+
containerPort: 80
|
|
291
|
+
|
|
292
|
+
service:
|
|
293
|
+
type: ClusterIP
|
|
294
|
+
port: 80
|
|
295
|
+
|
|
296
|
+
ingress:
|
|
297
|
+
enabled: false
|
|
298
|
+
path: /
|
|
299
|
+
hosts:
|
|
300
|
+
- chart-example.local
|
|
301
|
+
tls: []
|
|
302
|
+
|
|
303
|
+
resources: {}
|
|
304
|
+
nodeSelector: {}
|
|
305
|
+
tolerations: []
|
|
306
|
+
affinity: {}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
レプリカ数・イメージ・Service の種別・Ingress の有効化など、環境によって変わりうる値がここに集約されています。テンプレート本体には値を直書きせず、すべてこの `values.yaml` を経由して与えるのが Helm の基本方針です。
|
|
310
|
+
|
|
311
|
+
### templates/ — Go テンプレートで値を展開する
|
|
312
|
+
|
|
313
|
+
`templates/` 配下のマニフェストは Go テンプレートで書かれており、`{{ .Values.xxx }}` の形で `values.yaml` の値を参照します。Deployment を見てみましょう。
|
|
314
|
+
|
|
315
|
+
```yaml
|
|
316
|
+
# argocd-example-apps/helm-guestbook/templates/deployment.yaml
|
|
317
|
+
apiVersion: apps/v1
|
|
318
|
+
kind: Deployment
|
|
319
|
+
metadata:
|
|
320
|
+
name: {{ template "helm-guestbook.fullname" . }}
|
|
321
|
+
labels:
|
|
322
|
+
app: {{ template "helm-guestbook.name" . }}
|
|
323
|
+
chart: {{ template "helm-guestbook.chart" . }}
|
|
324
|
+
release: {{ .Release.Name }}
|
|
325
|
+
heritage: {{ .Release.Service }}
|
|
326
|
+
spec:
|
|
327
|
+
replicas: {{ .Values.replicaCount }}
|
|
328
|
+
revisionHistoryLimit: 3
|
|
329
|
+
selector:
|
|
330
|
+
matchLabels:
|
|
331
|
+
app: {{ template "helm-guestbook.name" . }}
|
|
332
|
+
release: {{ .Release.Name }}
|
|
333
|
+
template:
|
|
334
|
+
metadata:
|
|
335
|
+
labels:
|
|
336
|
+
app: {{ template "helm-guestbook.name" . }}
|
|
337
|
+
release: {{ .Release.Name }}
|
|
338
|
+
spec:
|
|
339
|
+
containers:
|
|
340
|
+
- name: {{ .Chart.Name }}
|
|
341
|
+
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
|
342
|
+
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
|
343
|
+
ports:
|
|
344
|
+
- name: http
|
|
345
|
+
containerPort: {{ .Values.containerPort }}
|
|
346
|
+
protocol: TCP
|
|
347
|
+
livenessProbe:
|
|
348
|
+
httpGet:
|
|
349
|
+
path: /
|
|
350
|
+
port: http
|
|
351
|
+
readinessProbe:
|
|
352
|
+
httpGet:
|
|
353
|
+
path: /
|
|
354
|
+
port: http
|
|
355
|
+
resources:
|
|
356
|
+
{{ toYaml .Values.resources | indent 12 }}
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
注目すべき記法を整理します。
|
|
360
|
+
|
|
361
|
+
- **`{{ .Values.replicaCount }}`**:`values.yaml` の `replicaCount` を埋め込みます。`replicas` の値がテンプレートではなく値ファイル側で決まります。
|
|
362
|
+
- **`"{{ .Values.image.repository }}:{{ .Values.image.tag }}"`**:リポジトリとタグを連結して `image` 文字列を組み立てます。
|
|
363
|
+
- **`{{ .Release.Name }}` / `{{ .Release.Service }}`**:`helm install` 時に決まる「リリース名」などの組み込みオブジェクトを参照します。
|
|
364
|
+
- **`{{ template "helm-guestbook.fullname" . }}`**:`_helpers.tpl` で定義した名前付きテンプレートを呼び出します。
|
|
365
|
+
- **`{{ toYaml .Values.resources | indent 12 }}`**:`resources` のような構造化された値を YAML に変換し、12 スペースのインデントを付けて差し込みます。
|
|
366
|
+
|
|
367
|
+
Service も同様に値で組み立てられます。`type` が `values.yaml` から渡される点に注目してください。
|
|
368
|
+
|
|
369
|
+
```yaml
|
|
370
|
+
# argocd-example-apps/helm-guestbook/templates/service.yaml
|
|
371
|
+
apiVersion: v1
|
|
372
|
+
kind: Service
|
|
373
|
+
metadata:
|
|
374
|
+
name: {{ template "helm-guestbook.fullname" . }}
|
|
375
|
+
labels:
|
|
376
|
+
app: {{ template "helm-guestbook.name" . }}
|
|
377
|
+
chart: {{ template "helm-guestbook.chart" . }}
|
|
378
|
+
release: {{ .Release.Name }}
|
|
379
|
+
heritage: {{ .Release.Service }}
|
|
380
|
+
spec:
|
|
381
|
+
type: {{ .Values.service.type }}
|
|
382
|
+
ports:
|
|
383
|
+
- port: {{ .Values.service.port }}
|
|
384
|
+
targetPort: http
|
|
385
|
+
protocol: TCP
|
|
386
|
+
name: http
|
|
387
|
+
selector:
|
|
388
|
+
app: {{ template "helm-guestbook.name" . }}
|
|
389
|
+
release: {{ .Release.Name }}
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### _helpers.tpl と NOTES.txt
|
|
393
|
+
|
|
394
|
+
`_helpers.tpl` は、複数のテンプレートから再利用する「名前付きテンプレート」を定義する場所です。たとえばリソース名を組み立てる `helm-guestbook.fullname` は次のように定義されています。
|
|
395
|
+
|
|
396
|
+
```yaml
|
|
397
|
+
# argocd-example-apps/helm-guestbook/templates/_helpers.tpl(抜粋)
|
|
398
|
+
{{- define "helm-guestbook.fullname" -}}
|
|
399
|
+
{{- if .Values.fullnameOverride -}}
|
|
400
|
+
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
|
|
401
|
+
{{- else -}}
|
|
402
|
+
{{- $name := default .Chart.Name .Values.nameOverride -}}
|
|
403
|
+
{{- if contains $name .Release.Name -}}
|
|
404
|
+
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
|
|
405
|
+
{{- else -}}
|
|
406
|
+
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
|
|
407
|
+
{{- end -}}
|
|
408
|
+
{{- end -}}
|
|
409
|
+
{{- end -}}
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
リリース名とチャート名を組み合わせ、DNS 名の上限である 63 文字に切り詰める処理が共通化されています。これにより、各テンプレートは `{{ template "helm-guestbook.fullname" . }}` と書くだけで一貫した命名規則を共有できます。
|
|
413
|
+
|
|
414
|
+
`NOTES.txt` は、インストール完了後にユーザーへ表示される案内文です。これもテンプレートなので、Service の種別に応じてアクセス方法を出し分けられます(出典: `helm-guestbook/templates/NOTES.txt`)。`ClusterIP` の場合は `kubectl port-forward` の手順を、`LoadBalancer` の場合は外部 IP の確認方法を案内する、といった条件分岐が組み込まれています。
|
|
415
|
+
|
|
416
|
+
### values-production.yaml — 環境ごとに値を差し替える
|
|
417
|
+
|
|
418
|
+
Helm では、デフォルトの `values.yaml` に対して、環境固有の値だけを別ファイルで上書きできます。helm-guestbook の本番向け値ファイルは、驚くほど短い内容です。
|
|
419
|
+
|
|
420
|
+
```yaml
|
|
421
|
+
# argocd-example-apps/helm-guestbook/values-production.yaml
|
|
422
|
+
service:
|
|
423
|
+
type: LoadBalancer
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
デフォルトでは `service.type` は `ClusterIP` ですが、本番ではこのファイルを重ねることで `LoadBalancer` に変わります。差分はこの 2 行だけで、それ以外の値はすべて `values.yaml` のものが使われます。「環境ごとに変えたい値だけを最小限の差分として書く」という、Kustomize の overlay と同じ思想がここにも表れています。
|
|
427
|
+
|
|
428
|
+
本書のサンプルにある echo チャートの値ファイルも同様で、Ingress を有効にしてホスト名を与えるだけのものです(出典: `gihyo-docker-kuberbetes/ch07/echo.yaml`)。
|
|
429
|
+
|
|
430
|
+
```yaml
|
|
431
|
+
# gihyo-docker-kuberbetes/ch07/echo.yaml
|
|
432
|
+
ingress:
|
|
433
|
+
enabled: true
|
|
434
|
+
hosts:
|
|
435
|
+
- ch06-echo.gihyo.local
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
### helm template / install / upgrade の使い方
|
|
439
|
+
|
|
440
|
+
Helm の代表的なコマンドを、用途別に整理します。
|
|
441
|
+
|
|
442
|
+
```bash
|
|
443
|
+
# 値を埋め込んだ最終マニフェストを表示する(クラスタには適用しない)
|
|
444
|
+
helm template my-guestbook ./helm-guestbook
|
|
445
|
+
|
|
446
|
+
# 本番向けの値ファイルを重ねて結果を確認する
|
|
447
|
+
helm template my-guestbook ./helm-guestbook -f ./helm-guestbook/values-production.yaml
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
`helm template` は Kustomize の `kubectl kustomize` に相当し、テンプレートの展開結果を手元で確認するためのコマンドです。クラスタには触れないため、レビューや CI でのチェックに使えます。
|
|
451
|
+
|
|
452
|
+
実際にクラスタへインストールするには `helm install` を使います。第 1 引数がリリース名、第 2 引数がチャートのパスです。
|
|
453
|
+
|
|
454
|
+
```bash
|
|
455
|
+
# my-guestbook というリリース名でチャートをインストールする
|
|
456
|
+
helm install my-guestbook ./helm-guestbook
|
|
457
|
+
|
|
458
|
+
# 本番向けの値で個別の値を上書きしてインストールする
|
|
459
|
+
helm install my-guestbook ./helm-guestbook -f ./helm-guestbook/values-production.yaml
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
`-f` で値ファイルを、`--set service.type=LoadBalancer` のように `--set` で個別の値を、コマンドラインから上書きできます。インストール後にチャートや値を変更したい場合は `helm upgrade` を使います。
|
|
463
|
+
|
|
464
|
+
```bash
|
|
465
|
+
# リリースを新しいチャート・値で更新する
|
|
466
|
+
helm upgrade my-guestbook ./helm-guestbook -f ./helm-guestbook/values-production.yaml
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
Helm はインストールごとに「リリース」を記録するため、`helm upgrade` での変更履歴を追跡でき、必要なら以前の状態へロールバックすることも可能です。これがバージョン管理されたパッケージとしての Helm の強みです。
|
|
470
|
+
|
|
471
|
+
---
|
|
472
|
+
|
|
473
|
+
## Kustomize と Helm の使い分け
|
|
474
|
+
|
|
475
|
+
Kustomize と Helm はどちらも「環境差分を最小限の記述で管理する」という同じ問題を解きますが、アプローチが異なります。両者の特徴を比較すると次のとおりです。
|
|
476
|
+
|
|
477
|
+
| 観点 | Kustomize | Helm |
|
|
478
|
+
| :--- | :--- | :--- |
|
|
479
|
+
| テンプレート | 使わない(素の YAML を重ね合わせる) | Go テンプレートで記述する |
|
|
480
|
+
| 値の差し替え方 | overlay の `kustomization.yaml`(`namespace`・`namePrefix`・`images` 等) | `values.yaml` / `values-production.yaml` / `--set` |
|
|
481
|
+
| 環境差分の表現 | base / overlay | デフォルト値 + 環境別 values ファイル |
|
|
482
|
+
| 学習コスト | 低い(YAML の知識があればよい) | やや高い(テンプレート構文を覚える必要がある) |
|
|
483
|
+
| 導入の手軽さ | `kubectl` に同梱(追加インストール不要) | 別途 `helm` のインストールが必要 |
|
|
484
|
+
| パッケージ配布 | ディレクトリ単位(チャートのような単一アーカイブはない) | `.tgz` 形式で配布・共有できる |
|
|
485
|
+
| バージョン管理・ロールバック | 仕組みなし(Git 等に委ねる) | リリース履歴を持ち `helm rollback` 可能 |
|
|
486
|
+
| 向いている場面 | 自分たちのアプリを環境別に管理する | サードパーティ製アプリの配布・再利用 |
|
|
487
|
+
|
|
488
|
+
大まかな指針としては、次のように考えると選びやすくなります。
|
|
489
|
+
|
|
490
|
+
- **自分たちが開発しているアプリケーションを、シンプルに環境別管理したい** → Kustomize。テンプレートを学ぶコストがなく、`kubectl` だけで完結します。
|
|
491
|
+
- **配布や再利用、バージョン管理を伴うパッケージにしたい** → Helm。OSS のミドルウェアの多くは Helm チャートとして公開されており、エコシステムが充実しています。
|
|
492
|
+
|
|
493
|
+
なお、両者は排他的ではありません。Helm でレンダリングした結果に Kustomize で最終調整を加えるなど、組み合わせて使うこともできます。まずはそれぞれの考え方を理解し、プロジェクトの規模と配布要件に応じて選択するとよいでしょう。
|
|
494
|
+
|
|
495
|
+
---
|
|
496
|
+
|
|
497
|
+
## まとめ
|
|
498
|
+
|
|
499
|
+
本章では、Kubernetes アプリケーションのパッケージング手法として Kustomize と Helm を学びました。
|
|
500
|
+
|
|
501
|
+
- 素の YAML を環境ごとに複製すると、重複・差分管理・再利用性の問題が生じます。パッケージングはこれを「共通部分」と「環境差分」に分離することで解決します。
|
|
502
|
+
- **Kustomize** は、テンプレートを使わずに `kustomization.yaml` で YAML を重ね合わせます。`resources`・`namespace`・`commonLabels`・`secretGenerator`・`namePrefix`・`images` といったフィールドで base に変換を加え、`kubectl kustomize` で結果を確認し、`kubectl apply -k` で適用します。
|
|
503
|
+
- **Helm** は、Go テンプレート化したマニフェストを `values.yaml` で組み立て、チャートとしてパッケージ化します。`Chart.yaml` でメタデータを管理し、`values-production.yaml` で環境差分を最小限に表現し、`helm template`・`helm install`・`helm upgrade` で展開・適用・更新します。
|
|
504
|
+
- 両者は「テンプレートの有無」「学習コスト」「エコシステム」で性格が異なります。自分たちのアプリの環境別管理には Kustomize、配布・再利用・バージョン管理を伴うパッケージには Helm が向いています。
|
|
505
|
+
|
|
506
|
+
パッケージングを導入することで、マニフェストは「変更を楽に安全にできる」状態に近づきます。これは継続的なデリバリーの土台でもあります。
|
|
507
|
+
|
|
508
|
+
- 前の章: [第 7 章 Kubernetes の発展的な利用](07-kubernetes-advanced.md)
|
|
509
|
+
- 次の章: [第 9 章 コンテナの運用](09-container-operations.md)
|