LoginSignup
47
35

More than 5 years have passed since last update.

chartを作りながらhelmの概要を理解する

Last updated at Posted at 2019-02-09

目的と対象読者

helmについて今まで理解していなかったのですが、Documentを読んでキャッチアップしてみました。しかしDocumentは網羅性がある一方で概要を把握するには情報過多で、それができるチュートリアルもうまく見つからなかったので、備忘録も兼ねて記事にすることにしました。

以下のような方を対象にして書いているつもりです。

  • helmのアーキテクチャーや用語を理解したい
  • helmの基本的な使い方を広く浅く理解したい

また以下の前提で動作を確認していきます。

  • kubernetes(以下k8s)クラスタが構築されている
  • helmやtillerがインストールされている
  • helmのバージョンはv2である

helmの構成要素

helmとはk8sのパッケージマネジャーのことです。
パッケージとはk8sのマニフェスト(リソースの設定ファイル)の集合であり、helmはそれらを管理するためのツールと言えます。

c.f https://github.com/helm/helm#helm

Helm is a tool for managing Kubernetes charts. Charts are packages of pre-configured Kubernetes resources.

このパッケージマネジャーは具体的には、以下のような機能を提供しています。
c.f https://docs.helm.sh/architecture/

  • パッケージを共有、取得、管理する
  • パッケージを作成、更新する
  • パッケージをk8sクラスタに適用、巻き戻し、削除

これらの機能があることで、誰かが作ったマニフェストと同じようなものを作る必要がなくなったり、誰がいつどんな目的でk8sクラスタにこのマニフェストを適用したのか分からなくなることを防いだり、あるタイミングでapplyした内容に巻き戻したりすることができます。

まずは、helmに登場する用語を整理しましょう。
用語はDocumentで解説されており、詳しくはそちらを参照してください。

用語 説明
helm k8sのパッケージマネジャー
chart パッケージ(マニフェストの集合)
repository chartを保管したりダウンロードするサーバー
release k8sクラスタに適用されたchartで履歴管理用に保管される
tiller chartをk8sクラスタに適用したりreleaseを管理するサーバー

これだけだとイメージが湧かないと思うので、図にすると以下のようになります。

helm-architecture.png

これらのことから、helmはchartを見つけたり作成してrepositoryに保管し、chartの内容からk8sリソースをクラスタ上に作成し、その度にreleaseを作ることができる一連の利用シーンが理解できるかと思います。そして、releaseが作られることで、適用した内容をバージョン管理できるので巻き戻しや更新などの管理も可能になります。

c.f https://docs.helm.sh/using_helm/#three-big-concepts

chartを作る

chartの構成要素

上述の通り、chartとはパッケージであり、k8sリソースの設定ファイルの集合です。

c.f https://docs.helm.sh/developing_charts/#charts

Helm uses a packaging format called charts. A chart is a collection of files that describe a related set of Kubernetes resources.

概要について説明できたので次は作りながらchartをどのように作るかを見ていきたい思います。まず、chartは以下のような構成要素から成り立ちます。

c.f https://docs.helm.sh/developing_charts/#the-chart-file-structure

構成要素 機能
Chart.yaml chartに関するメタ情報が記述される(nameなど)
requirements.yaml 依存する外部のchartが指定される
values.yaml templateに当てはめる値が記述される
charts/ 現在のchartが依存するchartの一覧
templates/ values.yamlの値を嵌め込むことができるk8sマニフェストを作る雛形の一覧

実際にchartを作ってみます。まず、chartをk8sクラスタにデプロイするには、tillerサーバーを初期化させる必要があります。

kubectl config view --minifyで現在接続しているクラスタを確認し、そのクラスタのkube-system namespace内にtillerのpodを作成します。

$ kubectl config view --minify
$ helm init
$ kubectl --namespace kube-system get pods --selector name=tiller
NAME                             READY   STATUS    RESTARTS   AGE
tiller-deploy-7995854f67-jzx4d   1/1     Running   0          55m

次に、以下のコマンドでmychartというchartを作成します。
c.f https://docs.helm.sh/chart_template_guide/#a-starter-chart

$ helm create mychart
Creating mychart

実際に、上記のchartの構成要素となるファイルが生成されていることが確認できます。

$ ls mychart
Chart.yaml      charts          templates       values.yaml

template

まずはtemplateを作ります。templateは、k8sマニフェストの雛形で後述のvalues.yamlやコマンド引数で渡される値を嵌め込み、tiller経由でk8sクラスタに適用されます。

c.f https://docs.helm.sh/chart_template_guide/#charts

The templates/ directory is for template files. When Tiller evaluates a chart, it will send all of the files in the templates/ directory through the template rendering engine. Tiller then collects the results of those templates and sends them on to Kubernetes.

The values.yaml file is also important to templates. This file contains the default values for a chart. These values may be overridden by users during helm install or helm upgrade

ここではconfigmapのtemplateを作ってみますが、先ほど生成されたデフォルトのtemplateは利用しないので削除します。

