Una prova su strada di k0s, Kubernetes in un singolo eseguibile by Mirantis, che ha raggiunto la versione 1.27

11 months ago 241

Quando abbiamo parlato la prima volta di k0s, nell’articolo “Per voi è troppo k8s? Avete provato k3s e lo trovate esoso? Arriva Mirantis con il suo k0s, Kubernetes in un eseguibile“, avevamo analizzato in maniera approssimativa le funzionalità di questa soluzione, senza approfondire.

L’occasione di rimediare viene però data dall’annuncio da parte di Mirantis della disponibilità della versione 1.27 di k0s che segue chiaramente Chill Vibes, la nuova release di Kubernetes.

L’aspetto su cui punta Mirantis per promuovere k0s è in prima istanza quello della sicurezza. Infatti ciò che è garantito dall’azienda proprietaria di Docker è il fatto che l’eseguibile viene distribuito senza alcuna CVE conosciuta riscontrabile.

Per chiarire meglio riportiamo le parole di Miska Kaipiainen, VP of engineering, product strategy, and open source in Mirantis:

Before 1.27, k0s relied on system images published by various upstream projects, this has worked pretty well, but there are some downsides. For one thing, it’s understood (sadly) that most upstream system images used by Kubernetes contain CVEs.

Prima della 1.27 k0s si basava sulle immagini di sistema pubblicate dai vari progetti upstream, e questo ha funzionato bene, ma con qualche controindicazione. Per prima cosa, è risaputo che (tristemente) la maggioranza delle immagini di sistema upstream usate da Kubernetes contiene CVE.

E la soluzione a questo è citata appunto nella nuova modalità con cui k0s è prodotto:

Starting with this 1.27 release, k0s will run all system components with images that we build ourselves. We still use pure upstream functionality and do not use any custom forks of project components. Essentially what we do is take the upstream components as-is and rebuild the images in a way that mitigates as many known CVEs as possible.

A partire da questa release 1.27 tutte le componenti di sistema con cui funzionerà k0s si baseranno su immagini che costruiremo per nostro conto. Usiamo ancora le funzionalità upstream, senza fare fork delle componenti di progetto. Quello che facciamo è essenzialmente prendere le componenti upstream come sono e farne la rebuild in modo da mitigare più CVE possibili.

Le premesse quindi sembrano interessanti, ma nella pratica come funziona questo k0s?

Installare k0s

L’installazione di k0s potrebbe essere fatta lanciando direttamente un file .sh da internet, ma non essendo particolarmente fan di questa modalità, qualcosa di più canonico funziona ugualmente:

rasca@ubuntu-jammy:~$ wget https://github.com/k0sproject/k0s/releases/download/v1.27.1%2Bk0s.0/k0s-v1.27.1+k0s.0-amd64 ... rasca@ubuntu-jammy:~$ sudo mv k0s-v1.27.1+k0s.0-amd64 /usr/local/bin/k0s rasca@ubuntu-jammy:~$ sudo chmod +x /usr/local/bin/k0s

Una volta che l’eseguibile è disponibile si può avviare la creazione del controller e l’avvio del cluster:

rasca@ubuntu-jammy:~$ sudo k0s install controller --single --verbose INFO[2023-05-05 13:21:12] creating user: etcd INFO[2023-05-05 13:21:12] creating user: kube-apiserver INFO[2023-05-05 13:21:12] creating user: konnectivity-server INFO[2023-05-05 13:21:12] creating user: kube-scheduler INFO[2023-05-05 13:21:12] Installing k0scontroller service rasca@ubuntu-jammy:~$ sudo k0s start rasca@ubuntu-jammy:~$ sudo k0s status Version: v1.27.1+k0s.0 Process ID: 1822 Role: controller Workloads: true SingleNode: true Kube-api probing successful: true Kube-api probing last error:

Da qui in poi il Kubernetes di k0s sarà accessibile mediante sudo k0s kubectl o, se avete già kubectl disponibile sul vostro sistema (come in questo caso) andando a creare il file kubeconfig di k0s che conterrà tutte le informazioni di accesso:

rasca@ubuntu-jammy:~$ sudo k0s kubeconfig admin > kubeconfig rasca@ubuntu-jammy:~$ export KUBECONFIG=kubeconfig rasca@ubuntu-jammy:~$ kubectl get nodes NAME STATUS ROLES AGE VERSION ubuntu-jammy Ready control-plane 6m32s v1.27.1+k0s rasca@ubuntu-jammy:~$ kubectl get namespaces NAME STATUS AGE kube-system Active 110s kube-public Active 110s kube-node-lease Active 110s default Active 110s k0s-autopilot Active 107s

Il cluster è quindi pronto all’uso.

Deploy di un’applicazione

k0s è Kubernetes ed in questo senso la creazione di un deployment e del relativo servizio può essere fatta nella consueta modalità:

rasca@ubuntu-jammy:~$ kubectl create namespace mynamespace namespace/mynamespace created rasca@ubuntu-jammy:~$ kubectl -n mynamespace create deployment nginx --image=nginx:latest deployment.apps/nginx created rasca@ubuntu-jammy:~$ kubectl -n mynamespace create service clusterip nginx --tcp=80:80 service/nginx created rasca@ubuntu-jammy:~$ kubectl -n mynamespace set selector service nginx 'app=nginx' service/nginx selector updated

In questo test k0s è stato installato in una macchina virtuale non particolarmente potente (2 CPU, 4 GB RAM), ma i tempi di risposta sono davvero eccellenti, ed in pochi secondi l’applicazione di test (il webserver nginx) è disponibile:

rasca@ubuntu-jammy:~$ kubectl -n mynamespace get all NAME READY STATUS RESTARTS AGE pod/nginx-7bf8c77b5b-rxxjv 1/1 Running 0 31s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/nginx ClusterIP 10.106.130.151 <none> 80/TCP 20s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/nginx 1/1 1 1 31s NAME DESIRED CURRENT READY AGE replicaset.apps/nginx-7bf8c77b5b 1 1 1 31s

A proposito di servizi

A questo punto, nella maggioranza degli ambienti Kubernetes verrebbe il dubbio in merito a come esporre i servizi all’esterno del cluster poiché il servizio creato qui sopra è di tipo ClusterIP, quindi visibile unicamente all’interno della rete cluster. Ci vorrebbe una componente ingress e verosimilmente un load balancer, entrambi non presenti di default in k0s.

C’è però un aspetto molto interessante di k0s che vale la pena citare, e lo si introduce andando a stampare lo stato delle interfacce di rete presenti nel sistema dopo l’installazione, ponendo attenzione sul device kube-bridge:

rasca@ubuntu-jammy:~$ ip a ... ... 5: kube-bridge: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 72:ff:99:76:bc:ec brd ff:ff:ff:ff:ff:ff inet 10.244.0.1/24 brd 10.244.0.255 scope global kube-bridge valid_lft forever preferred_lft forever inet6 fe80::24ce:51ff:fee5:a65b/64 scope link valid_lft forever preferred_lft forever ... ...

E visualizzando le regole di NAT del firewall, create in automatico mediante nft, relative all’indirizzo IP del servizio che abbiamo creato, ossia 10.106.130.151:

rasca@ubuntu-jammy:~$ kubectl -n mynamespace get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx ClusterIP 10.106.130.151 <none> 80/TCP 59m rasca@ubuntu-jammy:~$ sudo nft list table nat | grep -C 2 10.106.130.151 chain KUBE-SERVICES { meta l4proto tcp ip daddr 10.106.130.151 tcp dport 80 counter packets 0 bytes 0 jump KUBE-SVC-DHME6VD2S2S3MUZC meta l4proto tcp ip daddr 10.96.0.1 tcp dport 443 counter packets 0 bytes 0 jump KUBE-SVC-NPX46M4PTMTKRN6Y meta l4proto udp ip daddr 10.96.0.10 udp dport 53 counter packets 0 bytes 0 jump KUBE-SVC-TCOU7JCQXEZGVUNU -- chain KUBE-SVC-DHME6VD2S2S3MUZC { meta l4proto tcp ip saddr != 10.244.0.0/16 ip daddr 10.106.130.151 tcp dport 80 counter packets 5 bytes 300 jump KUBE-MARK-MASQ counter packets 5 bytes 300 jump KUBE-SEP-ELPBDVDUOHBNVX3R }

Quindi sì, kube-bridge viene usata dalle regole per mettere in comunicazione l’host con la rete cluster di Kubernetes, consentendo quindi l’accesso diretto ai servizi di tipo ClusterIP:

rasca@ubuntu-jammy:~$ curl 10.106.130.151 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>

In questo modo il test di eventuali applicazioni risulta assolutamente immediato e non vi è necessità di effettuare il deploy di componenti aggiuntive, comunque supportate da k0s, quali Ingress NGINX come ingress controller o MetalLB come load balancer.

Conclusioni

Se le esigenze poi esulano dai semplici test va sottolineato come k8s sia a tutti gli effetti adatto alla produzione, infatti mediante l’utilizzo di k0ctl è possibile creare e gestire istanze multiple di k0s attraverso un semplice yaml, in maniera centralizzata, andando a risolvere anche la problematica di gestione multi-cluster.

Mica male per un singolo eseguibile!

Da sempre appassionato del mondo open-source e di Linux nel 2009 ho fondato il portale Mia Mamma Usa Linux! per condividere articoli, notizie ed in generale tutto quello che riguarda il mondo del pinguino, con particolare attenzione alle tematiche di interoperabilità, HA e cloud.
E, sì, mia mamma usa Linux dal 2009.

Read Entire Article