Helm Deck

Download as pdf or txt
Download as pdf or txt
You are on page 1of 175

Instructor Mumshad

Mannambeth
Objectives

Helm Installation Architecture Charts

Functions Pipelines Conditionals With Blocks

Packaging &
Range Chart Hooks Uploading
Signing
What is Helm?
Service

PVC
Secret

PV

Deployment
apiVersion: v1 apiVersion: v1 apiVersion: v1
kind: Secret kind: Service
metadata: kind: PersistentVolumeClaim
metadata:
name: wordpress-admin-password metadata:
name: wordpress
data: name: wp-pv-claim
labels:
key: CalksdlkeBGmxcv23kjsdlkjr== labels:
app: wordpress
app: wordpress
Service
spec:
spec:
ports:
>_ - port: 80
accessModes:
- ReadWriteOnce
selector: resources:
app: wordpress requests:
$ kubectl apply –f wp-secret.yaml tier: frontend
type: LoadBalancer PVC storage: 20Gi

Secret
>_
>_
apiVersion: apps/v1
kind: Deployment PV
$ kubectl apply –f wp-pvc.yaml
metadata: $ kubectl apply –f wp-svc.yaml
name: wordpress-mysql
apiVersion: v1
labels:
app: wordpress Deployment kind: PersistentVolume
>_
spec:
selector:
metadata:
name: pv0003
matchLabels: spec:
app: wordpress capacity:
$ kubectl apply –f wp-deploy.yaml storage: 20Gi
tier: mysql
strategy: volumeMode: Filesystem
type: Recreate accessModes:
template: - ReadWriteOnce
metadata:
labels:
app: wordpress >_
tier: mysql
spec:
containers: $ kubectl apply –f wp-pv.yaml
- image: mysql:5.6
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: wp-pv-claim
labels:
apiVersion: v1
app: wordpress
kind: Secret
spec:
metadata:
accessModes:
name: wordpress-admin-password
- ReadWriteOnce
data:
resources:
key: CalksdlkeBGmxcv23kjsdlkjr==
apiVersion: v1
requests:
kind: Service
storage: 20Gi
metadata:
Service name: wordpress
apiVersion: v1
labels:
kind: PersistentVolume
app: wordpress
metadata:
spec:
name: pv0003
ports:
spec:
PVC - port: 80
capacity:
selector:
storage: 20Gi
app: wordpress
Secret volumeMode: Filesystem
tier: frontend
accessModes:
type: LoadBalancer
- ReadWriteOnce
apiVersion: apps/v1

PV
kind: Deployment
metadata:
name: wordpress-mysql
labels:

Deployment
app: wordpress
spec:
selector:
matchLabels:
app: wordpress
tier: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: wordpress
tier: mysql
spec:
containers:
- image: mysql:5.6
name: mysql
Service

PVC
Secret

PV

Deployment
INSTALL
>_
$ helm install wordpress values.yaml
Service

$ helm upgrade wordpress


PVC
Secret
$ helm rollback wordpress
PV

$ helm uninstall wordpress

Deployment
Install & Configuration
Installing Helm

>_
$ sudo snap install helm --classic

$ curl https://baltocdn.com/helm/signing.asc | sudo apt-key add –


sudo apt-get install apt-transport-https --yes
echo "deb https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.li
sudo apt-get update
sudo apt-get install helm
$ pkg install helm

kubectl

https://helm.sh/docs/intro/install/
Labs

• Install helm on an existing kubernetes cluster


• Explore helm version
• Explore basic helm cli
Helm 2 vs 3
Helm History

1.0 Feb 2016

2.0 Nov 2016

3.0 Nov 2019


Helm 2

helm cli

Role Based Access Control

Custom Resource Definitions


Helm 2

helm cli Tiller

Role Based Access Control

Custom Resource Definitions


Helm 3

helm cli

Role Based Access Control

Custom Resource Definitions


Helm 2 vs Helm 3

Helm 2 Helm 3

Tiller
3-Way Strategic Merge Patch
Helm 2

2 Previous Chart 1 Current Chart

Revision: 1 Revision: 2 Revision: 3

wordpress wordpress

$ helm install wordpress $ helm upgrade wordpress $ helm rollback wordpress


Helm 3
2

Previous Chart Current Chart


2 1

Revision: 1

3-Way Strategic Merge Patch

wordpress

$ helm install wordpress $ kubectl set image wordpress \ $ helm rollback wordpress
wordpress:5.8-apache

3 Live State
Helm Components
Helm Components

Online Chart Repository Secret

Revision: 1 Revision: 1

Revision: 2 Revision: 2

Revision: 3 Revision: 3

Release Release

Chart

helm cli
Helm Charts

apiVersion: v1 service.yaml apiVersion: apps/v1 deployment.yaml


kind: Service kind: Deployment
metadata: metadata:
name: hello-world name: hello-world
spec: spec:
type: NodePort replicas: {{ .Values.replicaCount }}
ports: selector:
- port: 80 matchLabels:
targetPort: http app: hello-world
protocol: TCP template:
name: http metadata:
selector: labels:
app: hello-world app: hello-world
spec:
containers:
- name: nginx
replicaCount: 1 values.yaml image: "{{ .Values.image.repository }}"
ports:
image: - name: http
repository: nginx containerPort: 80
protocol: TCP

hello-world
Helm Charts

apiVersion: {{ include "common.capabilities.deployment.apiVersion" . }} deployment.yaml


kind: Deployment
metadata:
name: {{ include "common.names.fullname" . }}
namespace: {{ .Release.Namespace | quote }}
labels: {{- include "common.labels.standard" . | nindent 4 }}
{{- if .Values.commonLabels }}
{{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ )
{{- end }}
{{- if .Values.commonAnnotations }}
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations..
spec:
selector:
matchLabels: {{- include "common.labels.matchLabels" . | nindent 6 }}
{{- if .Values.updateStrategy }}
strategy: {{- toYaml .Values.updateStrategy | nindent 4 }}
{{- end }}
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}

wordpress
Helm Releases

>_
# helm install [release-name][chart-name]

$ helm install my-site bitnami/wordpress

Revision: 3 Revision: 3
# helm install bitnami/wordpress
Revision: 2 Revision: 2

$ helm install my-SECOND-site bitnami/wordpress Revision: 1 Revision: 1

Release Release
my-site my-SECOND-site
Helm Repositories

ArtifactHub.io

Appscode Community Operators

TrueCharts Bitnami
Helm Repositories
Helm Repositories
Helm Charts
Helm Charts

apiVersion: v1 service.yaml apiVersion: apps/v1 deployment.yaml replicaCount: 1 values.yaml


kind: Service kind: Deployment
metadata: metadata: image:
name: hello-world name: hello-world repository: nginx
spec: spec:
type: NodePort replicas: {{ .Values.replicaCount }}
ports: selector:
- port: 80 matchLabels:
targetPort: http app: hello-world
protocol: TCP template: apiVersion: v2 Chart.yaml
name: http metadata: appVersion: "1.16.0"
selector: labels: name: hello-world
app: hello-world app: hello-world description: A web application
spec:
containers: type: application
- name: hello-world
image: "{{ .Values.image.repository }}"
ports:
- name: http
containerPort: 80
protocol: TCP

Template

$ helm install hello-world


Chart.yaml

apiVersion: v2
appVersion: 5.8.1
version: 12.1.27
name: wordpress
description: Web publishing platform for building blogs and websites.
type: application
dependencies:
- condition: mariadb.enabled
name: mariadb
repository: https://charts.bitnami.com/bitnami
version: 9.x.x
<code hidden>
keywords:
- application
- blog
- wordpress
maintainers:
- email: containers@bitnami.com
name: Bitnami
home: https://github.com/bitnami/charts/tree/master/bitnami/wordpress
icon: https://bitnami.com/assets/stacks/wordpress/img/wordpress-stack-220x234.png

