Helm Chart Syntax Summary

Catalog

1. Overview

Written earlier Syntax overview of JenkinsPipeline and Summary of Dockerfile syntax And recently picked up Helm Chart again, just recalling its grammar~

Helm is a package management tool in k8s that can be used to deploy k8s resources. The core of Helm is the template, which is the templated k8s manifests file

It is essentially a template for Go. Helm adds a lot to the Go template template. Some examples include custom metadata information, extended libraries, and workflows like programming, such as conditional statements, pipelines, and so on. These things will make templates richer

With templates, how to incorporate configurations is the values.yaml file

2. Debugging

Helm also provides--dry-run--debug debugging parameters to help verify the correctness of the template. With these two parameters when executing helm install, you can print out the corresponding values values and rendered resource lists without actually deploying a release

For example, debug a chart package you created:

# helm install web --dry-run /root/mychart

3. Built-in Objects

Use {{Release.Name}} to insert the name of the release into the template. Here, Release is Helm's built-in object. Here are some common built-in objects

Release.Name release name
Release.Name release name
Release.Namespace release namespace
Release.Service Name of release service
Release.Revision release revision number, cumulative from 1

4,Values

The Values object provides values for the Chart template, and the value of this object comes from four sources

  • The values.yaml file in the chart package

  • The values.yaml file of the parent chart package

  • Custom yaml files passed in through the helm install or helm upgrade's -f or--values parameters

  • Value passed in through--set parameter

The values provided by chart.yaml can be overwritten by a user-provided values file, which can also be overwritten by a parameter provided by--set

Edit the mychart/values.yaml file, empty all default values, and add a copy number

# cat values.yaml 
replicas: 3
image: "nginx"
imageTag: "1.17"

# cat templates/deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-deployment
spec:
  replicas: {{ .Values.replicas }}
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: {{ .Values.image }}:{{ .Values.imageTag }}
        name: nginx

View rendering results:

# helm install --dry-run web ../mychart/

values files can also contain structured content, such as

# cat values.yaml 
...
label:
  project: ms
  app: nginx

# cat templates/deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-deployment 
spec:
  replicas: {{ .Values.replicas }} 
  selector:
    matchLabels:
      project: {{ .Values.label.project }}
      app: {{ .Values.label.app }}
  template:
    metadata:
      labels:
        project: {{ .Values.label.project }}
        app: {{ .Values.label.app }}
    spec:
      containers:
      - image: {{ .Values.image }}:{{ .Values.imageTag }} 
        name: nginx

View rendering results:

# helm install --dry-run web ../mychart/

5. Pipelines and Functions

The related modules mentioned earlier actually pass the value to the template engine for rendering, and the template engine also supports the secondary processing of getting data

For example, a value read from.Values becomes a string and can be implemented using the quote function

# vi templates/deployment.yaml
app: {{ quote .Values.label.app }}
# helm install --dry-run web ../mychart/ 
        project: ms
        app: "nginx"

Quote.Values.label.app passes the following values as parameters to the quote function

The template function call syntax is: functionName arg1 arg2...

A default function is also frequently used that allows you to specify a default value in a template to prevent it from being ignored

For example, if you forget to define, executing helm install will fail to create resources due to missing fields, then you can define a default value

# cat values.yaml 
replicas: 2
# cat templates/deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
- name: {{ .Values.name | default "nginx" }}

Other Common Functions

  • Indent: {{Values.resources | indent 12}}

  • Uppercase: {{upper.Values.resources}}

  • Capitalize: {{title.Values.resources}}

6. Process Control

Process control provides a capability for templates to handle more complex data logic

The Helm template language provides the following process control statements

  • if/else conditional block
  • with specified range
  • range loop block

6.1 if

if/else blocks are the method used to conditionally include text blocks in a template, and the basic structure of conditional blocks is as follows

{{ if PIPELINE }}
  # Do something
{{ else if OTHER PIPELINE }}
  # Do something else
{{ else }}
  # Default case
{{ end }}

Example

# cat values.yaml 
devops: k8

# cat templates/deployment.yaml 
...
  template:
    metadata:
      labels:
        app: nginx
        {{ if eq .Values.devops "k8s" }}
        devops: 123
        {{ else }}
        devops: 456
        {{ end }}

In addition to the eq operator used in the above conditional statement to determine equality, the ne, lt, gt, and or operators are also supported

Rendering with the template engine yields the following results

# helm install --dry-run web ../mychart/ 
...
      labels:
        app: nginx

        devops: 456
       

You can see that there will be extra blank lines when rendered because when the template engine runs, the control instructions will be deleted and all previously occupied positions will be blank, requiring the {-if...} method to eliminate this blank line

# cat templates/deploymemt.yaml
...
        env:
        {{- if eq .Values.env.hello "world" }}
          - name: hello
            value: 123
        {{- end }}

There are no extra spaces now, so be careful if you use -}, such as in the template file above

# cat templates/deploymemt.yaml
...
       env:
        {{- if eq .Values.env.hello "world" -}}
           - hello: true
        {{- end }}

This renders as:

        env:- hello: true

Because -} it deletes line breaks for both parties

A conditional judgment is a judgment of whether a condition is true or false if the value is

  • A false boolean type

  • One Number Zero

  • An empty string

  • A nil (empty or null)

  • An empty collection (map, slice, tuple, dict, array)

All but the above are true

For example, determine an empty array

