HelmでKubernetesのマニフェストファイルを管理する

Helmを使って公開されているChartをインストール方法はたくさん紹介されていますが、独自のChartを作成する方法が簡潔に紹介されている記事が無かったので紹介します。

Helm自体の紹介やインストール方法などは省略します。

環境

Chartの初期化

$ helm create example

で必要となるファイル一式が作成されます。
中身は以下のようになっています。

$ tree example
example
├── Chart.yaml
├── charts
├── templates
│   ├── NOTES.txt
│   ├── _helpers.tpl
│   ├── deployment.yaml
│   ├── ingress.yaml
│   ├── service.yaml
│   ├── serviceaccount.yaml
│   └── tests
│       └── test-connection.yaml
└── values.yaml

3 directories, 9 files

このようなファイルが作成されますが、使わないファイルが多いので以下のファイル以外を削除します。

  • example/Chart.yaml
  • example/templates/deployment.yaml
  • example/templates/_helpers.tpl
  • example/values.yaml

テンプレートの内容

example/templates 配下がテンプレートが配置されるディレクトリになります。 deployment.yaml の中を見てみます。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "example.fullname" . }}
  labels:
    {{- include "example.labels" . | nindent 4 }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      {{- include "example.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "example.selectorLabels" . | nindent 8 }}
    spec:
    {{- with .Values.imagePullSecrets }}
      imagePullSecrets:
        {{- toYaml . | nindent 8 }}
    {{- end }}
      serviceAccountName: {{ include "example.serviceAccountName" . }}
      securityContext:
        {{- toYaml .Values.podSecurityContext | nindent 8 }}
      containers:
        - name: {{ .Chart.Name }}
          securityContext:
            {{- toYaml .Values.securityContext | nindent 12 }}
          image: "{{ .Values.image.repository }}:{{ .Chart.AppVersion }}"
          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 }}

これに変数が代入されてマニフェストファイルが生成されます。

マニフェストファイルの生成

helm template コマンドでマニフェストファイルを生成します。

$ helm template ./example --name-template example --namespace default
---
# Source: example/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: example_template
  labels:
    helm.sh/chart: example-0.1.0
    app.kubernetes.io/name: example
    app.kubernetes.io/instance: example_template
    app.kubernetes.io/version: "1.16.0"
    app.kubernetes.io/managed-by: Helm
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: example
      app.kubernetes.io/instance: example_template
  template:
    metadata:
      labels:
        app.kubernetes.io/name: example
        app.kubernetes.io/instance: example_template
    spec:
      serviceAccountName: example_template
      securityContext:
        {}
      containers:
        - name: example
          securityContext:
            {}
          image: "nginx:1.16.0"
          imagePullPolicy: IfNotPresent
          ports:
            - name: http
              containerPort: 80
              protocol: TCP
          livenessProbe:
            httpGet:
              path: /
              port: http
          readinessProbe:
            httpGet:
              path: /
              port: http
          resources:
            {}

テンプレートの変数

テンプレートに代入された変数がどこに定義されたものか紹介します。

  • .Values
    • values.yamlで宣言されているものを.つなぎで指定し読み込みます
  • include
    • _helpers.tpldefine "変数名"と宣言されているものが読み込まれます
  • .Chart
    • Chart.yaml`に書かれた値を読み込んでいます
  • .Release
    • 生成時に引数として渡されたものが読み込まれます

その他の変数や関数はなんとなく雰囲気で理解できそうですが、以下の公式ドキュメントに書かれています。

helm.sh

helm.sh

helm.sh

インストール

生成したマニフェストファイルをパイプでkubectlに渡せばOKです。

$ helm template ./example --name-template example --namespace default | kubectl apply -f -

また、helmが無い環境でもインストールするためにyamlファイルとして保存してしまうのも1つのやり方だと思います。

$ helm template ./example --name-template example --namespace default > bundle.yaml