Preklad článku bol pripravený v predstihu pred začiatkom kurzu .

Ak toto čítate, pravdepodobne ste už počuli o Kubernetes (ak nie, ako ste sa sem dostali?) Ale čo vlastne Kubernetes predstavuje? Je to ? Или ? Что вообще это значит?
Úprimne povedané, nie som si tým na 100% istý. Ale myslím si, že je zaujímavé preskúmať vnútornosti a pozrieť sa, čo sa vlastne deje v Kubernetes pod jeho mnohými vrstvami abstrakcie. Takže z čistej zvedavosti sa pozrime, ako vlastne vyzerá minimálny „Kubernetes klaster“. (Toto bude oveľa jednoduchšie ako .)
Predpokladám, že máte základné poznatky o Kubernetes, Linuxe a kontajneroch. Všetko, o čom tu budeme hovoriť, je určené iba na prieskum/výučbu, nespúšťajte nič z toho v produkcii!
Prehľad
Kubernetes obsahuje veľa komponentov. Podľa , architektúra vyzerá nasledovne:

Tu je zobrazených aspoň osem komponentov, ale väčšinu z nich ignorujeme. Chcem uviesť, že minimálna vec, ktorú je možné rozumne nazvať Kubernetes, pozostáva z troch základných komponentov:
- kubelet
- kube-apiserver (ktorý závisí od etcd — jeho databázy)
- prostredia pre spúšťanie kontajnerov (v tomto prípade Docker)
Pozrime sa, čo o každom z nich hovorí dokumentácia (., .). Najprv kubelet:
Agent, ktorý beží na každom uzle v klastri. Sleduje, aby boli kontajnery spustené v pode.
Znie to dostatočne jednoducho. Čo hovoríte na prostredie pre spúšťanie kontajnerov (container runtime)?
Prostredie pre spúšťanie kontajnerov je program určený na spúšťanie kontajnerov.
Veľmi informatívne. Ale ak ste oboznámení s Dockerom, mali by ste mať všeobecnú predstavu o tom, čo robí. (Detaily rozdelenia zodpovedností medzi prostredím pre spúšťanie kontajnerov a kubeletom sú vlastne dosť tenké a tu sa nimi nebudem zaoberať.)
A API-server?
API server je komponent Kubernetes ovládacieho panela, ktorý predstavuje API Kubernetes. API server je klientská časť ovládacieho panela Kubernetes.
Každý, kto kedykoľvek robil niečo s Kubernetes, musel interagovať s API buď priamo, alebo cez kubectl. Toto je srdce toho, čo robí Kubernetes Kubernetesom – mozog, ktorý premieňa hory YAML, ktoré všetci poznáme a milujeme, na fungujúcu infraštruktúru. Je zrejmé, že API by malo byť prítomné v našej minimálnej konfigurácii.
Predpoklady
- Virtuálny alebo fyzický server Linux s root prístupom (ja používam Ubuntu 18.04 na virtuálnom serveri).
- A to je všetko!
Nudná inštalácia
Na server, ktorý budeme používať, je potrebné nainštalovať Docker. (Nebudem podrobne vysvetľovať, ako Docker a kontajnery fungujú; ak vás to zaujíma, existujú ). Poďme ho jednoducho nainštalovať pomocou apt:
$ sudo apt install docker.io
$ sudo systemctl start docker Potom potrebujeme získať binárky Kubernetes. Na naštartovanie nášho "klastra" naozaj potrebujeme iba kubelet, pretože na spustenie ostatných serverových komponentov môžeme použiť kubelet. Na interakciu s naším klastrom po jeho spustení budeme tiež potrebovať kubectl.
$ curl -L https://dl.k8s.io/v1.18.5/kubernetes-server-linux-amd64.tar.gz > server.tar.gz
$ tar xzvf server.tar.gz
$ cp kubernetes/server/bin/kubelet .
$ cp kubernetes/server/bin/kubectl .
$ ./kubelet --version
Kubernetes v1.18.5 Čo sa stane, ak jednoducho spustíme kubelet?
$ ./kubelet
F0609 04:03:29.105194 4583 server.go:254] mkdir /var/lib/kubelet: permission denied kubelet musí bežať ako root. Čo je logické, pretože musí spravovať celý uzlový server. Poďme sa pozrieť na jeho parametre:
$ ./kubelet -h
$ ./kubelet -h | wc -l
284Wow, toľko možností! Našťastie, budeme potrebovať iba niekoľko z nich. Tu je jeden z parametrov, ktorý nás zaujíma:
--pod-manifest-path stringCesta k adresáru obsahujúcemu súbory pre statické pody, alebo cesta k súboru s popisom statických podov. Súbory, ktoré začínajú bodkou, sa ignorujú. (ZASTARALÉ: tento parameter by sa mal nastaviť v konfiguračnom súbore, ktorý sa predáva do Kubeletu cez možnosť —config. Pre viac informácií pozri .)
Tento parameter nám umožňuje spustiť — pod, ktoré nie sú spravované cez Kubernetes API. Statické pody sa používajú zriedka, ale sú veľmi užitočné na rýchle nasadenie klastra, a presne to potrebujeme. Toto hlasné varovanie ignorujeme (opäť, nespúšťajte to v produkcii!) a pozrime sa, či môžeme spustiť pod.
Najprv vytvoríme adresár pre statické pody a spustíme ho. kubelet:
$ mkdir pods
$ sudo ./kubelet --pod-manifest-path=podsPotom v inom termináli/okne tmux/niekde inde vytvoríme manifest podu:
$ cat < pods/hello.yaml
apiVersion: v1
kind: Pod
metadata:
name: hello
spec:
containers:
- image: busybox
name: hello
command: ["echo", "hello world!"]
EOF kubelet začne písať nejaké varovania a zdá sa, že sa nič nedeje. Ale nie je to tak! Pozrime sa na 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 prečítal manifest podu a dal Dockeru príkaz spustiť niekoľko kontajnerov podľa našej špecifikácie. (Ak vás zaujíma kontajner "pause", je to hack Kubernetes — podrobnosti nájdete v .) Kubelet spustí náš kontajner busybox s uvedeným príkazom a bude ho nekonečne reštartovať, pokiaľ nebude statický pod odstránený.
Blahoželajte si. Práve sme vymysleli jeden z najzložitejších spôsobov, ako vypísať text do terminálu!
Spúšťame etcd
Naším konečným cieľom je spustiť Kubernetes API, ale na to musíme najprv spustiť . Poďme spustiť minimálny klaster etcd a umiestnime jeho nastavenia do adresára pods (napríklad, pods/etcd.yaml):
apiVersion: v1
kind: Pod
metadata:
name: etcd
namespace: kube-system
spec:
containers:
- name: etcd
command:
- etcd
- --data-dir=/var/lib/etcd
image: k8s.gcr.io/etcd:3.4.3-0
volumeMounts:
- mountPath: /var/lib/etcd
name: etcd-data
hostNetwork: true
volumes:
- hostPath:
path: /var/lib/etcd
type: DirectoryOrCreate
name: etcd-dataAk ste niekedy pracovali s Kubernetes, mali by ste byť oboznámení s podobnými YAML súbormi. Tu stojí za zmienku len dva aspekty:
Pripojili sme adresár hostiteľa /var/lib/etcd v pody, aby sa dáta etcd ukladali po reštartovaní (ak to neurobíte, stav klastru sa pri každom reštartovaní podu vymaže, čo nie je dobré ani pre minimálnu inštaláciu Kubernetes).
Nainštalovali sme hostNetwork: true. Tento parameter, ako sa dalo očakávať, nastavuje etcd na používanie siete hostiteľa namiesto vnútornej siete podu (to uľahčí API serveru nájsť klaster etcd).
Jednoduchá kontrola ukazuje, že etcd skutočne beží na localhost a uklada dáta na disk:
$ 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.walSpustenie API servera
Spustiť API server Kubernetes je ešte jednoduchšie. Jediný parameter, ktorý treba zadať, --etcd-servers, robí to, čo očakávate:
apiVersion: v1
kind: Pod
metadata:
name: kube-apiserver
namespace: kube-system
spec:
containers:
- name: kube-apiserver
command:
- kube-apiserver
- --etcd-servers=http://127.0.0.1:2379
image: k8s.gcr.io/kube-apiserver:v1.18.5
hostNetwork: true Umiestnite tento YAML súbor do adresára pods, a API server sa spustí. Kontrola pomocou curl ukazuje, že Kubernetes API počúva na porte 8080 s úplným prístupom — autentifikácia nie je potrebná!
$ curl localhost:8080/healthz
ok
$ curl localhost:8080/api/v1/pods
{
"kind": "PodList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/pods",
"resourceVersion": "59"
},
"items": []
}(Opäť, nespúšťajte to v produkcii! Bol som trochu prekvapený, že predvolená konfigurácia je tak nebezpečná. Ale predpokladám, že je to urobené pre uľahčenie vývoja a testovania.)
A, príjemné prekvapenie, kubectl funguje hneď z krabice bez akýchkoľvek dodatočných nastavení!
$ ./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.Problém
Ale ak sa pozriete hlbšie, zdá sa, že niečo nie je v poriadku:
$ ./kubectl get pod -n kube-system
No resources found in kube-system namespace.Statické pody, ktoré sme vytvorili, zmizli! V skutočnosti, náš kubelet uzol nie je vôbec detekovaný:
$ ./kubectl get nodes
No resources found in default namespace.O čo ide? Ak si pamätáte, pred niekoľkými odstavcami sme spustili kubelet s veľmi jednoduchým súborom príkazových parametrov, takže kubelet nevie, ako sa pripojiť k serveru API a informovať ho o svojom stave. Po preskúmaní dokumentácie nájdeme vhodnú vlajku:
--kubeconfig reťazec
Cesta k súboru kubeconfig, v ktorom je uvedené, ako sa pripojiť k serveru API. Prítomnosť --kubeconfig aktívuje režim API servera, jeho absencia --kubeconfig aktívuje offline režim.
Po celý ten čas, ani si to neuvedomujúc, sme spúšťali kubelet v "offline režime". (Keby sme boli pedantskí, mohli by sme považovať offline režim kubeletu za "minimálne životaschopný Kubernetes", ale to by bola veľmi nudná myšlienka). Aby sme získali "právoplatnú" konfiguráciu, musíme odovzdať súbor kubeconfig kubeletu, aby vedel, ako komunikovať s API serverom. Našťastie je to celkom jednoduché (pretože nemáme problémy s autentifikáciou ani certifikátmi):
apiVersion: v1
kind: Config
clusters:
- cluster:
server: http://127.0.0.1:8080
name: mink8s
contexts:
- context:
cluster: mink8s
name: mink8s
current-context: mink8s Uložte to ako kubeconfig.yaml, zabite proces kubelet a reštartujte s požadovanými parametrami:
$ sudo ./kubelet --pod-manifest-path=pods --kubeconfig=kubeconfig.yaml(Mimochodom, ak sa pokúsite pristúpiť k API cez curl, keď kubelet nefunguje, zistíte, že stále funguje! Kubelet nie je "rodičom" svojich podov, ako Docker, je skôr podobný "správcovi démona". Kontajnery spravované kubeletom budú fungovať, pokiaľ ich kubelet nezastaví.)
O pár minút kubectl by sa mali zobraziť podi a uzly, ako očakávame:
$ ./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 21h v1.18.5 10.70.10.228 Ubuntu 18.04.4 LTS 4.15.0-109-generic docker://19.3.6Tentoraz si naozaj gratulujme (viem, že už som gratuloval) — máme minimálny "klaster" Kubernetes, ktorý funguje s plnohodnotným API!
Spúšťame pod
Teraz sa pozrime, čo všetko API dokáže. Začneme s podom nginx:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: nginx
name: nginxTu dostaneme celkom zaujímavú chybu:
$ ./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.Tu vidíme, ako hrozne neúplné je naše prostredie Kubernetes — nemáme žiadne účty pre služby. Skúsme to znova a vytvorme účet služby ručne a pozrime sa, čo sa stane:
$ 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 accountAj keď sme vytvorili účet služby ručne, autentifikačný token sa nevytvára. Pokračovaním v experimentovaní s naším minimalistickým „klastrom“ zistíme, že väčšina užitočných vecí, ktoré sa zvyčajne dejú automaticky, bude chýbať. Server Kubernetes API je dosť minimalistický, väčšina ťažkých automatických nastavení sa uskutočňuje v rôznych kontroléroch a background jobs, ktoré sa ešte nevykonávajú.
Túto situáciu môžeme obísť nastavením voľby automountServiceAccountToken pre účet služby (keďže ho aj tak nebudeme musieť používať):
$ 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 13mNakoniec sa pod objavil! Ale v skutočnosti sa nezapne, pretože nemáme (scheduler) — ďalšia dôležitá súčasť Kubernetes. Opäť vidíme, že API Kubernetes je prekvapivo „hlúpe“ — keď vytvoríte pod v API, zaregistruje ho, ale nesnaží sa zistiť, na ktorom uzle ho spustiť.
V skutočnosti na spustenie podu nie je plánovač potrebný. Môžete ručne pridať uzol do manifestu pomocou parametra nodeName:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: nginx
name: nginx
nodeName: mink8s
(Nahradiť mink8s názvom uzla.) Po delete a apply vidíme, že nginx sa spustil a počúva na vnútornom IP adrese:
$ .\/kubectl delete pod nginx
pod "nginx" bol vymazaný
$ .\/kubectl apply -f nginx.yaml
pod\/nginx bol vytvorený
$ .\/kubectl get pods -owide
NÁZOV PLNÝ STAV REŠTARTY VEK IP NOD NOMINOVANÝ NOD PRÍSTUPOVÉ BRÁNY
nginx 1\/1 Beží 0 30s 172.17.0.2 mink8s <none> <none>
$ curl -s 172.17.0.2 | head -4
<!DOCTYPE html>
<html>
<head>
<title>Vitajte pri nginx!</title>Aby sme sa uistili, že sieť medzi podmi funguje správne, môžeme spustiť curl z iného podu:
$ 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>Vitajte pri nginx!</title>Je celkom zaujímavé preskúmať toto prostredie a pozrieť sa, čo funguje a čo nie. Zistil som, že ConfigMap a Secret fungujú tak, ako sa očakáva, ale Service a Deployment nie.
Úspech!
Tento príspevok sa stáva väčším, preto sa chystám oznámiť víťaza a tvrdiť, že ide o funkčnú konfiguráciu, ktorú môžeme nazvať „Kubernetes“. Zhrnutie: štyri binárne súbory, päť parametrov príkazového riadku a „iba“ 45 riadkov YAML (nie tak veľa podľa štandardov Kubernetes) a máme rozbehnutých niekoľko vecí:
- Pody sú spravované prostredníctvom klasického Kubernetes API (s niekoľkými hackmi)
- Môžeme nahrávať verejné obrazy kontajnerov a spravovať ich
- Pody zostávajú aktívne a automaticky sa reštartujú
- Sieť medzi podmi v rámci jedného uzla funguje celkom dobre
- ConfigMap, Secret a najjednoduchšie montovanie úložiska funguje tak, ako má
Ale väčšina toho, čo robí Kubernetes skutočne užitočným, stále chýba, napríklad:
- Plánovač podov
- Autentifikácia / autorizácia
- Viaceré uzly
- Sieť služieb
- Klastrový vnútorný DNS
- Kontroléry pre účty služieb, nasadenia, integráciu s cloudovými poskytovateľmi a väčšinu ďalších „vychytávok“, ktoré Kubernetes prináša
Čo sme teda naozaj získali? Kubernetes API, fungujúce samostatne, je vlastne len platformou na automatizáciu kontajnerov. Nerobí veľa — je to práca pre rôzne kontroléry a operátory, ktorí používajú API — ale poskytuje konzistentné prostredie na automatizáciu.
Čítať ďalej:
Zdroj: habr.com
