Déployer des applications Kubernetes packagées avec Helm
Qu'est-ce que Helm ? Comment fonctionne Helm ? Comment pouvons-nous utiliser Helm pour déployer et gérer des applications Kubernetes packagées ? Familiarisons-nous avec Helm et apprenons à créer et distribuer nos propres packages Helm.
Qu'est-ce que Helm
Helm est un outil qui peut être utilisé pour créer et installer des packages prêts à l'emploi, configurables et partageables de manifestes de ressources Kubernetes pour des applications spécifiques.
Ces manifestes de ressources Kubernetes empaquetés sont appelés Charts Helm. Les Charts Helm sont distribués via des référentiels ou dépôts de Charts.
ArtefactHub est une application Web qui peut être utilisée pour explorer les Charts Helm à partir de nombreux référentiels publics de Charts Helm.
L'installation d'un Chart Helm spécifique dans un cluster Kubernetes crée une Release Helm..
Comment fonctionne Helm
Paramètres et fichiers de configuration de Helm
Lorsque l'utilitaire de ligne de commande Helm est invoqué pour gérer (installer, désinstaller, obtenir l'état...) des Releases Helm, par défaut, il utilise le fichier de configuration $HOME/.kube/config pour découvrir les points de terminaison des clusters Kubernetes actuellement configurés et obtenir les informations nécessaires pour communiquer en toute sécurité avec leurs serveurs d'API.
Le même fichier de configuration est utilisé par défaut par « kubectl » et par conséquent, les configurations effectuées avec « kubectl config » seront par défaut réutilisées par Helm.
La variable d'environnement $KUBECONFIG, ou l'option de ligne de commande « --kubeconfig » peuvent être utilisés pour modifier le chemin par défaut vers le fichier de configuration des clusters Kubernetes.
Pour répertorier les autres variables d'environnement de configuration ainsi que les options de ligne de commande disponibles pour la configuration de Helm, ainsi que les chemins de répertoire par défaut où Helm stocke ses données, configurations et caches, utilisez « helm --help ».
États des Releases Helm
Les états des Releases Helm sont stockés sous forme de ressources « secrets » Kubernetes dans les clusters cibles. Chaque fois qu'une Release Helm est créée ou mise à jour, une nouvelle version de la ressource « secret » est créée dans l'espace de noms de la Release.
Helm récupère l'historique des Releases à partir de ces « secrets » et les utilise pour effectuer des restaurations. La suppression de ces ressources « secrets » fera oublier à Helm tout ce qui concernait les Releases précédemment gérées.
Voici des exemples de ressources « secrets » d'état Helm pour deux versions d'une Release Helm nommée « grafana » :
$ kubectl get secret
NAME TYPE DATA AGE
sh.helm.release.v1.grafana.v1 helm.sh/release.v1 1 3m1s
sh.helm.release.v1.grafana.v2 helm.sh/release.v1 1 5s
Installation de Helm
- Les assets des versions de Helm peuvent être trouvés ici
- Pour installer Helm sous Linux, procédez comme suit :
$ helm_version=v3.15.3 # choose version
$ linux_arch=amd64 # choose OS arch
# Download Helm binary
$ wget https://get.helm.sh/helm-${helm_version}-linux-${linux_arch}.tar.gz
# Install Helm binary
$ sudo tar xzvf helm-${helm_version}-linux-${linux_arch}.tar.gz -C /usr/local/bin/
# Verify
$ helm version
Gestion des dépôts de Charts Helm
# Adding Helm Charts repositories
$ repo_name=grafana ; repo_url=https://grafana.github.io/helm-charts
$ helm repo add $repo_name $repo_url
"grafana" has been added to your repositories
# Listing added repositories
$ helm repo list
NAME URL
grafana https://grafana.github.io/helm-charts
# Synchronize/update local repo info from remote
$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "grafana" chart repository
Update Complete. ⎈Happy Helming!⎈
# Removing repositories
$ helm repo remove $repo_name
"grafana" has been removed from your repositories
Recherche de Charts Helm
# Searching through public artifacthub.io repositories
$ search_keyword=grafana
$ helm search hub $search_keyword
URL CHART VERSION APP VERSION DESCRIPTION
https://artifacthub.io/packages/helm/grafana/gr... 8.3.6 11.1.0 The leading tool for querying and visualizing t...
https://artifacthub.io/packages/helm/saurabh6-g... 0.2.0 1.1 This is a Helm Chart for Grafana Setup.
(...)
# Searching through locally added repositories
$ search_keyword=grafana/grafana
## Search for lastest versions of Charts matching the search keyword
$ helm search repo $search_keyword
NAME CHART VERSION APP VERSION DESCRIPTION
grafana/grafana 8.3.6 11.1.0 The leading tool for querying and visualizing t...
grafana/grafana-agent 0.42.0 v0.42.0 Grafana Agent
grafana/grafana-agent-operator 0.4.1 0.42.0 A Helm chart for Grafana Agent Operator
grafana/grafana-sampling 0.1.1 v0.40.2 A Helm chart for a layered OTLP tail sampling a...
(...)
## Search for all versions of Charts matching the search keyword
$ helm search repo $search_keyword -l
NAME CHART VERSION APP VERSION DESCRIPTION
grafana/grafana 8.3.6 11.1.0 The leading tool for querying and visualizing t...
grafana/grafana 8.3.5 11.1.0 The leading tool for querying and visualizing t...
(...)
grafana/grafana-agent 0.42.0 v0.42.0 Grafana Agent
grafana/grafana-agent 0.41.0 v0.41.1 Grafana Agent
(...)
grafana/grafana-agent-operator 0.4.1 0.42.0 A Helm chart for Grafana Agent Operator
grafana/grafana-agent-operator 0.4.0 0.41.1 A Helm chart for Grafana Agent Operator
(...)
# Download Charts files
$ helm pull --untar $chart_url
## Download from locally added repositories
$ helm pull --untar grafana/grafana
$ ls grafana/
Chart.yaml ci dashboards README.md templates values.yaml
Gestion des Releases Helm
Afficher les valeurs par défaut des Charts Helm
- Les « valeurs » des Charts Helm sont des variables/paramètres que nous pouvons définir afin de personnaliser les manifestes qui seront déployés par les Charts, lors de l'installation ou des mises à jour
- Pour obtenir toutes les « valeurs » possibles qui peuvent être fournies aux Charts, procédez comme suit :
$ chart_name=grafana/grafana
$ helm show values $chart_name
global:
# -- Overrides the Docker registry globally for all images
imageRegistry: null
(...)
# global:
# imagePullSecrets:
# - pullSecret1
# - pullSecret2
imagePullSecrets: []
rbac:
create: true
(...)
La sortie de la commande précédente pourrait être redirigée vers un fichier « values.yaml », qui sera ensuite personnalisé et utilisé comme fichier de valeurs d'entrée lors de la création des Releases de Charts.
Voir les valeurs, manifestes, hooks et notes des Releases Helm
Nous pouvons obtenir les données suivantes à partir d'une Release Helm :
- values: valeurs fournies par l'utilisateur
- hooks: hooks Helm utilisés
- manifest: les manifestes des ressources créées par la Release
- notes: le contenu du fichier NOTES.txt du Chart
Nous pourrions également utiliser all pour toutes les valeurs et manifestes actuellement utilisés, ainsi que les hooks actuellement utilisés et le contenu du fichier NOTES.txt du Chart.
Voici des exemples :
$ chart_name=grafana/grafana
$ release_name=grafana
$ helm get values $release_name [-n $namespace]
USER-SUPPLIED VALUES:
null
$ helm get manifest $release_name
---
# Source: grafana/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
automountServiceAccountToken: false
metadata:
labels:
helm.sh/chart: grafana-8.4.4
app.kubernetes.io/name: grafana
app.kubernetes.io/instance: grafana
app.kubernetes.io/version: "11.1.3"
app.kubernetes.io/managed-by: Helm
name: grafana
namespace: default
---
# Source: grafana/templates/secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: grafana
(...)
$ helm get hooks $release_name
(...)
---
# Source: grafana/templates/tests/test-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: grafana-test
namespace: default
annotations:
"helm.sh/hook": test
"helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded"
labels:
helm.sh/chart: grafana-8.4.4
app.kubernetes.io/name: grafana
app.kubernetes.io/instance: grafana
app.kubernetes.io/version: "11.1.3"
app.kubernetes.io/managed-by: Helm
data:
run.sh: |-
@test "Test Health" {
url="http://grafana/api/health"
code=$(wget --server-response --spider --timeout 90 --tries 10 ${url} 2>&1 | awk '/^ HTTP/{print $2}')
[ "$code" == "200" ]
}
---
(...)
$ helm get all $release_name
COMPUTED VALUES:
admin:
existingSecret: ""
passwordKey: admin-password
userKey: admin-user
adminUser: admin
affinity: {}
alerting: {}
assertNoLeakedSecrets: true
automountServiceAccountToken: true
autoscaling:
behavior: {}
enabled: false
maxReplicas: 5
minReplicas: 1
targetCPU: "60"
targetMemory: ""
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefault
(...)
Créer ou mettre à jour des Releases Helm à partir d'un Chart
helm upgrade --install $release_name $chart_name --create-namespace [-n $namespace] [--version $chart_version] [-f values.yaml] [--set key=value] [--wait]
- Les options « -n » et « --version » peuvent être utilisées pour spécifier respectivement l'espace de noms de la Release ainsi que la version du Chart à utiliser
- L'option « --create-namespace » est utilisée pour créer automatiquement l'espace de noms cible pour la Release s'il n'existe pas
- L'option « -f » ou « --values » permet de définir des valeurs personnalisées pour le Chart. Cette option peut être utilisée plusieurs fois avec plusieurs fichiers de valeurs. Les valeurs des derniers fichiers spécifiés auront une priorité plus élevée.
- Les valeurs des Charts peuvent également être spécifiées directement en ligne de commande à l'aide de « --set key1=value1,key2=value2... ». Les valeurs spécifiées avec l'option « --set » ont une priorité supérieure à celles spécifiées avec « -f » ou « --values ». La barre oblique inverse peut être utilisée pour échapper certains caractères.
Exemple :--set nodeSelector."kubernetes\.io/role"=master - L'option « --wait » permet d'attendre que tous les pods soient prêts. Helm attendra le temps spécifié par l'option « --timeout » (valeur par défaut : « 5 minutes »).
Lister et obtenir le statut des Releases Helm
$ helm list [-n $namespace]
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
grafana default 2 <release_creation_date> deployed grafana-8.3.6 11.1.0
$ release_name=grafana
$ helm status $release_name [-n $namespace]
NAME: grafana
(...)
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
1. Get your 'admin' user password by running:
kubectl get secret --namespace default grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
(...)
Voir l'historique des versions de Helm
$ release_name=grafana
$ helm history $release_name [-n $namespace]
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 <release_creation_date> superseded grafana-8.3.6 11.1.0 Install complete
2 <release_creation_date> deployed grafana-8.3.6 11.1.0 Upgrade complete
Rollback des Releases Helm
# Rolling back
$ release_name=grafana
# Rollback to previous release
$ helm rollback $release_name [-n $namespace]
# Rollback to specific revision of a release
# Revision numbers are shown in release history
$ revision_number=1
$ helm rollback $release_name $revision_number [-n $namespace]
Rollback was a success! Happy Helming!
# Show release created after rollback
$ helm history $release_name
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
(...)
3 <release_creation_date> deployed grafana-8.3.6 11.1.0 Rollback to 1
Désinstaller des Releases Helm
$ release_name=grafana
$ helm uninstall $release_name [--keep-history -n $namespace]
release "grafana" uninstalled
L'option facultative « --keep-history » permet de conserver les enregistrements de suppression. Cela permet d'afficher les Releases supprimées avec les options « --uninstalled » ou « --all » lors de l'affichage des Releases avec la commande « helm list ».
$ helm list --uninstalled
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
grafana default 1 <release_creation_date> uninstalled grafana-8.4.4 11.1.3
Création de Charts Helm
Structure des Charts Helm
Voici la structure de base des sources de Charts Helm :
$ tree mychart/
mychart/
├── charts
├── Chart.yaml
├── NOTES.txt
├── templates
│ ├── deployment.yaml
│ └── _helpers.tpl
└── values.yaml
- Préférez utiliser l'extension « .yaml » plutôt que « .yml » lors du développement de Charts Helm
- Pour générer rapidement un exemple de Chart pouvant servir de base de développement, utilisez la commande suivante :
helm create $chart_directory_path
Le fichier Chart.yaml
Le fichier « Charts.yaml » contient les métadonnées des Charts. Voici un exemple :
apiVersion: v2
version: 0.0.1 # Sementic Versioning (SemVer)
name: myapp
description: Helm Chart for myapp
type: application # or 'library'
appVersion: 10.2.3
Tous les champs disponibles pour ce fichier sont répertoriés ici. Le champ « type » indique le type de Chart que nous créons. Il existe deux types de Charts : « application » et « library ».
Les Charts d'application sont les Charts classiques que nous utilisons pour déployer des applications Kubernetes. C'est celui que nous allons créer dans cet article.
Les Charts de librairie ne sont utiles que lors du développement de Charts pour ajouter de nouveaux utilitaires ou fonctions dans le pipeline de rendu. Ils ne contiennent aucun template de ressources Kubernetes et ne peuvent donc pas être déployés.
Les champs apiVersion, name et version sont obligatoires.
Le répertoire charts
Le répertoire « charts » est utilisé pour stocker les packages des Charts de dépendances. Les Charts de dépendances requis sont déclarés via le champ « dependencies » à l'intérieur du fichier Chart.yaml.
Les « valeurs » personnalisées pour les dépendances sont définies sous la clé correspondant au nom des dépendances. Voici un exemple :
# File: Charts.yaml
(...)
dependencies:
- name: ingress-nginx
repository: https://helm.nginx.com/stable
(...)
(...)
# File: values.yaml
nginx:
# Charts values from the ingress-nginx Helm Charts repository:
# https://github.com/kubernetes/ingress-nginx/blob/main/charts/ingress-nginx/values.yaml
namespaceOverride: mynamespace
controller:
name: mycontroller
(...)
Le répertoire templates
Le répertoire « templates » contient les fichiers manifestes « .yaml » des ressources Kubernetes. Ces fichiers contiennent la définition des ressources Kubernetes pouvant être déployées à l'aide du Chart.
La syntaxe, ainsi que les fonctions du moteur de templating Go peuvent être utilisées à l'intérieur de ces fichiers. Les Fonctions Sprig ainsi que des Objets natifs Helm supplémentaires peuvent également être utilisés. Pour obtenir une liste de toutes les fonctions disponibles dans les templates de manifestes de ressources Kubernetes, consultez Liste des fonctions de templating de Charts Helm.
Notez que les fichiers de templates préfixés par un underscore (_) ne génère pas de sortie interprétée, mais leur contenu peut être utilisé dans d'autres templates de manifestes. C'est le cas, par exemple, du fichier « _helpers.tpl », utilisé pour stocker des blocs de templates réutilisables. Voici un exemple :
# File: templates/_helpers.tpl
{{- define "name" -}}
{{- default .Chart.Name .Values.nameOverride }}
{{- end -}}
# File: templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "name" . }}
(...)
Le fichier NOTES.txt
Le contenu du fichier « NOTES.txt » sera affiché sur la sortie standard après la création d'une Release à partir du Chart. Ce fichier est également compatible avec le langage de templating Go . Voici un exemple de contenu :
=> Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
{{- range $host := .Values.ingress.hosts }}
{{- range .paths }}
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
{{- end }}
{{- end }}
{{- else if contains "ClusterIP" .Values.service.type }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "..name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
{{- end }}
Le fichier values.yaml
Le fichier « values.yaml » contient les paramètres de configuration par défaut du Chart, que les utilisateurs peuvent définir pour personnaliser leurs Releases. Ces personnalisations peuvent consister, par exemple, à attribuer un nom personnalisé à toutes les ressources de la Release, à activer/désactiver des ressources ou fonctionnalités spécifiques, ou encore à définir des valeurs personnalisées pour des champs spécifiques de certaines ressources. Voici un exemple de contenu :
# values.yaml
nameOverride: myapp
image:
repository: selenium/node-firefox
tag: 3.141.59
replicaCount: 3
autoscaling:
enabled: false
(...)
Tous les paramètres du Chart spécifiés comme valeurs (via values.yaml ou l'option « --set » de la CLI Helm) sont exportés vers l'objet Helm « .Values », accessible depuis les fichiers de templates. Voici un exemple d'utilisation des paramètres de values de Charts Helm dans un template de manifeste de ressources de type deployment :
# File: templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
(...)
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
(...)
Notions de base pour templating de Charts Helm
- Pour afficher les manifestes des ressources Kubernetes à partir d'un répertoire Helm Chart, utilisez :
helm template $path_to_chart_directory --debug
- Les directives et fonctions de création de templates sont placées entre des accolades doubles.
{{ }} - Voici comment nous pouvons utiliser des commentaires à l'intérieur de fichiers de templates, sur une ou plusieurs lignes :
{{/* my comment */}} - La routine shell
-est utilisé au début des doubles accolades comme ceci{{- }}ou à la fin{{ -}}afin de supprimer respectivement tous les caractères d'espacement avant ou après les directives de création de templates. Voici quelques exemples :
# Without '-', whitespaces before and after
# the double curly braces '{{ }}' are preserved
# File: templates/test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ "myapp" }}
labels:
{{ "app.kubernetes.io/name: myapp" }}
# Result
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
labels:
app.kubernetes.io/name: myapp
# Removing all whitespaces before the label
# File: templates/test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ "myapp" }}
labels:
{{- "app.kubernetes.io/name: myapp" }}
# Result
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
labels:app.kubernetes.io/name: myapp
- La routine shell
{{- }}est couramment utilisé pour les blocs de templates définis dans le fichier « _helpers.tpl ». Il est également couramment utilisé dans les templates de ressources Kubernetes, en combinaison avec la fonctionnindentqui ajoute une nouvelle ligne et le nombre d'espaces souhaité pour l'indentation. Voici un exemple :
# Removing all whitespaces before the label
# File: templates/test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ "myapp" }}
labels:
{{- "app.kubernetes.io/name: myapp" }}
# Result
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
labels:app.kubernetes.io/name: myapp
# Adding a new line + 4 spaces for indentation
# File: templates/test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ "myapp" }}
labels:
{{- "app.kubernetes.io/name: myapp" | nindent 4 }}
# Result
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
labels:
app.kubernetes.io/name: myapp
- La routine shell
{{ -}}est généralement utilisé lors de la définition de blocs de templates dans le fichier « _helpers.tpl ». Voici un exemple :
# File: templates/_helpers.tpl
{{- define "name" -}}
{{- default .Chart.Name .Values.nameOverride }}
{{- end }}
- Le point
{{ . }}est un objet contenant toutes les valeurs ainsi que d'autres objets natifs Helm ou une portion des valeurs en fonction de l'emplacement à partir duquel il est appelé à l'intérieur d'un fichier template. Voici un exemple où nous obtenons tous les objets :
# File: values.yaml
(...)
autoscaling:
enabled: true
env:
- name: HUB_HOST
value: "selenium-hub"
- name: HUB_PORT
value: "4444"
- name: NODE_MAX_INSTANCES
value: "1"
- name: NODE_MAX_SESSION
value: "1"
(...)
# File: templates/test.yaml
{{ toYaml . }}
# Result
$ helm template . --debug
install.go:178: [debug] Original chart version: ""
install.go:195: [debug] CHART PATH: /home/gmkziz/helm-charts/mychart
---
# Source: myapp/templates/test.yaml
Capabilities:
APIVersions:
- v1
(...)
HelmVersion:
git_commit: 414ff28d4029ae8c8b05d62aa06c7fe3dee2bc58
(...)
KubeVersion:
Major: "1"
(...)
IsRoot: true
apiVersion: v2
appVersion: 10.2.3
description: Helm Chart for myapp
name: myapp
type: application
version: 0.0.1
Files:
(...)
Release:
IsInstall: true
(...)
Subcharts: {}
Template:
BasePath: myapp/templates
Name: myapp/templates/test.yaml
Values:
autoscaling:
enabled: true
env:
- name: HUB_HOST
value: selenium-hub
- name: HUB_PORT
value: "4444"
- name: NODE_MAX_INSTANCES
value: "1"
- name: NODE_MAX_SESSION
value: "1"
(...)
- Maintenant, changeons la portée avec un block
rangeet vérifions que le{{ . }}contient uniquement les objets à l'intérieur de cette portée :
# File: values.yaml
(...)
autoscaling:
enabled: true
env:
- name: HUB_HOST
value: "selenium-hub"
- name: HUB_PORT
value: "4444"
- name: NODE_MAX_INSTANCES
value: "1"
- name: NODE_MAX_SESSION
value: "1"
(...)
# File: templates/test.yaml
{{- range .Values.env }}
{{ toJson . }}
{{- end }}
# Result
$ helm template . --debug
install.go:178: [debug] Original chart version: ""
install.go:195: [debug] CHART PATH: /home/gmkziz/helm-charts/mychart
---
# Source: myapp/templates/test.yaml
{"name":"HUB_HOST","value":"selenium-hub"}
{"name":"HUB_PORT","value":"4444"}
{"name":"NODE_MAX_INSTANCES","value":"1"}
{"name":"NODE_MAX_SESSION","value":"1"}
- Les objets que nous obtenons en utilisant
{{ . }}dépendent de la portée ou du contexte dans lequel nous nous trouvons actuellement - La portée à partir de laquelle nous obtenons tous les objets natifs Helm s'appelle portée racine (root scope)
- Nous pouvons obtenir les objets de portée racine à partir d'un emplacement quelconque depuis les fichiers de template en utilisant le signe
$. Exemple :
# File: values.yaml
(...)
autoscaling:
enabled: true
env:
- name: HUB_HOST
value: "selenium-hub"
- name: HUB_PORT
value: "4444"
- name: NODE_MAX_INSTANCES
value: "1"
- name: NODE_MAX_SESSION
value: "1"
(...)
# File: templates/test.yaml
{{- with .Values.autoscaling }}
{{ toJson . }}
{{ toJson $.Values.env }}
{{- end }}
# Result
$ helm template . --debug
install.go:178: [debug] Original chart version: ""
install.go:195: [debug] CHART PATH: /home/gmkziz/helm-charts/mychart
---
# Source: myapp/templates/test.yaml
{"enabled":true}
[{"name":"HUB_HOST","value":"selenium-hub"},{"name":"HUB_PORT","value":"4444"},{"name":"NODE_MAX_INSTANCES","value":"1"},{"name":"NODE_MAX_SESSION","value":"1"}]
Conditions et variables dans les Charts Helm
# File: templates/deployment.yaml
# if autoscaling.enabled is not set to true,
# set the number of replicas from the replicaCount value
apiVersion: apps/v1
kind: Deployment
metadata:
(...)
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
(...)
# Set resource type depending on the podController value
apiVersion: apps/v1
{{- if eq .Values.podController "Deployment" }}
kind: Deployment
{{- else if eq .Values.podController "Statefulset" }}
kind: Statefulset
{{- else }}
kind: Deployment
{{- end }}
metadata:
(...)
# File: templates/ingress.yaml
{{/* Defining variables */}}
{{- $svcPort := .Values.service.port -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
(...)
{{/* Referencing variables */}}
(...)
spec:
(...)
rules:
- host: myhost.local
http:
paths:
- path: /
backend:
service:
name: myservice
port:
number: {{ $svcPort }}
Actions couramment utilisées dans les Charts Helm
defineincludewithrange
Fonctions couramment utilisées dans les Charts Helm
Liste des fonctions de templating Helm
nindenttoYamltrunctrimSuffixreplacedefaultprintf
Template de Chart Helm pour le nommage des ressources
Une manière courante de définir les noms des ressources de Charts Helm est la suivante :
- « .Values.fullnameOverride » si défini, sinon
- une combinaison de « .Release.Name » et « .Values.nameOverride » si « .Values.nameOverride » est défini et ne contient pas « .Release.Name », sinon
- Une combinaison de « .Release.Name » et « .Chart.Name » si « .Chart.Name » ne contient pas « .Release.Name », sinon
- « .Release.name »
Les noms des ressources doivent également être tronqués à 63 caractères en raison d'une limitation de certains champs de noms Kubernetes (spécification de nommage DNS) et le suffixe - supprimé.
Voici un exemple de bloc de template de Chart Helm pour définir les noms de ressources :
# File: templates/_helpers.tpl
{{- define "fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
Template de Chart Helm pour la labellisation des ressources
Voici les clés d'étiquettes (labels) courantes que nous pouvons utiliser dans nos Charts :
helm.sh/chart: une combinaison du nom et de la version du Chartapp.kubernetes.io/version: la version de l'application gérée par le Chartapp.kubernetes.io/managed-by:app.kubernetes.io/name: le nom de l'application gérée par le Chartapp.kubernetes.io/instance: le nom de la release
app.kubernetes.io/name et app.kubernetes.io/instance sont couramment utilisés comme labels de sélecteur pour les ressources de type Deployments et StatefulSets.
Voici quelques exemples d'utilisation de labels dans les Charts Helm :
# File: templates/_helpers.tpl
# Define reusable templating blocks
{{/*
Return .Values.nameOverride if defined,
otherwise .Chart.name
*/}}
{{- define "name" -}}
{{- default .Chart.Name .Values.nameOverride }}
{{- end -}}
{{- define "labels" -}}
helm.sh/chart: {{ .Chart.Name }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{ include "selectorLabels" . }}
{{- end }}
{{- define "selectorLabels" -}}
app.kubernetes.io/name: {{ include "name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
# File: templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
(...)
labels:
{{- include "labels" . | nindent 4 }}
spec:
(...)
selector:
matchLabels:
{{- include "selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "selectorLabels" . | nindent 8 }}
(...)
Création et packaging d'un Chart Helm simple
Créons un exemple de Chart Helm qui servira à créer une ressource de type deployment. Voici le contenu du dossier du Chart :
$ tree helm-chart-example/
helm-chart-example/
├── charts
├── Chart.yaml
├── NOTES.txt
├── templates
│ ├── deployment.yaml
│ └── _helpers.tpl
└── values.yaml
- Contenu du fichier Chart.yaml
apiVersion: v2
version: 0.0.1
name: myapp
description: Helm Chart for myapp
type: application
appVersion: 10.2.3
- Contenu du fichier _helpers.tpl
{{- define "name" -}}
{{- default .Chart.Name .Values.nameOverride }}
{{- end -}}
{{/*
The fullname tempating block will be
used to set resources names
*/}}
{{- define "fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := include "name" . }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name }}
{{- end }}
{{- end }}
{{- end }}
{{- define "chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- define "labels" -}}
helm.sh/chart: {{ include "chart" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{ include "selectorLabels" . }}
{{- end }}
{{- define "selectorLabels" -}}
app.kubernetes.io/name: {{ include "name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
- Contenu du fichier deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "fullname" . }}
labels:
{{- include "labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.volumes }}
volumes:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: {{ include "name" . }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
{{- with .Values.volumeMounts }}
volumeMounts:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.env }}
env:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.resources }}
resources:
{{- toYaml . | nindent 10 }}
{{- end }}
- Contenu du fichier values.yaml
nameOverride: myapp2
fullnameOverride:
image:
repository: selenium/node-firefox
tag: 3.141.59
replicaCount: 3
autoscaling:
enabled: true
volumes:
- name: dshm
emptyDir:
medium: Memory
volumeMounts:
- name: dshm
mountPath: /dev/dshm
env:
- name: HUB_HOST
value: "selenium-hub"
- name: HUB_PORT
value: "4444"
- name: NODE_MAX_INSTANCES
value: "1"
- name: NODE_MAX_SESSION
value: "1"
resources:
limits:
memory: "2000Mi"
requests:
memory: "2000Mi"
- Pour afficher le contenu des manifestes résultants sur la sortie standard à partir du Chart, nous utilisons :
# From inside the helm-chart-example directory
$ helm template --debug .
- Pour créer un package de Chart, nous utilisons :
$ helm package helm-chart-example
Successfully packaged chart and saved it to: /home/gmkziz/helm-charts/myapp-0.0.1.tgz
Création d'une Release à l'aide du Chart Helm précédent
$ helm show values myapp-0.0.1.tgz > values.yaml
nameOverride: primary
fullnameOverride:
image:
repository: selenium/node-firefox
tag: 3.141.59
replicaCount: 3
(...)
# Set the custom Charts values as desired inside the values.yaml file,
# then:
$ helm upgrade --install myapp -f values.yaml myapp-0.0.1.tgz
NAME: myapp
(...)
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
$ helm list
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
myapp default 1 <release_creation_date> deployed myapp-0.0.1 10.2.3
$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
myapp-primary 1/1 1 1 84s
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-primary-65596d9948-k7m2z 1/1 Running 0 79s
$ kubectl get deploy -o yaml
apiVersion: v1
items:
- apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
meta.helm.sh/release-name: myapp
meta.helm.sh/release-namespace: default
creationTimestamp: "***"
generation: 1
labels:
app.kubernetes.io/instance: myapp
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: primary
app.kubernetes.io/version: 10.2.3
helm.sh/chart: myapp
name: myapp-primary
namespace: default
resourceVersion: "990"
uid: bf577704-2d19-4b43-88ac-a7450c32ced1
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app.kubernetes.io/instance: myapp
app.kubernetes.io/name: primary
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app.kubernetes.io/instance: myapp
app.kubernetes.io/name: primary
spec:
containers:
- env:
- name: HUB_HOST
value: selenium-hub
- name: HUB_PORT
value: "4444"
- name: NODE_MAX_INSTANCES
value: "1"
- name: NODE_MAX_SESSION
value: "1"
image: selenium/node-firefox:3.141.59
imagePullPolicy: IfNotPresent
name: primary
resources:
limits:
memory: 2000Mi
requests:
memory: 2000Mi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /dev/dshm
name: dshm
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
volumes:
- emptyDir:
medium: Memory
name: dshm
status:
availableReplicas: 1
conditions:
- lastTransitionTime: "***"
lastUpdateTime: "***"
message: Deployment has minimum availability.
reason: MinimumReplicasAvailable
status: "True"
type: Available
- lastTransitionTime: "***"
lastUpdateTime: "***"
message: ReplicaSet "myapp-primary-74fdbf6bd" has successfully progressed.
reason: NewReplicaSetAvailable
status: "True"
type: Progressing
observedGeneration: 1
readyReplicas: 1
replicas: 1
updatedReplicas: 1
kind: List
metadata:
resourceVersion: ""