$ rm -rf mychart/templates/*

その上で、mychart/templates/configmap.yamlに以下のconfigmapのマニフェストを作成します。これはtemplateですが、値は既に嵌め込まれた状態です。

# mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: mychart-configmap
data:
  myvalue: "Hello World"

helm install [chart-name]で先ほどのtemplateをtiller経由でデプロイしてみます。

$ helm install ./mychart
NAME:   hardy-grizzly
LAST DEPLOYED: Sat Feb  9 19:23:20 2019
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/ConfigMap
NAME               DATA  AGE
mychart-configmap  1     0s

実際に、hardy-grizzlyという名前のchartが以下のマニフェストとしてデプロイされたようです。
c.f https://docs.helm.sh/chart_template_guide/#debugging-templates

$ helm get manifest hardy-grizzly

---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: mychart-configmap
data:
  myvalue: "Hello World"

実際にconfigmapが作成されていることも確認できました。

$ kubectl get cm
NAME                DATA   AGE
mychart-configmap   1      47m

また、templateは値を嵌め込むだけではなく、値に応じた条件分岐(if)や利用する値のスコープの制御(with)、ループ(range)などを使ってtemplateを作ることもできます。
c.f https://docs.helm.sh/chart_template_guide/#flow-control

values

templateに値を渡す

templateを作成したので、次はtemplateに値を渡してみましょう。
templateに値を提供する方法は主に二つあります。

c.f https://docs.helm.sh/developing_charts/#templates-and-values

  1. values.yamlを開発者が用意する
  2. chartの利用者が helm install コマンド時に値を渡す(values.yamlを上書きすることができる)

実際にvalues.yamlからtemplateに値を渡してみます。以下のように、values.yamlを書き換えます。

# mychart/values.yaml
favoriteDrink: coffee

先ほどのconfigmapのtemplateを以下のように書き換えます。

# mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  drink: {{ .Values.favoriteDrink }}

以下の--dry-run --debugフラグを使うことで、実際にはデプロイせずに、デプロイされるchartの内容を確認できます。
c.f https://docs.helm.sh/chart_template_guide/#adding-a-simple-template-call

When you want to test the template rendering, but not actually install anything, you can use helm install --debug --dry-run ./mychart. This will send the chart to the Tiller server, which will render the templates. But instead of installing the chart, it will return the rendered template to you so you can see the output:

$ helm install --dry-run --debug ./mychart
NAME:   wishing-porcupine
REVISION: 1
RELEASED: Sat Feb  9 19:39:31 2019
CHART: mychart-0.1.0
USER-SUPPLIED VALUES:
{}

COMPUTED VALUES:
favoriteDrink: coffee

HOOKS:
MANIFEST:

---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: wishing-porcupine-configmap
data:
  myvalue: "Hello World"
  drink: coffee

values.yamlで指定した値がtemplateで利用されていることが確認できます。

また、--setフラグでvalues.yamlの値をinstall時に上書きすることもできます。

$ helm install --dry-run --debug --set favoriteDrink=slurm ./mychart
NAME:   jittery-aardvark
REVISION: 1
RELEASED: Sat Feb  9 19:41:04 2019
CHART: mychart-0.1.0
USER-SUPPLIED VALUES:
favoriteDrink: slurm

COMPUTED VALUES:
favoriteDrink: slurm

HOOKS:
MANIFEST:

---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: jittery-aardvark-configmap
data:
  myvalue: "Hello World"
  drink: slurm

subchartの値を操作する

次にsubchart(現在のchartが依存するchart)を作ってみます。

$ helm create mychart/charts/mysubchart
Creating mysubchart
$ rm -rf mysubchart/templates/*

subchartのtemplateに以下のファイルを追加します。

# mychart/charts/mysubchart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-cfgmap2
data:
  dessert: {{ .Values.dessert }}

そして、subchartのvalues.yamlを以下のように書き換えます。

# mychart/charts/mysubchart/values.yaml
dessert: cake

top levelのchart(mychart)はsubchart(mychart/charts/mysubchart)のvalues.yamlも利用することができます。その場合は対象のsubchartの名前を挟む必要があります。

c.f https://docs.helm.sh/developing_charts/#scope-dependencies-and-values

Charts at a higher level have access to all of the variables defined beneath

以下のように、対象のsubchartの名前を指定して、そのsubchartのvalues.yamlの値をtop levelのtemplateから参照できます。

# mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  drink: {{ .Values.favoriteDrink }}
  dessert: {{ .Values.mysubchart.dessert }}
$ helm install --dry-run --debug ./mychart
---
# Source: mychart/charts/mysubchart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: imprecise-chimp-cfgmap2
data:
  dessert: cake
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: imprecise-chimp-configmap
data:
  myvalue: "Hello World"
  drink: coffee
  dessert: cake

またsubchartのtemplateに渡される値をtop level のvalues.yamlから上書きすることもできます。

subchartでは、以下のように値が指定されています。

# mychart/charts/mysubchart/values.yaml
dessert: cake

これをtop levelのvalues.yamlで上書きしてみます。

# mychart/values.yaml
favoriteDrink: coffee
mysubchart:
  dessert: ice cream

cakeではなく、ice creamに値が上書きされていることが確認できます。

$ helm install --dry-run --debug ./mychart
---
# Source: mychart/charts/mysubchart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: illocutionary-seal-cfgmap2
data:
  dessert: ice cream
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: illocutionary-seal-configmap
data:
  myvalue: "Hello World"
  drink: coffee
  dessert: ice cream

値の上書きの優先順位

実際は以下のような優先順位でtemplateに渡す値を上書きすることができます。
c.f https://docs.helm.sh/chart_template_guide/#values-files

  1. --set フラグでkey-valueを指定
  2. -f フラグで利用するvalues.yamlを指定
  3. top levelのvalues.yaml
  4. subchartのvalues.yaml

このような前提を成り立たせるためにsubchartはそれだけで独立(親のchartに依存しない)する必要があります。なぜなら親が必ずsubchartで定義した値を上書きするとは限らないからです。

c.f https://docs.helm.sh/chart_template_guide/#subcharts-and-global-values

global values

ここまでvalues.yamlの機能を説明してきましたが、グローバルな値を定義することも可能です。
c.f https://docs.helm.sh/chart_template_guide/#global-chart-values

Global values are values that can be accessed from any chart or subchart by exactly the same name.
The Values data type has a reserved section called Values.global where global values can be set.

今まで特定のsubchartのvalues.yamlを上書きするには、subchartの名前(Chart.yamlのname)を指定する必要がありました。

# values.yaml
mysubchart_1:
  dessert: ice cream
mysubchart_2:
  dessert: ice cream

しかし、global valuesだとsubchartの名前の指定なく全てのsubchartの{{ .Values.global.dessert }}の値を上書きできます。

# values.yaml
global:
  dessert: ice cream

書くための規則

chartを今まで作成してきましたが、書く上でのベストプラクティスが存在します。

yamlのフォーマット

c.f https://docs.helm.sh/chart_best_practices/#formatting-yaml

  • tabではなく、2 spaceでインデントする

chart

c.f https://docs.helm.sh/chart_best_practices/#chart-names

  • 小文字で始まる名前をつける
  • 大文字やアンダースコア, ドットは名前に使うべきではない

template

c.f https://docs.helm.sh/chart_best_practices/#templates

  • camelCaseではなくdashed notationでファイルを名付ける(e.g my-example-configmap.yaml)
  • resourceの種類を反映したファイル名前にする(e.g my-service.yaml)

values

c.f https://docs.helm.sh/chart_best_practices/#values

  • 小文字で始まるcamelCaseで名付ける(e.g chickenNoodleSoup: true
  • 丁寧にnestして値を定義した方がいい
    • nestしていると、それぞれの名前空間が存在するかチェックされるので安全
    • 名前空間が区切られていた方が分かりやすい

release管理をする

releaseとは、k8sクラスタにデプロイされたマニフェストの集合(chart)です。
したがって、helm install [chart-name]でtillerがk8sクラスタにapplyするとreleaseが作成されます。

$ helm ls
NAME            REVISION        UPDATED                         STATUS          CHART           APP VERSION     NAMESPACE
hardy-grizzly   1               Sat Feb  9 19:23:20 2019        DEPLOYED        mychart-0.1.0   1.0             default

helm delete [release-name]でクラスタからreleaseの内容のマニフェストを削除することができます。
しかし削除されても履歴管理のためにrelease自体は残されます。
c.f https://docs.helm.sh/using_helm/#uninstall-a-release

Because Helm tracks your releases even after you’ve deleted them, you can audit a cluster’s history, and even undelete a release (with helm rollback).

$ helm delete hardy-grizzly
release "hardy-grizzly" deleted

$ helm ls --deleted
NAME            REVISION        UPDATED                         STATUS  CHART           APP VERSION     NAMESPACE
hardy-grizzly   1               Sat Feb  9 19:23:20 2019        DELETED mychart-0.1.0   1.0             default

これを以下のように巻き戻すこともできます。

$ helm rollback hardy-grizzly 1
Rollback was a success! Happy Helming!

$ helm ls
NAME            REVISION        UPDATED                         STATUS          CHART           APP VERSION     NAMESPACE
hardy-grizzly   2               Sat Feb  9 20:27:44 2019        DEPLOYED        mychart-0.1.0   1.0             default

また以下のように履歴を確認することもできます。
c.f https://docs.helm.sh/helm/#helm-history

$ helm history hardy-grizzly
REVISION        UPDATED                         STATUS          CHART           DESCRIPTION
1               Sat Feb  9 20:46:21 2019        SUPERSEDED      mychart-0.1.0   Deletion complete
2               Sat Feb  9 20:47:09 2019        DEPLOYED        mychart-0.1.0   Rollback to 1

--purgeフラグでreleaseも含めて完全に削除することができます。

$ helm delete --purge hardy-grizzly
release "hardy-grizzly" deleted

最後に

ちなみに、tillerはv3からは無くなる予定のようです。
c.f https://github.com/helm/community/blob/master/helm-v3/000-helm-v3.md#summary

Tiller is gone, and there is only one functional component (helm)

47
35
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
47
35