f in x
Helm per Kubernetes Guida Operativa a Chart Personalizzate e Deploy Professionali
> cd .. / HUB_EDITORIALE > Visualizza in Inglese
Sviluppo di siti web

Helm per Kubernetes Guida Operativa a Chart Personalizzate e Deploy Professionali

[2026-06-16] Author: Ing. Calogero Bono

Hai Kubernetes in produzione. Ogni deploy è un copia-incolla di YAML? I manifest sono sparsi tra cartelle, valori hardcoded, nessuna tracciabilità. Lo vediamo spesso nei progetti che analizziamo: cluster funzionanti ma gestiti come fossero prototipi. Un errore di sintassi in un Deployment e l'app resta in CrashLoopBackOff per ore. Il tempo perso a correggere è tempo che potevi dedicare al prodotto.

Noi, di Meteora Web, lavoriamo con Kubernetes da anni — da quando i container non erano ancora la norma. Abbiamo visto aziende risparmiare centinaia di ore semplicemente strutturando i deploy con Helm. E abbiamo anche visto il lato economico: un deploy manuale sbagliato su un cluster di produzione costa più di una giornata di sviluppo. Con Helm il deploy diventa riproducibile, versionato, testabile. E si paga una volta sola.

Questa guida è il secondo spoke del nostro pillar su Kubernetes e orchestrazione container. Ti portiamo dentro Helm: dalla struttura di un chart alle best practice per ambienti reali. Niente teoria astratta — tutto quello che serve per smettere di scrivere YAML a mano e iniziare a usare un package manager degno di questo nome.

Perché Helm non è solo un abbellimento

Helm è il package manager di Kubernetes. Ma non limitarti a pensarlo come un 'apt per cluster'. È molto di più: è un motore di templating, un sistema di gestione delle release, un repository di pacchetti pronti all'uso. Se non lo usi, ogni deploy è un assemblaggio artigianale: copia un YAML, incolla, cambia namespace, modifica il nome, incrocia le dita. Con Helm definisci una volta la struttura e poi la parametrizzi. Il risultato? Uno stesso chart deployato in development, staging e production con valori diversi, zero duplicazione di codice.

L'analogia che usiamo coi nostri clienti è quella del fatturino di un negozio: se devi calcolare ogni scontrino a mano, perdi tempo e sbagli. Se hai un ERP che lo fa per te con regole fisse, guadagni precisione e velocità. Helm è il tuo ERP per Kubernetes.

Sponsored Protocol

Il costo di non usare Helm

Un cliente ci ha portato un cluster con 15 microservizi, ognuno con la propria cartella di YAML. Ogni deploy richiedeva tra 20 e 40 minuti di attenzione umana. Un errore di typo in un nome di volume — e il pod non partiva. Helm ha ridotto il deploy a helm upgrade --install con un singolo comando. Il risparmio? Circa 15 ore al mese. Non è solo tecnologia: è economia.

Anatomia di un Helm Chart

Un chart è una directory strutturata. Se non la rispetti, Helm non lo interpreta. Ecco i file obbligatori e quelli tipici:

mio-chart/
├── Chart.yaml          # metadati del chart (nome, versione, dipendenze)
├── values.yaml         # valori predefiniti per i template
├── templates/          # file Go template che generano YAML
│   ├── deployment.yaml
│   ├── service.yaml
│   └── _helpers.tpl    # funzioni riutilizzabili (underscore = non generare risorse)
├── charts/             # dipendenze (chart annidati)
└── .helmignore         # file da escludere

Chart.yaml è il biglietto da visita. Esempio minimo:

apiVersion: v2
name: mia-webapp
description: Un semplice web server
version: 0.1.0
appVersion: "1.16.0"

values.yaml è dove metti i valori che cambi per ambiente: replicaCount, immagine, porta, risorse. È il cuore della parametrizzazione.

templates/ contiene file che Helm elabora con il motore Go template. Ogni file che inizia con _ non produce un oggetto Kubernetes, ma può essere incluso da altri template (es. helper per label comuni).

