By Alwyn Botha, Alibaba Cloud Community Blog author.
This tutorial explains how the deployment.yaml Helm template gets converted from template to YAML manifest.
It does not follow the traditional programming reference guide: statements and functions listed in alphabetical order.
It explains template syntax as needed to explain deployment.yaml top to bottom.
Here is the complete deployment.yaml for reference:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "myhelm1.fullname" . }}
labels:
app.kubernetes.io/name: {{ include "myhelm1.name" . }}
helm.sh/chart: {{ include "myhelm1.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app.kubernetes.io/name: {{ include "myhelm1.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
template:
metadata:
labels:
app.kubernetes.io/name: {{ include "myhelm1.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }}
command: ['sh', '-c', 'sleep 60']
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
Extract of this deployment.yaml :
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
replicas: {{ .Values.replicaCount }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
.Release.Name and .Release.Service are built in objects - complete list at https://docs.helm.sh/chart_template_guide/ ( Unfortunately there are no links to specific parts of their VERY long web pages - you have to scroll down to find it ) ... Built-in Objects
Below is how the final deployment.yaml gets rendered if you use:
helm install .\myhelm1\ --name test5 --dry-run --debug
For this top 50% part of the tutorial you do not run any commands, just read. ( Even debug has too much output if all we want is to investigate the syntax of a 3 line template. )
( After you have read the full tutorial once you may want to read it again, but this time editing the template and value files and running helm install with debug to play / learn )
app.kubernetes.io/instance: test5
app.kubernetes.io/managed-by: Tiller
app.kubernetes.io/instance: test5
- name: myhelm1
image: "radial/busyboxplus:base"
imagePullPolicy: IfNotPresent
These 3 values below are pulled in from the values.yaml file:
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
Extract of values.yaml
image:
repository: radial/busyboxplus
tag: base
pullPolicy: IfNotPresent
- name: {{ .Chart.Name }} is from the Chart.yaml file. Its contents is shown below.
apiVersion: v1
appVersion: "1.0"
description: A Helm chart for Kubernetes
name: myhelm1
version: 0.1.0
Probably half of all templates are just such simple values replacements.
You have seen that within YAML files we have template directives embedded in {{ and }}.
You must have blank space after opening {{ and a blank space before closing }}.
Those leading dots are needed.
The values that are passed into a template can be thought of as namespaced objects, where a dot (.) separates each namespaced element.
The leading dot before Chart indicates that we start with the top-most namespace. Read .Chart.name as "start at the top namespace, find the Chart object, then look inside of it for an object called name".
**values.yaml** extract:
nodeSelector:
disktype: ssd
gpu: Nvidia
**deployment.yaml** extract:
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
Gets rendered as:
nodeSelector:
disktype: ssd
gpu: Nvidia
VERY important: spaces have syntax meaning in YAML.
The rendered two selectors have 8 spaces before them since in deployment.yaml we have {{- toYaml . | nindent 8 }}
nindent 8 indents it 8 spaces.
with is a loop construct. With the values in .Values.nodeSelector: convert it toYaml.
That dot after toYaml is the current value of .Values.nodeSelector in the loop. It must be there.
Consider it similar to sum(1,34,454) ... as toYaml(.) ... it is the value of the parm passed.
The pipe symbol | works as you are familiar in Linux shell.
affinity: and tolerations: with work exactly the same.
Unfortunately these examples do not show how with is also a current scope modifier. That is explained well at MODIFYING SCOPE USING WITH
Except for include you now fully understand how the whole deployment.yaml gets rendering by using values from values.yaml, Chart.yaml, and Built-in Objects.
The full service.yaml below:
You now fully understand it as well.
apiVersion: v1
kind: Service
metadata:
name: {{ include "myhelm1.fullname" . }}
labels:
app.kubernetes.io/name: {{ include "myhelm1.name" . }}
helm.sh/chart: {{ include "myhelm1.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
app.kubernetes.io/name: {{ include "myhelm1.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
Extract of first and last 3 lines of ingress.yaml
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "myhelm1.fullname" . -}}
{{- $ingressPaths := .Values.ingress.paths -}}
... rest of yaml ....
{{- end }}
{{- end }}
{{- end }}
**values.yaml** extract:
ingress:
enabled: false
All the content of ingress.yaml is wrapped in a big if ... starting at line 1 and ending at very last line. If ingress enabled is false NO yaml content gets generated - as we want it to be.
Line 2 and 3 demonstrates how to declare Helm template variables.
Note the hyphens at {{ and }}
Those hyphens/dashes eat whitespace characters. {{- eats all whitespaces to the left
-}} means whitespace to the right should be consumed - including the newline - the line is entirely removed.
Extract of values.yaml
ingress:
enabled: false
hosts:
- chart-example.local
tls:
- secretName: chart-example-tls
hosts:
- chart-example.local-1
- chart-example.local-2
- chart-example.local-3
Extract of deployment.yaml :
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
Gets rendered as:
spec:
tls:
- hosts:
- "chart-example.local-1"
- "chart-example.local-2"
- "chart-example.local-3"
secretName: chart-example-tls
Note how the range loop generates the list of hosts. The quote surrounds each host with quotes.
There is also a range .Values.ingress.tls loop that loops only once. Giving this loop 3 values will demonstrate how it will range over the values.
Extract of **values.yaml**
ingress:
enabled: false
hosts:
- chart-example.local
tls:
- secretName: chart-example-tls-a
hosts:
- chart-example.local-1-a
- chart-example.local-2-a
- chart-example.local-3-a
- secretName: chart-example-tls-b
hosts:
- chart-example.local-1-b
- chart-example.local-2-b
- secretName: chart-example-tls-c
hosts:
- chart-example.local-1-c
- chart-example.local-2-c
- chart-example.local-3-c
- chart-example.local-4-c
Gets rendered as:
tls:
- hosts:
- "chart-example.local-1-a"
- "chart-example.local-2-a"
- "chart-example.local-3-a"
secretName: chart-example-tls-a
- hosts:
- "chart-example.local-1-b"
- "chart-example.local-2-b"
secretName: chart-example-tls-b
- hosts:
- "chart-example.local-1-c"
- "chart-example.local-2-c"
- "chart-example.local-3-c"
- "chart-example.local-4-c"
secretName: chart-example-tls-c
Original template with hyphens.
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
template with hyphens removed:
{{ if .Values.ingress.tls }}
tls:
{{ range .Values.ingress.tls }}
- hosts:
{{ range .hosts }}
- {{ . | quote }}
{{ end }}
secretName: {{ .secretName }}
{{ end }}
{{ end }}
Renders as:
tls:
- hosts:
- "chart-example.local-1-a"
- "chart-example.local-2-a"
- "chart-example.local-3-a"
secretName: chart-example-tls-a
- hosts:
- "chart-example.local-1-b"
- "chart-example.local-2-b"
secretName: chart-example-tls-b
- hosts:
- "chart-example.local-1-c"
- "chart-example.local-2-c"
- "chart-example.local-3-c"
- "chart-example.local-4-c"
secretName: chart-example-tls-c
You need to have the space-and-line-end eating hyphens.
We now understand how values are used to generate all our templates.
One exception: name: {{ include "myhelm1.fullname" . }} - the include.
We now explore the include
We use include to include other templates into our YAML templates.
The file _helpers.tpl is the standard way to define several short template snippets we want to include in other templates.
Here is the first named template in _helpers.tpl :
{{- define "myhelm1.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
On the first line we give the template snippet a name. We then refer to this name to include it.
The second line gives "myhelm1.name" a default value: .Chart.Name
If the default value does not exist "myhelm1.name" gets the value of .Values.nameOverride
trunc 63 truncates it to 63 characters in length.
trimSuffix "-" removes ONE trailing - if one exists.
but
trimSuffix "--" removes only two trailing -- if it exists.
( It does not work as in some programming languages where trim will remove all trailing characters )
app.kubernetes.io/name: {{ include "myhelm1.name" . }}
render as
app.kubernetes.io/name: myhelm1
Next: the template code
helm.sh/chart: {{ include "myhelm1.chart" . }}
renders as
helm.sh/chart: myhelm1-0.1.0
This is the template function :
{{- define "myhelm1.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
printf "%s-%s" .Chart.Name .Chart.Version concatenates .Chart.Name and .Chart.Version - plus it places a hyphen between the two.
replace "+" "_" replaces plus characters with underscores.
Now that you can understand those two one-liner functions you should be able to understand the 10-liner define "myhelm1.fullname" with ease.
If you have any programming experience you will see the if/else works as expected:
if condition
do something
else
do something else
end
The only difference is the {{ and }} template syntax.
The official Helm documentation contains detailed reference information about charts and templates.
The Chart Developer's Guide : https://helm.sh/docs/topics/charts/
The Chart Template Developer's Guide : https://docs.helm.sh/chart_template_guide/
It may take a day to read each page. The best way to learn is via interactive use.
This part of the tutorial explains how to learn Helm interactively. It is an ugly but fast hack.
The hack involves:
Let's convert our current chart files to this as quickly as possible - remember ugly and hack is FAST.
Edit your values.yaml file to look like below:
replicaCount: 1
terminationGracePeriodSeconds: 30
image:
repository: radial/busyboxplus
tag: base
pullPolicy: IfNotPresent
Ensure ./myhelm1/.helmignore contains these lines at bottom:
NOTES.txt
test-connection.yaml
service.yaml
ingress.yaml
Make deployment.yaml content as below:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: {{ include "myhelm1.name" . }}
helm.sh/chart: {{ include "myhelm1.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
spec:
replicas: {{ .Values.replicaCount }}
template:
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }}
ALL we need is some ( even INVALID ) yaml to play with.
Do a dry run:
helm install .\myhelm1\ --name test5 --dry-run --debug
Output too long as shown below:
PS C:\k8> helm install .\myhelm1\ --name test5 --dry-run --debug
[debug] Created tunnel using local port: '50327'
[debug] SERVER: "127.0.0.1:50327"
[debug] Original chart version: ""
[debug] CHART PATH: C:\k8\myhelm1
NAME: test5
REVISION: 1
RELEASED: Fri Feb 15 13:47:49 2019
CHART: myhelm1-0.1.0
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
image:
pullPolicy: IfNotPresent
repository: radial/busyboxplus
tag: base
replicaCount: 1
terminationGracePeriodSeconds: 30
HOOKS:
MANIFEST:
---
# Source: myhelm1/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: myhelm1
helm.sh/chart: myhelm1-0.1.0
app.kubernetes.io/instance: test5
spec:
replicas: 1
template:
spec:
containers:
- name: myhelm1
image: "radial/busyboxplus:base"
imagePullPolicy: IfNotPresent
terminationGracePeriodSeconds: 30
Get rid of the first few 'useless' lines via grep.
helm install .\myhelm1\ --name test5 --dry-run --debug | grep -vE 'debug]|NAME|REVIS|RELEA|ART:|OKS:|FEST:'
See below. This is all we need: some values to play with and some yaml template content to play with template syntax.
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
image:
pullPolicy: IfNotPresent
repository: radial/busyboxplus
tag: base
replicaCount: 1
terminationGracePeriodSeconds: 30
---
# Source: myhelm1/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: myhelm1
helm.sh/chart: myhelm1-0.1.0
app.kubernetes.io/instance: test5
spec:
replicas: 1
template:
spec:
containers:
- name: myhelm1
image: "radial/busyboxplus:base"
imagePullPolicy: IfNotPresent
terminationGracePeriodSeconds: 30
Now go wild and learn some syntax:
See below deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: {{ include "myhelm1.name" . }}
helm.sh/chart: {{ include "myhelm1.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
spec: #-------------------->> learn spacing << ------------------------
replicas1: {{ .Values.replicaCount }}
replicas2: {{ .Values.replicaCount }}
replicas3: {{ .Values.replicaCount }}
replicas4: '{{ .Values.replicaCount }}'
replicas5: "{{ .Values.replicaCount }}"
replicas6: "{{ .Values.replicaCount }}"
replicas7: "{{ .Values.replicaCount }}"
replicas: "{{ .Values.replicaCount }}'
replicas: '{{ .Values.replicaCount }}"
replicas: {{ .Values.replicaCount }}"
replicas: "{{ .Values.replicaCount }}
template:
spec:
containers:
- name: {{ .Chart.Name }}
image1: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
image2: "{{ .Values.image.repository }} {{ .Values.image.tag }}"
image3: "{{ .Values.image.repository }}{{ .Values.image.tag }}"
image4: {{ .Values.image.repository }}{{ .Values.image.tag }}
imagePullPolicy1: {{ .Values.image.pullPolicy }}
imagePullPolicy2: {{ .Values.image.pullPolicyzzz }}
imagePullPolicy3: {{ .Values.image.pullPolicyeeeeeeeeeee }}
terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }}
Output:
spec: #-------------------->> learn spacing << ------------------------
replicas1: 1
replicas2: 1
replicas3: 1
replicas4: '1'
replicas5: "1"
replicas6: "1"
replicas7: "1"
template:
spec:
containers:
- name: myhelm1
image1: "radial/busyboxplus:base"
image2: "radial/busyboxplus base"
image3: "radial/busyboxplusbase"
image4: radial/busyboxplusbase
imagePullPolicy1: IfNotPresent
imagePullPolicy2:
imagePullPolicy3:
terminationGracePeriodSeconds: 30
See how much syntax you learned in seconds.
Make mistakes so you can learn what errors really mean. You also learn when error message helps and when it misleads.
Edit deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: {{ include "myhelm1.name" . }}
helm.sh/chart: {{ include "myhelm1.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
spec: #
replicas1: {{ .Values.replicaCount }}
template:
spec:
containers:
- name: {{ .Chart.Name }}
image1: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy-correct: {{ .Values.image.pullPolicy }}
imagePullPolicy1: {{ Values.image.pullPolicy }}
imagePullPolicy2: {{ .Valu.image.pullPolicyzzz }}
imagePullPolicy3: {{ ..Values.image.pullPolicyeeeeeeeeeee }}
Dry run:
helm install .\myhelm1\ --name test5 --dry-run --debug | grep -vE 'debug]|NAME|REVIS|RELEA|ART:|OKS:|FEST:'
Error: parse error in "myhelm1/templates/deployment.yaml": template: myhelm1/templates/deployment.yaml:19: function "Values" not defined
READ, understand and fix error, resubmit.
Error: parse error in "myhelm1/templates/deployment.yaml": template: myhelm1/templates/deployment.yaml:21: unexpected . after term "."
READ, understand and fix error, resubmit.
Error: render error in "myhelm1/templates/deployment.yaml": template: myhelm1/templates/deployment.yaml:20:36: executing "myhelm1/templates/deployment.yaml" at
<.Valu.image.pullPoli...>: can't evaluate field image in type interface {}
helm install .\myhelm1\ --name test5 --dry-run --debug | grep -vE 'debug]|NAME|REVIS|RELEA|ART:|OKS:|FEST:'
Some different syntax experiments below:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: {{ include "myhelm1.name" . }}
helm.sh/chart: {{ include "myhelm1.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
spec: #
replicas1: {{ .Values.replicaCount }}
template:
spec:
containers:
- name: {{ .Chart.Name }}
image1: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy1: {{ quote .Values.image.pullPolicy }}
imagePullPolicy2: {{ .Values.image.pullPolicy | quote }}
imagePullPolicy3: "{{ .Values.image.pullPolicy }}"
imagePullPolicy4: {{ .Values.image.pullPolicy | upper }}
imagePullPolicy5: {{ .Values.image.pullPolicy | lower }}
{{ $variable := 123 }}
variable: $variable
variable: {{ $variable }}
See the extra 3 lines at bottom - use those - characters to remove it. Remove all 3 lines.
Helm is not as interactive as Python but this way you can nearly make it so.
Gets rendered as:
containers:
- name: myhelm1
image1: "radial/busyboxplus:base"
imagePullPolicy1: "IfNotPresent"
imagePullPolicy2: "IfNotPresent"
imagePullPolicy3: "IfNotPresent"
imagePullPolicy4: IFNOTPRESENT
imagePullPolicy5: ifnotpresent
variable: $variable
variable: 123
Another trick. See imagePullPolicy 1 to 3 looks the same. What did we do? You can ugly hack titles like this:
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: {{ include "myhelm1.name" . }}
helm.sh/chart: {{ include "myhelm1.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
spec: #
replicas1: {{ .Values.replicaCount }}
template:
spec:
containers:
- name: {{ .Chart.Name }}
image1: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
# imagePullPolicy1: {{ quote .Values.image.pullPolicy }}
imagePullPolicy1: {{ quote .Values.image.pullPolicy }}
# imagePullPolicy2: {{ .Values.image.pullPolicy | quote }}
imagePullPolicy2: {{ .Values.image.pullPolicy | quote }}
imagePullPolicy3: " .Values.image.pullPolicy "
imagePullPolicy3: "{{ .Values.image.pullPolicy }}"
imagePullPolicy4: .Values.image.pullPolicy | upper
imagePullPolicy4: {{ .Values.image.pullPolicy | upper }}
imagePullPolicy5: .Values.image.pullPolicy | lower
imagePullPolicy5: {{ .Values.image.pullPolicy | lower }}
{{ $variable := 123 }}
variable: $variable
variable: {{ $variable }}
helm install .\myhelm1\ --name test5 --dry-run --debug | grep -vE 'debug]|NAME|REVIS|RELEA|ART:|OKS:|FEST:'
Output:
- name: myhelm1
image1: "radial/busyboxplus:base"
# imagePullPolicy1: "IfNotPresent"
imagePullPolicy1: "IfNotPresent"
# imagePullPolicy2: "IfNotPresent"
imagePullPolicy2: "IfNotPresent"
imagePullPolicy3: " .Values.image.pullPolicy "
imagePullPolicy3: "IfNotPresent"
imagePullPolicy4: .Values.image.pullPolicy | upper
imagePullPolicy4: IFNOTPRESENT
imagePullPolicy5: .Values.image.pullPolicy | lower
imagePullPolicy5: ifnotpresent
Note comments does not help. Template syntax inside comments gets interpreted.
Remove the {{ and }} always works. Then you can look at your source template code and the result on the following line in the output.
Best way to show titles of what is been tested seem to be to use { { and { } instead of {{ and }} .. policy 1 below.
{ and } also works in titles and look very similar to read syntax of {{ and }}
imagePullPolicy1: { { quote .Values.image.pullPolicy } }
imagePullPolicy1: {{ quote .Values.image.pullPolicy }}
imagePullPolicy2: { .Values.image.pullPolicy | quote }
imagePullPolicy2: {{ .Values.image.pullPolicy | quote }}
this gets rendered as :
imagePullPolicy1: { { quote .Values.image.pullPolicy } }
imagePullPolicy1: "IfNotPresent"
imagePullPolicy2: { .Values.image.pullPolicy | quote }
imagePullPolicy2: "IfNotPresent"
helm install .\myhelm1\ --set replicaCount={1,2,3} --name test5 --dry-run --debug | grep -vE 'debug]|NAME|REVIS|RELEA|ART:|OKS:|FEST:'
There are nearly 300 superb Helm chart and template examples at the official Helm repository at https://github.com/helm/charts
You want to learn from the best: these people.
You will see that after just these 2 tutorials you are already able to understand more than 80% of all the template coding. ( But these 2 tutorials covered maybe 10 percent of the syntax ).
You now have 4 independent, different ways of learning charts and templates:
Helm reference docs are low-level focussed on detail.
Look for structural chart design insights while looking at the Helm chart repository.
From https://github.com/helm/charts/blob/master/stable/lamp/templates/NOTES.txt
See how the lamp chart only displays certain notes help text when .Values.ingress.enabled
{{- if .Values.ingress.enabled }}
INGRESS:
Please make sure that you have an ingress controller instance {{ if .Values.ingress.ssl }}and a lego instance
{{- end -}} running
and that you have configured the A Records of {{ template "lamp.domain" . }} and its
subdomains to point to your ingress controllers ip address.
{{- else }}
Most other charts use this idea since charts are infinitely flexible: many features to enable or disable.
Another example use of displaying NOTES.txt based on what the user enabled:
From https://github.com/helm/charts/blob/master/stable/lamp/templates/NOTES.txt
1. You can now connect to the following services:
{{- if not .Values.ingress.enabled }}
export CHARTIP=$(kubectl get svc {{ template "lamp.fullname" . }} --output=jsonpath={.status.loadBalancer.ingress..ip})
{{- end }}
Main Site:
{{- if .Values.ingress.enabled }}
http{{ if .Values.ingress.ssl }}s{{ end }}://{{ template "lamp.domain" . }}
{{- else }}
http://$CHARTIP
{{- end }}
{{- if .Values.phpmyadmin.enabled }}
PHPMyAdmin:
{{- if .Values.ingress.enabled }}
http{{ if .Values.ingress.ssl }}s{{ end }}://{{ .Values.phpmyadmin.subdomain }}.{{ template "lamp.domain" . }}
{{- else }}
http://$CHARTIP:{{ .Values.phpmyadmin.port }}
{{- end }}
{{- end }}
Another frequently used method is to warn users if a chart is set up incorrectly or insecurely.
From https://github.com/helm/charts/blob/master/stable/mongodb/templates/NOTES.txt
{{- if contains .Values.service.type "LoadBalancer" }}
{{- if not .Values.mongodbRootPassword }}
-------------------------------------------------------------------------------
WARNING
By specifying "service.type=LoadBalancer" and not specifying "mongodbRootPassword"
you have most likely exposed the MongoDB service externally without any
authentication mechanism.
For security reasons, we strongly suggest that you switch to "ClusterIP" or
"NodePort". As alternative, you can also specify a valid password on the
"mongodbRootPassword" parameter.
-------------------------------------------------------------------------------
{{- end }}
{{- end }}
Perfect example of how to handle .Values.service.type "NodePort" or "LoadBalancer" or "ClusterIP"
From https://github.com/helm/charts/blob/master/stable/mongodb/templates/NOTES.txt
To connect to your database from outside the cluster execute the following commands:
{{- if contains "NodePort" .Values.service.type }}
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "mongodb.fullname" . }})
mongo --host $NODE_IP --port $NODE_PORT {{- if .Values.usePassword }} --authenticationDatabase admin -p $MONGODB_ROOT_PASSWORD{{- end }}
{{- else if contains "LoadBalancer" .Values.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
Watch the status with: 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "mongodb.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "mongodb.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
mongo --host $SERVICE_IP --port {{ .Values.service.nodePort }} {{- if .Values.usePassword }} --authenticationDatabase admin -p $MONGODB_ROOT_PASSWORD{{- end }}
{{- else if contains "ClusterIP" .Values.service.type }}
kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ template "mongodb.fullname" . }} 27017:27017 &
mongo --host 127.0.0.1 {{- if .Values.usePassword }} --authenticationDatabase admin -p $MONGODB_ROOT_PASSWORD{{- end }}
{{- end }}
These examples are from spending less than 3 minutes looking at some chart examples. You can easily spend a day there ( and it will be worth it ... if you make notes ).
At https://docs.helm.sh/chart_template_guide/ ... Accessing Files Inside Templates ... ( cannot link to that paragraph directly ) there are several examples of how to include files inside templates.
The Helm repo has 80 examples of how to use .Files.Get
https://github.com/helm/charts/search?utf8=%E2%9C%93&q=.Files.Get&type=
In the first 10 results I found 5 different uses of .Files.Get.
To learn more about Helm, visit https://github.com/helm/charts/tree/master/stable
Running Microsoft Exchange Server with Alibaba Cloud ECS
This article covers setting up Exchange Server 2019 on Windows Server 2019 Datacenter edition image using an Alibaba Cloud ECS Instance.
2,599 posts | 763 followers
FollowAlibaba Clouder - October 29, 2019
Alibaba Clouder - December 17, 2019
Alibaba Cloud Native Community - December 29, 2023
Alibaba Cloud Native Community - December 29, 2023
Alibaba Clouder - April 22, 2019
Alibaba Developer - June 21, 2021
2,599 posts | 763 followers
FollowAlibaba Cloud Container Service for Kubernetes is a fully managed cloud container management service that supports native Kubernetes and integrates with other Alibaba Cloud products.
Learn MoreA secure image hosting platform providing containerized image lifecycle management
Learn MoreElastic and secure virtual cloud servers to cater all your cloud hosting needs.
Learn MoreMore Posts by Alibaba Clouder