Una prova su strada di k0s, Kubernetes in un singolo eseguibile by Mirantis, che ha raggiunto la versione 1.27
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!
Raoul Scarazzini
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.
Se vuoi sostenerci, puoi farlo acquistando qualsiasi cosa dai diversi link di affiliazione che abbiamo nel nostro sito o partendo da qui oppure alcune di queste distribuzioni GNU/Linux che sono disponibili sul nostro negozio online, quelle mancanti possono essere comunque richieste, e su cui trovi anche PC, NAS e il ns ServerOne. Se ti senti generoso, puoi anche donarmi solo 1€ o più se vuoi con PayPal e aiutarmi a continuare a pubblicare più contenuti come questo. Grazie!
Hai dubbi o problemi? Ti aiutiamo noi!
Se vuoi rimanere sempre aggiornato, iscriviti al nostro canale Telegram.Se vuoi ricevere supporto per qualsiasi dubbio o problema, iscriviti alla nostra community Facebook o gruppo Telegram.
Cosa ne pensi? Fateci sapere i vostri pensieri nei commenti qui sotto.
Ti piace quello che leggi? Per favore condividilo con gli altri.