Charts Complessi

Dipendenze

Un chart può dipendere da altri chart.

Dipendenza lasca

Corrisponde ad un'installazione manuale del chart dipendente nella directory charts.

Dipendenza stretta

Formalizza la dipendenza e la gestisce tramite comandi Helm.

Le dipendenze sono specificate nel file Chart.yaml.

Esempio:

dependencies:
  - name: booster
    version: ^1.0.0
    repository: https://raw.githubusercontent.com/Masterminds/learning-helm/main/chapter6/repository/

Per la versione si usa comunemente un range espresso da simboli.

La notazione è la corrente:

SintassiEquivalente a
^1.2.3>= 1.2.3 < 2.0.0
^1.2.x>= 1.2.0 < 2.0.0
^2.3>= 2.3 < 3
^2.x>= 2.0.0 < 3
^0.2.3to >= 0.2.3 < 0.3.0
^0.2>= 0.2.0 < 0.3.0
^0.0.3to >= 0.0.3 < 0.0.4
^0.0>= 0.0.0 < 0.1.0
^0= 0.0.0 < 1.0.0
~1.2.3to >= 1.2.3 < 1.3.0
~1= 1 < 2
~2.3>= 2.3 < 2.4
~1.2.xto >= 1.2.0 < 1.3.0
~1.x>= 1 < 2

Il repository può essere:

  • una URL
  • un repository di Helm aggiunto con helm repo add, prefissoda un @, p.es. "@myrepo"

Update di Dipendenze

Col comando:

helm dependency update .

Si ottiene un risultato simile a:

Saving 1 charts
Downloading booster from repo https://raw.githubusercontent.com/Masterminds/learning-helm/main/chapter6/repository/
Deleting outdated charts

Durante l'update:

  • Vieme generato il file Chart.lock
  • la dipendenza viene copiata nells sottodirectory charts

In luogo dell'argomento . (punto), si può passare come parametro un oggetto, ma non è quasi mai usato.

Dipendenze Condizionali

E' fornita dalla prorietà condition nella descrizione di dipendenza.

Per esempio nel file Charts.yaml:

dependencies:
  - name: booster
    version: ^1.0.0
    condition: booster.enabled
    repository: https://raw.githubusercontent.com/Masterminds/learning-helm/main/chapter6/repository/

Controllata dal file values.yaml

booster:
  enabled: false

Importare Valori

A volte si desiderano importare valori da un chart dipendente (child) nel chart corrente (parent).

Proprietà exports

Esempio. Nel file values.yaml del child:

exports:
  types:
    foghorn: rooster

Nel file Charts.yaml del parent:

dependencies:
  - name: example-child
    version: ^1.0.0
    repository: https://charts.example.com/
    import-values:
      - types

Questo è l'equivalente di aver settato, in values.yaml del parent:

foghorn: rooster

Import Diretto

Se il child ha nel file values.yaml:

types:
  foghorn: rooster

Il parent ha nel file Charts.yaml:

dependencies:
  - name: example-child
    version: ^1.0.0
    repository: https://charts.example.com/
    import-values:
      - child: types
        parent: characters

Questo è l'equivalente di aver settato, in values.yaml del parent:

characters:
  foghorn: rooster

Librerie di Charts

Le librerie di charts sono concettualmente simili a librerie software Forniscono funzionalità riusabili e sono importate da altri charts.

Le librerie di charts non sono esse stesse installabili.

Creazione di un Library Chart

  • Creare un chart normalmente col comando helm create
  • Rimuovere il file values,yaml
  • Rimuovere il contenuto della directory templates
  • Modificare il file Chart.yaml inserendo il parametro type: library

Per esempio:

apiVersion: v2
name: mylib
type: library
description: an example library chart
version: 0.1.0

I files implementativi della libreria si trovano nella directory templates e il loro nome inizia con _ (underscore). Helm non genera templates da nomi che iniziano con _.

Le loro estensioni sono .tpl o .yaml.

Un esempio può essere _configmap.yaml:

{{- define "mylib.configmap.tpl" -}}
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ include "mylib.fullname" . }}
  labels:
    {{- include "mylib.labels" . | nindent 4 }}
data: {}
{{- end -}}
{{- define "mylib.configmap" -}}
{{- template "mylib.util.merge" (append . "mylib.configmap.tpl") -}}
{{- end -}}

Il template mylib.util.merge deve essere altrove definito come:

{{- /*
mylib.util.merge will merge two YAML templates and output the result.
This takes an array of three values:
- the top context
- the template name of the overrides (destination)
- the template name of the base (source)
*/ -}}
{{- define "mylib.util.merge" -}}
{{- $top := first . -}}
{{- $overrides := fromYaml (include (index . 1) $top) | default (dict ) -}}
{{- $tpl := fromYaml (include (index . 2) $top) | default (dict ) -}}
{{- toYaml (merge $overrides $tpl) -}}
{{- end -}}

Il seguente esempio, da un chart mychart, illustra l'uso di questa funzione di libreria:

