K8sを使って時間が経ってくると、マニフェストが氾濫して、整理ができなくなってくる。幾つかのマニフェストを組み合わせたい場合や、少しづつ変更して再利用したい場合など、いろいろと不便を感じるようになる。そこで「Helmを勉強しないで、Helmのメリットを享受したい」と作ったメモである。
とりあえずマニフェストを再利用したければ、ココに置け
テンプレートのチャートを作って、templateのフォルダへ必要なマニフェストで置き換える。そのあとは、helm install でデプロイ完了となる。
テンプレート・チャートを作成
$ helm create my-apl
Creating my-apl
テンプレートのチャートを削除して、利用したいマニフェストで置き換える
$ rm -fr my-apl/templates/*
$ cp my-manifest/* my-apl/template
Helmを使ってインストール -n は、リリース名を明示的に付与するもので、省略すると適当にリリース名が付与される。--namespace <名前空間名> を付与した場合、既存になければ新しい名前空間を作成して、その下にアプリケーションをデプロイしてくれる。
$ helm install -n test1 ./my-apl
実行中のHelmチャートを確認は、ls または list
$ helm ls
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
test1 1 Wed Aug 14 22:16:35 2019 DEPLOYED my-apl-0.1.0 1.0 default
実行中のHelmチャートを削除する場合、--purgeを忘れないようにする。
$ helm delete mini1 --purge
release "mini1" deleted
複数のリリースに対応したければ {{ .Release.Name }} を利用
Helmはリリースによって、同じ名前空間に複数のオブジェクトをデプロイできる。この機能を活かすために、
templatesにおくマニフェストに、幾つかの変更を加える。
この機能を有効に使うには、重複が許されないオブジェクト名やラベルに、{{ .Release.Name }}を追加する。
サービスをデプロイするマニフェストでは、metadata.name の値、selector.appの値に追加して、同じ名前空間内で重複がないようにする。
apiVersion: v1
kind: Service
metadata:
name: web-{{ .Release.Name }}
spec:
selector:
app: web-{{ .Release.Name }}
ports:
- protocol: TCP
port: 80
ポッドをデプロイするためのデプロイメント・コントローラーのマニフェストも同じで、サービスやデプロイメント・コントローラーとポッドを繋ぐための
レベルとデプロイメントのオブジェクト名に「-{{ .Release.Name }}」を追加する。
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-{{ .Release.Name }}
spec:
replicas: 3
selector:
matchLabels:
app: web-{{ .Release.Name }}
template:
metadata:
labels:
app: web-{{ .Release.Name }}
spec:
containers:
- name: nginx
image: nginx:latest
上記の変更を加えたチャートを使って、
リリース名として、test2, test3 を付与してインストールする。
この変更を加えなければ、オブジェクト名重複するために、デプロイ時にエラーが発生する。また、マッチ・ラベルに{{ .Release.Name }}を加えなければ、
サービスが、リクエストを転送する先のポッドが、test1〜test3で混ざってしまい、想定外の動作をする。
$ helm install -n test2 ./my-apl
$ helm install -n test3 ./my-apl
$ helm ls
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
test1 1 Wed Aug 14 22:16:35 2019 DEPLOYED my-apl-0.1.0 1.0 default
test2 1 Wed Aug 14 22:27:17 2019 DEPLOYED my-apl-0.1.0 1.0 default
test3 1 Wed Aug 14 22:27:23 2019 DEPLOYED my-apl-0.1.0 1.0 default
これで、セレクターとラベルの対応が、混ざっていないことを確認できる。
$ kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
web ClusterIP 172.21.53.158 <none> 80/TCP 23m app=web
web-test2 ClusterIP 172.21.148.177 <none> 80/TCP 12m app=web-test2
web-test3 ClusterIP 172.21.61.96 <none> 80/TCP 12m app=web-test3
$ kubectl get po --show-labels
NAME READY STATUS RESTARTS AGE LABELS
web-d97869bd8-d67vt 1/1 Running 0 12m app=web,pod-template-hash=d97869bd8
web-d97869bd8-kw8v9 1/1 Running 0 12m app=web,pod-template-hash=d97869bd8
web-d97869bd8-tbqpr 1/1 Running 0 12m app=web,pod-template-hash=d97869bd8
web-test2-78d55dc8b4-2jscx 1/1 Running 0 97s app=web-test2,pod-template-hash=78d55dc8b4
web-test2-78d55dc8b4-7qxg6 1/1 Running 0 97s app=web-test2,pod-template-hash=78d55dc8b4
web-test2-78d55dc8b4-m5qwt 1/1 Running 0 97s app=web-test2,pod-template-hash=78d55dc8b4
web-test3-79d548cc9f-pvgzc 1/1 Running 0 92s app=web-test3,pod-template-hash=79d548cc9f
web-test3-79d548cc9f-zk7rq 1/1 Running 0 92s app=web-test3,pod-template-hash=79d548cc9f
web-test3-79d548cc9f-zpzdr 1/1 Running 0 92s app=web-test3,pod-template-hash=79d548cc9f
デプロイの前提となるマニフェストは、ここへ置け
$ tree my-apl/
my-apl/
├── Chart.yaml
├── charts <-- ここに置けば、前提のHelmチャートとして、実行される。
├── templates
│ ├── deployment.yml
│ └── service.yml
└── values.yaml
Redis Cluster でノードのストレージを localとして利用する際に、ストレージクラス local のセットアップと永続ボリュームのセットアップに利用している例である。
$ tree redis-cluster/
redis-cluster/
├── Chart.yaml
├── README.md
├── charts <-- このチャートのテンプレートが最初に実行
│ └── setup-local-pv
│ ├── Chart.yaml
│ ├── charts <-- さらにその前のチャートは、ここに置く
│ ├── templates
│ │ ├── create-pv-zone-A.yml
│ │ ├── create-pv-zone-B.yml
│ │ ├── create-pv-zone-C.yml
│ │ ├── sc.yml
│ │ ├── setup-local-zone-A.yml
│ │ ├── setup-local-zone-B.yml
│ │ └── setup-local-zone-C.yml
│ └── values.yaml
├── templates
│ ├── redis-cluster-on-zone-A.yml
│ ├── redis-cluster-on-zone-B.yml
│ ├── redis-cluster-on-zone-C.yml
│ ├── redis-configmap.yml
│ └── redis-service.yml
└── values.yaml
マニフェストに変数を埋め込んで再利用性を高めよ
テンプレートのマニフェストに、変数を置いて、デプロイ時に置き換えるには、values.yamlに変数の値を書いて、マニフェストから参照する。
次の例は、グローバル変数を参照する例です。グローバルに、つまり、前提とするチャートからも参照したい時は、globalの下に変数名と値を記述する。ローカルのテンプレートで良い場合は、最初のレベルに記述する。
global:
region: jp-tok
zoneA: tok02
zoneB: tok04
zoneC: tok05
変数の値で置き換えたいマニフェストからは、{{ .Vaules.global.zoneA}}を置くことで、最終的にデプロイされる時には、変数の値の文字列で置き換られる。
spec:
# ゾーンを指定
nodeSelector:
failure-domain.beta.kubernetes.io/zone: {{ .Values.global.zoneA | quote }}
上記の例では、パイプ記号で繋いで、quoteが書かれている。こうすることで、置き換えられた文字鉄の前後を"で囲むことができる。
利用方法などを伝えるには、NOTES.txtを活用せよ
チャートのディレクトリ templatesの下に、NOTES.txtを置いて、伝達事項を記述することができる。このファイルも、ユーザー変数やビルドイン変数で置き換えられるので、リリースに応じて変化する項目などを親切に表示できる。それに、日本語も記述できた。
最後に
ここに挙げた以上のことを使いたくなったら、参考資料を見ましょう。
参考資料
- https://github.com/helm/helm
- https://helm.sh/docs/
- Helmの使い方を3分で理解する、https://qiita.com/MahoTakara/items/3c509235cc18bd407f07
- カスタムなHELMチャートを開発してローカル・リポジトリでテストする方法のメモ、https://qiita.com/MahoTakara/items/8d8e8b45ef91341c3ee2