# cat values.yaml 
resources: {}
  # limits:
  #   cpu: 100m
  #   memory: 128Mi
  # requests:
  #   cpu: 100m
  #   memory: 128Mi

# cat templates/deploymemt.yaml
...
    spec:
      containers:
      - image: nginx:1.16
        name: nginx
        {{- if .Values.resources }}
        resources:
{{ toYaml .Values.resources | indent 10 }}
        {{- end }}

For example, determine a Boolean value

# cat values.yaml 
service:
  type: ClusterIP
  port: 80

ingress:
  enabled: true 
  host: example.ssgeek.com

# cat templates/ingress.yaml 
{{- if .Values.ingress.enabled -}}
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: {{ .Release.Name }}-ingress
spec:
  rules:
  - host: {{ .Values.ingress.host }}
    http:
      paths:
      - path: /
        backend:
          serviceName: {{ .Release.Name }}
          servicePort: {{ .Values.service.port }}
{{ end }}

6.2 with

with: controls the scope of variables

Previous {{Release.xxx}} or {{Values.xxx}}, where.Is a reference to the current scope and.Values is a value that tells the template to look for Values objects in the current scope. The with statement controls the scope of the variable, and its syntax is similar to a simple if statement

{{ with PIPELINE }}
  #  restricted scope
{{ end }}

The with statement allows you to set the current range. to a specific object, such as.Values.label, which you have been using previously. You can use with to point the. range to.Values.label

# cat values.yaml 
...
replicas: 3
label:
  project: ms
  app: nginx

# cat templates/deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      {{- with .Values.nodeSelector }}
      nodeSelector:
        team: {{ .team }}
        gpu: {{ .gpu }}
      {{- end }}
      containers:
      - image: nginx:1.16
        name: nginx

After optimization

      {{- with .Values.nodeSelector }}
      nodeSelector:
        {{- toYaml . | nindent 8 }}
      {{- end }}

A {{-with.Values.label}} XXX {{-end}} block has been added above so that.team and.gpu can be referenced directly within the current block.

with is a cyclic construct. Use the value in Values.nodeSelector: convert it to Yaml

The point after toYaml is the current value of the.Values.nodeSelector in the loop

6.3 range

In Helm template language, use range keyword for looping operations

Add the previous list of variables to the values.yaml file

# cat values.yaml 
test:
  - 1
  - 2
  - 3

Print the list in a loop

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}
data:
  test: |
  {{- range .Values.test }}
    {{ . }}
  {{- end }}

Inside the loop is a., because the current scope is within the current loop, which references the currently read element

7. Variables

This is the basic concept in language: variables, which are not used in many cases in templates, but you can see how to use them to simplify your code and make better use of with and range, for example

Example 1: Get list key values

# cat ../values.yaml
env:
  NAME: "gateway"
  JAVA_OPTS: "-Xmx1G"
  
# cat deployment.yaml 
...
		env:
		{{- range $k, $v := .Values.env }}
           - name: {{ $k }}
             value: {{ $v | quote }}
        {{- end }}

give the result as follows

    env:
       - name: JAVA_OPTS
         value: "-Xmx1G"
       - name: NAME
         value: "gateway"

The above uses the $key and $value variables in the range loop to receive keys and values for subsequent list loops

Example 2: Built-in objects cannot be used in with

Release.Name objects can no longer be in the with statement block, otherwise an error is reported

You can solve this problem by assigning the object to a variable

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-deployment
spec:
  replicas: {{ .Values.replicas }}
  template:
    metadata:
      labels:
        project: {{ .Values.label.project }}
        app: {{ quote .Values.label.app }}
      {{- with .Values.label }}
        project: {{ .project }}
        app: {{ .app }}
        release: {{ .Release.Name }}
      {{- end }}

Error above

      {{- $releaseName := .Release.Name -}}
      {{- with .Values.label }}
        project: {{ .project }}
        app: {{ .app }}
        release: {{ $releaseName }}
        # Or you can use the $symbol to introduce a global namespace
        release: {{ $.Release.Name }}
      {{- end }}

You can see that a sentence {{-$releaseName:=.Release.Name-} has been added to the with statement, where $releaseName is a reference variable to the following object in the form of $name, and the assignment operation uses: =, so the $releaseName variable inside the with statement block still points to.Release.Name

8. Naming Templates

Named Template: Defined by define, introduced by template, underlined by default in templates directory_ The starting file is a public template (_helpers.tpl)

# cat _helpers.tpl
{{- define "demo.fullname" -}}
{{- .Chart.Name -}}-{{ .Release.Name }}
{{- end -}}

# cat deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ template "demo.fullname" . }}
...

The template directive is a way to include one template in another. However, the template function cannot be used in the Go template pipeline. To solve this problem, add include functionality

# cat _helpers.tpl
{{- define "demo.labels" -}}
app: {{ template "demo.fullname" . }}
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
{{- end -}}

# cat deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "demo.fullname" . }}
  labels:
    {{- include "demo.labels" . | nindent 4 }}
...

It contains a template named demo.labels, passes the value.to the template, and passes the output of the template to the nindent function

9. Process for Chart Development

Create a template first

helm create demo

Modify Chart.yaml, Values.yaml, and add commonly used variables

Create the yaml file needed to deploy the image in the templates directory, and the variable references the frequently changing fields in yaml

More can be referred to Official Documents

See you ~

Pay attention to the public numbers and share more original dry goods with you~

Posted on Thu, 04 Nov 2021 13:15:01 -0400 by penkomitev