17
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

helm Chartを書くときに先に知っておきたかった良い8つのこと

Posted at

Kubernetes3 Advent Calendar 201811日目の記事です。

自分がhelm Chartのテンプレートを書く前に知っておけば良かったなーというポイントを紹介します。

大体、The Chart Template Developer’s Guideに書いてあるので、ここをちゃんと読んでから始めれば良いのですが...

1. 複数環境ある場合は--valuesオプションで変数を環境別に指定するのがよさそう

このスライドのように環境別に変数ファイルを使うのがよさそうな感じです。(同社なので、マネしてます...)

2. --setオプションは--valuesで指定したファイルを上書きする

tagの指定だけ上書きする時などに使っています。

3. - は難しい

ifの-は前の空白と改行を削除してくれるのですが、elseだけ表示したい場合にコントロールが難しいです...
下のように書くと、

  {{- if .Values.hpa.enabled -}}
  {{- else -}}
  replicas: {{ .Values.replicas | default "2" }}
  {{- end -}}
  selector:
    matchLabels:
      app.kubernetes.io/name: {{ include "my-chart.name" . }}
      app.kubernetes.io/instance: {{ .Release.Name }}

下のようになってしまいますが、yamlとして正しくないので、エラーになります...

spec:replicas: 3selector:
    matchLabels:
      app.kubernetes.io/name: my-chart
      app.kubernetes.io/instance: my-chart

ドキュメントには indent function ({{indent 2 "mug:true"}})と書けとあるのですが、この方法だとdefaultが使えない(?)ので、結局、下のようにしました。

spec:
  {{- if .Values.hpa.enabled -}}
  {{- else }}
  replicas: {{ .Values.replicas | default "2" }}
  {{- end }}
  selector:
    matchLabels:
      app.kubernetes.io/name: {{ include "my-chart.name" . }}
      app.kubernetes.io/instance: {{ .Release.Name }}

.Values.hpa.enabled trueの時、

spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: my-chart
      app.kubernetes.io/instance: my-chart

.Values.hpa.enabled falseの時、

spec:
  replicas: 3
  selector:
    matchLabels:
      app.kubernetes.io/name: my-chart
      app.kubernetes.io/instance: my-chart

下のようにしてみると、

  {{- if .Values.hpa.enabled -}}
  {{- else }}
  replicas: {{ .Values.replicas | default "2" }}
  {{ end -}}
  selector:
    matchLabels:
      app.kubernetes.io/name: {{ include "my-chart.name" . }}
      app.kubernetes.io/instance: {{ .Release.Name }}

trueの時ダメでした...

spec:selector:
    matchLabels:
      app.kubernetes.io/name: my-chart
      app.kubernetes.io/instance: my-chart
  template:
    metadata:
      labels:
        app.kubernetes.io/name: my-chart
        app.kubernetes.io/instance: my-chart

4. templateよりもincludeとnindentを使った方がよさそう

templateはインデントが制御されないので、 {{- include xxx . | nindent n }} と書いた方が良いようです。
複数containerあるときなど便利です。

apiVersion: apps/v1beta2
kind: Deployment
metadata:
  name: {{ include "my-chart.fullname" . }}
  labels:
    app.kubernetes.io/name: {{ include "my-chart.name" . }}
    helm.sh/chart: {{ include "my-chart.chart" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
    app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
  {{- if .Values.hpa.enabled -}}
  {{- else }}
  replicas: {{ .Values.replicas | default "2" }}
  {{- end }}
  selector:
    matchLabels:
      app.kubernetes.io/name: {{ include "my-chart.name" . }}
      app.kubernetes.io/instance: {{ .Release.Name }}
  template:
    metadata:
      labels:
        app.kubernetes.io/name: {{ include "my-chart.name" . }}
        app.kubernetes.io/instance: {{ .Release.Name }}
    spec:
      containers:
      # ここ
      {{- include "my-chart.app" . | nindent 6 }}
      {{- include "my-chart.sidecar" . | nindent 6 }}

5. withは書く量が減るが諸刃の剣

withを使った場合、endまでそのスコープの変数しか使えなくなるので、その階層とは別の変数を使いたい場合、endするか、再度定義するしかないです。
なので、さっき複数containerでテンプレートを分けると良いかもといいましたが、withを使うとスコープ毎に変数を定義しないといけない場合もあります。

{{- define "my-chart.sidecar" -}}
{{- with .Values.sidecar -}}
- image: "{{ .image.repository }}:{{ .image.tag | default "v1.0.2" }}"
  name: sidecar
  resources:
    requests:
      cpu: {{ .resources.requests.cpu | default "50m" }}
      memory: {{ .resources.requests.memory | default "50Mi" }}
    limits:
      cpu: {{ .resources.limits.cpu | default "100m" }}
      memory: {{ .resources.limits.memory | default "100Mi" }}
  ports:
  - containerPort: 24224
    name: sidecar
    protocol: "TCP"
  env:
  - name: SIDECAR_WEB_HOST
    value: "localhost:9990"
{{- end -}}
{{- end -}}

6. テンプレートのネストとwithのネスト

テンプレートのネストは普通に出来ます。インデントは継承されるので、下記の例だと6 + 2になります。
(上で例示したdeployment内の{{- include "my-chart.app" . | nindent 6 }}のため)

{{- define "my-chart.app" -}}
{{- with .Values.app -}}
- name: app
  image: "{{ .image.repository }}:{{ .image.tag }}"
  ports:
    - name: http
      containerPort: 80
      protocol: TCP
  livenessProbe:
    httpGet:
      path: /
      port: http
  readinessProbe:
    httpGet:
      path: /
      port: http
  resources:
    requests:
      cpu: {{ .resources.requests.cpu | default "100m" }}
      memory: {{ .resources.requests.memory | default "500Mi" }}
    limits:
      cpu: {{ .resources.limits.cpu | default "100m" }}
      memory: {{ .resources.limits.memory | default "500Mi" }}
  env:
    {{- include "my-chart.app.env" . | nindent 2 }}
{{- end -}}
{{- end -}}

ただし、with のスコープは親のままなので、.Values.appの中のでテンプレートをincludeすると .Values.app スコープとなってしまいます。

{{- define "my-chart.app.env" -}}
# .Values.app.envではない
{{- with .env -}}
env:
- name: APP_ENVIRONMENT
  value: {{ .APP_ENVIRONMENT | quote }}
- name: WRK_WARMUP_DURATION
  value: {{ .WRK_WARMUP_DURATION | default "10" | quote }}
{{- end -}}
{{- end -}}

8. Valuesのキーは必須

cpu: {{ .resources.requests.cpu | default "100m" }}とdefaultを設定しても、
変数ファイルには、必ず、下のようにrequestsまで書かないといけません。

resources:
  requests: {}
  limits: {}

なので、上のようにcontainersごとに分けて、構造化すると、デフォルト値で良いものでもキーを多めに書かないといけなくなります。

environment: dev

replicas: 3

app:
  image:
    repository: nginx
    tag: stable
  resources:
    requests: {}
    limits: {}
  env:
    APP_ENVIRONMENT: dev

sidecar:
  image:
    repository: fluentd
    tag: stable
  resources:
    requests: {}
    limits: {}

hpa:
  enabled: false

最後に

変数とテンプレートの設計をどうするかが頭を悩ませる所です。まだ、模索中です...

17
9
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
17
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?