Helm 2 Helm 3 Types


v1 v2 application library
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
Helm Chart Structure

hello-world-chart

templates # Templates directory


values.yaml # Configurable values
Chart.yaml # Chart information
LICENSE # Chart License
README.md # Readme file
charts # Dependency Charts
Working with Helm
Helm CLI

>_
$ helm --help
The Kubernetes package manager

Common actions for Helm:

- helm search: search for charts


- helm pull: download a chart to your local directory to view
- helm install: upload the chart to Kubernetes
- helm list: list releases of charts

Usage:
helm [command]

Available Commands:
completion generate autocompletion scripts for the specified shell
create create a new chart with the given name
dependency manage a chart's dependencies
env helm client environment information
get download extended information of a named release
help Help about any command
history fetch release history
Helm CLI

>_
$ helm repo --help
This command consists of multiple subcommands to interact with chart repositories.

It can be used to add, remove, list, and index chart repositories.

Usage:
helm repo [command]

Available Commands:
add add a chart repository
index generate an index file given a directory containing packaged charts
list list chart repositories
remove remove one or more chart repositories
update update information of available charts locally from chart repositories

$ helm repo update --help


Update gets the latest information about charts from the respective chart repositories.
Information is cached locally, where it is used by commands like 'helm search'.

Usage:
helm repo update [flags]

Aliases:
update, up
Wordpress
Wordpress

>_
$ helm search wordpress
Search provides the ability to search for Helm charts in the various places
they can be stored including the Artifact Hub and repositories you have added.
Use search subcommands to search different locations for charts.

Usage:
helm search [command]

Available Commands:
hub search for charts in the Artifact Hub or your own hub instance
repo search repositories for a keyword in charts

$ helm search hub wordpress


URL CHART VERSION APP VERSION DESCRIPTION
https://artifacthub.io/packages/helm/riftbit/wo... 12.1.16 5.8.1 Web publishing platform for building blogs
https://artifacthub.io/packages/helm/bitnami-ak... 12.1.18 5.8.1 Web publishing platform for building blogs
https://artifacthub.io/packages/helm/bitnami/wo... 12.1.27 5.8.1 Web publishing platform for building blogs
Deploying Wordpress

>_
$ helm repo add bitnami https://charts.bitnami.com/bitnami

"bitnami" has been added to your repositories

$ helm install my-release bitnami/wordpress

NAME: my-release
LAST DEPLOYED: Wed Nov 10 18:03:50 2021
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: wordpress
CHART VERSION: 12.1.27
APP VERSION: 5.8.1

** Please be patient while the chart is being deployed **

Your WordPress site can be accessed through the following DNS name
from within your cluster:

my-release-wordpress.default.svc.cluster.local (port 80)


Helm Releases

>_
$ helm list
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
my-release default 1 2021-11-10 18:03:50.414174217 +0000 UTC deployed wordpress-12.1.27 5.8.1

$ helm uninstall my-release


release "my-release" uninstalled
Helm Repo

>_
$ helm repo
This command consists of multiple subcommands to interact with chart repositories.

It can be used to add, remove, list, and index chart repositories.

Usage:
helm repo [command]

Available Commands:
add add a chart repository
index generate an index file given a directory containing packaged charts
list list chart repositories
remove remove one or more chart repositories
update update information of available charts locally from chart repositories

$ helm repo list


NAME URL
bitnami https://charts.bitnami.com/bitnami

$ helm repo update


Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "bitnami" chart repository
Update Complete. ⎈Happy Helming!⎈
Customizing Chart Parameters
>_

$ helm install my-release bitnami/wordpress


Helm Charts

apiVersion: {{ include "apiVersion" . }} deployment.yaml


