2021年3月追記(本当はもっと後に書いたけど、そういうことにする)
本記事は Helm v2 に関して記載しており、情報が相当古いです。
今から読むならこちらの記事を参照ください 🙇♂️🙇♂️
Prometheus、Grafanaあたりをコード管理していくにはHelmが良さそうなので勉強。
コンセプト
コマンド
リポジトリ系
$ helm repo add loki https://grafana.github.io/loki/charts #リポジトリの追加 $ helm repo list $ helm inspect chart loki/loki-stack $ helm inspect values loki/loki-stack $ helm install -n monitoring loki/loki-stack --generate-name #リポジトリで公開されているChartを使ってアプリケーションをインストール(デプロイ)する $ helm list -n monitoring #デプロイされたReleaseの一覧 NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION loki-stack-1591529810 monitoring 1 2020-06-07 20:36:59.2916867 +0900 JST deployed loki-stack-0.37.3 v1.5.0
デプロイ時にパラメータ設定を行う
以下2通り。
helm install --set <パラメータ名>=<値>, <パラメータ名>=<値> helm install -f <YAMLファイル>
インストールしたHelmのアップグレード
$ helm upgrade loki-stack-1591529810 -n monitoring loki/loki-stack --set wordpressBlogName=foobar#Releaseのアップグレード $ helm history loki-stack-1591529810 -n monitoring #「helm upgrade」コマンドでアップグレードを行った履歴
既存Chartのダウンロード
$ helm pull stable/wordpress #既存Chartのダウンロード $ helm install wordpress ./wordpress #ファイルでのインストール
リリース系
- helm install : チャートからリリースを作成
# v2 $ helm install <チャート名> -n <リリース名> # v3 $ helm install <リリース名> <チャート名> # デバッグ $ helm install . --debug --dry-run
- helm upgrade : チャート更新があったら、作成済みリリースに更新適用
- helm delete : リリースを削除
- helm ls : リリースをリストアップ
- helm get [values, manifest] : リリースの情報表示
チャート系
- helm repository [list, add, delete] : チャートのレポジトリを追加/削除
- helm create : 自作チャートの雛形作成
- helm dependency : チャート内の依存関係解決
- helm search : チャートを検索
チャート作成
$ helm create mychart Creating mychart $ tree mychart/ mychart/ ├── Chart.yaml # チャートの概要 ├── charts # このチャートが依存するチャート(Subchart)を格納するディレクトリー ├── templates # マニフェストのテンプレートを格納するディレクトリー │ ├── NOTES.txt # OPTIONAL: チャートの使用方法を記載したプレーンテキスト │ ├── _helpers.tpl # includeやtemplateアクションでの参照先 │ ├── deployment.yaml │ ├── ingress.yaml │ ├── service.yaml │ ├── serviceaccount.yaml │ └── tests │ └── test-connection.yaml └── values.yaml # このチャートのデフォルト値を記載したyaml。install/update時に環境に応じたファイルを渡すことで定義し値を差し替え可能 3 directories, 9 files
構文
- 構文は
{{}}
に囲まれて表記。それ以外の部分はk8sマニフェスト {{- -}}
のように-
をつけることで、それより前の半角スペース、それより後の改行コードを除外できる{{- /**/ -}}
のように/**/
でコメント
変数
{{ . }}
による参照と{{ $ }}
による参照があり、前者はvalues.yamlなどでの定義、後者は自ファイル内での定義- 事前定義変数
# template/deployment.yaml replicas: {{ .Values.replicaCount }} --- # values.yaml replicaCount: 1
# https://qiita.com/keiSunagawa/items/db0db26579d918c81457 {{- $volumeName := "myvolume" -}} volumeMounts: - mountPath: /etc/{{ $volumeName }}/ name: {{ $volumeName }} volumes: - name: {{ $volumeName }}
# template/deployment.yaml containers: - name: {{ .Chart.Name }} ---
# template/deployment.yaml app.kubernetes.io/instance: {{ .Release.Name }} ---
関数
nindent
- パイプで渡すことで、引数に渡した数の半角インデントを埋め込む
toYaml
- 変数をyaml形式で展開
# template/deployment.yaml securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} --- # values.yaml podSecurityContext: {}
include
templates/_helpers.tpl
に定義した名前付きtemplateの展開include <定義名> パス
。基本パスは.
(ルート)を使うぽい
# template/deployment.yaml metadata: name: {{ include "mychart.fullname" . }} labels: {{ include "mychart.labels" . | indent 4 }} spec: replicas: {{ .Values.replicaCount }} selector: matchLabels: app.kubernetes.io/name: {{ include "mychart.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} --- # templates/_helpers.tpl {{- define "mychart.name" -}} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} {{- end -}} {{- define "mychart.labels" -}} app.kubernetes.io/name: {{ include "mychart.name" . }} helm.sh/chart: {{ include "mychart.chart" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- if .Chart.AppVersion }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} {{- end }} app.kubernetes.io/managed-by: {{ .Release.Service }} {{- end -}} # .Values.nameOverrideがなければ$name=.Chart.Name # .Chart.Nameに.Release.Nameが含まれなければ、.Release.Name-.Chart.Nameを返す(なるほどだから、sample-mychartとなったわけだ {{- define "mychart.fullname" -}} {{- if .Values.fullnameOverride -}} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} {{- else -}} {{- $name := default .Chart.Name .Values.nameOverride -}} {{- if contains $name .Release.Name -}} {{- .Release.Name | trunc 63 | trimSuffix "-" -}} {{- else -}} {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} {{- end -}} {{- end -}} {{- end -}}
アクション
- if/for/withなどをアクションと呼ぶらしい
if
-
付きが推奨
# templates/_helpers.tpl {{- if .Chart.AppVersion }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} {{- end }}
with
- 引数に渡したオブジェクトをルートオブジェクトとして展開
# template/deployment.yaml spec: {{- with .Values.imagePullSecrets }} imagePullSecrets: {{- toYaml . | nindent 8 }} #この.(ルート)は.Vlues.imagePullSecretsを指す {{- end }} --- # values.yaml imagePullSecrets: []
- withブロック内では事前定義オブジェクトは使えないため、事前にファイル定義しておく
# https://helm.sh/docs/chart_template_guide/variables/ {{- $relname := .Release.Name -}} {{- with .Values.favorite }} drink: {{ .drink | default "tea" | quote }} food: {{ .food | upper | quote }} release: {{ $relname }} {{- end }}
range
- 引数に渡した配列でループを回す
# https://qiita.com/keiSunagawa/items/db0db26579d918c81457#range # values.yaml configPaths: - key: nginx.conf path: "files/nginx.conf" - key: postfix.main.cf path: "files/main.cf" --- # comfigmap.yaml {{- $files = .Files -}} data: {{- range .Values.configPaths -}} {{ .key }}: | {{ $files.get .path | nindent 4 }} {{- end -}}
template
_helpers.tpl
に定義してある名前付きtemplateを展開- ほぼincludeと一緒?
# template/deployment.yaml serviceAccountName: {{ template "mychart.serviceAccountName" . }} --- # templates/_helpers.tpl {{- define "mychart.serviceAccountName" -}} {{- if .Values.serviceAccount.create -}} {{ default (include "mychart.fullname" .) .Values.serviceAccount.name }} {{- else -}} {{ default "default" .Values.serviceAccount.name }} {{- end -}} {{- end -}}
yamlサンプル
deployment.yaml
# mychart/templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "mychart.fullname" . }} labels: {{ include "mychart.labels" . | indent 4 }} spec: replicas: {{ .Values.replicaCount }} selector: matchLabels: app.kubernetes.io/name: {{ include "mychart.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} template: metadata: labels: app.kubernetes.io/name: {{ include "mychart.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} spec: {{- with .Values.imagePullSecrets }} imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} serviceAccountName: {{ template "mychart.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} containers: - name: {{ .Chart.Name }} securityContext: {{- toYaml .Values.securityContext | nindent 12 }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" imagePullPolicy: {{ .Values.image.pullPolicy }} ports: - name: http containerPort: 80 protocol: TCP livenessProbe: httpGet: path: / port: http readinessProbe: httpGet: path: / port: http resources: {{- toYaml .Values.resources | nindent 12 }} {{- with .Values.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.affinity }} affinity: {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.tolerations }} tolerations: {{- toYaml . | nindent 8 }} {{- end }}
values.yaml
# mychart/values.yaml # Default values for mychart. # This is a YAML-formatted file. # Declare variables to be passed into your templates. replicaCount: 1 image: repository: nginx tag: stable pullPolicy: IfNotPresent imagePullSecrets: [] nameOverride: "" fullnameOverride: "" serviceAccount: # Specifies whether a service account should be created create: true # The name of the service account to use. # If not set and create is true, a name is generated using the fullname template name: podSecurityContext: {} # fsGroup: 2000 securityContext: {} # capabilities: # drop: # - ALL # readOnlyRootFilesystem: true # runAsNonRoot: true # runAsUser: 1000 service: type: ClusterIP port: 80 ingress: enabled: false annotations: {} # kubernetes.io/ingress.class: nginx # kubernetes.io/tls-acme: "true" hosts: - host: chart-example.local paths: [] tls: [] # - secretName: chart-example-tls # hosts: # - chart-example.local resources: {} # We usually recommend not to specify default resources and to leave this as a conscious # choice for the user. This also increases chances charts run on environments with little # resources, such as Minikube. If you do want to specify resources, uncomment the following # lines, adjust them as necessary, and remove the curly braces after 'resources:'. # limits: # cpu: 100m # memory: 128Mi # requests: # cpu: 100m # memory: 128Mi nodeSelector: {} tolerations: [] affinity: {}
templates/_helpers.tpl
# templates/_helpers.tpl {{/* vim: set filetype=mustache: */}} {{/* Expand the name of the chart. */}} {{- define "mychart.name" -}} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} {{- end -}} {{/* Create a default fully qualified app name. We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). If release name contains chart name it will be used as a full name. */}} {{- define "mychart.fullname" -}} {{- if .Values.fullnameOverride -}} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} {{- else -}} {{- $name := default .Chart.Name .Values.nameOverride -}} {{- if contains $name .Release.Name -}} {{- .Release.Name | trunc 63 | trimSuffix "-" -}} {{- else -}} {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} {{- end -}} {{- end -}} {{- end -}} {{/* Create chart name and version as used by the chart label. */}} {{- define "mychart.chart" -}} {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} {{- end -}} {{/* Common labels */}} {{- define "mychart.labels" -}} app.kubernetes.io/name: {{ include "mychart.name" . }} helm.sh/chart: {{ include "mychart.chart" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- if .Chart.AppVersion }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} {{- end }} app.kubernetes.io/managed-by: {{ .Release.Service }} {{- end -}} {{/* Create the name of the service account to use */}} {{- define "mychart.serviceAccountName" -}} {{- if .Values.serviceAccount.create -}} {{ default (include "mychart.fullname" .) .Values.serviceAccount.name }} {{- else -}} {{ default "default" .Values.serviceAccount.name }} {{- end -}} {{- end -}}