Installazione e Configurazione di base di un cluster Kubernetes con Calico CNI su Debian 12

da | Gen 20, 2025

Kubernetes è un sistema open source di orchestrazione di containers che permette l’automazione del deploy, dello scaling e della gestione del lifecycle.
Un cluster K8s è formato da diversi componenti, tra i principali ci sono i nodi “Control Plane” che si occupano del controllo del cluster e della gestione di “Etcd” (uno “key-value data store” condiviso) e i “Working Nodes” dove vengono eseguiti i pods.
In piccoli cluster è possibile utilizzare i nodi “Control Plane” come nodi di carico (Working Nodes) ed eseguire i pods su di essi.
I pods sono le istanze dei containers, ad esempio è possibile istanziare uno o più pods partendo da un’immagine Docker.
Il Container Runtime è il componente repsonsabile del lifecycle dei container e tipicamente viene utilizzato CRI-O (Docker è sconsigliato).
Un’altro componente fondamentale è la CNI (Container Network Interface) poiché ha in carico la gestione e la segmentazione della rete dei pods.
La CNI viene installata in seguito alla inizializzazione del cluster Kubernetes ed è possibile scegliere tra diverse opzioni.
In questo articolo verrà mostrato come installare un cluster K8s a tre nodi (Control Plane + Working Node) su Debian 12 e verrà utilizzato Calico come CNI.

PREREQUISTI

Per garantire l’alta affidabilità del servizio API dei nodi Control Plane è necessario un reverse proxy, in questa guida verranno mostrate le configurazioni per HAProxy.
Calico utilizza il BGP per diffondere le rotte tra i nodi del cluster ed opzionalmente con dei routers esterni, perciò se si vuole contattare il cluster K8s dall’esterno è necessario utilizzare un firewall compatibile con il protocollo BGP.

PREREQUISTI DEI NODI

Aggiornare il sistema:

Installare alcuni pacchetti necessari:

Disabilitare lo Swap:

Commentare nel file /etc/fstab la riga relativa allo swap:

Ricaricare il file “fstab”:

CONFIGURAZIONE DELLA RETE

Disabilitare IPv6 e abilitare IPv4 forwarding:

Abilitare il modulo del kernel br_netfilter:

Modificare il file /etc/network/interfaces (modificare i nomi delle interfacce di rete ed assegnare IP univoci ai nodi):

Ricaricare la rete:

 

VERIFICA DELL’UNIVOCITÁ DEGLI ID DEI NODI

Eseguire i seguenti comandi su tutti i nodi e verificare che gli identificativi siano univoci.

Verificare che i MAC addresses dei nodi siano univoci:

Verificare che gli UUIDs dei nodi siano univoci:

 

CONFIGURAZIONE NTP

Affinché il cluster K8s possa funzionare è necessario che l’orologio di sistema dei nodi sia sincronizzato.
Per mantenere l’orologio sincronizzato è sufficiente installare un servizio NTP e configurare il medesimo peer (ad esempio il firewall) su tutti i nodi.

Installre il pacchetto “chrony”:

Commentare nel file /etc/chrony/chrony.conf:

Aggiungere nel file /etc/chrony/chrony.conf (sostituire l’IP con l’IP del proprio peer):

Riavviare il servizio:

 

GENERAZIONE DELLE CHIAVI SSH

Può essere utile collegarsi in SSH tra un nodo e l’altro per la gestione o per lo scambio di files (SFTP), per l’autenticazione è consigliato l’utilizzo di chiavi SSH.

Generare una coppia di chiavi SSH (da eseguire su tutti i nodi):

Aggiungere al file /root/.ssh/authorized_keys di tutti i nodi le chiavi degli altri nodi.

HARDENING SSH

Questo step è opzionale e serve a limitare l’accesso in SSH dalla rete BGP.
Dal momento che viene aggiunta la direttiva ListenAddress nella configurazione del demone sshd, è necessario che il servizio venga avviato dopo che configurazione degli IP sia stata completata.
Un’alternativa consiste nel modificare un parametro del kernel per consentire il bind su IP non configurati su nessuna interfaccia, ma questo approcio non verrà preso in considerazione in questo articolo.

Creare la directory per le configurazioni aggiuntive del servizio ssh.service:

Creare il file “/etc/systemd/system/ssh.service.d/override.conf” con il seguente contenuto:

Modificare il file /lib/systemd/system/systemd-networkd-wait-online.service:

