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
最後に
変数とテンプレートの設計をどうするかが頭を悩ませる所です。まだ、模索中です...