{{- include "mylib.configmap" (list . "mychart.configmap") -}}
{{- define "mychart.configmap" -}}
data:
  myvalue: "Hello Bosko"
{{- end -}}

La prima linea include il template mylib.configmap dalla chart di libreria. L'argomento passato è una lista con l'oggetto corrente e il nome del template i cui contenuti compiranno un override di quelli del template di libreria.

L'output prodotto è:

apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    app.kubernetes.io/instance:example
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: mychart
    helm.sh/chart: mychart-0.1.0
  name: example-mychart
data:
  myvalue: Hello Bosko

Schema per Values

E' possibile fornire uno schema per controllare con lint la validità del file values.yaml.

Il file di schema si chiama values.schema.json, nella directory principale del chart ove si trova anche values.yaml. ed è scritto in JSON.

Esempio. Se values.yaml è il seguente:

image:
  repository: ghcr.io/masterminds/learning-helm/anvil-app
  pullPolicy: IfNotPresent
  tag: ""

Uno schema corrispondente potrebbe essere:

{
  "$schema": "http://json-schema.org/schema#",
  "type": "object",
  "properties": {
    "image": {
      "type": "object",
      "properties": {
        "pullPolicy": {
          "type": "string",
          "enum": ["Always", "IfNotPresent"]
        },
        "repository": {
          "type": "string"
        },
        "tag": {
          "type": "string"
        }
      }
    }
  }
}

Esempio d'uso con un errore:

helm lint . --set image.pullPolicy=foo

Output prodotto:

==> Linting .
[ERROR] templates/: values don't meet the specifications of the schema(s) in the
following chart(s):
booster:
- image.pullPolicy: image.pullPolicy must be one of the following: 
  "Always", "IfNotPresent"

Error: 1 chart(s) linted, 1 chart(s) failed

Helm Hooks

Azioni compiute ad un certo stadio del ciclo di vita dell'oggetto Kubernetes.

Si specificano nella proprietà annotations e possono avere le seguenti chiavi:

  • "helm.sh/hook" - azione durante il ciclo di vita dell'oggetto. Vi possono essere più azioni, separate da virgola e senza spazi
  • "helm.sh/hook-weight" - specifica l'annotazione precedente; deve sempre esseere un numero intero, positivo, negativo o zero (default), ma espresso come stringa. Helm sortizza gli hooks in ordine ascendente, dal più piccolo al più grande.
  • "helm.sh/hook-delete-policy" - se cancellare l'oggetto Kubernetes trattato relativamente allo hook

Gli hook possono essere:

NomeQuando viene eseguito
pre-installprima dell'invio a Kubernetes
post-installdopo l'invio a Kubernetes
pre-deleteprima della cancellazione
post-deletedopo la cancellazione
pre-upgradedurante un upgrade, prima dell'invio a Kubernetes
post-upgradedurante un upgrade, dopo l'invio a Kubernetes
pre-rollbackprima di un rollback
post-rollbackdopo un rollback
testdurante il comando helm test

Le policy di cancellazione, relative ad una risorsa di Kubernetes,possono essere:

PolicyDescrizione
before-hook-creationcancellata prima dello hook (default)
hook-succeededcancellata se lo hook ha avuto successo
hook-failedcancellata se lo hook è fallito

Esempio del templato di un pod con uno hook di tipo post-install:

apiVersion: v1
kind: Pod
metadata:
  name: "{{ include "mychart.fullname" . }}-post-install"
  labels:
    {{- include "mychart.labels" . | nindent 4 }}
  annotations:
    "helm.sh/hook": post-install
    "helm.sh/hook-weight": "-1"
    "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
spec:
  containers:
    - name: wget
      image: busybox
      command: ["/bin/sleep","{{ default "10" .Values.sleepTime }}"]
  restartPolicy: Never

L'esecuzione degli hooks durante un comando Helm, può essere saltata con l'opzione --no-hooks.

Helm Test

Helm fornisce di serie il comando di linea helm test.

I templati di test risiedono nella directory del chart templates/tests.

Reinstalliamo il nostro chart d'esercizio:

helm install myapp anvil

Il templato di test è anvil/templates/tests/test-connection.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: "{{ include "anvil.fullname" . }}-test-connection"
  labels:
    {{- include "anvil.labels" . | nindent 4 }}
  annotations:
    "helm.sh/hook": test
spec:
  containers:
    - name: wget
      image: busybox
      command: ['wget']
      args: ['{{ include "anvil.fullname" . }}:{{ .Values.service.port }}']
  restartPolicy: Never

Che sia un test è specificato da:

  annotations:
    "helm.sh/hook": test

Proviamo il test:

helm test myapp
NAME: myapp
LAST DEPLOYED: Thu Feb 15 12:07:55 2024
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE:     myapp-anvil-test-connection
Last Started:   Thu Feb 15 12:08:31 2024
Last Completed: Thu Feb 15 12:08:58 2024
Phase:          Succeeded
NOTES:
.....