Helm と Kustomize の違い
v1.37 時点(2026年10月26日 確認)
目次
この記事ではマニフェストを環境ごとに組み立てて管理する 2 つのツール Helm と Kustomize の違いを、図で説明します。同じアプリケーションを開発用(dev)と本番用(prod)で少しずつ変えて動かすときに、Helm はテンプレートに値を埋め込み、Kustomize は元のマニフェストにパッチ(変えたい部分だけを書いた小さなマニフェストなど)を重ねる、という違いがわかります。Helm が持つリリースの履歴とロールバックの仕組みもわかります。後半では kind のクラスタで、第12回の nginx の Deployment を 2 つのツールで dev と prod の Namespace にデプロイし、組み立てたマニフェストと履歴を比べる手順を示します。
第12回の Deployment のマニフェストを前提にしています。第37回で扱った、Namespace で置き場所を分ける考え方も使います。まだの方は先にこちらをどうぞ。
Deployment とローリングアップデートの仕組みReplicaSet を持ち、Pod を宣言的に更新する Deployment の仕組みを図で説明します。ひな形を変えたときに新しい ReplicaSet へ Pod を少しずつ移すローリングアップデート、pod-template-hash の役割、リビジョンと切り戻しを押さえ、kind のクラスタでイメージを更新して rollout undo で戻す手順を紹介します。以下の図は同じ nginx を dev の Namespace にデプロイするときに、Kustomize と Helm がそれぞれ何を材料にするかを表しています。後半の手順で作るファイルと名前を例にしています。
Kustomize は元になる base のマニフェストに、dev 用の overlay で違う部分だけを重ねます。Helm は値の入る場所を書いたチャートのテンプレートに、dev 用の values を埋めます。どちらも最後は Deployment になりますが、Helm は Deployment のほかに、既定ではリリースの記録を同じ Namespace の Secret に残します。この記録が Helm の履歴とロールバックのもとになります。
参考:Declarative Management of Kubernetes Objects Using Kustomize | Kubernetes、Introduction to Helm | Helm、Advanced Helm Techniques | Helm
Helm と Kustomize とは
Kustomize は kustomization ファイルを使って Kubernetes のオブジェクトをカスタマイズする、単体のツール です。Kubernetes の公式ドキュメントは Kustomize の機能を次の 3 つにまとめています。
- ほかの材料(ファイルや文字列)からリソースを作る
- すべてのリソースに共通のフィールドを付ける
- リソースの集まりを組み合わせて、カスタマイズする
Kubernetes 1.14 からは、kubectl も kustomization ファイルでオブジェクトを管理できます。kustomization ファイルのあるディレクトリから組み立てたリソースを表示するのが kubectl kustomize、そのリソースをクラスタに反映するのが kubectl apply -k です。そのため Kustomize は、kubectl があれば別に入れなくても使えます。
参考:Declarative Management of Kubernetes Objects Using Kustomize | Kubernetes
Helm は Kubernetes のパッケージマネージャー(アプリケーションを入れる、更新する、消すをまとめて行う道具。第2回の Homebrew の Kubernetes 版のようなもの)で、アプリケーションを Kubernetes のクラスタに定義し、入れ、更新するのを助けるツール です。Helm の公式ドキュメントによると、Helm は手元のマシンで動くコマンドラインのツールで、Kubernetes の API サーバー(kube-apiserver)と通信します。Helm は Kubernetes の公式ドキュメントの外のプロジェクトなので、この回では Helm の仕組みを Helm の公式ドキュメントで確かめます。
この回に出てくる言葉を、次の表にまとめます。どれも「Helm と Kustomize の仕組み」で詳しく説明します。
| 言葉 | ツール | 意味 |
|---|---|---|
| kustomization ファイル | Kustomize | 組み立て方を書いた kustomization.yaml。使うマニフェストと、重ねる変更を書く |
| base | Kustomize | kustomization.yaml とリソースを置いたディレクトリ。共通の元になる |
| overlay | Kustomize | base を参照し、その上に変更を重ねる kustomization.yaml のディレクトリ |
| チャート(chart) | Helm | Helm のパッケージ。アプリケーションを動かすのに要るリソースの定義をすべて含む |
| values | Helm | チャートのテンプレートに埋める値の集まり。ふつうは values.yaml に書く |
| リリース(release) | Helm | クラスタで動いているチャートの実体。入れるたびに 1 つでき、名前が付く |
参考:Declarative Management of Kubernetes Objects Using Kustomize | Kubernetes、Introduction to Helm | Helm
なぜ Helm や Kustomize が必要なのか
第12回の nginx の Deployment を、dev と prod の 2 つの環境で動かす場面を考えます。dev では Pod を 1 つにして新しいタグ 1.16.1 を試し、prod では Pod を 3 つにして 1.14.2 のまま動かしたいとします。タグは第12回で見た、イメージの名前の : の後ろに付けてバージョンを見分けるものです。
いちばん素直なやり方はマニフェストを環境の数だけコピーして、それぞれを書き換えることです。ただし、このやり方では 2 つのファイルのほとんどが同じ内容になります。共通の部分を直すときは両方を直す必要があり、片方だけ直し忘れると、意図しない違いが環境のあいだに生まれると考えられます。
2 つのツールはどちらもこの問題を扱います。Kustomize の README は開発・ステージング・本番のような設定の違い(variants)を、共通の base に変更を重ねる overlay で管理する、と説明しています。Helm の公式ドキュメントも、同じチャートに違う values を渡せば、マニフェストを複製せずに開発・ステージング・本番にデプロイできるとしています。
参考:kubernetes-sigs/kustomize(README)、Introduction to Helm | Helm
Helm にはもう 1 つ、パッケージを配る役目があります。Helm の公式ドキュメントはデータベースや監視の仕組みのような既製のアプリケーションを、マニフェストを自分で組み立てずにチャートから入れられると説明しています。チャートは、チャートを集めて共有する場所(チャートのリポジトリ)で配られます。たとえば第35回では metrics-server を components.yaml で入れましたが、metrics-server の README によると、metrics-server は YAML のマニフェストからでも、公式の Helm のチャートからでも入れられます。この回では手元のディレクトリに書いたチャートだけを使います。
参考:Introduction to Helm | Helm、Introduction to Helm | Helm、kubernetes-sigs/metrics-server(README)
Helm と Kustomize の仕組み
Kustomize:base に overlay を重ねる
Kustomize は kustomization.yaml を読んで、リソースを組み立てます。kustomization.yaml の resources には使うマニフェストのファイルを並べます。公式ドキュメントによると、Kustomize は別々のファイルのリソースを組み合わせ、それにパッチなどのカスタマイズを加えられます。
参考:Declarative Management of Kubernetes Objects Using Kustomize | Kubernetes
環境ごとの違いは base と overlay で表します。公式ドキュメントの説明は次の 3 つです。
- base は
kustomization.yamlとリソースの集まりを置いたディレクトリ。手元のディレクトリでも、Git などのリモートのリポジトリのディレクトリでもよい - overlay はほかの kustomization のディレクトリを参照する
kustomization.yamlのディレクトリ。複数の base を参照し、その上にカスタマイズを加えられる - base は overlay のことを知らないので、1 つの base を複数の overlay で使える
参考:Declarative Management of Kubernetes Objects Using Kustomize | Kubernetes
以下の図は後半の手順で作る base と 2 つの overlay から、Namespace ごとの Deployment ができる関係を表しています。
base には第12回のマニフェストをそのまま置き、overlay には環境ごとに違う部分だけを書きます。overlay dev は置く Namespace を dev に決めたうえで Pod の数とタグを変え、overlay prod は置く Namespace だけを決めて、ほかは base のままにします。base のファイルはどちらの overlay からも書き換えられません。
kubectl で Kustomize を使うコマンドを、v1.37 時点の公式ドキュメントとリファレンスに沿って次の表にまとめます。どれも kustomization のディレクトリを指定します。
| コマンド | すること |
|---|---|
kubectl kustomize <ディレクトリ> | kustomization.yaml からリソースを組み立てて表示する |
kubectl apply -k <ディレクトリ> | 組み立てたリソースを作るか更新する |
kubectl get -k <ディレクトリ>、kubectl describe -k <ディレクトリ> | 組み立てたリソースにあたるオブジェクトを表示する |
kubectl delete -k <ディレクトリ> | 組み立てたリソースにあたるオブジェクトを消す |
参考:Declarative Management of Kubernetes Objects Using Kustomize | Kubernetes、kubectl kustomize | Kubernetes、kubectl apply | Kubernetes、kubectl delete | Kubernetes
kubectl apply と kubectl delete のリファレンスによると、-k は -f と一緒には使えません。kubectl apply -k も kubectl apply なので、第7回で見た last-applied のアノテーションを使う仕組みが、組み立てたリソースにもそのまま働くと考えられます。
Kustomize のよく使う機能
kustomization.yaml に書ける、よく使うフィールドを次の表にまとめます。
| フィールド | すること |
|---|---|
namespace | すべてのリソースに同じ Namespace を付ける |
namePrefix、nameSuffix | すべてのリソースの名前の前(後ろ)に文字列を付ける |
labels | すべてのリソースにラベルを付ける。includeSelectors: true にすると、セレクタとひな形のラベルにも付ける |
images | パッチを作らずに、イメージの名前、タグ、ダイジェスト(イメージの中身から計算した識別子。第2回)を変える |
patches | パッチを、書いた順に当てる。マニフェストの形で書くパッチ(strategic merge patch)などを使える |
configMapGenerator、secretGenerator | ファイルや文字列から ConfigMap(第17回)や Secret(第18回)を作る |
参考:Declarative Management of Kubernetes Objects Using Kustomize | Kubernetes、Declarative Management of Kubernetes Objects Using Kustomize | Kubernetes、Declarative Management of Kubernetes Objects Using Kustomize | Kubernetes、labels | Kustomize
公式ドキュメントのパッチの例は、apiVersion、kind、metadata.name と、変えたい spec.replicas だけを書いたマニフェストの形(strategic merge patch)をしています。当て先はこのファイルの apiVersion(グループとバージョン。第5回)、kind、name で決まります。公式ドキュメントは 1 つのことだけをする小さなパッチを勧めています(recommended)。後半の手順でもこの形のパッチで Pod の数を変えます。
参考:Declarative Management of Kubernetes Objects Using Kustomize | Kubernetes
第18回で、公式ドキュメントが Secret を作る方法の 1 つに Kustomize を挙げていると触れました。その手順はこの secretGenerator を kustomization.yaml に書くものです。ジェネレーターで作った ConfigMap と Secret の名前には、中身から計算したハッシュ(第12回)の接尾辞が付きます。公式ドキュメントは、接尾辞を付ける理由を、中身を変えたときに新しい ConfigMap や Secret が作られるようにするためと説明しています。Deployment からジェネレーターの名前で参照しておけば、Kustomize がハッシュ付きの名前に置き換えます。接尾辞は generatorOptions の disableNameSuffixHash: true で止められます。
参考:Managing Secrets using Kustomize | Kubernetes、Declarative Management of Kubernetes Objects Using Kustomize | Kubernetes
ラベルを付けるフィールドには commonLabels もあり、v1.37 時点の Kubernetes の公式ドキュメントの機能の一覧にも載っています。ただし Kustomize の公式ドキュメントによると、commonLabels は Kustomize v5.0.0 で非推奨 になり、代わりに labels を使うよう案内されています。commonLabels はラベルをセレクタにも必ず加えます。Kustomize の公式ドキュメントは、Deployment や Service のセレクタは適用したあとで変えるべきではない(shouldn’t)とし、適用済みのリソースで commonLabels を変えると失敗することがあると注意しています。適用済みのリソースで labels の includeSelectors を true にすることや、true のままラベルを変えることも、commonLabels を変えるのと同じだとされています。第12回で見たとおり、Deployment のセレクタは作ったあとで変えられません。
参考:commonLabels | Kustomize、labels | Kustomize、Declarative Management of Kubernetes Objects Using Kustomize | Kubernetes
Helm:チャートと values からリリースを作る
Helm のチャートは決まった形のディレクトリです。helm create が作るひな形の主なファイルは次の 3 つです。
| ファイル | 中身 |
|---|---|
Chart.yaml | チャートの情報。apiVersion(Helm 3 以降向けは v2 にするべき)、name、version(SemVer 2 に従うべき)は必須 |
values.yaml | テンプレートに埋める値の既定値 |
templates/ | テンプレートのファイルを置くディレクトリ |
参考:helm create | Helm、Charts | Helm、Charts | Helm、Charts | Helm
テンプレートは Go のテンプレート言語で書きます。Helm がチャートを描画(render)するときは、templates/ のすべてのファイルをテンプレートエンジンに通します。テンプレートの中で {{ .Values.replicaCount }} のように書いた場所に、.Values の値が埋め込まれます。. でつないで、values の YAML の入れ子を上からたどります。たとえば .Values.image.tag は values.yaml の image: の下の tag: を指します。{{ .Release.Name }}(リリースの名前)や {{ .Release.Namespace }}(リリースを入れた Namespace)のような、Helm が用意する値もあります。
.Values に入る値はいくつかの場所から来ます。Helm の公式ドキュメントでは、次の順に、後のものが前のものを上書きします(チャートが別のチャートの一部になる場合の親の values.yaml は省きます)。
| 順 | 値の出どころ | 例 |
|---|---|---|
| 1 | チャートの中の values.yaml(既定値) | replicaCount: 3 |
| 2 | -f(--values)で渡す、利用者の values ファイル | -f values-dev.yaml |
| 3 | --set で渡す、個々の値 | --set replicaCount=2 |
-f は何度でも指定でき、いちばん右のファイルが優先されます。--set も複数指定でき、いちばん右のものが優先されます。チャートに渡せる値は helm show values で確かめられます。環境ごとの違いは環境ごとの values ファイルを用意して -f で渡す形で表せます。
Helm の公式ドキュメントによると、Helm はチャートと values を合わせてリリースを作ります。リリースの版の番号はリビジョン(revision)と呼ばれ(Chart.yaml の version とは別のもの)、最初は必ず 1 で、install、upgrade、rollback のたびに 1 ずつ増えます。
以下の図は Helm のチャートと values から、Namespace dev にリリースができる関係を表しています。後半の手順の helm upgrade の段を例にしています。Helm のアイコンは Kubernetes の公式アイコンに無いので、箱で描いています。
テンプレートに値を埋めるのは、手元の PC で動く helm のコマンドです。Helm 2 にはクラスタの中で動く Tiller というコンポーネントがありましたが、Helm 3 で取り除かれ、チャートをクライアント側で描画して、入れた記録を Kubernetes に保存する形になりました。描画したマニフェストとリリースの記録は kube-apiserver に送られ、Deployment ができるか更新されます。そこから先の ReplicaSet や Pod を作るのは、第12回と同じく deployment-controller と replicaset-controller です。replicaCount は values.yaml の 3 を values-dev.yaml の 1 が上書きし、さらに --set の 2 が上書きするので、2 になります。
参考:Changes Since Helm 2 | Helm、Introduction to Helm | Helm、Values Files | Helm
リリースの記録は既定ではリリースの Namespace の Secret に保存されます。保存先は環境変数 HELM_DRIVER で ConfigMap などに変えられます。公式ドキュメントによると、--set で渡した値もこの Secret に残り、helm get values で表示できます。Secret を読める人には記録の中身も読めると考えられます。パスワードのような値を --set で渡すときは、この点に気を付けてください。
参考:Advanced Helm Techniques | Helm、Using Helm | Helm、helm get values | Helm
2026年10月現在、Helm の最新の安定版は 2026年10月15日に出た v4.3.1 です。Helm の公式ドキュメントによると、Helm 4.3.x が対応する Kubernetes は 1.34.x から 1.37.x です。Helm 4 は新しいリリースを入れるときに、既定で server-side apply(第7回の注意点の補足)を使います。
参考:Release Helm v4.3.1 · helm/helm、Helm Version Support Policy | Helm、Helm 4 Overview | Helm
Helm のコマンド
この回で使う helm のコマンドを、Helm 4 の公式ドキュメント(2026年10月時点、v4.3.1)に沿って次の表にまとめます。
| コマンド | すること |
|---|---|
helm install [NAME] [CHART] | チャートを入れて、リリースを作る。チャートは手元のディレクトリのパスでも指定できる |
helm upgrade [RELEASE] [CHART] | リリースを新しいバージョンのチャートや値に更新する |
helm history RELEASE_NAME | リリースのリビジョンの履歴を表示する |
helm rollback <RELEASE> [REVISION] | リリースを前のリビジョンに戻す。リビジョンを省くか 0 にすると、1 つ前に戻す |
helm uninstall RELEASE_NAME | リリースに関係するリソースと、リリースの履歴を消す。--keep-history を付けると履歴を残す |
helm template [NAME] [CHART] | チャートのテンプレートを手元で描画して表示する |
参考:helm install | Helm、helm upgrade | Helm、helm history | Helm、helm rollback | Helm、helm uninstall | Helm、helm template | Helm
helm template はクラスタに問い合わせずに手元で描画し、サーバー側の確認もしないので、描画できてもクラスタで受け付けられるとは限らないと考えられます。
2 つの違い
ここまでの内容をもとに、2 つのツールの違いを次の表にまとめます。
| 項目 | Kustomize | Helm |
|---|---|---|
| 環境ごとの違いの書き方 | base のマニフェストに、overlay でパッチや共通のフィールドを重ねる。テンプレートは使わない | テンプレートに値の入る場所を書き、環境ごとの values で埋める |
| 使うコマンド | kubectl に組み込まれている(kubectl apply -k など)。単体のツールもある | helm のコマンドを別に入れる |
| 再利用・共有のしかた | base を、手元のディレクトリか、Git などのリモートのリポジトリのディレクトリから参照する | チャートにまとめてバージョンを付け、チャートのリポジトリで共有する |
| クラスタに残る記録 | 組み立てたオブジェクト | オブジェクトに加えて、リリースの記録を残す。既定ではリリースの Namespace の Secret |
| 履歴と戻し方 | 確かめた範囲の公式ドキュメントに、Kustomize 自身の履歴の仕組みは出てこない | リビジョンの履歴を helm history で見て、helm rollback で戻す |
| 消し方 | kubectl delete -k | helm uninstall |
参考:kubernetes-sigs/kustomize(README)、Declarative Management of Kubernetes Objects Using Kustomize | Kubernetes、Introduction to Helm | Helm、Introduction to Helm | Helm、Charts | Helm、Using Helm | Helm
表の 1 行目の違いが、2 つのツールの考え方の違いの中心です。Kustomize の README によると、Kustomize はテンプレートを使わない(template-free)素の YAML をカスタマイズするもので、元の YAML には手を付けず、そのまま使える形で残します。この回の base の deployment.yaml は第12回のマニフェストそのものなので、README の言う「そのまま使える」のとおり、kubectl apply -f にも使えるはずです。一方、Helm のテンプレートは {{ }} を含むので、Helm で描画するまでは Kubernetes のマニフェストとして使えないと考えられます。
Kustomize で戻したいときは、overlay や base のファイルを前の内容に戻して、もう一度 kubectl apply -k することになると考えられます。第7回で見たとおり、マニフェストのファイルは Git などで履歴を残せるので、戻す先の内容はファイルの履歴に残ることになるはずです。
どちらを使うべきかは、確かめた範囲の Kubernetes と Helm と Kustomize の公式ドキュメントには比べて書かれていません。ここまでの違いからは、既製のアプリケーションを入れたり、自分のアプリケーションを他の人に配ったりするなら Helm、自分たちのマニフェストをテンプレートなしで環境ごとに少し変えるなら Kustomize が向いていると考えられます。2 つを組み合わせることもでき、kubectl kustomize には Helm のチャートを展開する仕組みを有効にする --enable-helm のフラグがあります。この回では組み合わせ方は扱いません。
手元で試す
ここまでの内容を手元の kind のクラスタで試す手順を示します。第12回の nginx の Deployment を、Kustomize と Helm のそれぞれで組み立ててマニフェストを比べ、dev と prod の Namespace にデプロイします。最後に、Helm だけで upgrade と rollback を試して履歴を確かめます。比べるために、dev と prod のそれぞれに、Kustomize の nginx-deployment と Helm の nginx-helm の 2 つを並べて置きます。実際の運用では、ふつうはどちらか一方で管理すると考えられます。
この節で引用する出力の例は、公式ドキュメントに載っている、ほかの環境で取ったものです。名前や時間などの値は手元とは違います。各段に書く成功の目安は公式ドキュメントから予想される結果で、手元で実行して確かめたものではありません。
コマンドは macOS や Linux のシェル(bash や zsh)で実行する前提で書いています。Windows では WSL(Windows の中で Linux を動かす仕組み)などを使ってください。
試す環境は次のとおりです。
| 項目 | 内容 |
|---|---|
| kind | v0.33.0 |
| Kubernetes | v1.37.0(kind v0.33.0 の既定のノードイメージ) |
| ノード構成 | シングルノード(クラスタ名 kind):コントロールプレーン 1 |
| 必要なもの | Docker、kubectl(v1.36〜v1.38)、Helm v4.3.1、テキストエディタ、端末(ターミナル)2 つ |
参考:Release v0.33.0 · kubernetes-sigs/kind、Version Skew Policy | Kubernetes、Helm Version Support Policy | Helm
この回ではシングルノードのクラスタを使います。マニフェストを組み立てて渡す仕組みを試すので、ノードが 1 つでも確かめられるからです。kind でクラスタを作る手順は、以下の記事で解説しています。
kind で検証用のクラスタを作るDocker のコンテナをノードにして、手元のマシンに Kubernetes のクラスタを作るツール kind の仕組みを図で説明します。kind create cluster で何が起きるかを押さえ、シングルノードとマルチノードのクラスタを作って、ノードの正体が Docker のコンテナであることを確かめる手順を紹介します。この回では端末を 2 つ使います。これまでの回と同じく、1 つ目の端末は変化の監視(この回では Namespace dev の Deployment)に取っておきます。クラスタの準備も含めて、操作は 2 つ目の端末で行います。2 つ目の端末では最初にこの回のファイルを置く作業用のディレクトリを作って移ります。ディレクトリの名前は一例です。
$ mkdir helm-kustomize && cd helm-kustomize
この回のファイルとコマンドはすべてこのディレクトリで扱います。
シングルノードのクラスタを用意する
2 つ目の端末で、前の回のクラスタが残っていないかを確かめます。
$ kind get clusters
kind が表示されたら、作り直さずにそのまま使えるので、クラスタを作る次のコマンドは飛ばします。表示されなければ、クラスタを作ってから、もう一度一覧します。
$ kind create cluster
$ kind get clusters
kind get clusters に kind が表示されれば、クラスタができています。第3回で決めたとおり、ここからの kubectl のコマンドには --context kind-kind を付けて、操作するクラスタをはっきりさせます。続けて、ノードを一覧します。
$ kubectl get nodes --context kind-kind
ノードが 1 つ表示され、STATUS 列が Ready になっていれば準備ができています。Ready になっていなければ、少し待ってからもう一度実行します。
前の回のクラスタを使い続けている場合は、この回で使う dev と prod の Namespace が無いことも確かめます。
$ kubectl get namespace dev prod --context kind-kind
dev と prod のそれぞれについて、見つからないことを知らせる行が出れば、そのまま進められます。どちらかが表示されたら、第37回で見たとおり、Namespace を消すと中のリソースも一緒に消えるので、残したいものが無いかを確かめてから kubectl delete namespace <名前> --context kind-kind で消します。
Kustomize のバージョンを確かめて Helm を入れる
2 つ目の端末で、kubectl とそれに組み込まれた Kustomize のバージョンを表示します。
$ kubectl version --client
Kustomize の README の例(kubectl v1.31.0)のとおりなら、Client Version: の行と Kustomize Version: の行が表示されるはずです。手元では Client Version: が v1.36 から v1.38 のどれかになります。Kustomize Version: の行があれば、Kustomize を別に入れなくても、このあとの手順を進められます。README によると、組み込まれた Kustomize のバージョンは kubectl のバージョンごとに決まり、更新は Kubernetes のリリースノートに載ります。Kustomize の公式ドキュメントに載っている機能が、手元のバージョンではまだ使えないこともあると考えられます。
参考:kubernetes-sigs/kustomize(README)、kubectl version | Kubernetes
続けて、Helm を手元の PC に入れます。Helm の公式ドキュメントが示す入れ方のうち、この回の前提(macOS か、Linux や WSL のシェル)に合うものを次の表にまとめます。
| OS | 入れ方 |
|---|---|
| macOS | Homebrew で brew install helm |
| Linux と WSL | Helm のプロジェクトが用意したインストーラーのスクリプト(下の 3 行) |
Homebrew などのパッケージマネージャーで配られている Helm は、コミュニティが提供するもので、Helm のプロジェクトはサポートしていません。WSL を使う場合は、WSL の中に Linux の手順で入れると、同じシェルから helm を使えます。Windows で WSL を使わずに直接使う場合の入れ方は、公式ドキュメントの Installing Helm のページを見てください。
Linux と WSL では作業用のディレクトリで次の 3 行を実行します。スクリプトは最新の Helm を取ってきて手元に入れます。1 行目でスクリプトを get_helm.sh という名前で取ってきて、2 行目で実行できるようにし、3 行目で実行します。
$ curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-4
$ chmod 700 get_helm.sh
$ ./get_helm.sh
公式ドキュメントは、スクリプトには説明が多く書かれているので、実行する前に読んで何をするかを理解できるとしています。スクリプトの中身によると、既定では helm を /usr/local/bin に入れ、root でなければ sudo を使います。そのため、途中で sudo のパスワードを聞かれることがあります。入れたら、バージョンを表示します。
$ helm version --short
v4.3.1 のようなバージョン番号が表示されるはずです。前から入っていた Helm 3(v3. で始まる番号)が表示されたら、この回は Helm 4 を前提にしているので、Helm 4 に入れ替えてから進めてください。スクリプトがバージョンを比べて入れ替えるのは、/usr/local/bin にある helm だけです。Homebrew や apt などほかの方法で入れた Helm 3 は、入れたときと同じ方法で更新するか消してください。そのあと helm version --short で v4. が表示されることを確かめます。この記事より新しい Helm が入った場合は、Helm Version Support Policy で、そのバージョンが Kubernetes v1.37 に対応しているかを確かめてください。
参考:get-helm-4 · helm/helm、Helm Version Support Policy | Helm
2 つの Namespace を作って監視する
以下は dev と prod の 2 つの Namespace のマニフェストです。第37回と同じ書き方で、名前だけを変えました。作業用のディレクトリに namespaces.yaml という名前で保存します。
apiVersion: v1
kind: Namespace
metadata:
name: dev
---
apiVersion: v1
kind: Namespace
metadata:
name: prod2 つ目の端末で、マニフェストを渡します。
$ kubectl apply -f namespaces.yaml --context kind-kind
namespace/dev と namespace/prod が作られたことを知らせる 2 行が出るはずです。
1 つ目の端末で、Namespace dev の Deployment を監視します。監視だけなので、作業用のディレクトリに移る必要はありません。この監視は片付けの前まで止めずに続けます。
$ kubectl get deployments -n dev --watch --context kind-kind
まだ dev に Deployment は無いので、見つからないことを知らせる 1 行が出たあと、止まったように見えると考えられます。これからの段で dev に Deployment を作ったり変えたりすると、この端末に行が書き足されるはずです。書き足されるのは、Kustomize の nginx-deployment と Helm の nginx-helm の 2 つの Deployment の行です。
Kustomize の base と overlay を作る
2 つ目の端末で、Kustomize のファイルを置くディレクトリを作ります。-p は途中のディレクトリもまとめて作る指定です。
$ mkdir -p kustomize/base kustomize/overlays/dev kustomize/overlays/prod
base には第12回のマニフェストをそのまま置きます。次の内容を kustomize/base/deployment.yaml に保存します。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80次の内容を kustomize/base/kustomization.yaml に保存します。resources に、同じディレクトリの deployment.yaml を書きます。先頭の 2 行は Kustomize の公式ドキュメントの例と同じく、このファイルが Kustomization であることを表します。
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml続けて dev の overlay です。次の内容を kustomize/overlays/dev/kustomization.yaml に保存します。
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
namespace: dev
patches:
- path: replicas.yaml
images:
- name: nginx
newTag: "1.16.1"resources の ../../base で base を参照し、namespace で置く Namespace を dev にします。.. は 1 つ上のディレクトリなので、../../base は kustomize/overlays/dev から 2 つ上がった kustomize の下の base を指します。images は nginx という名前のイメージのタグだけを 1.16.1 に変えます。images の name はコンテナの名前ではなくイメージの名前(: の前の部分)と合わせます。Kustomize の公式ドキュメントにも、newName を書かずに newTag だけで nginx のタグを変える例があります。
参考:Declarative Management of Kubernetes Objects Using Kustomize | Kubernetes、images | Kustomize
patches に書いた replicas.yaml は Pod の数を 1 にするパッチです。次の内容を kustomize/overlays/dev/replicas.yaml に保存します。公式ドキュメントの strategic merge patch の例と同じ形で、当て先を決める apiVersion、kind、metadata.name と、変える spec.replicas だけを書いています。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 1参考:Declarative Management of Kubernetes Objects Using Kustomize | Kubernetes
最後に prod の overlay です。次の内容を kustomize/overlays/prod/kustomization.yaml に保存します。prod は Namespace だけを決め、Pod の数とイメージは base のままにします。
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
namespace: prodこの段では kustomize/base に 2 つ、kustomize/overlays/dev に 2 つ、kustomize/overlays/prod に 1 つのファイルがあれば準備ができています。
kubectl kustomize で組み立てたマニフェストを比べる
2 つ目の端末で、dev の overlay から組み立てたマニフェストを表示します。
$ kubectl kustomize kustomize/overlays/dev
1 つ目の kustomize は kubectl のサブコマンド、2 つ目の kustomize/overlays/dev はさきほど作ったディレクトリです。kubectl kustomize は組み立てたリソースを表示するコマンドで、クラスタにはまだ何も作りません。そのため、この段の kubectl のコマンドには --context を付けていません。1 つ目の端末には変化が無いはずです。
表示される Deployment は base のマニフェストに overlay の変更が重なったものになるはずです。見るところを次の表にまとめます。
| 見るところ | dev の overlay から組み立てたもの |
|---|---|
metadata.namespace | dev(base には無かった行が加わる) |
spec.replicas | 1(パッチで 3 から変わる) |
コンテナの image | nginx:1.16.1(images でタグが変わる) |
metadata.name とラベル | base のまま(nginx-deployment、app: nginx) |
参考:Declarative Management of Kubernetes Objects Using Kustomize | Kubernetes
公式ドキュメントの kubectl kustomize の出力の例では、コンテナの image が name より前にあるなど、フィールドが元のファイルとは違う順に並んでいます。手元でも base のファイルとは行の順番が違って見えると考えられます。
続けて、prod の overlay から組み立てます。
$ kubectl kustomize kustomize/overlays/prod
metadata.namespace が prod になり、spec.replicas が 3、image が nginx:1.14.2 のままなら、この段は成功です。overlay は base のファイルを書き換えずに、組み立てるときだけ変更を重ねています。
kubectl apply -k で dev と prod にデプロイする
2 つ目の端末で、dev と prod の overlay をそれぞれクラスタに反映します。
$ kubectl apply -k kustomize/overlays/dev --context kind-kind
$ kubectl apply -k kustomize/overlays/prod --context kind-kind
公式ドキュメントの例(名前の前に dev- を付けた dev-my-nginx を作る例)では、出力は次のとおりです。
参考:Declarative Management of Kubernetes Objects Using Kustomize | Kubernetes
この回の overlay は名前を変えないので、手元ではどちらのコマンドでも deployment.apps/nginx-deployment created の 1 行が出るはずです。1 つ目の端末には Namespace dev の nginx-deployment の行が書き足され、しばらくすると READY 列が 1/1 になるはずです。イメージを初めて取ってくるときは、時間がかかることがあります。数分たっても 0/1 のままなら、第41回の手順で Pod の状態とイベントを確かめます。そのときは -n dev を、prod なら -n prod を付けます。このあとの段で READY 列を待つときも同じです。
dev と prod の Deployment を、overlay を指定して表示します。
$ kubectl get -k kustomize/overlays/dev --context kind-kind
$ kubectl get -k kustomize/overlays/prod --context kind-kind
dev は READY 列が 1/1、prod は 3/3 になれば、この段は成功です。3/3 になるまでは、少し待ってからもう一度実行します。同じ nginx-deployment という名前でも、Namespace が違うので両方作れます(第37回)。
Helm のチャートを作る
Helm でも同じことをします。この回では中身を小さく保つため、helm create のひな形ではなく最小のチャートを手で書きます。2 つ目の端末で、チャートのディレクトリを作ります。
$ mkdir -p nginx-chart/templates
次の内容を nginx-chart/Chart.yaml に保存します。必須の 3 つのフィールドだけを書いています。
apiVersion: v2
name: nginx-chart
version: 0.1.0次の内容を nginx-chart/values.yaml に保存します。値は第12回のマニフェストと同じで、prod ではこの既定値をそのまま使います。タグは文字列として扱うため、引用符で囲んでいます(Kustomize の公式ドキュメントの例も newTag を引用符で囲んでいます)。
replicaCount: 3
image:
tag: "1.14.2"次の内容を nginx-chart/templates/deployment.yaml に保存します。第12回のマニフェストをもとに、環境で変わる場所を {{ }} に置き換えたテンプレートです。{{ }} を含むので、Helm で描画するまでは、そのままでは kubectl apply に使えないと考えられます。
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Release.Name }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ .Release.Name }}
template:
metadata:
labels:
app: {{ .Release.Name }}
spec:
containers:
- name: nginx
image: "nginx:{{ .Values.image.tag }}"
ports:
- containerPort: 80第12回のマニフェストと違い、名前とラベルにはリリースの名前を使います。同じ Namespace に Kustomize の nginx-deployment もあるので、ラベルを app: nginx のままにすると、2 つの Deployment のセレクタが重なります。第11回と第12回で見たとおり、セレクタが重なるとコントローラーが Pod を取り合うおそれがあるので、ラベルを分けています。Deployment のページもほかのコントローラー(ほかの Deployment を含む)とラベルやセレクタを重ねないよう注意しています。
最後に、dev 用の values ファイルを、チャートの外に values-dev.yaml という名前で保存します。
replicaCount: 1
image:
tag: "1.16.1"この段では nginx-chart の中に 3 つのファイルがあり、その横に values-dev.yaml があれば準備ができています。
helm template で描画したマニフェストを比べる
2 つ目の端末で、dev 用の値で描画したマニフェストを表示します。nginx-helm はこれから作るリリースの名前、./nginx-chart はチャートのディレクトリです。
$ helm template nginx-helm ./nginx-chart -n dev -f values-dev.yaml
Helm では kubeconfig のコンテキスト(第3回)を --kube-context で指定します。kubectl の --context にあたるフラグです。helm template はチャートのテンプレートを手元で描画して表示するコマンドなので、--kube-context は付けていません。1 つ目の端末には変化が無いはずです。
表示される Deployment は {{ }} が値に置き換わったものになるはずです。さきほどの kubectl kustomize の dev の出力と比べると、次のようになると考えられます。
| 見るところ | kubectl kustomize(dev) | helm template(dev) |
|---|---|---|
metadata.name | nginx-deployment | nginx-helm(リリースの名前) |
metadata.namespace | dev | dev(-n で決めた Namespace) |
spec.replicas | 1 | 1(values-dev.yaml が上書き) |
コンテナの image | nginx:1.16.1 | nginx:1.16.1 |
表の項目では、名前のほかは同じ値になるはずです。2 つのツールは、同じことを違うやり方で表していると言えます。行の並び順など、表に無いところでは違って見えると考えられます。-f を付けずに -n prod で描画すれば、values.yaml の既定値(replicas が 3、image が nginx:1.14.2)になるはずです。
helm install で dev と prod にデプロイする
2 つ目の端末で、dev と prod にリリースを入れます。ここからはクラスタを操作するので、--kube-context kind-kind を付けます。
$ helm install nginx-helm ./nginx-chart -n dev -f values-dev.yaml --kube-context kind-kind
$ helm install nginx-helm ./nginx-chart -n prod --kube-context kind-kind
Helm の公式ドキュメントの例では、出力の始めに NAME:、LAST DEPLOYED:、NAMESPACE:、STATUS:、REVISION: の行が並びます。手元では NAME: が nginx-helm、NAMESPACE: がそれぞれ dev と prod、STATUS: が deployed、REVISION: が 1 になるはずです。例は別のチャートを入れたものなので、続く行は手元と違います。Helm の公式ドキュメントによると、Helm はすべてのリソースが動き出すまで待たずに終わります。1 つ目の端末を見ると、nginx-helm の行が書き足され、しばらくすると READY 列が 1/1 になるはずです。待つときの目安は「kubectl apply -k で dev と prod にデプロイする」の段と同じです。
すべての Namespace のリリースを一覧します。helm でも、-A はすべての Namespace を指す指定です。
$ helm list -A --kube-context kind-kind
dev と prod に 1 つずつ、nginx-helm のリリースが並べば、この段は成功です。Helm 3 の変更点のページによると、リリースの名前の範囲は Namespace ごとで、リリースの記録はリリースと同じ Namespace に保存されます。そのため同じ名前でも両方入れられます。
helm upgrade と helm rollback で履歴を比べる
dev のリリースの Pod の数を 2 に変えます。2 つ目の端末で、install のときと同じく values-dev.yaml を渡し、それに加えて --set で replicaCount を渡します。
$ helm upgrade nginx-helm ./nginx-chart -n dev -f values-dev.yaml --set replicaCount=2 --kube-context kind-kind
仕組みの図のとおり、--set が values-dev.yaml より優先されるので、replicaCount は 2 になります。
1 つ目の端末の nginx-helm の行で、READY 列の / の右側(望ましい数)が 2 に変わり、しばらくすると 2/2 になるはずです。Kustomize の nginx-deployment の行は変わらないはずです。
リリースの履歴と、このリリースに渡した値を表示します。
$ helm history nginx-helm -n dev --kube-context kind-kind
$ helm get values nginx-helm -n dev --kube-context kind-kind
Helm の公式ドキュメントの helm history の例は次のとおりです。
手元では例の 1 行目と 2 行目のような 2 行が並ぶはずです。CHART 列は nginx-chart-0.1.0 になるはずです。APP VERSION 列は、Chart.yaml に appVersion を書いていないので空になると考えられます。いちばん新しいリビジョン 2 の STATUS 列は deployed になるはずです。
helm get values には、values-dev.yaml と --set を合わせた、利用者が渡した値(replicaCount が 2、tag が 1.16.1)が表示されると考えられます。
リリースをリビジョン 1 に戻します。
$ helm rollback nginx-helm 1 -n dev --kube-context kind-kind
ロールバックが終わったことを知らせる 1 行が出るはずです。1 つ目の端末の nginx-helm の行は、READY 列が 1/1 に戻るはずです。
helm get manifest はリリースのチャートから描画されたマニフェストを取り出すコマンドで、--revision でリビジョンを指定できます。そのため、リリースの記録にはリビジョンごとのマニフェストが残っていると読めます。リビジョン 1 のマニフェストの replicas は 1 だったので、それに戻ると考えられます。Helm 3 の変更点のページにも、kubectl scale で 0 にした Deployment を helm rollback すると、前のマニフェストの 3 に戻す例があります(Helm 3 についての説明です)。
もう一度、履歴を表示します。
$ helm history nginx-helm -n dev --kube-context kind-kind
rollback でもリビジョンは 1 つ増えるので、3 行になるはずです。例の 3 行目と同じ形で、リビジョン 3 の DESCRIPTION 列は Rolled back to 1 になると考えられます。
ここで、Deployment 自身の履歴(第12回)と比べます。
$ kubectl rollout history deployment/nginx-helm -n dev --context kind-kind
REVISION 列に並ぶのは 1 行だけのはずです。第12回で見たとおり、Deployment のリビジョンが増えるのは Pod のひな形が変わったときだけで、この段で変えたのは replicas だけだからです。2 つの履歴の違いを次の表にまとめます。
| 項目 | Helm のリリースのリビジョン | Deployment のリビジョン(第12回) |
|---|---|---|
| 増えるとき | install、upgrade、rollback のたび | Pod のひな形が変わったとき(切り戻しを含む) |
| 戻す範囲 | 前のリビジョンのマニフェストに戻す。replicas も戻ると考えられ、1 つ目の端末の READY 列で確かめられる | Pod のひな形だけ。replicas は戻らない |
| 記録の場所 | 既定ではリリースの Namespace の Secret | Deployment が持つ古い ReplicaSet |
参考:Using Helm | Helm、Changes Since Helm 2 | Helm、Advanced Helm Techniques | Helm、Deployments | Kubernetes
最後に、リリースの記録の Secret を一覧します。Helm の公式ドキュメントはリリースの記録を owner=helm のラベルで一覧する手順を示しています。ここではそれを Namespace dev に絞ります。
$ kubectl get secrets -n dev -l owner=helm --context kind-kind
Secret が並べば、リリースの記録がクラスタに残っていることを確かめられます。Secret の名前の形や、リビジョンごとにいくつ作られるかは、確かめた範囲の Helm の公式ドキュメントには書かれていません。同じ dev にある Kustomize の nginx-deployment については、こうした記録の Secret はありません。この回の overlay が作るのは Deployment だけだからです。この段では helm history が 3 行になり、nginx-helm の READY 列が 1/1 に戻れば成功です。
片付け
1 つ目の端末で Ctrl+C を押して、Deployment の監視を止めます。
2 つ目の端末で、Helm のリリースを消します。Helm で作ったものは Helm で、Kustomize で作ったものは kubectl delete -k で消します。第7回で見た、1 つのオブジェクトを 1 つの方法で管理する考え方に合わせるためです。
$ helm uninstall nginx-helm -n dev --kube-context kind-kind
$ helm uninstall nginx-helm -n prod --kube-context kind-kind
$ helm list -A --kube-context kind-kind
それぞれリリースを消したことを知らせる 1 行が出て、helm list -A に nginx-helm が並ばなければ、リリースは消えています。
続けて、Kustomize で作った Deployment を消します。
$ kubectl delete -k kustomize/overlays/dev --context kind-kind
$ kubectl delete -k kustomize/overlays/prod --context kind-kind
公式ドキュメントの例(deployment.apps "dev-my-nginx" deleted)と同じ形で、手元ではどちらのコマンドでも名前が nginx-deployment の 1 行が出るはずです。
参考:Declarative Management of Kubernetes Objects Using Kustomize | Kubernetes
最後に、Namespace を消して、残っていないかを確かめます。
$ kubectl delete -f namespaces.yaml --context kind-kind
$ kubectl get namespace dev prod --context kind-kind
第37回で見たとおり、kubectl delete は既定では Namespace が消えるまで待ってから戻ります。そのため、ふつうは dev と prod のそれぞれについて見つからないことを知らせる行が出て、削除できたことがわかるはずです。Ctrl+C で待つのを止めた場合などに Terminating と表示されたら、少し待ってからもう一度実行します。
参考:kubectl delete | Kubernetes、Share a Cluster with Namespaces | Kubernetes
クラスタを削除し、消えたことを確かめます。続けて次の回を試す場合は、クラスタを残しておいてもかまいません。手元の PC に入れた helm と、作業用のディレクトリのファイル(スクリプトで入れた場合は get_helm.sh も)は残ります。要らなければ、作業用のディレクトリごと消してかまいません。
$ kind delete cluster
$ kind get clusters
kind delete cluster は存在しないクラスタを指定してもエラーを返しません。kind get clusters に kind が表示されなくなったことを確かめます。kubeconfig に kind-kind のコンテキストが残っていたら、第3回の片付けと同じく kubectl config delete-context kind-kind で消します。
注意点
Helm と Kustomize でつまずきやすい点と、バージョンで変わる点を、次の表にまとめます。
| 項目 | 内容 |
|---|---|
commonLabels は非推奨 | Kustomize v5.0.0 で非推奨。labels を使うよう案内されている |
| セレクタに入るラベルを後から変えない | commonLabels や includeSelectors: true の labels はセレクタにもラベルを加える。適用済みのリソースで変えると失敗することがある |
| kubectl の Kustomize のバージョンは kubectl のバージョンで決まる | 組み込まれたバージョンは kubectl version で表示できる。更新は Kubernetes のリリースノートに載る |
| ジェネレーターの名前にはハッシュが付く | 中身を変えると新しい ConfigMap や Secret ができる。disableNameSuffixHash: true で止められる |
--set の値はリリースの記録に残る | 既定では Secret に残り、helm get values で表示できる。Secret を読める人には見えると考えられるので、パスワードのような値に注意 |
helm install は既定では待たない | すべてのリソースが動き出す前に終わる。様子は kubectl で確かめる |
helm uninstall で履歴も消える | 履歴を残したいときは --keep-history を付ける |
| Helm と Kubernetes のバージョンの組み合わせ(Helm v4.3.1 時点) | Helm 4.3.x が対応するのは Kubernetes 1.34.x〜1.37.x |
参考:commonLabels | Kustomize、labels | Kustomize、kubernetes-sigs/kustomize(README)、Declarative Management of Kubernetes Objects Using Kustomize | Kubernetes、kubectl apply | Kubernetes、Using Helm | Helm、Advanced Helm Techniques | Helm、Helm Version Support Policy | Helm
Helm で入れたリソースを kubectl apply や kubectl edit で直接変えると、第7回で見た「1 つのオブジェクトを 1 つの管理の方法で扱う」という警告に反すると考えられます。Helm のリリースの記録にもそうした変更は残らないと考えられます。Helm で入れたものは、values を変えて helm upgrade で直すのが、この警告に沿ったやり方だと考えられます。
関連記事
次の回では Kubernetes に自分のリソースの種類を足す CustomResourceDefinition(CRD)と、Operator の考え方を扱います。
CRD とは何かKubernetes の API に自分のリソースの種類を足す CRD(CustomResourceDefinition)の仕組みを図で説明します。CRD のマニフェストの書き方、登録すると kube-apiserver が新しいエンドポイントを用意すること、スキーマによる検証、コントローラーと組み合わせる Operator の考え方を押さえ、kind のクラスタで CRD を登録して kubectl get で扱う手順を紹介します。この回で base に使った Deployment と、replicas を戻さない Deployment 自身のリビジョンと切り戻しについては、以下の記事で解説しています。
kubectl apply が last-applied を使って更新する仕組みと、1 つのオブジェクトを 1 つの方法で管理する理由については、以下の記事で解説しています。