TT Lab
はじめる
学ぶ 学習パス コース

Helmチャートの作成とデプロイ

このクラスタにその API はあるか — Capabilities と crds

TT Labで続きを見る

目標

.CapabilitiesでクラスターのバージョンとAPIのリストを読んで分岐し、その値がコマンドごとにどこから来るのかを、自分で比較します。crds/ディレクトリがreleaseの外側にあることを、インストールとアップグレードで確認します。

なぜ重要なのか

チャート1つを複数のクラスターにデプロイする瞬間、「このクラスターにそのAPIがあるか」という問いが生じます。Helmは.Capabilitiesでその答えをテンプレートの中に持ち込みますが、この値がどこから来るかは、コマンドごとに違います。helm templateは、クラスターを見ずに、内蔵のデフォルト値を使い、helm installは、dry-runでも、実際のクラスターに問い合わせます。そのため、「ローカルでは出ないのに、デプロイすると出る」ことが生じ、逆に、CIのレンダリング検査だけを信じていて、本番で初めて見るオブジェクトが飛び出すこともあります。crds/は、これにもう1層を加えます。テンプレートではなく、releaseのマニフェストにもなく、インストールのときに先に入り、アップグレードでは手を付けられず、releaseを削除しても残ります。この5つを1回ずつ確認しておけば、CRDを含むチャートを運用するとき、人が何をしなければならないかが、はっきりします。

ステップ

  1. /root/hc-cap/sensorチャート(名前sensor、バージョン0.1.0、valuesにwidgetSize: large)を作成し、templates/cap.yamlに<릴리스이름>-cap(プレースホルダーはrelease名です)ConfigMapを置いてください。dataは6行です。kubeVersion・major・minor(すべて.Capabilities.KubeVersionから)、helmVersion、hasIngress(networking.k8s.io/v1/Ingressがあるか)、hasWidget(demo.labhub.io/v1/Widgetがあるか)です。6つの値すべてを引用符で囲みます。helm template sense /root/hc-cap/sensorの結果を/root/hc-cap/out/offline.yamlに保存してください。
  2. 同じチャートを、Kubernetes 1.21.0であるかのようにレンダリングして、/root/hc-cap/out/kube121.yamlに保存してください。結果のkubeVersionはv1.21.0、minorは21である必要があります。
  3. demo.labhub.io/v1/Widgetがあるかのようにレンダリングして、/root/hc-cap/out/apiversions.yamlに保存してください。結果のhasWidgetはtrueになり、hasIngressは相変わらずfalseである必要があります。このオプションがデフォルトのリストを置き換えるのか、足すのかを、その結果で判断してください。
  4. /root/hc-cap/sensor/templates/widget.yamlを作成してください。demo.labhub.io/v1/Widgetがあるときだけ、apiVersion: demo.labhub.io/v1、kind: Widget、名前<릴리스이름>-widget(プレースホルダーはrelease名です)、spec.sizeが.Values.widgetSizeであるオブジェクトを出力します。オプションなしでレンダリングした結果を/root/hc-cap/out/branch-off.yamlに、そのAPIがあるかのようにレンダリングした結果を/root/hc-cap/out/branch-on.yamlに保存してください。
  5. /root/hc-cap/sensor/crds/widget.yamlに、widgets.demo.labhub.ioCRDを置いてください(グループdemo.labhub.io、種類Widget、複数形widgets、ネームスペーススコープ、バージョンv1が1つ、spec.sizeが文字列のスキーマ)。そのあと、オプションなしでレンダリングした結果を/root/hc-cap/out/tpl-no-crd.yamlに、CRDまで一緒に出力するオプションを付けた結果を/root/hc-cap/out/tpl-with-crd.yamlに保存してください。
  6. helm install sense /root/hc-cap/sensorで、実際にインストールしてください。そのあと、3つを保存します。releaseのマニフェストを/root/hc-cap/out/manifest.yamlに、クラスターに作られたCRDを/root/hc-cap/out/crd-live.yamlに、インストールされたcap ConfigMapのdataをJSONで/root/hc-cap/out/cap-live.jsonに保存してください。マニフェストにCRDが入っているか、Widgetオブジェクトは入っているかを、確認してください。
  7. /root/hc-cap/sensor/crds/widget.yamlのスキーマに、color(文字列)フィールドを加えて、helm upgrade sense /root/hc-cap/sensorを実行してください。そのあと、クラスターに今あるCRDのspecの下のプロパティ名を、カンマでつないで、/root/hc-cap/out/crd-after-upgrade.txtに1行で保存してください。チャートには2つのフィールドがあるのに、クラスターにはいくつあるかが、このステップの答えです。
  8. helm template sense /root/hc-cap/sensor --validateの結果を/root/hc-cap/out/validate.yamlに、helm install probe /root/hc-cap/sensor --dry-run=serverの結果を/root/hc-cap/out/server-dryrun.yamlに保存してください。そして、/root/hc-cap/out/cap-compare.jsonに、offline_has_widget・validate_has_widget・dryrun_has_widgetの3つのキーをブール値で書いてください。値は、ステップ1と、今作った2つのファイルのhasWidgetから読み取ります。