Errore comune: dimenticare di versionare i chart in git. Il chart deve essere sotto controllo versione, esattamente come il codice. Altrimenti perdi la riproducibilità.

Sponsored Protocol

Creare il tuo primo chart da zero

Basta un terminale. Usiamo helm create per generare una struttura di esempio, ma noi preferiamo partire da zero per capire tutto.

Passo 1: la directory

mkdir nginx-private
cd nginx-private
mkdir templates

Passo 2: Chart.yaml

apiVersion: v2
name: nginx-private
description: Il mio nginx custom con valori parametrizzati
version: 0.1.0
appVersion: "1.25.0"

Passo 3: values.yaml

replicaCount: 2
image:
  repository: nginx
  tag: "1.25.0"
  pullPolicy: IfNotPresent
service:
  type: ClusterIP
  port: 80
resources: {}
nodeSelector: {}

Passo 4: deployment.yaml in templates/

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "nginx-private.fullname" . }}
  labels:
    {{- include "nginx-private.labels" . | nindent 4 }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      {{- include "nginx-private.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "nginx-private.selectorLabels" . | nindent 8 }}
    spec:
      containers:
        - name: nginx
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          ports:
            - containerPort: {{ .Values.service.port }}

Passo 5: service.yaml

apiVersion: v1
kind: Service
metadata:
  name: {{ include "nginx-private.fullname" . }}
  labels:
    {{- include "nginx-private.labels" . | nindent 4 }}
spec:
  type: {{ .Values.service.type }}
  ports:
    - port: {{ .Values.service.port }}
      targetPort: {{ .Values.service.port }}
      protocol: TCP
      name: http
  selector:
    {{- include "nginx-private.selectorLabels" . | nindent 4 }}

Passo 6: _helpers.tpl (nomi e label standard)

{{- define "nginx-private.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{- define "nginx-private.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 }}

{{- define "nginx-private.labels" -}}
helm.sh/chart: {{ include "nginx-private.name" . }}-{{ .Chart.Version | replace "+" "_" }}
{{ include "nginx-private.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{- define "nginx-private.selectorLabels" -}}
app.kubernetes.io/name: {{ include "nginx-private.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

Ora puoi installare il chart con:

Sponsored Protocol

helm install mio-nginx ./nginx-private

Go Template nel dettaglio: quello che ti serve davvero

I template Helm usano il linguaggio Go con funzioni di Sprig. Non serve essere esperti di Go, ma devi conoscere le funzioni chiave.

Accesso ai valori

.Values.replicaCount — il punto indica l'oggetto globale. .Chart, .Release, .Files sono altri oggetti built-in.

Condizioni

Utili per esporre servizi solo se necessari:

{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
...
{{- end }}

Range (cicli)

Per iterare su un elenco, ad esempio più variabili d'ambiente:

env:
{{- range $key, $val := .Values.envVars }}
  - name: {{ $key }}
    value: {{ $val | quote }}
{{- end }}

Funzioni di manipolazione stringhe

upper, lower, trimSuffix, quote, default, required. required è fantastico per validare che un valore obbligatorio sia presente:

domain: {{ required "Un valore per domain è obbligatorio" .Values.domain }}

Spazi e indentazione

Usa {{- per rimuovere spazi bianchi prima e -}} per rimuovere dopo. nindent aggiunge newline e indentazione. Regola d'oro: per gli elementi di una lista, usa nindent per mantenere YAML valido.

Sponsored Protocol

Gestione delle dipendenze: chart che contengono chart

Una webapp ha bisogno di un database? Invece di scrivere un Deployment per MySQL a mano, puoi dichiarare la dipendenza da un chart ufficiale (es. bitnami/mysql).

File Chart.yaml con dipendenze

apiVersion: v2
name: webapp-con-db
dependencies:
  - name: mysql
    version: "9.10.2"
    repository: "https://charts.bitnami.com/bitnami"
    condition: mysql.enabled
    tags:
      - database

Poi esegui:

helm dependency update

Scarica il chart nella cartella charts/. Ora puoi passare valori di configurazione per MySQL nel tuo values.yaml sotto la chiave mysql.

Attenzione: le dipendenze non vengono aggiornate automaticamente. Se il chart padre cambia versione, devi esplicitamente rifare helm dep update.

Deploy e rollback: il comando che salva la giornata

Il ciclo di vita di Helm è gestito con helm install, helm upgrade, helm rollback. Ogni deploy è una release con un numero di revisione.

Installazione

helm install mia-webapp ./mio-chart -f valori-produzione.yaml --namespace produzione --create-namespace

Upgrade

helm upgrade mia-webapp ./mio-chart -f valori-produzione.yaml --atomic --timeout 10m

Flag --atomic ripristina la release precedente se fallisce. Non volare senza rete.

Rollback

helm rollback mia-webapp 2  # torna alla revisione 2
helm history mia-webapp    # elenca revisioni

Best practice per chart personalizzate

  • Usa i naming standard: app.kubernetes.io/name, app.kubernetes.io/instance, app.kubernetes.io/version. I tool di monitoring e networking si aspettano queste label.
  • Valida i valori con JSON Schema: crea un file values.schema.json nella root del chart. Helm lo usa per validare i valori prima di iniziare il rendering. Un semplice schema previene errori come replicaCount: "tre".
  • Non hardcodare nomi: usa sempre gli helper per generare fullname. Eviti collisioni in namespace condivisi.
  • Separa i valori per ambiente: file values-dev.yaml, values-prod.yaml separati dal chart. Il chart è l'unica fonte di verità per la struttura; i valori sono configurazione.
  • Aggiorna l'appVersion: quando il container cambia tag, aggiorna appVersion in Chart.yaml e incrementa version. Così il team di Operations sa subito se il chart è allineato.

Integrazione con CI/CD

Helm brilla in pipeline automatiche. Una volta costruita l'immagine del container, la pipeline può eseguire helm upgrade --install con i valori giusti. Questo tema lo approfondiamo nel nostro articolo dedicato alla CI/CD.

Sponsored Protocol

Inoltre, ti consigliamo di leggere la nostra guida pillar su Kubernetes per inquadrare Helm nel contesto completo dell'orchestrazione.

In sintesi — cosa fare adesso

  1. Converti un tuo deploy manuale in un chart Helm. Prendi il Deployment, Service e ConfigMap più semplici che hai e crea un chart seguendo i passi di questa guida.
  2. Parametrizza i valori: sposta in values.yaml tutto ciò che cambia per ambiente (repliche, immagine, variabili d'ambiente, risorse).
  3. Aggiungi gli helper per i nomi: non usare nomi fissi, usa include "tuo-chart.fullname" .
  4. Aggiungi un JSON Schema: un semplice file values.schema.json nella root del chart. Riduce errori di configurazione.
  5. Integra Helm nella tua pipeline CI/CD: se già usi GitLab CI, GitHub Actions o Jenkins, aggiungi uno step che esegue helm upgrade --install --atomic.

E se hai dubbi sul tuo cluster, sui costi nascosti del deploy manuale o sulla sicurezza dei tuoi manifest, parliamone. Lavoriamo con Kubernetes da quando non era ancora moda.

Ing. Calogero Bono

> AUTHOR_EXTRACTED

Ing. Calogero Bono

Ingegnere Informatico, co-fondatore di Meteora Web. Esperto in architetture software, sicurezza informatica e sviluppo sistemi scalabili.
[ Read Full Dossier ]

> METEORA_WEB // WEB AGENCY

Costruiamo la presenza digitale che la tua azienda merita.

Siti web, social, pubblicità online, e-commerce e hosting performante: ingegnerizzati con metodo da ingegneri informatici a Sciacca, per tutta Italia.

> MW_JOURNAL

> READ_ALL()