Abilitare il servizio systemd-networkd-wait-online:

Ricaricare i demoni di systemd:

Aggiungere la direttiva necessaria per limitare l’accesso:

Riavviare il servizio ssh:

 

CONFIGURAZIONE DELLE REPOSITORIES DI KUBERNETES E CRI-O

Aggiungere le repositories di Kubernetes:

Aggiungere le repositories di CRI-O

Aggiornare le repositories:

 

INSTALLAZIONE DEL CONTAINER RUNTIME (CRI-O)

Installare il pacchetto cri-o:

Marcare come hold il pacchetto di CRI-O per evitare che venga aggiornato:

Abilitare il servizio:

 

INSTALLAZIONE DI KUBERNETES

Installare i pacchetti necessari:

Marcare come hold di pacchetti di Kubernetes per evitare che vengano aggiornati:

Abilitare il servizio:

 

CONFIGURAZIONE DELL’AUTOCOMPLETAMENTO PER BASH

Può essere utile utilizzare l’autocomplemento quando si utilizza il comando kubectl, per abilitarlo eseguire i seguenti comandi:

 

CONFIGURAZIONE DI HAPROXY

Per ottenere l’alta affidabilità del controller Kubernetes è necessario configurare un load balancer, come ad esempio HAProxy, che gestisca le richieste alle API.

Esempio di configurazione di HAProxy per il controller Kubernet (nel file /etc/haproxy/haproxy.cfg):

Per verificare la configurazione:

Per applicare la configurazione:

 

CREAZIONE DEL CLUSTER K8S

ATTENZIONE

: Le configurazioni effettuate tramite il comando kubeadm init sono difficilmente modificabili dopo la creazione del cluster, perciò si consiglia una particolare attenzione nella scelta di quest’ultime.

Configurazioni iniziali:

Creare il cluster eseguendo questo comando su un solo nodo:

Sugli altri nodi effettuare il join tramite le istruzioni mostrate in fase di creazione del cluster:

Se il comando non dovesse funzionare è possibile che il token per il join sia scaduto, per elencare i token validi eseguire (su un nodo già appartenente al cluster):

Se l’output risulta vuoto, allora è necessario rigenerare il token con il seguente comando:

Se invece si ottiene un errore durante il download dei ceritificati, è necessario rigenerarli e sostituire la certificate key nel comando di join.

Eseguire su un nodo già appartenente al cluster:

Per autenticarsi con le API di Kubernetes quando si utilizza l’utente root è necessario configurare la variabile d’ambiente KUBECONFIG:

 

DISABILITARE L’ISOLAMENTO

Nel caso di piccoli cluster K8s è possibile disabilitare l’isolamento dei nodi control plane e permettere di esseguire i Pod su quest’ultimi.

Dopo aver aggiunto tutti i nodi, eseguire su un solo nodo:

 

CONFIGURAZIONE DI COREDNS

CoreDNS

è il servizio DNS del cluster Kubernetes.
Per modificare la configurazione è sufficiente modificare la sua ConfigMap e ricreare i pods.

Creare il file coredns_cm.yaml:

Modificare il dominio pizza.k8s con il dominio del cluster.

Tramite la seguente configurazione è possibile gestire il comportamento di CoreDNS quando deve risolvere domini esterni al cluster:

Con questa configurazione i nomi DNS vengono risolti utilizzando i servers indicati nel file /etc/hosts degli hosts scelti in modo sequenziale.

Se non viene specificata una policy, i servers vengono scelti in modo randomico.

CONFIGURAZIONE DELLE ROTTE STATICHE

Per evitare situazioni di traffico assimmetrico è necessario configurare che il traffico proveniente dai pods utilizzi come gateway il router sulla rete BGP.

Nei seguenti comandi e nello script sostituire gli IP e le reti in base alle proprie esigenze considerando che negli esempi essi corrispondono a:

  • 10.10.150.181, 10.10.150.182, 10.10.150.183: sono gli IP che utilizzo per la gestione del cluster e l’accesso ai nodi in SSH
  • 10.10.170.181, 10.10.170.182, 10.10.170.183: sono gli IP sulla rete BGP
  • 10.10.170.1: è l’IP del gateway sulla rete BGP che utlizzo anche come peer BGP
  • 10.190.0.0/16: è la rete pods del mio cluster

Aggiugere una routing table dedicata alle rotte necessarie per Kubernetes:

