チャートの骨格を作り標準ラベルを付ける
目標
Helmチャートの標準構造を自分で作り、名前とラベルを1か所で管理して、すべてのオブジェクトに一貫した標準ラベルが付くようにします。
なぜ重要なのか
チャートを学ぶとき、人々はテンプレートの文法から気にしますが、実際にチャートの寿命を決めるのは構造です。Chart.yamlはこの一式が何であるか、values.yamlはユーザーが何を触れるか、templates/はその値がどんな形になるかを、それぞれ担います。この分離があってはじめて、「環境ごとにファイルをコピーして直す」習慣がなくなります。ラベルも好みの問題ではありません。app.kubernetes.io/*はKubernetesの公式推奨標準で、管理ツールやダッシュボードがこのラベルでリソースをまとめます。特に、共通ラベルとセレクターラベルは必ず分離する必要があります。Deploymentのspec.selectorは、作成後に変更できないフィールドですが、共通ラベルにはチャートのバージョンとアプリのバージョンが混ざっているので、セレクターにそのまま使うと、バージョンを上げた瞬間にアップグレードが拒否されます。
ステップ
/root/helm/lab/labhub-webにチャートのスケルトンを作成してください(helm create labhub-webを/root/helm/labの中で実行すれば構いません)。Chart.yaml、values.yaml、.helmignoreの3つのファイルと、templates/(ファイル3つ以上)、charts/ディレクトリがすべて必要です。出力物を入れる/root/helm/lab/outディレクトリも、あらかじめ作っておいてください。/root/helm/lab/labhub-web/Chart.yamlを埋めてください。apiVersion: v2、name: labhub-web、type: application、versionは0.1.0のようなSemVer、appVersion: "1.27"、そしてdescriptionが1行、必ず必要です。/root/helm/lab/labhub-web/values.yamlのデフォルト値を次のように合わせてください。replicaCount: 2、image.repository: nginx、image.tag: "1.27"、image.pullPolicy: IfNotPresent、service.port: 80。このファイルには、#で始まるコメントが最低1行必要です。/root/helm/lab/labhub-web/templates/_helpers.tplに、labhub-web.fullname、labhub-web.labels、labhub-web.selectorLabelsの3つの定義が必要で、名前を作る場所にtrunc 63の処理が入っている必要があります。そして、/root/helm/lab/labhub-web/templates/deployment.yamlは、これらの定義をinclude "labhub-web...の形で呼び出して使う必要があります。helm template labhub-web /root/helm/lab/labhub-web > /root/helm/lab/out/rendered.yamlでレンダリングを保存してください。結果にはオブジェクトが2つ以上あり、Deploymentのmetadata.labelsにapp.kubernetes.io/managed-by: Helm、app.kubernetes.io/name: labhub-web、app.kubernetes.io/versionがあり、Serviceのmetadata.labelsにも、同じ共通ラベルが付いている必要があります。/root/helm/lab/labhub-web/templates/NOTES.txtが、.Release.Nameと.Values.で始まる値を、最低1つずつ参照するようにしてください。そして、実際にレンダリングされた案内文を/root/helm/lab/out/notes.txtに保存してください。helm install labhub-web /root/helm/lab/labhub-web --dry-runの出力から、NOTES:の下の部分だけを切り出せば構いません(sed -n '/^NOTES:/,$p')。保存したファイルにはlabhub-webが入っている必要があり、レンダリングされていない波括弧の構文が残っていてはいけません。helm lint /root/helm/lab/labhub-web > /root/helm/lab/out/lint.txtでリントの結果を保存してください。ファイルにリントのサマリー行があり、[ERROR]が1つもない必要があります。- 値を上書きしたレンダリングを、
helm template labhub-web /root/helm/lab/labhub-web --set replicaCount=5 > /root/helm/lab/out/scaled.yamlで保存してください。最終的な確認条件は4つです。/root/helm/lab/out/rendered.yamlのDeploymentのspec.replicasは2、/root/helm/lab/out/scaled.yamlのものは5、コンテナイメージはnginx:1.27、Serviceの最初のポートは80です。そして、Serviceのspec.selectorにあるapp.kubernetes.io/nameと、DeploymentのPodテンプレートのラベルのapp.kubernetes.io/nameが、同じ値である必要があります。
参考
- ラボのPodはラボごとに新しく起動するので、ほかのラボで作ったチャートやreleaseは残っていません。必要なチャートは、毎回ここで最初から作ります。チャートがそのまま再現可能なパッケージであるという事実が、ここで現れます。
- スケルトン生成コマンドが作ってくれるデフォルトのチャートには、すでにヘルパーと標準ラベルが入っています。消して新しく書くよりも、値と名前を合わせるほうが速いです。
helm templateはクラスターなしでも動作し、helm install --dry-runは、クラスターに何も作らずに、NOTESまで見せてくれます。案内文を確認するときは、後者が必要です。- よくある間違い1:
appVersionをそのままにすることです。イメージタグのデフォルト値とapp.kubernetes.io/versionラベルがここから出るので、値がずれます。 - よくある間違い2:
NOTES.txtの原本をそのままコピーして、/root/helm/lab/out/notes.txtに保存することです。そうすると、波括弧が残っているので、レンダリングされた結果ではないと判定されます。
チャートのスケルトンを作る
/root/helm/lab/labhub-webにチャートのスケルトンを作成してください(helm create labhub-webを/root/helm/labの中で実行すれば構いません)。Chart.yaml、values.yaml、.helmignoreの3つのファイルと、templates/(ファイル3つ以上)、charts/ディレクトリがすべて必要です。出力物を入れる/root/helm/lab/outディレクトリも、あらかじめ作っておいてください。
Helmには、標準構造を一度に作ってくれるコマンドがあります。作られたあと、Chart.yaml、values.yaml、.helmignore、templates/、charts/の5か所がすべてあるかを確認してください。charts/は、空でもなければなりません。
Chart.yamlの身分を埋める
/root/helm/lab/labhub-web/Chart.yamlを埋めてください。apiVersion: v2、name: labhub-web、type: application、versionは0.1.0のようなSemVer、appVersion: "1.27"、そしてdescriptionが1行、必ず必要です。
Helm 3のapiVersionは1つに固定です。そして、チャート自体のバージョンとアプリのバージョンは、別のフィールドであることに注意してください。イメージタグと合わせる必要があるのがどちらなのか、考えてみてください。
values.yamlのデフォルト値を設計する
/root/helm/lab/labhub-web/values.yamlのデフォルト値を次のように合わせてください。replicaCount: 2、image.repository: nginx、image.tag: "1.27"、image.pullPolicy: IfNotPresent、service.port: 80。このファイルには、#で始まるコメントが最低1行必要です。
関連する値は、平らに並べずに、imageのようにまとめます。そして、values.yamlはユーザーが読む唯一のドキュメントなので、コメントが最低1つはある必要があります。
名前とラベルをヘルパーとして切り出す
/root/helm/lab/labhub-web/templates/_helpers.tplに、labhub-web.fullname、labhub-web.labels、labhub-web.selectorLabelsの3つの定義が必要で、名前を作る場所にtrunc 63の処理が入っている必要があります。そして、/root/helm/lab/labhub-web/templates/deployment.yamlは、これらの定義をinclude "labhub-web...の形で呼び出して使う必要があります。
アンダースコアで始まるテンプレートファイルは、マニフェストとしてレンダリングされません。共通ラベルとセレクターラベルを別々に定義する必要がある理由を、考えてみてください。名前には、長さの制限の処理が必要です。
すべてのオブジェクトに標準ラベルを付ける
helm template labhub-web /root/helm/lab/labhub-web > /root/helm/lab/out/rendered.yamlでレンダリングを保存してください。結果にはオブジェクトが2つ以上あり、Deploymentのmetadata.labelsにapp.kubernetes.io/managed-by: Helm、app.kubernetes.io/name: labhub-web、app.kubernetes.io/versionがあり、Serviceのmetadata.labelsにも、同じ共通ラベルが付いている必要があります。
Deploymentだけでなく、Serviceにも、同じ共通ラベルが付く必要があります。managed-byの値は、手で書かずに、releaseの情報から取得してください。レンダリング結果をファイルに保存してはじめて採点されます。
インストール案内文を書いてレンダリングする
/root/helm/lab/labhub-web/templates/NOTES.txtが、.Release.Nameと.Values.で始まる値を、最低1つずつ参照するようにしてください。そして、実際にレンダリングされた案内文を/root/helm/lab/out/notes.txtに保存してください。helm install labhub-web /root/helm/lab/labhub-web --dry-runの出力から、NOTES:の下の部分だけを切り出せば構いません(sed -n '/^NOTES:/,$p')。保存したファイルにはlabhub-webが入っている必要があり、レンダリングされていない波括弧の構文が残っていてはいけません。
NOTES.txtもテンプレートです。release名とvaluesの値を一緒に使うと、ユーザーが何をインストールしたのかがわかります。保存するファイルにはレンダリングされた結果が入る必要があり、波括弧が残っていてはいけません。
チャートのリントを通す
helm lint /root/helm/lab/labhub-web > /root/helm/lab/out/lint.txtでリントの結果を保存してください。ファイルにリントのサマリー行があり、[ERROR]が1つもない必要があります。
リントの出力全体をファイルに残してください。ERRORが1つでもあれば失敗です。警告は通過しますが、なぜ出たのかは読んでみるほうがよいです。
レンダリング結果を検証する
値を上書きしたレンダリングを、helm template labhub-web /root/helm/lab/labhub-web --set replicaCount=5 > /root/helm/lab/out/scaled.yamlで保存してください。最終的な確認条件は4つです。/root/helm/lab/out/rendered.yamlのDeploymentのspec.replicasは2、/root/helm/lab/out/scaled.yamlのものは5、コンテナイメージはnginx:1.27、Serviceの最初のポートは80です。そして、Serviceのspec.selectorにあるapp.kubernetes.io/nameと、DeploymentのPodテンプレートのラベルのapp.kubernetes.io/nameが、同じ値である必要があります。
デフォルトのレンダリングと、値を上書きしたレンダリングの2つが必要です。そして、Serviceのセレクターと、Podテンプレートのラベルが、同じキー・値かどうかを、自分の目で突き合わせてみてください。違っていれば、トラフィックがPodに届きません。