Per esse onesto, ùn sò micca sicuru à u 100%. Ma pensu chì hè interessante per sfondà in l'internu è vede ciò chì succede veramente in Kubernetes sottu i so numerosi strati di astrazioni. Dunque, solu per divertimentu, fighjemu un ochju à ciò chì hè veramente un "cluster Kubernetes" minimu. (Questu serà assai più faciule ch'è Kubernetes The Hard Way.)
Pensu chì avete una cunniscenza basica di Kubernetes, Linux è cuntenituri. Tuttu ciò chì parlemu quì hè solu per scopi di ricerca / apprendimentu, ùn ne mette micca in produzzione !
riassuntu
Kubernetes cuntene assai cumpunenti. Secondu Wikipedia, l'architettura s'assumiglia cusì:
Ci sò almenu ottu cumpunenti mostrati quì, ma ignuremu a maiò parte di elli. Vogliu dichjarà chì u minimu minimu chì pò esse chjamatu Kubernetes hè custituitu da trè cumpunenti principali:
kubelet
kube-apiserver (chì dipende da etcd - a so basa di dati)
runtime di u containeru (Docker in questu casu)
Videmu ciò chì a documentazione dice nantu à ognunu di elli (rus., Inglese.). Prima kubelet:
Un agente chì corre nantu à ogni node in u cluster. Hè assicuratu chì i cuntenituri currenu in u pod.
Sona abbastanza simplice. Chì ne dici i tempi di esecuzione di u containeru (durata di u containeru)?
Un runtime di cuntainer hè un prugramma cuncepitu per eseguisce cuntenituri.
Moltu informativu. Ma sè cunnosci Docker, allora duvete avè una idea generale di ciò chì face. (I detaglii di a separazione di e responsabilità trà u runtime di u containeru è u kubelet sò in realtà abbastanza sottili è ùn entreraghju micca quì.)
И servitore API?
API Server hè u cumpunente di u pannellu di cuntrollu di Kubernetes chì espone l'API Kubernetes. U servitore API hè u cliente di u pannellu di cuntrollu di Kubernetes
Qualchissia chì hà mai fattu qualcosa cù Kubernetes hà avutu à interagisce cù l'API direttamente o attraversu kubectl. Questu hè u core di ciò chì face Kubernetes Kubernetes - u cervellu chì trasforma e muntagne di YAML chì tutti sapemu è amemu (?) In infrastruttura di travagliu. Sembra evidenti chì l'API deve esse presente in a nostra cunfigurazione minima.
Precondizioni
Macchina virtuale o fisica Linux cù accessu root (aghju utilizatu Ubuntu 18.04 in una macchina virtuale).
È hè tuttu!
Installazione boring
Avemu bisognu di stallà Docker nantu à a macchina chì useremu. (Ùn andaraghju micca in i dettagli nantu à cumu funziona Docker è i cuntenituri; se site interessatu, ci hè articuli meravigliosi). Stallà solu cù apt:
Dopu quì, avemu bisognu di ottene i binari Kubernetes. In fatti, per u lanciu iniziale di u nostru "cluster" avemu solu bisognu kubelet, postu chì per eseguisce altri cumpunenti di u servitore pudemu usà kubelet. Per interagisce cù u nostru cluster dopu chì hè in esecuzione, avemu ancu aduprà kubectl.
kubelet deve correre cum'è root. Piuttostu logicu, postu chì hà bisognu di gestisce u node sanu. Fighjemu i so paràmetri:
$ ./kubelet -h
<слишком много строк, чтобы разместить здесь>
$ ./kubelet -h | wc -l
284
Wow, tante opzioni! Per furtuna, avemu bisognu solu un paru di elli. Eccu unu di i parametri chì ci interessanu:
--pod-manifest-path string
Percorsu à u cartulare chì cuntene i fugliali per pods statici, o percorsu à un schedariu chì descrive pods statici. I schedari chì cumincianu cù punti sò ignorati. (DEPRECATED: Questa opzione deve esse stabilita in u schedariu di cunfigurazione passatu à u Kubelet via l'opzione --config. Per più infurmazione, vede kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file .)
Questa opzione ci permette di correre baccelli statici - pods chì ùn sò micca gestiti via l'API Kubernetes. I pods statici sò raramente usati, ma sò assai convenienti per elevà rapidamente un cluster, è questu hè esattamente ciò chì avemu bisognu. Ignuremu stu grande avvisu (di novu, ùn eseguite micca questu in a pruduzzione!) È vede s'ellu pudemu avè u pod in funziunamentu.
Prima creeremu un repertoriu per pods statici è eseguite kubelet:
kubelet cumencia à scrive qualchi avvisi è pare chì nunda ùn succede. Ma ùn hè micca vera ! Fighjemu à Docker:
$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8c8a35e26663 busybox "echo 'hello world!'" 36 seconds ago Exited (0) 36 seconds ago k8s_hello_hello-mink8s_default_ab61ef0307c6e0dee2ab05dc1ff94812_4
68f670c3c85f k8s.gcr.io/pause:3.2 "/pause" 2 minutes ago Up 2 minutes k8s_POD_hello-mink8s_default_ab61ef0307c6e0dee2ab05dc1ff94812_0
$ sudo docker logs k8s_hello_hello-mink8s_default_ab61ef0307c6e0dee2ab05dc1ff94812_4
hello world!
kubelet Aghju lettu u manifestu di pod è detti à Docker u cumandimu per lancià un paru di cuntenituri secondu e nostre specificazioni. (Se vi dumandate di u containeru "pausa", hè un hack Kubernetes - vede stu bloggu.) Kubelet lanciarà u nostru containeru busybox cù u cumandamentu specificatu è riavviarà indefinitu finu à chì u pod staticu hè sguassatu.
Felicitate sè stessu. Avemu ghjustu ghjuntu cù unu di i modi più cunfusu per pruduce testu à u terminal!
Lanciari etcd
U nostru scopu ultimu hè di eseguisce l'API Kubernetes, ma per fà questu avemu prima bisognu di eseguisce eccd. Cuminciamu un cluster minimale etcd mettendu i so paràmetri in u cartulare pods (per esempiu, pods/etcd.yaml):
Se avete mai travagliatu cù Kubernetes, questi schedarii YAML duveranu esse familiarizati per voi. Ci sò solu dui punti chì vale a pena nutà quì:
Avemu muntatu u cartulare host /var/lib/etcd in u pod in modu chì i dati etcd sò cunservati dopu un reiniciu (se ùn hè micca fattu, u statu di cluster serà sguassatu ogni volta chì u pod hè riavviatu, chì ùn serà micca bonu per ancu una stallazione minima di Kubernetes).
Avemu stallatu hostNetwork: true. Stu paràmetru, senza sorpresa, cunfigurà etcd per utilizà a reta di l'ospite invece di a reta interna di u pod (questu farà più faciule per u servitore API per truvà u cluster etcd).
Un cuntrollu simplice mostra chì l'etcd hè veramente in esecuzione nantu à l'host local è salvà dati à u discu:
$ curl localhost:2379/version
{"etcdserver":"3.4.3","etcdcluster":"3.4.0"}
$ sudo tree /var/lib/etcd/
/var/lib/etcd/
└── member
├── snap
│ └── db
└── wal
├── 0.tmp
└── 0000000000000000-0000000000000000.wal
Accuminciari u servitore API
Eseguisce un servitore API Kubernetes hè ancu più faciule. U solu paràmetru chì deve esse passatu hè --etcd-servers, faci ciò chì aspetta:
Pone stu schedariu YAML in u cartulare pods, è u servitore API inizierà. Cuntrollà cun curl mostra chì l'API Kubernetes sta à sente nantu à u portu 8080 cù un accessu cumpletamente apertu - senza autentificazione necessaria!
(In novu, ùn eseguite micca questu in a pruduzzione! Eru un pocu sorpresu chì u paràmetru predeterminatu hè cusì inseguru. Ma supponu chì questu hè per fà u sviluppu è a prova più faciule.)
E, sorpresa piacevule, kubectl funziona fora di a scatula senza paràmetri supplementari!
$ ./kubectl version
Client Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.5", GitCommit:"e6503f8d8f769ace2f338794c914a96fc335df0f", GitTreeState:"clean", BuildDate:"2020-06-26T03:47:41Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.5", GitCommit:"e6503f8d8f769ace2f338794c914a96fc335df0f", GitTreeState:"clean", BuildDate:"2020-06-26T03:39:24Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}
$ ./kubectl get pod
No resources found in default namespace.
prublemu
Ma s'è scavate un pocu più in fondu, qualcosa pare chì andarà male:
$ ./kubectl get pod -n kube-system
No resources found in kube-system namespace.
I pods statici chì avemu creatu sò andati! In fattu, u nostru node kubelet ùn hè micca scupertu à tuttu:
$ ./kubectl get nodes
No resources found in default namespace.
Chì ci hè? Se vi ricordate uni pochi di paragrafi fà, avemu principiatu u kubelet cun un set estremamente simplice di paràmetri di linea di cummanda, perchè u kubelet ùn sapi micca cumu cuntattà u servitore API è avvisà u so statu. Dopu avè studiatu a documentazione, truvamu a bandiera currispundente:
--kubeconfig string
A strada di u schedariu kubeconfig, chì specifica cumu cunnette à u servitore API. A dispunibilità --kubeconfig attiva u modu di u servitore API, no --kubeconfig permette u modu offline.
Tuttu stu tempu, senza sapè, stavamu eseguendu u kubelet in "modu offline". (Se eramu esse pedanti, pudemu pensà à un kubelet standalone cum'è "Kubernetes viable minimu", ma questu seria assai noioso). Per fà u travagliu di cunfigurazione "reale", avemu bisognu di passà u schedariu kubeconfig à u kubelet per sapè cumu parlà à u servitore API. Per furtuna, hè abbastanza simplice (perchè ùn avemu micca prublemi cù l'autentificazione o i certificati):
(A propositu, se pruvate d'accede à l'API via curl quandu u kubelet ùn hè micca in esecuzione, truverete chì hè sempre in esecuzione! Kubelet ùn hè micca un "parent" di i so pods cum'è Docker, hè più cum'è un "controllu". daemon." I cuntenituri gestiti da un kubelet continuanu à curriri finu à chì u kubelet li ferma.)
In pochi minuti kubectl duverebbe mustrà i pods è i nodi cum'è l'aspettemu:
$ ./kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
default hello-mink8s 0/1 CrashLoopBackOff 261 21h
kube-system etcd-mink8s 1/1 Running 0 21h
kube-system kube-apiserver-mink8s 1/1 Running 0 21h
$ ./kubectl get nodes -owide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
mink8s Ready <none> 21h v1.18.5 10.70.10.228 <none> Ubuntu 18.04.4 LTS 4.15.0-109-generic docker://19.3.6
Congratulemu veramente noi sta volta (sò chì aghju digià felicitatu) - avemu un "cluster" minimu di Kubernetes chì funziona cù una API cumplettamente funziunale!
Lanciamu sottu
Avà vede ciò chì l'API hè capace di. Cuminciamu cù u pod nginx:
$ ./kubectl apply -f nginx.yaml
Error from server (Forbidden): error when creating "nginx.yaml": pods "nginx" is
forbidden: error looking up service account default/default: serviceaccount
"default" not found
$ ./kubectl get serviceaccounts
No resources found in default namespace.
Quì vedemu quant'ellu hè incompletu u nostru ambiente Kubernetes - ùn avemu micca cunti per i servizii. Pruvemu di novu creendu manualmente un contu di serviziu è vede ciò chì succede:
$ cat <<EOS | ./kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
name: default
namespace: default
EOS
serviceaccount/default created
$ ./kubectl apply -f nginx.yaml
Error from server (ServerTimeout): error when creating "nginx.yaml": No API
token found for service account "default", retry after the token is
automatically created and added to the service account
Ancu quandu avemu creatu u contu di serviziu manualmente, u token di autentificazione ùn hè micca generatu. Mentre cuntinuemu à sperimentà cù u nostru "cluster" minimalista, truveremu chì a maiò parte di e cose utili chì generalmente succedenu automaticamente saranu mancanti. U servitore API di Kubernetes hè abbastanza minimalista, cù a maiò parte di l'elevazione pesante è a cunfigurazione automatica chì succede in diversi cuntrolli è travaglii di fondo chì ùn sò ancu in esecuzione.
Pudemu travaglià stu prublema mettendu l'opzione automountServiceAccountToken per u contu di serviziu (perchè ùn avemu micca bisognu à aduprà in ogni modu):
$ cat <<EOS | ./kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
name: default
namespace: default
automountServiceAccountToken: false
EOS
serviceaccount/default configured
$ ./kubectl apply -f nginx.yaml
pod/nginx created
$ ./kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx 0/1 Pending 0 13m
Finalmente, u pod hè apparsu! Ma in fatti ùn principia micca perchè ùn avemu micca pianificatore (scheduler) hè un altru cumpunente impurtante di Kubernetes. In novu, vedemu chì l'API Kubernetes hè sorprendentemente "mutu" - quandu crea un Pod in l'API, u registra, ma ùn prova micca di capisce quale nodu per eseguisce.
In fatti, ùn avete micca bisognu di un pianificatore per eseguisce un pod. Pudete aghjunghje manualmente un node à u manifestu in u paràmetru nodeName:
(Sustituitu mink8s à u nome di u node.) Dopu sguassate è applicà, vedemu chì nginx hà iniziatu è stà à sente l'indirizzu IP internu:
$ ./kubectl delete pod nginx
pod "nginx" deleted
$ ./kubectl apply -f nginx.yaml
pod/nginx created
$ ./kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 30s 172.17.0.2 mink8s <none> <none>
$ curl -s 172.17.0.2 | head -4
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
Per assicurà chì a reta trà pods funziona bè, pudemu eseguisce curl da un altru pod:
$ cat <<EOS | ./kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: curl
spec:
containers:
- image: curlimages/curl
name: curl
command: ["curl", "172.17.0.2"]
nodeName: mink8s
EOS
pod/curl created
$ ./kubectl logs curl | head -6
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
Hè assai interessante di scavà in questu ambiente è vede ciò chì funziona è ciò chì ùn hè micca. Aghju trovu chì ConfigMap è Secret travaglianu cum'è previstu, ma u Serviziu è u Deployment ùn sò micca.
Successu!
Stu postu hè diventatu longu, dunque aghju da dichjarà a vittoria è dicu chì questa hè una cunfigurazione viable chì pò esse chjamata "Kubernetes". Per riassume: quattru binari, cinque paràmetri di linea di cummanda è "solu" 45 linee di YAML (micca). tantu per i standard Kubernetes) è avemu parechje cose chì travaglianu:
I pods sò gestiti cù l'API Kubernetes regulare (cun pochi pirate)
Pudete carricà è gestisce l'imaghjini di u containeru publicu
I pods restanu vivi è riavvianu automaticamente
A rete trà pods in u stessu node funziona abbastanza bè
ConfigMap, segretu è simplice di stallazione di almacenamentu travaglia cum'è previstu
Ma assai di ciò chì rende Kubernetes veramente utile hè sempre mancante, cum'è:
Pod Scheduler
Autentificazione / auturizazione
Nodi multipli
Rete di servizii
DNS internu in cluster
Controllers per i cunti di serviziu, implementazioni, integrazione cù i fornitori di nuvola è a maiò parte di l'altri boni chì Kubernetes porta
Allora chì avemu veramente uttene? L'API Kubernetes, chì funziona da sè stessu, hè veramente solu una piattaforma per l'automatizazione di u containeru. Ùn face micca assai - hè un travagliu per diversi cuntrolli è operatori chì utilizanu l'API - ma furnisce un ambiente coherente per l'automatizazione.