Eseguire i seguenti comandi per aggiungere le rotte necessarie (sostituire ens20 con il nome dell’interfaccia sulla rete BGP):

Aggiungere il file /etc/network/if-up.d/k8s-up (sostituire ens20 con il nome dell’interfaccia sulla rete BGP):

Aggiungere il file /etc/network/if-down.d/k8s-down (sostituire ens20 con il nome dell’interfaccia sulla rete BGP):

Rendere i file eseguibili:

 

CONFIGURAZIONE DI CALICO

ATTENZIONE

: Quando si applica un file YAML tramite “kubectl apply” o “kubectl create”, esso viene applicato a livello di cluster, perciò gli step mostrati in questo paragrafo vanno eseguiti solamente su un nodo.

Creare le risorse necessarie all’operatore per Calico (Tigera Operator):

Effettuare il download del file custom-resources.yaml da GitHub:

Modificare la opzioni della rete di default per i pods nel file custom-resources.yaml:

La rete indicata con il parametro cidr deve essere una subnet della pod network configurata in fase di inizializzazione del cluter.
Il NAT può essere disabilitato tramite il parametro natOutgoing, poiché viene utilizzato il BGP per esportare le rotte.
Il parametro disableBGPExport viene mantenuto false per effettuare la configurazione manuale del BGP.

Applicare le risorse:

Creare il file bgp.yaml con le configurazioni relative al BGP:

Sostituire i due parametri asNumber con il numero AS della propria rete locale.
Sostituire l’IP indicato nel parametro peerIP con l’IP del router BGP (il firewall); è possibile aggiungere più routers indicando più BGPPeer.

Applicare le risorse:

Creare il file podnetpools.yaml con le reti dei pods, in seguito un esempio di una rete:

Sostituire custom-pod-network con il nome della rete e modificare il valore del parametro cidr indicando la rete in formato CIDR.
La rete deve essere una subnet della pod network configurata in fase di inizializzazione del cluter.

Applicare le risorse:

A questo punto le rotte BGP dovrebbero venir diffuse verso i routers indicati come peers.
Assicurarsi di aver configurato il firewall ed eventuali altri routers per ricevere le rotte dai nodi K8s.

INSTALLAZIONE DELL’UTILITY CALICOCTL

Per sfruttare a pieno le funzionalità di Calico è possibile scaricare l’eseguibile calicoctl:

Rendere il file eseguibile:

Verificare il funzionamento dell’utility:

 

ASSEGNARE GLI IP POOLS AI NAMESPACES

Tramite Calico è possibile segmentare la rete in modo che i pods di namespaces diversi appartengano a reti diverse.
Tramite le Network Policies è possibile evitare che le diverse reti comunichino tra di loro e consentire solo i flussi richiesti, però è al di fuori dallo scopo di questo articolo.

Per assegnare al namespace default l’IPPool chiamato default-ipv4-ippool eseguire:

Analogamente è possibile configurare un IPPool specifico per ogni namespace.
Per applicare le modifiche della rete è possibile rimuovere i pods tramite “kubectl delete” ed attendere che Kubernetes li ricrei.

DEPLOY DI NGINX

Per verificare il funzionamento del cluster K8s è possibile inizializzare un deployment di Nginx.

Creare il deployment utilizzando l’immagine nginx:

Modificare il deployment appena creato:

Inserire l’annotazione utilizzata da Calico per assegnare il deployment ad una specifico IP Pool (sostituire custom-pod-network con il nome del pool):

Per applicare le modifiche alla rete è possibile modificare il numero di replicas prima a 0 e poi al numero desiderato:

Tramite il seguente comando è possibile visualizzare i pods nel namespace default ed il loro IP:

Articoli Recenti

Veeam Backup

Monitoring

Friends

  • My English Lab  English School
  • ChrSystem   Servizi ICT
  • Since 01  Kreative Graphics

Database

Networking

Autori

  • Raffaele Chiatto  Amministratore
  • Marco Valle  Autore
  • Angelo Lauria  Autore
  • Edoardo Prot  Autore
  • Davide D’Urso  Autore
Marco Valle

Marco Valle

Mi chiamo Marco Valle e da sempre sono appassionato di Cybersicurezza e Linux. Per lavoro implemento soluzioni open source.

Related Post

0 commenti

Invia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Virtualizzazione

Linux

Microsoft

Apple

Backup

Database

Security

Automazione