helmを導入してK8sのyamlをテンプレート記載したい
- helmとは
- なぜhelmがほしいのか
helmとは
Kubernetes(K8s)に関する技術で、K8s用のyamlを記載しやすいようにするモノ、という理解
そもそもパッケージ管理ソフトなので、wordpress
をK8sで入れたい!とかいうときに世の中にあるパッケージを使ってインストールということも可能(ぽい)
- 参考 qiita.com
なぜhelmがほしいのか
どういうシーンでほしいかというと
例えば、iamgeのpullするUrlを隠蔽したい場合、です。(もしくは環境毎にimageの情報が変わる、など)
- imageはECRからpullしたい
- 例:
<i>aws_account_id</i>.dkr.ecr.us-west-2.amazonaws.com/amazonlinux:latest
からpullしたい
- 例:
- でもGitHubのpublicなリポジトリに直接AWSアカウントをpushしたくない
結論
例えば、
apiVersion: apps/v1 kind: Deployment metadata: name: sample-deployment labels: app: sample spec: replicas: 2 selector: matchLabels: app: sample template: metadata: labels: app: sample spec: containers: - name: sample image: aws_account_id.dkr.ecr.us-west-2.amazonaws.com/amazonlinux:latest ports: - containerPort: 80
こんなふうに、直接imageを記載するのを避けたい。
(aws_account_id.dkr.ecr.us-west-2.amazonaws.com/amazonlinux:latest
を直接記載したくない)
version情報
$ helm version version.BuildInfo{Version:"v3.3.3", GitCommit:"55e3ca022e40fe200fbc855938995f40b2a68ce0", GitTreeState:"dirty", GoVersion:"go1.15.2"}
$ kubectl version Client Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.0", GitCommit:"70132b0f130acc0bed193d9ba59dd186f0e634cf", GitTreeState:"clean", BuildDate:"2019-12-13T11:52:32Z", GoVersion:"go1.13.4", Compiler:"gc", Platform:"darwin/amd64"} Server Version: version.Info{Major:"1", Minor:"16+", GitVersion:"v1.16.6-beta.0", GitCommit:"e7f962ba86f4ce7033828210ca3556393c377bcc", GitTreeState:"clean", BuildDate:"2020-01-15T08:18:29Z", GoVersion:"go1.13.5", Compiler:"gc", Platform:"linux/amd64"}
helm
上記問題点をhelmを使うことによって解決できます
helmはyamlの一つの機能として、テンプレーティングを行えます。
上記sample-deployment
というdeploymentを例にすると
apiVersion: apps/v1 kind: Deployment metadata: name: sample-deployment labels: app: sample spec: replicas: 2 selector: matchLabels: app: sample template: metadata: labels: app: sample spec: containers: - name: sample image: {{ .Values.app.imageUrl }} ports: - containerPort: 80
このように{{ .Values.app.imageUrl }}
と記載し、この部分をhelmに別ファイルで渡すことができます
そしてその別ファイルをGitHubにpushしない運用によって、秘匿情報を隠蔽できたり、環境毎にyamlを用意しなくても済む、というもの。
helmを使うと、K8sのyamlを直接記載せずに、
上記テンプレートだけをひたすら記載するような運用になる(と思います)
helm使い方
- helmのインストール
$ brew install helm
- helmの初期化(プロジェクト作成)
$ helm create mychart
mychart
フォルダにサンプルとなるchart類が作成されます
フォルダ構成は以下の感じ
./mychart ├── Chart.yaml ├── charts ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── deployment.yaml │ ├── hpa.yaml │ ├── ingress.yaml │ ├── service.yaml │ ├── serviceaccount.yaml │ └── tests │ └── test-connection.yaml └── values.yaml
基本的にいじるのが、templates
ディレクトリの中身と、values.yaml
の中身
最小限の構成への変更
シンプルな構成とするために、上記helm create mychart
で作ったchartから、不要部分を削除します
以下のファイルを削除
mychart/charts/
削除mychart/templates/
の中身削除mychart/values.yaml
の中身を全削除
mychart/values.yaml
を記入
app: imageUrl: aws_account_id.dkr.ecr.us-west-2.amazonaws.com/amazonlinux:latest
mychart/tempates/deployment.yaml
を記入
apiVersion: apps/v1 kind: Deployment metadata: name: sample-deployment labels: app: sample spec: replicas: 2 selector: matchLabels: app: sample template: metadata: labels: app: sample spec: containers: - name: sample image: {{ .Values.app.imageUrl }} ports: - containerPort: 80
上記2つのファイルを記載した状態でheml install
していきます
helm installのチェック
$ helm install --dry-run --debug --generate-name ./mychart
これで、このhelmを実行した際に何が起こるか(どのようなK8sリソースが作成されるか)がわかる
$ helm install --dry-run --debug --generate-name ./mychart NAME: mychart-1600747915 LAST DEPLOYED: Tue Sep 22 13:11:56 2020 NAMESPACE: default STATUS: pending-install REVISION: 1 TEST SUITE: None USER-SUPPLIED VALUES: {} COMPUTED VALUES: app: imageUrl: aws_account_id.dkr.ecr.us-west-2.amazonaws.com/amazonlinux:latest HOOKS: MANIFEST: --- # Source: mychart/templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: sample-deployment labels: app: sample spec: replicas: 2 selector: matchLabels: app: sample template: metadata: labels: app: sample spec: containers: - name: sample image: aws_account_id.dkr.ecr.us-west-2.amazonaws.com/amazonlinux:latest ports: - containerPort: 80
このように表示されます
肝心のimage
部分image: aws_account_id.dkr.ecr.us-west-2.amazonaws.com/amazonlinux:latest
となっているので想定通り
helm install
helm install
にてリソースをK8sに反映していきます。
以下のようなコマンド構成です。
$ helm install <chart-name> <chart-directory>
chartに名前を付ける必要があります
(省略できるようですが、省略した場合ランダムな名前がつけられてめんどくさいので、原則名前つけないといけない)
$ helm install chartname ./mychart NAME: chartname LAST DEPLOYED: Tue Sep 22 13:20:16 2020 NAMESPACE: default STATUS: deployed REVISION: 1 TEST SUITE: None
このように出ます。
kubectlで確認
$ kubectl get all NAME READY STATUS RESTARTS AGE pod/sample-deployment-b978cbc69-lczpd 0/1 ErrImagePull 0 32s pod/sample-deployment-b978cbc69-tswdg 0/1 ErrImagePull 0 32s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 9d NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/sample-deployment 0/2 2 0 32s NAME DESIRED CURRENT READY AGE replicaset.apps/sample-deployment-b978cbc69 2 2 0 32s
image
がめちゃくちゃ適当な名前(aws_account_id.dkr.ecr.us-west-2.amazonaws.com/amazonlinux:latest
)なので起動は失敗していますが、なんかそれっぽい。
helm list
$ helm listNAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION chartname default 1 2020-09-22 13:20:16.082367 +0900 JST deployed mychart-0.1.0 1.16.0
インストール済みのhelmのlistが出ます
helm upgradeの準備
インストール済みのchartを更新したい場合にはhelm upgrade
です
$ helm upgrade <chart-name>
今回以下の内容を変更します
- deploymentのコンテナ名称を
myapp
にする - imageを
nginx:latest
にする
values.yamlの変更
app: imageUrl: nginx:latest appName: myapp
このように変更しました
deployment.yaml
を変更
apiVersion: apps/v1 kind: Deployment metadata: name: sample-deployment labels: app: sample spec: replicas: 2 selector: matchLabels: app: sample template: metadata: labels: app: sample spec: containers: - name: {{ .Values.app.appName }} image: {{ .Values.app.imageUrl }} ports: - containerPort: 80
{{ .Values.app.appName }}
を追記
helm upgradeの実行
helm upgrade
によってchartが更新できるわけですが、その前に内容を確認したいです。
その場合には--dry-run
を使います。
ついでに--debug
表示もします
$ helm upgrade --dry-run --debug chartname ./mychart upgrade.go:121: [debug] preparing upgrade for chartname upgrade.go:129: [debug] performing update for chartname upgrade.go:287: [debug] dry run for chartname Release "chartname" has been upgraded. Happy Helming! NAME: chartname LAST DEPLOYED: Tue Sep 22 13:29:21 2020 NAMESPACE: default STATUS: pending-upgrade REVISION: 2 TEST SUITE: None USER-SUPPLIED VALUES: {} COMPUTED VALUES: app: appName: myapp imageUrl: nginx:latest HOOKS: MANIFEST: --- # Source: mychart/templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: sample-deployment labels: app: sample spec: replicas: 2 selector: matchLabels: app: sample template: metadata: labels: app: sample spec: containers: - name: myapp image: nginx:latest ports: - containerPort: 80
これで結果を確認できます(まだ適応されてはおらず、結果を表示しただけです)
pluginについて
helm upgrade
を実行する前に、diffというプラグインを使ってみます
helmの差分を表示できるpluginのようです
github.com
hlem用のプラグインが多く開発されており、いろいろなものがあるようです。
- diff pluginのinstall
$ helm plugin install https://github.com/databus23/helm-diff
diffの確認
--values
でvalues.yamlを指定しています(これしないとうまく差分が出ない)
helm diff upgrade chartname ./mychart --values ./mychart/values.yaml default, sample-deployment, Deployment (apps) has changed: # Source: mychart/templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: sample-deployment labels: app: sample spec: replicas: 2 selector: matchLabels: app: sample template: metadata: labels: app: sample spec: containers: - - name: sample - image: aws_account_id.dkr.ecr.us-west-2.amazonaws.com/amazonlinux:latest + - name: myapp + image: nginx:latest ports: - containerPort: 80
内容は問題なさそうなので、helm upgrade
をやっていきます
helm upgradeの実行
helm upgrade
の実行をします
コマンドの実行結果は以下のような感じでした。
-values
に./mychart/values.yaml
を指定しています(diffのコマンドからdiff
部分を削除しただけ)
$ helm upgrade chartname ./mychart --values ./mychart/values.yaml Release "chartname" has been upgraded. Happy Helming! NAME: chartname LAST DEPLOYED: Tue Sep 22 13:58:40 2020 NAMESPACE: default STATUS: deployed REVISION: 2 TEST SUITE: None
upgrade
の結果の確認
$ kubectl get all NAME READY STATUS RESTARTS AGE pod/sample-deployment-787c75d69d-99gk7 1/1 Running 0 112s pod/sample-deployment-787c75d69d-x6krf 1/1 Running 0 106s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 9d NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/sample-deployment 2/2 2 2 4m7s NAME DESIRED CURRENT READY AGE replicaset.apps/sample-deployment-787c75d69d 2 2 2 112s replicaset.apps/sample-deployment-b978cbc69 0 0 0 4m7s
imageをnginxにしたので動き出しました。
一部設定の隠蔽
今回の目的はGitHubにPushしたくないことでした。
以下のような方針で秘匿情報を隠蔽します
values.yaml
にはデフォルト値を書いておくoverride.yaml
というファイルを作り、ここに秘匿情報を書く- 秘匿にしたい情報のみこのファイルに書く
- ファイル名はなんでもOKです
override.yaml
を.gitignore
登録しておく
override.yaml
以下のように記載します(今回はapp.imageUrl
を隠蔽したい)
app: imageUrl: aws_account_id.dkr.ecr.us-west-2.amazonaws.com/amazonlinux:latest
app.imageUrl
のみを上書きします
この状態でdiff
してみます
--values
コマンドを2つ以上指定することができます
helm diff upgrade chartname ./mychart --values ./mychart/values.yaml --values ./mychart/override.yaml default, sample-deployment, Deployment (apps) has changed: # Source: mychart/templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: sample-deployment labels: app: sample spec: replicas: 2 selector: matchLabels: app: sample template: metadata: labels: app: sample spec: containers: - name: myapp - image: nginx:latest + image: aws_account_id.dkr.ecr.us-west-2.amazonaws.com/amazonlinux:latest ports: - containerPort: 80
こうなります。
想定通り。
upgrade
します
$ helm upgrade chartname ./mychart --values ./mychart/values.yaml --values ./mychart/override.yaml
無事にupgrade
が完了
helm delete
最後は削除します
$ helm delete chartname