参考

クラスターなしでレンダリングすると、何が見えるか

/root/hc-cap/sensorチャート(名前sensor、バージョン0.1.0、valuesにwidgetSize: large)を作成し、templates/cap.yamlに<릴리스이름>-cap(プレースホルダーはrelease名です)ConfigMapを置いてください。dataは6行です。kubeVersion・major・minor(すべて.Capabilities.KubeVersionから)、helmVersion、hasIngress(networking.k8s.io/v1/Ingressがあるか)、hasWidget(demo.labhub.io/v1/Widgetがあるか)です。6つの値すべてを引用符で囲みます。helm template sense /root/hc-cap/sensorの結果を/root/hc-cap/out/offline.yamlに保存してください。

helm templateはクラスターに問い合わせません。Helmの中に埋め込まれたデフォルトのCapabilitiesのリストを使うので、実際にはあるIngressも、ここではないと出ます。この事実を先に目で確認しておくと、後のステップで値が変わる理由がはっきりします。release名は、このラボの間ずっとsenseです。

クラスターなしで別のバージョンのふりをしてレンダリングする

同じチャートを、Kubernetes 1.21.0であるかのようにレンダリングして、/root/hc-cap/out/kube121.yamlに保存してください。結果のkubeVersionはv1.21.0、minorは21である必要があります。

helm templateには、バージョンを直接渡すオプションがあります(helm template --helpで、kubeで始まるもの)。古いクラスターをまだ使っているお客様がいるとき、そのクラスターを作らなくても、分岐が正しく動くかをテストできるというのが、このオプションの価値です。

ないAPIがあるふりをしてレンダリングする

demo.labhub.io/v1/Widgetがあるかのようにレンダリングして、/root/hc-cap/out/apiversions.yamlに保存してください。結果のhasWidgetはtrueになり、hasIngressは相変わらずfalseである必要があります。このオプションがデフォルトのリストを置き換えるのか、足すのかを、その結果で判断してください。

APIのリストを直接渡すオプションが別にあります。複数渡すには、オプションを複数回書くか、カンマでつなぎます。形式は<그룹>/<버전>/<종류>(プレースホルダーは順にグループ、バージョン、種類です)です。CRDとして入ってくるリソースに依存するチャートを、クラスターなしでテストするときに使う方法です。

Capabilitiesに応じてオブジェクトを入れたり外したりする

/root/hc-cap/sensor/templates/widget.yamlを作成してください。demo.labhub.io/v1/Widgetがあるときだけ、apiVersion: demo.labhub.io/v1、kind: Widget、名前<릴리스이름>-widget(プレースホルダーはrelease名です)、spec.sizeが.Values.widgetSizeであるオブジェクトを出力します。オプションなしでレンダリングした結果を/root/hc-cap/out/branch-off.yamlに、そのAPIがあるかのようにレンダリングした結果を/root/hc-cap/out/branch-on.yamlに保存してください。