image: values.yaml kind: Deployment
registry: docker.io metadata:
repository: bitnami/wordpress name: {{ include "common.names.fullname" . }}
tag: 5.8.2-debian-10-r0 namespace: {{ .Release.Namespace | quote }}
labels: {{- include "common.labels.standard" . | nindent 4 }}
## @param wordpressUsername WordPress username spec:
## selector:
wordpressUsername: user matchLabels: {{- include "common.labels.matchLabels"
## @param wordpressPassword WordPress user replicas: {{ .Values.replicaCount }}
password {{- end }}
## Defaults to a random 10-character alphanumeric template:
string if not set spec:
## containers:
wordpressPassword: "" - name: wordpress
## @param existingSecret image: {{ template "wordpress.image" . }}
## env:
existingSecret: "" - name: WORDPRESS_DATABASE_NAME
## @param wordpressEmail WordPress user email value: {{ include "wordpress.databaseName" . | quote }}
## - name: WORDPRESS_DATABASE_USER
wordpressEmail: user@example.com value: {{ include "wordpress.databaseUser" . | quote }}
## @param wordpressFirstName WordPress user first - name: WORDPRESS_USERNAME
name value: {{ .Values.wordpressUsername | quote }}
## - name: WORDPRESS_PASSWORD
## @param wordpressBlogName Blog name valueFrom:
## secretKeyRef:
wordpressBlogName: User's Blog! name: {{ include "wordpress.secretName" . }}
key: wordpress-password
- name: WORDPRESS_BLOG_NAME
value: {{ .Values.wordpressBlogName | quote }}
>_
image: values.yaml
$ helm install my-release bitnami/wordpress registry: docker.io
repository: bitnami/wordpress
tag: 5.8.2-debian-10-r0

## @param wordpressUsername WordPress username


##
wordpressUsername: user
## @param wordpressPassword WordPress user
password
## Defaults to a random 10-character alphanumeric
string if not set
##
wordpressPassword: ""
## @param existingSecret
##
existingSecret: ""
## @param wordpressEmail WordPress user email
##
wordpressEmail: user@example.com
## @param wordpressFirstName WordPress user first
name
##
## @param wordpressBlogName Blog name
##
wordpressBlogName: User's Blog!
Custom Parameters in Command Line
--set

>_
image: values.yaml
$ helm install --set wordpressBlogName="Helm Tutorials" my-release bitnami/wordpress registry: docker.io
repository: bitnami/wordpress
tag: 5.8.2-debian-10-r0
--set wordpressEmail="john@example.com"
## @param wordpressUsername WordPress username
##
wordpressUsername: user
## @param wordpressPassword WordPress user
password
## Defaults to a random 10-character alphanumeric
string if not set
##
wordpressPassword: ""
## @param existingSecret
##
existingSecret: ""
## @param wordpressEmail WordPress user email
##
wordpressEmail: user@example.com
## @param wordpressFirstName WordPress user first
name
##
## @param wordpressBlogName Blog name
##
wordpressBlogName: User's Blog!
Custom Parameters from a YAML file
--values

>_
custom-values.yaml
$ helm install --values custom-values.yaml my-release bitnami/wordpress
wordpressBlogName: Helm Tutorials
wordpressEmail: john@example.com
Helm Pull

>_
image: values.yaml
$ helm pull bitnami/wordpress registry: docker.io
repository: bitnami/wordpress
tag: 5.8.2-debian-10-r0
$ helm pull --untar bitnami/wordpress ## @param wordpressUsername WordPress username
##
wordpressUsername: user
$ ls ## @param wordpressPassword WordPress user
password
## Defaults to a random 10-character alphanumeric
wordpress string if not set
##
wordpressPassword: ""
$ ls wordpress ## @param existingSecret
##
Mode LastWriteTime Length Name existingSecret: ""
---- ------------- ------ ---- ## @param wordpressEmail WordPress user email
##
d----- 13-Nov-21 10:36 PM ci wordpressEmail: user@example.com
d----- 13-Nov-21 10:36 PM templates ## @param wordpressFirstName WordPress user first
-a---- 13-Nov-21 10:36 PM 354 .helmignore name
##
-a---- 13-Nov-21 10:36 PM 399 Chart.lock ## @param wordpressBlogName Blog name
-a---- 13-Nov-21 10:36 PM 984 Chart.yaml ##
-a---- 13-Nov-21 10:36 PM 51019 README.md wordpressBlogName: User's Blog!

-a---- 13-Nov-21 10:36 PM 5918 values.schema.json


-a---- 13-Nov-21 10:36 PM 35737 values.yaml

$ helm install my-release ./wordpress


Lifecycle Management
Helm Releases

>_

$ helm install my-site bitnami/wordpress

$ helm install my-SECOND-site bitnami/wordpress Revision: 3 Revision: 3

Revision: 2 Revision: 2

Revision: 1 Revision: 1

Release Release
my-site my-SECOND-site
Helm Upgrade

>_

$ helm install nginx-release bitnami/nginx --version 7.1.0

$ kubectl get pods


NAME READY STATUS RESTARTS AGE
nginx-release-687cdd5c75-ztn2n 0/1 ContainerCreating 0 13s

$ kubectl describe pod nginx-release-687cdd5c75-ztn2n Revision: 1

Containers:
nginx: nginx-release
Container ID: docker://81bb5ad6b5..
Image: docker.io/bitnami/nginx:1.19.2-debian-10-r28
Image ID: docker-pullable://bitnami/nginx@sha256:2fcaf026b8acb7a..
Port: 8080/TCP
Host Port: 0/TCP
State: Running
Helm Upgrade

>_

$ helm upgrade nginx-release bitnami/nginx


Release "nginx-release" has been upgraded. Happy Helming!
NAME: nginx-release
LAST DEPLOYED: Mon Nov 15 19:25:55 2021
NAMESPACE: default
STATUS: deployed
REVISION: 2 Revision: 2

TEST SUITE: None


NOTES: Revision: 1

CHART NAME: nginx


CHART VERSION: 9.5.13
nginx-release
APP VERSION: 1.21.4

$ kubectl get pods


NAME READY STATUS RESTARTS AGE
nginx-release-7b78f4fdcd-2zr7k 1/1 Running 0 2m50s

$ kubectl describe pod nginx-release-7b78f4fdcd-2zr7k


Containers:
nginx:
C I k 2 92 969 9 3 3 7 …
Image: docker.io/bitnami/nginx:1.21.4-debian-10-r0
Image ID: docker-pullable://bitnami 2 6 9 2 7 9 …
Helm Upgrade

>_

$ helm list
NAME NAMESPACE REVISION STATUS CHART APP VERSION
nginx-release default 2 deployed nginx-9.5.13 1.21.4

$ helm history nginx-release


Revision: 2
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 Mon Nov 15 19:20:51 2021 superseded nginx-7.1.0 1.19.2 Install complete
2 Mon Nov 15 19:25:55 2021 deployed nginx-9.5.13 1.21.4 Upgrade complete Revision: 1

nginx-release
Helm Rollback

>_

$ helm list
NAME NAMESPACE REVISION STATUS CHART APP VERSION
nginx-release default 2 deployed nginx-9.5.13 1.21.4

Revision: 3
$ helm history nginx-release
Revision: 2
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 Mon Nov 15 19:20:51 2021 superseded nginx-7.1.0 1.19.2 Install complete
2 Mon Nov 15 19:25:55 2021 deployed nginx-9.5.13 1.21.4 Upgrade complete Revision: 1

nginx-release
$ helm rollback nginx-release 1
Rollback was a success! Happy Helming!

$ helm history nginx-release


REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 Mon Nov 15 19:20:51 2021 superseded nginx-7.1.0 1.19.2 Install complete
2 Mon Nov 15 19:25:55 2021 superseded nginx-9.5.13 1.21.4 Upgrade complete
3 Mon Nov 15 20:24:27 2021 deployed nginx-7.1.0 1.19.2 Rollback to 1
Helm Upgrade

>_

$ helm upgrade wordpress-release bitnami/wordpress


Revision: 1

wordpress-release
Understanding
Helm Charts
Writing
Templating Functions
Charts

Chart Hooks Chart Tests Provenance


Writing a
Helm Charts
$ helm upgrade wordpress-release bitnami/wordpress

Revision: 2

Revision: 1
Initiate Backup
(Hook)

wordpress-release
Writing Our First Helm Chart

hello-world-chart
apiVersion: v1 service.yaml apiVersion: apps/v1 deployment.yaml
templates kind: Service kind: Deployment
metadata: metadata:
values.yaml name: hello-world
spec:
name: hello-world
spec:
type: NodePort replicas: 2
Chart.yaml ports: selector:
- port: 80 matchLabels:
targetPort: http app: hello-world
LICENSE protocol: TCP template:
name: http metadata:
selector: labels:
README.md app: hello-world app: hello-world
spec:
containers:
- name: hello-world
image: nginx
$ helm create nginx-chart ports:
- name: http
containerPort: 80
$ ls nginx-chart protocol: TCP
charts Chart.yaml templates values.yaml
>_

$ cd nginx-chart
apiVersion: v2 Chart.yaml
$ vi Chart.yaml name: nginx-chart
description: ABasic
Helm nginx
chart website
for Kubernetes

$ ls templates #...
type: application
deployment.yaml _helpers.tpl hpa.yaml ingress.yaml
NOTES.txt serviceaccount.yaml service.yaml tests #...
version: 0.1.0

#...
$ rm -r templates/* appVersion: "1.16.0"

maintainers:
- email: john@example.com
name: john smith
>_

apiVersion: v1 service.yaml apiVersion: apps/v1 deployment.yaml


$ helm install hello-world-1 ./nginx-chart kind: Service kind: Deployment
metadata: metadata:
name: hello-world name: hello-world
spec: spec:
$ kubectl get deployment type: NodePort replicas: 2
ports: selector:
NAME READY UP-TO-DATE AVAILABLE AGE - port: 80 matchLabels:
hello-world 0/2 2 0 24s targetPort: http app: hello-world
protocol: TCP template:
name: http metadata:
selector: labels:
app: hello-world app: hello-world
$ helm install hello-world-2 ./nginx-chart
spec:
containers:
Error: rendered manifests contain a resource that - name: hello-world
already exists. Unable to continue with install: image: nginx
Deployment "hello-world" in namespace "default" exists ports:
and cannot be imported into the current release: - name: http
invalid ownership metadata; annotation validation containerPort: 80
error: key "meta.helm.sh/release-name" must equal protocol: TCP
"hello-world-2": current value is "hello-world-1"

hello-world

hello-world-1 hello-world-2
Templatize

>_

apiVersion: v1 service.yaml apiVersion: apps/v1 deployment.yaml


hello-world-1 ./nginx-chart
$ helm install hello-world-1 kind: Service kind: Deployment
metadata: metadata:
name: hello-world name: hello-world
{{ .Release.Name }}-nginx
spec: spec:
type: NodePort replicas: 2
ports: selector:
- port: 80 matchLabels:
targetPort: http app: hello-world
protocol: TCP template:
name: http metadata:
selector: labels:
app: hello-world app: hello-world
spec:
containers:
- name: hello-world
image: nginx
ports:
- name: http
containerPort: 80
protocol: TCP

hello-world-1-nginx

hello-world-1
Templatize

hello-world-1 {{ .Release.Name }}-nginx


-nginx

Template Directive

Go Template Language
Templatize

hello-world-1-nginx
Objects

Release.Name Chart.Name Capabilities.KubeVersion


Release.Namespace Chart.ApiVersion Capabilities.ApiVersions
Release.IsUpgrade Chart.Version Capabilities.HelmVersion Values.replicaCount
Release.IsInstall Chart.Type Capabilities.GitCommit Values.image
Release.Revision Chart.Keywords Capabilities.GitTreeState
Release.Service Chart.Home Capabilities.GoVersion

apiVersion: v2 Chart.yaml # Default values for nginx-chart. values.yaml


# This is a YAML-formatted file.
appVersion: 5.8.1 # Declare variables to be passed into your templates.
version: 12.1.27
name: wordpress replicaCount: 2
image: nginx
description: Web publishing platform for building blogs and websites.
type: application
dependencies:
- condition: mariadb.enabled
name: mariadb
repository: https://charts.bitnami.com/bitnami
version: 9.x.x
Templatize

>_

apiVersion: v1 service.yaml apiVersion: apps/v1 deployment.yaml


hello-world-1 ./nginx-chart
$ helm install hello-world-1 kind: Service kind: Deployment
metadata: metadata:
name: hello-world
{{ .Release.Name }}-svc name: hello-world
{{ .Release.Name }}-nginx
spec: spec:
type: NodePort replicas: 2
$ helm install hello-world-2 ./nginx-chart ports: selector:
- port: 80 matchLabels:
targetPort: http app: hello-world
protocol: TCP template:
$ kubectl get deployment name: http metadata:
selector: labels:
NAME READY UP-TO-DATE AVAILABLE AGE
app: hello-world app: hello-world
hello-world-1-nginx 1/2 2 1 8s spec:
hello-world-2-nginx 0/2 2 0 4s containers:
- name: hello-world
image: nginx
ports:
- name: http
containerPort: 80
protocol: TCP

hello-world-1-nginx hello-world-2-nginx

hello-world-1 hello-world-2
Templatize

>_
$ helm install hello-world-1 ./nginx-chart apiVersion: v1 service.yaml apiVersion: apps/v1 deployment.yaml
--set replicaCount=2 kind: Service kind: Deployment
metadata: metadata:
--set image=nginx name: hello-world
{{ .Release.Name }}-svc name: hello-world
{{ .Release.Name }}-nginx
spec: spec:
type: NodePort replicas: 2{{ .Values.replicaCount }}
ports: selector:
- port: 80 matchLabels:
targetPort: http app: hello-world
protocol: TCP template:
name: http metadata:
selector: labels:
app: hello-world app: hello-world
spec:
containers:
- name: hello-world
image: {{
nginx
.Values.image }}
ports:
- name: http
containerPort: 80
protocol: TCP

# Default values for nginx-chart. values.yaml


# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

replicaCount: 2
image: nginx
Templatize

apiVersion: apps/v1 deployment.yaml


kind: Deployment
metadata:
name: {{ .Release.Name }}-nginx
hello-world
spec:
# Default values for nginx-chart. values.yaml
replicas: {{
2 .Values.replicaCount }}
# This is a YAML-formatted file. selector:
# Declare variables to be passed into your templates. matchLabels:
app: hello-world
replicaCount: 2 template:
image: nginx metadata:
image:
image_repository: nginx
labels:
repository: nginx
image_pullPolicy: IfNotPresent
app: hello-world
pullPolicy:
image_tag: IfNotPresent
"1.16.0" spec:
tag: "1.16.0" containers:
- name: hello-world
image: nginx
{{ .Values.image.repository
.Values.image }} }}:{{ .Values.image.tag }}
ports:
- name: http
containerPort: 80
protocol: TCP
Templatize

image:
repository: nginx
pullPolicy: IfNotPresent
{{ .Values.image.repository
nginx }}:{{ .Values.image.tag
1.16.0 }}
tag: "1.16.0"
Templatize

image:
repository: nginx
pullPolicy: IfNotPresent
{{ .Values.image.repository
nginx
}}:{{
1.16.0
.Values.image.tag }}
tag: "1.16.0"
Templatize

apiVersion: apps/v1 templates/deployment.yaml apiVersion: apps/v1 deployment.yaml


kind: Deployment kind: Deployment
metadata: metadata:
name: {{ .Release.Name }}-nginx
hello-world Release Details name: hello-world
spec: spec:
replicas: {{
2 .Values.replicaCount }} replicas: 2
selector: selector:
matchLabels: matchLabels:
values.yaml
app: hello-world app: hello-world
template: replicaCount: 2 template:
metadata: metadata:
labels: image: labels:
app: hello-world repository: nginx app: hello-world
spec: pullPolicy: IfNotPresent spec:
containers: tag: "1.16.0" containers:
- name: hello-world - name: hello-world
image: {{
nginx
.Values.image.repository }} image: nginx
ports: ports:
- name: http - name: http
containerPort: 80 Chart Details containerPort: 80
protocol: TCP protocol: TCP
Making Sure Chart is Working as
Intended
Verifying Helm Charts

Lint

Template

Dry Run
Lint

>_
$ helm lint ./nginx-chart service.yaml
apiVersion: v1 apiVersion: apps/v1 deployment.yaml
kind: Service kind: Deployment
==> Linting ./nginx-chart/
metadata: metadata:
[INFO] Chart.yaml: icon is recommended name: hello-world
{{ .Release.Name }}-svc name: hello-world
{{ .Releese.Name
.Release.Name }}-nginx
[ERROR] templates/: template: nginx- spec: spec:
chart/templates/deployment.yaml:4:19: executing "nginx- type: NodePort replicas: 2{{ .Values.replicaCount }}
chart/templates/deployment.yaml" at <.Releese.Name>: nil ports: selector:
pointer evaluating interface {}.Name - port: 80 matchLabels:
targetPort: http app: hello-world
[ERROR] templates/deployment.yaml: unable to parse YAML: protocol: TCP template:
error converting YAML to JSON: yaml: line 20: did not name: http metadata:
find expected '-' indicator selector: labels:
app: hello-world app: hello-world
spec:
Error: 1 chart(s) linted, 1 chart(s) failed
containers:
- name: hello-world
image: {{
nginx
.Values.image }}
$ helm lint ./nginx-chart ports:
- name: http
==> Linting ./nginx-chart/ containerPort: 80
[INFO] Chart.yaml: icon is recommended protocol: TCP

1 chart(s) linted, 0 chart(s) failed


# Default values for nginx-chart. values.yaml
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

replicaCount: 2
image: nginx
Validating Template

>_
$$ helm
helm template
template ./nginx-chart
hello-world-1 ./nginx-chart service.yaml
apiVersion: v1 apiVersion: apps/v1 deployment.yaml
--- kind: Service kind: Deployment
# ---
Source: nginx-chart/templates/deployment.yaml metadata: metadata:
# Source: nginx-chart/templates/deployment.yaml
apiVersion: apps/v1
apiVersion: apps/v1 name: hello-world
{{ .Release.Name }}-svc name: hello-world
{{ .Release.Name }}-nginx
kind: Deployment
kind: Deployment
metadata:
spec: spec:
metadata:
name: RELEASE-NAME-nginx type: NodePort replicas: 2{{ .Values.replicaCount }}
name: hello-world-1-nginx
spec: ports: selector:
spec:
replicas: 2 - port: 80 matchLabels:
replicas: 2
selector: targetPort: http app: hello-world
selector:
matchLabels: protocol: TCP template:
matchLabels:
app: hello-world name: http metadata:
app: hello-world
template:
template:
selector: labels:
metadata:
metadata: app: hello-world app: hello-world
labels:
labels:
app: hello-world spec:
spec: app: hello-world containers:
spec:
containers: - name: hello-world
containers:
- name: hello-world image: {{
nginx
.Values.image }}
-image:
name: nginx
hello-world ports:
image: nginx
ports: - name: http
ports:
- name: http containerPort: 80
-containerPort:
name: http 8
containerPort: 8 protocol: TCP
---
# ---
Source: nginx-chart/templates/service.yaml
# Source: nginx-chart/templates/service.yaml
apiVersion: v1
apiVersion:
kind: Service v1
kind: Service
# Default values for nginx-chart. values.yaml
metadata: # This is a YAML-formatted file.
metadata:
name: RELEASE-NAME-nginx # Declare variables to be passed into your templates.
name: hello-world-1-nginx
spec:
spec:
type: NodePort replicaCount: 2
type: NodePort
ports: image: nginx
ports:
- port: 80
-targetPort:
port: 80 http
targetPort:
protocol: TCP http
protocol:
name: http TCP
name: http
selector:
Validating Template

>_
$ helm template ./nginx-chart service.yaml
apiVersion: v1 apiVersion: apps/v1 deployment.yaml
Error: YAML parse error on nginx-chart/templates/deployment.yaml: kind: Service kind: Deployment
error converting YAML to JSON: yaml: line 5: mapping values are not metadata: metadata:
allowed in this context name: hello-world
{{ .Release.Name }}-svc name: hello-world
{{ .Release.Name }}-nginx
spec: spec:
type: NodePort replicas: 2{{ .Values.replicaCount }}
ports: selector:
$ helm template ./nginx-chart --debug - port: 80 matchLabels:
targetPort: http app: hello-world
apiVersion: apps/v1 protocol: TCP template:
kind: Deployment name: http metadata:
metadata: selector: labels:
name: hello-world app: hello-world app: hello-world
spec: spec:
replicas: 2
containers:
selector:
matchLabels:
- name: hello-world
app: hello-world image: {{
nginx
.Values.image }}
template: ports:
- name: http
Error: YAML parse error on nginx-chart/templates/deployment.yaml: containerPort: 80
error converting YAML to JSON: yaml: line 5: mapping values are not protocol: TCP
allowed in this context

# Default values for nginx-chart. values.yaml


# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

replicaCount: 2
image: nginx
Dry Run

>_
$ helm install hello-world-1 ./nginx-chart --dry-run apiVersion: v1 service.yaml apiVersion: apps/v1 deployment.yaml
kind: Service kind: Deployment
Error: unable to build kubernetes objects from release
metadata: metadata:
manifest: error validating "": error validating data: name: hello-world
{{ .Release.Name }}-svc name: hello-world
{{ .Release.Name }}-nginx
[ValidationError(Deployment.spec.template.spec): unknown spec: spec:
field "container" in io.k8s.api.core.v1.PodSpec, type: NodePort replicas: 2{{ .Values.replicaCount }}
ValidationError(Deployment.spec.template.spec): missing ports: selector:
required field "containers" in - port: 80 matchLabels:
io.k8s.api.core.v1.PodSpec] targetPort: http app: hello-world
protocol: TCP template:
name: http metadata:
selector: labels:
$ helm install hello-world-1 ./nginx-chart --dry-run app: hello-world app: hello-world
spec:
NAME: hello-world-1 containers:
container:
LAST DEPLOYED: Fri Nov 19 18:34:51 2021 - name: hello-world
NAMESPACE: default image: {{
nginx
.Values.image }}
STATUS: pending-install ports:
REVISION: 1 - name: http
TEST SUITE: None containerPort: 80
HOOKS: protocol: TCP
MANIFEST:
---
# Source: nginx-chart/templates/service.yaml # Default values for nginx-chart. values.yaml
apiVersion: v1 # This is a YAML-formatted file.
# Declare variables to be passed into your templates.
kind: Service
metadata: replicaCount: 2
name: hello-world-1-nginx image: nginx
spec:
type: NodePort
ports:
- port: 80
Functions
apiVersion: apps/v1 templates/deployment.yaml apiVersion: apps/v1 deployment.yaml
kind: Deployment kind: Deployment
metadata: metadata:
name: {{ .Release.Name }}-nginx
hello-world name: hello-world
spec: spec:
replicas: {{
2 .Values.replicaCount }} replicas: 2
selector: selector:
matchLabels: matchLabels:
values.yaml
app: hello-world app: hello-world
template: replicaCount: 2 template:
metadata: metadata:
labels: image: labels:
app: hello-world repository: nginx app: hello-world
spec: pullPolicy: IfNotPresent spec:
containers: tag: "1.16.0" containers:
- name: hello-world - name: hello-world
image: {{
nginx
.Values.image.repository }} image: nginx
ports: ports:
- name: http - name: http
containerPort: 80 containerPort: 80
protocol: TCP protocol: TCP

$ kubectl get pods


NAME READY STATUS RESTARTS AGE
nginx-deployment-6c76ffbdd7-z4qgf 0/1 InvalidImageName 0 3s
Functions

upper("helm")
"helm" "HELM"

trim(" ")
" helm " "helm"
Templatize

apiVersion: apps/v1 templates/deployment.yaml apiVersion: apps/v1 deployment.yaml


kind: Deployment kind: Deployment
metadata: metadata:
name: {{ .Release.Name }}-nginx
hello-world name: hello-world
spec: spec:
replicas: {{
2 .Values.replicaCount }} replicas: 2
selector: selector:
matchLabels:
Release Details matchLabels:
app: hello-world app: hello-world
template: template:
metadata: metadata:
labels: labels:
app: hello-world values.yaml app: hello-world
spec: replicaCount: 2 spec:
containers: containers:
- name: hello-world image: - name: hello-world
image: {{
nginx
.Values.image.repository }} repository: nginx image: nginx
ports: pullPolicy: IfNotPresent image: nginx
ports:
- name: http tag: "1.16.0" - name: http
containerPort: 80 containerPort: 80
protocol: TCP protocol: TCP

Chart Details
{{ .Values.image.repository }} image: nginx
String Functions

{{ upper .Values.image.repository }} image: NGINX


nginx

{{ quote .Values.image.repository }} image: "nginx"


nginx

{{ replace "x" "y" .Values.image.repository }} image: "nginy"


nginx

{{ shuffle .Values.image.repository }} image: "xignn"


nginx

abbrev, abbrevboth, camelcase, cat, contains, hasPrefix, hasSuffix, indent,


initials, kebabcase, lower, nindent, nospace, plural, print, printf, println, quote,
randAlpha, randAlphaNum, randAscii, randNumeric, repeat, replace, shuffle,
snakecase, squote, substr, swapcase, title, trim, trimAll, trimPrefix, trimSuffix,
trunc, untitle, upper, wrap, wrapWith.
https://helm.sh/docs/chart_template_guide/function_list/#string-functions
Function List

Cryptographic
Date Dictionaries Encoding
and Security

File Path Kubernetes Chart Logic and Flow

Lists Math Network Reflection

Type
Regex String URL
Conversion

https://helm.sh/docs/chart_template_guide/function_list/
apiVersion: apps/v1 templates/deployment.yaml apiVersion: apps/v1 deployment.yaml
kind: Deployment kind: Deployment
metadata: metadata:
name: {{ .Release.Name }}-nginx
hello-world name: hello-world
spec: spec:
replicas: {{
2 .Values.replicaCount }} replicas: 2
selector: selector:
matchLabels: matchLabels:
values.yaml
app: hello-world app: hello-world
template: replicaCount: 2 template:
metadata: metadata:
labels: image: labels:
app: hello-world repository: nginx app: hello-world
spec: pullPolicy: IfNotPresent spec:
containers: tag: "1.16.0" containers:
- name: hello-world - name: hello-world
image: {{
nginx
.Values.image.repository }} image: nginx
ports: ports:
- name: http - name: http
containerPort: 80 containerPort: 80
protocol: TCP protocol: TCP
apiVersion: apps/v1 templates/deployment.yaml apiVersion: apps/v1 deployment.yaml
kind: Deployment kind: Deployment
metadata: metadata:
name: {{ .Release.Name }}-nginx
hello-world name: hello-world
spec: spec:
replicas: {{
2 .Values.replicaCount }} replicas: 2
selector: selector:
matchLabels: matchLabels:
values.yaml
app: hello-world app: hello-world
template: replicaCount: 2 template:
metadata: metadata:
labels: image: labels:
app: hello-world repository: nginx app: hello-world
spec: pullPolicy: IfNotPresent spec:
containers: tag: "1.16.0" containers:
- name: hello-world - name: hello-world
image: {{
nginx
default "nginx" .Values.image.repository }} image: nginx
ports: ports:
- name: http - name: http
containerPort: 80 containerPort: 80
protocol: TCP protocol: TCP
Pipelines
Pipelines

>_
$ echo "abcd"
abcd

$ echo "abcd" | tr a-z A-Z


ABCD
String Functions

{{ upper .Values.image.repository }} image: NGINX


nginx
String Functions

{{ .Values.image.repository | upper }} image: NGINX


nginx
String Functions

{{ .Values.image.repository | upper | quote }} nginx


image: NGINX
"NGINX"
String Functions

{{ .Values.image.repository | upper | quote | shuffle }} nginx


GN"XNI"
image: NGINX
"NGINX"
Conditionals
values.yaml apiVersion: v1 service.yaml

kind: Service
replicaCount: 2 metadata:
image: nginx name: {{ .Release.Name }}-nginx
labels:
orgLabel: payroll
org: {{ .Values.orgLabel }}
payroll
spec:
ports:
- port: 80
name: http
selector:
app: hello-world
Conditionals

orgLabel = "payroll"

print(orgLabel)
Conditionals

orgLabel = "payroll"

if orgLabel:
print(orgLabel)
end
Conditionals

values.yaml apiVersion: v1 service.yaml

kind: Service
replicaCount: 2 metadata:
image: nginx name: {{ .Release.Name }}-nginx
labels:
orgLabel: payroll
org: {{ .Values.orgLabel }}
payroll
spec:
ports:
- port: 80
name: http
selector:
app: hello-world
Conditionals

values.yaml apiVersion: v1 service.yaml

kind: Service
replicaCount: 2 metadata:
image: nginx name: {{ .Release.Name }}-nginx
orgLabel: payroll {{ if .Values.orgLabel }}
labels:
org: {{ .Values.orgLabel }}
payroll
{{ end }}
spec:
ports:
- port: 80
name: http
selector:
app: hello-world
Conditionals

values.yaml apiVersion: v1 service.yaml apiVersion: v1 service.yaml

kind: Service kind: Service


replicaCount: 2 metadata: metadata:
image: nginx name: {{ .Release.Name }}-nginx name: RELEASE-NAME-nginx
orgLabel: payroll {{ if .Values.orgLabel }}
labels: labels:
org: {{ .Values.orgLabel }}
payroll org: payroll
{{ end }}
spec: spec:
ports: ports:
- port: 80 - port: 80
name: http name: http
selector: selector:
app: hello-world app: hello-world
Conditionals

apiVersion: v1 service.yaml apiVersion: v1 service.yaml

kind: Service kind: Service


metadata: metadata:
name: {{ .Release.Name }}-nginx name: RELEASE-NAME-nginx
{{- if .Values.orgLabel }}
labels: labels:
org: {{ .Values.orgLabel }}
payroll org: payroll
{{- end }}
spec: spec:
ports: ports:
- port: 80 - port: 80
name: http name: http
selector: selector:
app: hello-world app: hello-world
Conditionals

apiVersion: v1 service.yaml apiVersion: v1 service.yaml

kind: Service kind: Service


metadata: metadata:
name: {{ .Release.Name }}-nginx name: RELEASE-NAME-nginx
{{- if .Values.orgLabel }} labels:
labels: org: payroll
spec:
org: {{ .Values.orgLabel }}
payroll
ports:
{{- end }} - port: 80
spec: name: http
ports: selector:
- port: 80 app: hello-world
name: http
selector:
app: hello-world
Conditionals

orgLabel = "payroll"

if orgLabel:
print(orgLabel)
end
Conditionals

orgLabel = "payroll"

if orgLabel:
print(orgLabel)
else:
print("nothing")
end
Conditionals

orgLabel = "payroll"

if orgLabel:
print(orgLabel)
else if orgLabel=="hr":
print("human resources")
else:
print("nothing")
end
Conditionals

apiVersion: v1 service.yaml

kind: Service
metadata:
name: {{ .Release.Name }}-nginx
{{- if .Values.orgLabel }}
labels:
org: {{ .Values.orgLabel }}
payroll
{{- end }}
spec:
ports:
- port: 80
name: http
selector:
app: hello-world
Conditionals

apiVersion: v1 service.yaml Function Purpose


kind: Service
eq equal
metadata:
name: {{ .Release.Name }}-nginx ne not equal
{{- if .Values.orgLabel }} lt less than
labels:
le less than or equal to
org: {{ .Values.orgLabel }}
payroll
gt greater than
{{- else if eq .Values.orgLabel "hr" }}
ge greater than or equal
labels:
to
org: human resources
not negation
{{- end }}
spec: empty value is empty
ports:
- port: 80
name: http
selector:
app: hello-world
Example

# Default values for nginx-chart. values.yaml serviceaccount.yaml


{{- if .Values.serviceAccount.create }}
# This is a YAML-formatted file.
apiVersion: v1
kind: ServiceAccount
serviceAccount:
# Specifies whether a ServiceAccount should be created metadata:
create: true name: {{ .Release.Name }}-robot-sa
{{- else }}
Setting scope using With
app: values.yaml apiVersion: v1 configmap.yaml
ui: kind: ConfigMap
bg: red metadata:
fg: black name: {{ .Release.Name }}-appinfo
db: data:
name: "users" background: {{ .Values.app.ui.bg }}
conn: "mongodb://localhost:27020/mydb" foreground: {{ .Values.app.ui.fg }}
database: {{ .Values.app.db.name }}
connection: {{ .Values.app.db.conn }}
Root

apiVersion: v1 configmap.yaml
kind: ConfigMap
Release Values metadata:
name: {{ .Release.Name }}-appinfo
data:
background: {{ .Values.app.ui.bg }}
Name app foreground: {{ .Values.app.ui.fg }}
database: {{ .Values.app.db.name }}
connection: {{ .Values.app.db.conn }}

ui db

bg fg name conn
With

Root

apiVersion: v1 configmap.yaml
kind: ConfigMap
Release Values metadata:
name: {{ .Release.Name }}-appinfo
data:
{{- with .Values.app }}
Name app
background: {{ .Values.app.ui.bg }}
foreground: {{ .Values.app.ui.fg }}
database: {{ .Values.app.db.name }}
connection: {{ .Values.app.db.conn }}
ui db {{- end }}

bg fg name conn
With

Root

apiVersion: v1 configmap.yaml
kind: ConfigMap
Release Values metadata:
name: {{ .Release.Name }}-appinfo
data:
{{- with .Values.app }}
Name app
background: {{ .Values.app.ui.bg }}
foreground: {{ .Values.app.ui.fg }}
database: {{ .Values.app.db.name }}
connection: {{ .Values.app.db.conn }}
ui db {{- end }}

bg fg name conn
With

Root

apiVersion: v1 configmap.yaml
kind: ConfigMap
Release Values metadata:
name: {{ .Release.Name }}-appinfo
data:
{{- with .Values.app }}
Name app
{{- with .ui }}
background: {{ .Values.app.ui.bg }}
foreground: {{ .Values.app.ui.fg }}
{{- end }}
ui db database: {{ .Values.app.db.name }}
connection: {{ .Values.app.db.conn }}
{{- end }}

bg fg name conn
With

Root

apiVersion: v1 configmap.yaml
kind: ConfigMap
Release Values metadata:
name: {{ .Release.Name }}-appinfo
data:
{{- with .Values.app }}
Name app
{{- with .ui }}
background: {{ .Values.app.ui.bg }}
foreground: {{ .Values.app.ui.fg }}
{{- end }}
ui db database: {{ .Values.app.db.name }}
connection: {{ .Values.app.db.conn }}
{{- end }}

bg fg name conn
With

Root

apiVersion: v1 configmap.yaml
kind: ConfigMap
Release Values metadata:
name: {{ .Release.Name }}-appinfo
data:
{{- with .Values.app }}
Name app
{{- with .ui }}
background: {{ .Values.app.ui.bg }}
foreground: {{ .Values.app.ui.fg }}
{{- end }}
ui db {{- with .db }}
database: {{ .Values.app.db.name }}
connection: {{ .Values.app.db.conn }}
{{- end }}
{{- end }}
bg fg name conn
With

Error: template: nginx-chart/templates/cfg.yaml:15:24: executing "nginx-


$
Root
chart/templates/cfg.yaml" at <.Release.Name>: nil pointer evaluating
interface {}.Name

apiVersion: v1 configmap.yaml
kind: ConfigMap
Release Values metadata:
name: {{ .Release.Name }}-appinfo
data:
{{- with .Values.app }}
Name app
{{- with .ui }}
background: {{ .Values.app.ui.bg }}
foreground: {{ .Values.app.ui.fg }}
{{- end }}
ui db {{- with .db }}
database: {{ .Values.app.db.name }}
connection: {{ .Values.app.db.conn }}
{{- end }}
release: {{ $.Release.Name }}
bg fg name conn {{- end }}
Range
Loops

1 i

2 i

3 i
for i in 1 to 10: 1
4 i print i 2
end 3
5 i
4
6 i 5
6
7 i
7
8 i 8
9 i 9
10
10 i
regions: values.yaml apiVersion: v1 configmap.yaml

- ohio kind: ConfigMap


- newyork metadata:
name: RELEASE-NAME-regioninfo
- ontario
data:
- london regions:
- singapore - "ohio"
- mumbai - "newyork"
- "ontario"
- "london"
- "singapore"
- "mumbai"
Range

configmap.yaml apiVersion: v1 configmap.yaml


regions: values.yaml apiVersion: v1
kind: ConfigMap
- ohio kind: ConfigMap
metadata:
- newyork metadata: name: RELEASE-NAME-regioninfo
name: {{ .Release.Name }}-regioninfo data:
- ontario
data: regions:
- london regions: - ohio
"ohio"
- singapore {{- range .Values.regions }} - newyork
"newyork"
- mumbai ontario
- "ontario"
- {{ . }}
| quote }} - london
"london"
singapore
- "singapore"
$ {{- end }} - mumbai
"mumbai"

Values
apiVersion: v1 configmap.yaml
regions kind: ConfigMap
metadata:
name: RELEASE-NAME-regioninfo
ohio .
data:
newyork . regions:
- "ohio"
ontario . - "newyork"
- "ontario"
london . - "london"
- "singapore"
singapore . - "mumbai"

mumbai .
Named Templates
apiVersion: v1 service.yaml apiVersion: apps/v1 deployment.yaml
kind: Service kind: Deployment
metadata: metadata:
name: {{ .Release.Name }}-nginx name: {{ .Release.Name }}-nginx
labels: labels:
app.kubernetes.io/name: nginx app.kubernetes.io/name: nginx
app.kubernetes.io/instance: nginx app.kubernetes.io/instance: nginx
spec: spec:
ports: selector:
- port: 80 matchLabels:
targetPort: http app.kubernetes.io/name: nginx
protocol: TCP app.kubernetes.io/instance: nginx
name: http template:
selector: metadata:
app: hello-world labels:
app.kubernetes.io/name: nginx
app.kubernetes.io/instance: nginx
spec:
containers:
- name: nginx
image: "nginx:1.16.0"
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
protocol: TCP
Template

_helpers.tpl apiVersion: v1 service.yaml apiVersion: v1 service.yaml


{{- define "labels" }} kind: Service kind: Service
metadata: metadata:
app.kubernetes.io/name: {{ .Release.Name }}
nginx
name: {{ .Release.Name }}-nginx name: nginx-release-nginx
app.kubernetes.io/instance: {{
nginx
.Release.Name }}
labels: labels:
{{- end }} app.kubernetes.io/name: nginx
{{- template "labels" . }}
app.kubernetes.io/instance: nginx
spec: spec:
ports: ports:
- port: 80 - port: 80
targetPort: http targetPort: http
protocol: TCP protocol: TCP
name: http name: http
selector: selector:
app: hello-world app: hello-world
Template

_helpers.tpl apiVersion: apps/v1 deployment.yaml apiVersion: apps/v1 deployment.yaml


{{- define "labels" }} kind: Deployment kind: Deployment
app.kubernetes.io/name: {{ .Release.Name }}
nginx metadata: metadata:
app.kubernetes.io/instance: {{
nginx name: {{ .Release.Name }}-nginx name: RELEASE-NAME-nginx
.Release.Name }}
labels: labels:
{{- end }} app.kubernetes.io/name:
{{- template "labels" . nginx }} app.kubernetes.io/name: nginx-chart
app.kubernetes.io/instance: nginx app.kubernetes.io/instance: nginx-release
spec: spec:
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name:
{{- nginx 2 }}
template "labels" . | indent
include app.kubernetes.io/name: nginx-chart
app.kubernetes.io/instance: nginx app.kubernetes.io/instance: nginx-release
template: template:
metadata: metadata:
template action labels: labels:
app.kubernetes.io/name:
{{- nginx 4 }}
template "labels" . | indent
include app.kubernetes.io/name: nginx-chart
include function app.kubernetes.io/instance: nginx app.kubernetes.io/instance: nginx-release
spec: spec:
containers: containers:
- name: nginx - name: nginx
image: "nginx:1.16.0" image: "nginx:1.16.0"
imagePullPolicy: IfNotPresent imagePullPolicy: IfNotPresent
ports: ports:
- name: http - name: http
containerPort: 80 containerPort: 80
protocol: TCP protocol: TCP
template is an action, and not a function, there is no way to pass the output of a template call to other functions; the data is simply inserted
inline.

https://stackoverflow.com/questions/71086697/how-does-template-and-include-differ-in-helm
Chart Hooks
$ helm upgrade wordpress-release bitnami/wordpress

Revision: 2

Revision: 1
Initiate Backup
(Hook)

wordpress-release
upgrade
$ helm upgrade verify render upgrade
pre-upgrade hook

pre-
upgrade
$ helm upgrade verify render upgrade
upgrade

Backup database
post-upgrade hook

pre- post-
upgrade
$ helm upgrade verify render upgrade
upgrade upgrade

Email Status
hooks

pre- post-
install
$ helm install verify render install
install install

pre- post-
install
$ helm delete verify render delete
delete delete

pre- post-
upgrade
$ helm upgrade verify render upgrade
upgrade upgrade

pre- post-
install
$ helm rollback verify render rollback
rollback rollback
Creating Hooks

apiVersion: batch/v1 backup-job.yaml


hello-world-chart kind: Job
metadata:
name: {{ .Release.Name }}-nginx
templates spec:

pre-
template:
metadata:
service.yaml upgrade name: {{ .Release.Name }}-nginx
spec:
restartPolicy: Never
deployment.yaml containers:
- name: pre-upgrade-backup-job
image: "alpine"
secret.yaml command: ["/bin/backup.sh"]

Pod
Job
backup-job.yaml

backup.sh
Creating Hooks

apiVersion: batch/v1 backup-job.yaml


hello-world-chart kind: Job
metadata:
name: {{ .Release.Name }}-nginx
templates annotations:
pre- "helm.sh/hook": pre-upgrade
service.yaml upgrade spec:
template:
deployment.yaml metadata:
name: {{ .Release.Name }}-nginx
spec:
secret.yaml restartPolicy: Never
containers:
Job - name: pre-upgrade-backup-job
backup-job.yaml image: "alpine"
command: ["/bin/backup.sh"]

backup.sh
pre-upgrade hook

apiVersion: batch/v1 backup-job.yaml


kind: Job
metadata:
name: {{ .Release.Name }}-nginx

annotations:
"helm.sh/hook": pre-upgrade

spec:
template:
metadata:
pre- name: {{ .Release.Name }}-nginx
upgrade
$ helm upgrade verify render upgrade spec:
upgrade restartPolicy: Never
containers:
- name: pre-upgrade-backup-job
image: "alpine"
command: ["/bin/backup.sh"]
3 Setup Banner

5 Backup database

-4 Email Announcement
pre-upgrade hook

apiVersion: batch/v1 backup-job.yaml


kind: Job
metadata:
name: {{ .Release.Name }}-nginx

annotations:
"helm.sh/hook": pre-upgrade
"helm.sh/hook-weight": "5"
"helm.sh/hook-delete-policy": hook-succeeded
spec:
template:
metadata:
pre- name: {{ .Release.Name }}-nginx
upgrade
$ helm upgrade verify render upgrade spec:
upgrade restartPolicy: Never
containers:
- name: pre-upgrade-backup-job
image: "alpine"
command: ["/bin/backup.sh"]
-4 Email Announcement

3 Setup Banner

5 Backup database
hook-succeeded
hook-failed
before-hook-creation
Packaging and Signing Charts
Packaging & Uploading

Online Chart Repository


>_
$ ls nginx-chart
charts Chart.yaml templates values.yaml README.md
LICENSE

$ helm package ./nginx-chart


Successfully packaged chart and saved it to:
/vagrant/nginx-chart-0.1.0.tgz
Helm Provenance and Integrity

>_
$ ls nginx-chart
charts Chart.yaml templates values.yaml README.md
LICENSE

public Key

$ helm package ./nginx-chart


Online Chart Repository
Successfully packaged chart and saved it to:
/vagrant/nginx-chart-0.1.0.tgz

nginx-chart-0.1.0.tgz

Private Key
Packaging

>_
$ gpg --quick-generate-key "John Smith"
gpg: keybox '/home/vagrant/.gnupg/pubring.kbx' created
About to create a key for:
"John Smith"
public Key
Continue? (Y/n) Y
gpg: /home/vagrant/.gnupg/trustdb.gpg: trustdb created
gpg: key 70D5188339885A0B marked as ultimately trusted Online Chart Repository
gpg: directory '/home/vagrant/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as
'/home/vagrant/.gnupg/openpgp-
revocs.d/20F2395A3176A22DD33DA45470D5188339885A0B.rev'
public and secret key created and signed.

pub rsa3072 2021-12-01 [SC] [expires: 2023-12-01]


20F2395A3176A22DD33DA45470D5188339885A0B
uid John Smith
sub rsa3072 2021-12-01 [E]
nginx-chart-0.1.0.tgz
# gpg --full-generate-key "John Smith"
Private Key

$ gpg --export-secret-keys >~/.gnupg/secring.gpg


gpg: starting migration from earlier GnuPG versions
gpg: porting secret keys from
'/home/vagrant/.gnupg/secring.gpg' to gpg-agent
gpg: migration succeeded
Signing and Verifying Helm Charts

>_

$ helm package --sign --key 'John Smith' --keyring ~/.gnupg/secring.gpg ./nginx-chart


Successfully packaged chart and saved it to: /vagrant/nginx-chart-0.1.0.tgz

$ gpg --list-keys

gpg: checking the trustdb


gpg: marginals needed: 3 completes needed: 1 trust model:
pgp
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n,
0m, 0f, 1u
gpg: next trustdb check due at 2023-12-01
/home/vagrant/.gnupg/pubring.kbx
--------------------------------
pub rsa3072 2021-12-01 [SC] [expires: 2023-12-01]
20F2395A3176A22DD33DA45470D5188339885A0B
uid [ultimate] John Smith
sub rsa3072 2021-12-01 [E]
Provenance File

>_
$ ls

nginx-chart nginx-chart-0.1.0.tgz nginx-chart-0.1.0.tgz.prov

$ ls
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

apiVersion: v2
appVersion: 1.16.0
description: A Helm chart for Kubernetes
maintainers:
- - email: john@example.com
name: john smith
name: nginx-chart
type: application
version: 0.1.0

...
files:
nginx-chart-0.1.0.tgz: sha256:b7d05022a9617ab953a3246bc7ba6a9de9d4286b2e78e3ea7975cc54698c4274
-----BEGIN PGP SIGNATURE-----

...

=kser
-----END PGP SIGNATURE-----

$ sha256sum nginx-chart-0.1.0.tgz
b7d05022a9617ab953a3246bc7ba6a9de9d4286b2e78e3ea7975cc54698c4274 nginx-chart-0.1.0.tgz
Verify Signature

>_

$ helm verify ./nginx-chart-0.1.0.tgz


Error: failed to load keyring: open /home/vagrant/.gnupg/pubring.gpg: no such file or directory

$ gpg --export 'John Smith' > mypublickey

$ helm verify --keyring ./mypublickey ./nginx-0.1.0.tgz


Signed by: John Smith
Using Key With Fingerprint: 20F2395A3176A22DD33DA45470D5188339885A0B
Chart Hash Verified: sha256:b7d05022a9617ab953a3246bc7ba6a9de9d4286b2e78e3ea7975cc54698c4274

$ gpg --recv-keys --keyserver keyserver.ubuntu.com 8D40FE0CACC3FED4AD1C217180BA57AAFAAD1CA5

$ helm install --verify nginx-chart-0.1.0


Uploading Charts
index.yaml

>_
$ ls
nginx-chart nginx-chart-0.1.0.tgz nginx-chart-0.1.0.tgz.prov

$ mkdir nginx-chart-files

$ cp nginx-chart-0.1.0.tgz nginx-chart-0.1.0.tgz.provn ginx-chart-files/

$ helm repo index nginx-chart-files/ --url https://example.com/charts

$ ls nginx-chart-files
index.yaml nginx-chart-0.1.0.tgz nginx-chart-0.1.0.tgz.prov
apiVersion: v1 index.yaml
entries:
nginx-chart:
- apiVersion: v2
appVersion: 1.16.0
created: "2021-12-01T15:29:35.073405539Z"
description: A Helm chart for Kubernetes
digest: 2c83c29dc4c56d20c45c3de8eff521fbfb6ef6c0b66854a6f4b5539bebcff879
maintainers:
- email: john@example.com
name: john smith
name: nginx-chart
type: application
urls:
- https://charts.bitnami.com/bitnami/nginx-chart-0.1.0.tgz
version: 0.1.0
generated: "2021-12-01T15:29:35.047718855Z"
https://example-charts.storage.googleapis.com

package index.yaml provenance


index.yaml

>_
$ helm repo add our-cool-charts https://example-charts.storage.googleapis.com

$ helm repo list


NAME URL
bitnami https://charts.bitnami.com/bitnami
our-cool-charts https://example-charts.storage.googleapis.com

$ helm install my-new-release our-cool-charts/nginx-chart


Conclusion
Helm Installation Architecture Charts

Functions Pipelines Conditionals With Blocks

Packaging &
Range Chart Hooks Uploading
Signing

You might also like