Installare Kubernetes su Ubuntu 22.04

Aggiornato e validato in data 23 maggio 2023: Dopo qualche mese d’utilizzo, è ora di installare Kubernetes su Ubuntu 22.04.

L’installazione di Kubernetes (K8s) su Ubuntu 22.04 differisce da quella fatta per Ubuntu 20.04 in quanto non andremmo più ad installare Docker.

Esatto! La mancanza di Docker non è un problema anzi un’opportunità in quanto uno dei componenti di Kubernetes, chiamato dockershim, che permetteva a Kubernetes di interloquire con Docker è stato rimosso dalla versione 1.24 di K8s. Ora l’installazione di Kubernetes con Docker non è più così immediata come prima, per cui passare a containerd come runtime risulta più agevole e non limita le funzionalità.

Se avete l’esigenza di creare un disco (o un filesystem) separato dove ospitare i container farlo usando come mount point /var/lib/containerd.

Installazione di Kubernetes su Ubuntu 22.04

Dopo aver installato la versione server di Ubuntu 22.04 (l’installazione minimal con server SSH è sufficiente), il primo passaggio è quello di assegnare un IP statico (che non cambia) ai nodi Kubernetes.
Questo in quanto cambiare l’indirizzo IP successivamente all’installazione è un po’ problematico e comporta dei tempi di indisponibilità del cluster.
Altro suggerimento è quello di non cambiare l’hostname del server successivamente all’installazione e configurazione di K8s, per lo stesso motivo.

Ora procediamo! E’ necessario disabilitare la swap e attivare e modificare alcune impostazioni al kernel.

sudo swapoff -a
sudo sed -i '/swap/ s/^\(.*\)$/#\1/g' /etc/fstab

Aggiugere questa configurazione per il kernel:

sudo tee /etc/modules-load.d/containerd.conf <<EOF
overlay
br_netfilter
EOF

Attivare questi 2 moduli del kernel (il comando è persistente al riavvio):

sudo modprobe overlay
sudo modprobe br_netfilter

Poi aggiungere ancora queste impostazioni dedicate a Kubernetes

sudo tee /etc/sysctl.d/kubernetes.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF

Per renderle attive è necessario ricaricare sysctl con il seguente comando:

sudo sysctl --system

Si può installare il runtime containerd: containerd oppure un altro runtime come CRI-O. Tale scelta poteva essere saltata fino alla versione 1.23 di Kuberentes perchè si potevano usare dei componenti creati ad-hoc per docker, ma da Kuberentes > 1.24 questi sono stati rimossi da Kuberentes per cui è più semplice usare uno di questi 2 runtime. In questa guida è stato scelto di installare il runtime di containerd anzichè docker.

Sono necessari degli strumenti prima di poter installare un runtime:

sudo apt install -y curl gnupg2 software-properties-common apt-transport-https ca-certificates

Abilitare repository Docker:

sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmour -o /etc/apt/trusted.gpg.d/docker.gpg
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

Procedere all’ installazione di containerd (che proviene dai repository di docker):

sudo apt update
sudo apt install -y containerd.io

Configurare containerd in modo che usi systemd come cgroup.

containerd config default | sudo tee /etc/containerd/config.toml >/dev/null 2>&1
sudo sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml

Riavvia e abilita il servizio containerd

sudo systemctl restart containerd
sudo systemctl enable containerd

Xenial è ancora l’ultimo repository Kubernetes disponibile per Ubuntu 22.04 (Jammy Jellyfish).
Aggiungere ora il repository per Kubernetes

sudo curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmour -o /etc/apt/trusted.gpg.d/cloud.google.gpg
sudo apt-add-repository "deb http://apt.kubernetes.io/ kubernetes-xenial main"

Installare i componenti Kubernetes Kubectl, kubeadm e kubelet e impostare il fatto che futuri aggiornamenti sono bloccati per questi pacchetti. La gestione degli aggiornamenti sarà una questione futura.

sudo apt update
sudo apt install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

Ricordiamoci che al termine dell’installazione e configurazione di Kubernetes è opportuno attivare un componente aggiuntivo di rete Pod basato su Container Network Interface (CNI) in modo che i Pod possano comunicare tra loro.

Scegliamo una rete dalla quale saranno prelevati gli IP che saranno assegnati ai vari container e servizi.
Questa rete deve essere diversa da quella del nostro ambiente in quanto altrimenti si potranno avere degli IP duplicati che porteranno all’irraggiunbilità dei servizi e ad altri malfunzionamenti.