ifブロック全体を{{- ... }}で囲むと、条件が偽のとき、空行さえ残りません。条件が偽なら、このファイルは何も出力しないので、レンダリング結果からドキュメントが1つまるごと消えます。チャート1つで、CRDがあるクラスターとないクラスターを一緒にサポートする、標準的な方法です。

crdsディレクトリはテンプレートではない

/root/hc-cap/sensor/crds/widget.yamlに、widgets.demo.labhub.ioCRDを置いてください(グループdemo.labhub.io、種類Widget、複数形widgets、ネームスペーススコープ、バージョンv1が1つ、spec.sizeが文字列のスキーマ)。そのあと、オプションなしでレンダリングした結果を/root/hc-cap/out/tpl-no-crd.yamlに、CRDまで一緒に出力するオプションを付けた結果を/root/hc-cap/out/tpl-with-crd.yamlに保存してください。

crds/の中のファイルは、テンプレートエンジンを通りません。波括弧を書いても、ただの文字です。そのため、デフォルトのレンダリング結果にも出てきません。出力するには、オプションを別に渡す必要があります(helm template --helpで、crdsが入ったオプション)。このディレクトリが特別扱いされる理由は、CRDが、それを使うオブジェクトより先に入る必要があるからです。

本物のクラスターに入れると、Capabilitiesが変わる

helm install sense /root/hc-cap/sensorで、実際にインストールしてください。そのあと、3つを保存します。releaseのマニフェストを/root/hc-cap/out/manifest.yamlに、クラスターに作られたCRDを/root/hc-cap/out/crd-live.yamlに、インストールされたcap ConfigMapのdataをJSONで/root/hc-cap/out/cap-live.jsonに保存してください。マニフェストにCRDが入っているか、Widgetオブジェクトは入っているかを、確認してください。

helm get manifest <릴리스>(プレースホルダーはreleaseです)が、そのreleaseに記録されたマニフェストを出力します。kubectl get cm sense-cap -o jsonpath='{.data}'で、dataをJSONで取り出せます。インストールはクラスターに問い合わせるので、hasIngressがローカルのレンダリングと変わります。CRDはテンプレートより先に入るので、最初のインストールでも、Widgetの条件が真になります。自分で確認してください。

crdsを直してアップグレードしても、クラスターはそのまま

/root/hc-cap/sensor/crds/widget.yamlのスキーマに、color(文字列)フィールドを加えて、helm upgrade sense /root/hc-cap/sensorを実行してください。そのあと、クラスターに今あるCRDのspecの下のプロパティ名を、カンマでつないで、/root/hc-cap/out/crd-after-upgrade.txtに1行で保存してください。チャートには2つのフィールドがあるのに、クラスターにはいくつあるかが、このステップの答えです。

Helmはcrds/をインストールのときだけ入れて、アップグレードでは手を付けません。公式ドキュメントがこれを制限として明記していて、CRDの更新は、人がkubectl applyで行うよう案内しています。プロパティ名は、kubectl get crd <이름> -o json(プレースホルダーは名前です)の.spec.versions[0].schema.openAPIV3Schema.properties.spec.propertiesのキーとして取り出します。

同じチャートで3つの答え: 整理する

helm template sense /root/hc-cap/sensor --validateの結果を/root/hc-cap/out/validate.yamlに、helm install probe /root/hc-cap/sensor --dry-run=serverの結果を/root/hc-cap/out/server-dryrun.yamlに保存してください。そして、/root/hc-cap/out/cap-compare.jsonに、offline_has_widget・validate_has_widget・dryrun_has_widgetの3つのキーをブール値で書いてください。値は、ステップ1と、今作った2つのファイルのhasWidgetから読み取ります。

--validateは、レンダリング結果をAPIサーバーに送って検証するので、Capabilitiesもクラスターから取得します。--dry-run=serverも同様です。クラスターを見ないのは、オプションなしのhelm templateだけです。引用符のないtrue/falseである必要があります。文字列で書いてはいけません。