Va fatta una considerazione sulla rete e su pod-network-cidr.

Siccome ad ogni nodo generalmente viene attribuito un pool di 256 indirizzi che verranno assegnati ai servizi e container bisogna calcolare una rete amplia anche per usi futuri. Con una rete come 192.168.240.0/21 è possibile avere fino ad 8 nodi in quanto ci sono 2046 indirizzi utilizzabili. Per questo motivo se pensate di aggiungere più di 8 nodi al vostro cluster, sarebbe opportuno fin da subito ampliare il pod network cidr con una rete più amplia es. 192.168.240.0/20, così da poter avere ben 16 nodi e un intervallo di indirizzi utilizzabili da 192.168.240.1 a 192.168.255.254.
Quindi nel successivo comando dovreste cambiare la rete 192.168.240.0/21 con una che soddisfa i vostri requisti. Ricordatevi di sostituire anche 192.168.1.1 con l’indirizzo del server K8s che disporrà del componente Control Plane (quello che una volta era chiamato Master).

sudo kubeadm init --control-plane-endpoint 192.168.1.1 --pod-network-cidr 192.168.240.0/21

Annotarsi il comando da usare per aggiungere nuovi nodi, come worker, al nostro cluster K8s. Il comando viene dato come output alla fine dell’inizializzazione di Kubernetes.

sudo kubeadm join 192.168.1.1:6443 --token s1o2xh.sqcjbkc7f1iocf15 \
        --discovery-token-ca-cert-hash sha256:bbb0aded78f6138b3bf185dabce1f9441e6c224aa270a98b0f782dc52062af5c

192.168.1.1 dovrebbe corrispondere all’indirizzo del vostro control plane e poi vi viene fornito un token generato a caso e l’hash del token.

E’ possibile comunque rigenerare un token sostituivo per il join di un worker lanciando il seguente comando sul nodo control plane

kubeadm token create --print-join-command

Al termine dell’installazione è possibile configurare l’ambiente dei comandi in maniera comoda, lanciando quanto sotto:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

Ora è necessario configurare la parte di rete; questa parte va fatta solo sul control plane non sui nodi worker.
Come gestore utilizzeremo Calico, come nel precedente tutorial su Ubuntu 20.04.

kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.1/manifests/tigera-operator.yaml

Scarichiamo il file https://raw.githubusercontent.com/projectcalico/calico/v3.25.1/manifests/custom-resources.yaml e modifichiamolo in modo da cambiare il valore di cidr: 192.168.0.0/16 in cidr: 192.168.240.0/21 (ossia al nostro pool di indirizzi), dopo di che lanciare:

kubectl create -f custom-resources.yaml

Attendere una decina di minuti (dipende dalla vostra connessione) oppure verificare che tutti i pod necessari a Calico siano in esecuzione:

watch kubectl get pods --all-namespaces

E’ possibile aggiungere altri nodi, come worker, seguendo la procedura sopra ma saltando la parte di kubectl init e la configurazione del gestore di rete, per riferimento potete leggere la guida di installazione di Kubernetes su Ubuntu 20.04.

Passaggio facoltativo:

E’ possibile consentire l’esecuzione di pod anche sul nodo control plane (master); chiaramente non è un’operazione consigliata in un ambiente produttivo, ma così è possibile usare il nodo col control plane per far girare i container come se fosse un po’ un worker.

kubectl taint nodes --all node-role.kubernetes.io/control-plane-

Risoluzione dei problemi di Kubernetes (troubleshooting)

Cosa fare quando un nodo Kubernetes risulta NotReady?

Uno dei possibile stati di un nodo, che sia Control Plane o Worker, è NotReady. Se un nodo K8s è NotReady significa che non può essere utilizzato completamente e ha qualche anomalia. Per indagare su questa eventualità si può usare il comando:
kubectl describe node

L’output di questo comando è alquanto prolisso ma possiamo trovare questa riga che ho sottolineato in giallo:

Questo significa che il gestore di rete non sta funzionando correttamente. Solitamente si consiglia di verificare che i pod del gestore siano attivi sul cluster.

GNU/Linux

Articolo precedente

Installare Kubernetes su Ubuntu 20.04
GNU/Linux

Articolo successivo

Docker su Ubuntu 22.04