Artikli tõlge on koostatud kursuse alguse eelõhtul .

Kui te seda loete, olete tõenäoliselt kuulnud Kubernetesest (ja kui ei, siis kuidas te siia sattusite?). Aga mis Kubernetes tegelikult on? See on ? Или ? Что вообще это значит?
Ausalt öeldes ei ole ma 100% kindel. Aga arvan, et on huvitav uurida, mis toimub Kuberneteses selle paljude abstraktsioonikihtide all. Nii et huvi pärast, vaatame, kuidas tegelikult näeb välja minimaalne "Kubernetes klaster". (See on palju lihtsam kui .)
Ma arvan, et teil on põhiteadmised Kubernetesest, Linuxist ja konteineritest. Kõik, millest me siin räägime, on mõeldud ainult uurimiseks/õppimiseks, ärge käitage seda tootmises!
Ülevaade
Kubernetes sisaldab palju komponente. Vastavalt , näeb arhitektuur välja järgmiselt:

Siin on näidatud vähemalt kaheksa komponenti, kuid enamik neist me ignoreerime. Soovin märkida, et minimaalne asi, mida tõeliselt võiks nimetada Kuberneteseks, koosneb kolmest põhikomponendist:
- kubelet
- kube-apiserver (mis sõltub etcd-st – selle andmebaasist)
- konteinerite töötlemiskeskkond (antud juhul Docker)
Vaatame, mida öeldakse igaühe kohta dokumentatsioonis (., .). Esiteks kubelet:
Agent, mis töötab igas klastris asuvas sõlmes. See jälgib, et konteinerid oleksid podis käimas.
Kõlab piisavalt lihtsalt. Aga kuidas on konteinerite töötlemiskeskkonnaga (container runtime)?
Konteinerite töötlemiskeskkond on programm, mis on mõeldud konteinerite käitamiseks.
Väga informatiivne. Aga kui olete Dockeriga tuttav, peaks teil olema üldine arusaam sellest, mida see teeb. (Detailid konteinerite töötlemiskeskkonna ja kubeleti vastutuse jaotamise vahel on tegelikult üsna peened ja ma ei süvene nendesse siin.)
Ja API-server?
API-server on Kubernetes juhtpaneeli komponent, mis esindab Kubernetes API-t. API-server on Kubernetes juhtpaneeli kliendipoolne osa.
Igaühel, kes on kunagi Kubernetesega midagi teinud, tuli API-ga suhelda kas otse või kubectl'i kaudu. See on süda, mis muudab kõik need YAML-id, mida me kõik tunneme ja armastame (?), töötavaks infrastruktuuriks. Tundub ilmselge, et API peab olema meie minimaalses konfiguratsioonis kohal.
Eeltingimused
- Virtuaalne või füüsiline Linuxi masin root-privileegidega (kasutan virtuaalmasinas Ubuntu 18.04).
- Ja see on kõik!
Igav paigaldamine
Meie kasutatavale masinale tuleb paigaldada Docker. (Ma ei plaani detailselt seletada, kuidas Docker ja konteinerid toimivad; kui see teid huvitab, on ). Lihtsalt paigaldame selle kasutades apt:
$ sudo apt install docker.io
$ sudo systemctl start docker Pärast seda peame hankima Kubernetes'e binaarfailid. Tegelikult on meie "klastri" algseks käivitamiseks vajalik ainult kubelet, kuna teiste serveri komponentide käitamiseks saame kasutada kubelet. Kliendiga suhtlemiseks pärast meie klastri töölepanekut kasutame ka 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 Mis juhtub, kui me lihtsalt käivitame kubelet?
$ ./kubelet
F0609 04:03:29.105194 4583 server.go:254] mkdir /var/lib/kubelet: permission denied kubelet peab töötama root kasutajana. Piisavalt loogiline, kuna ta peab kogu sõlme haldama. Vaatame tema parameetreid:
$ ./kubelet -h
$ ./kubelet -h | wc -l
284Vau, nii palju valikuid! Õnneks vajame ainult mõnda neist. Siin on üks meile huvitav parameeter:
--pod-manifest-path stringTeekond katalooge, mis sisaldab staatiliste pod'ide faile, või tee staatiliste pod'ide kirjelduse failini. Punktiga algavad failid jäetakse kõrvale. (AEGUNUD: see parameeter tuleks seadistada konfiguratsioonifailis, mis antakse Kubelet'ile läbi —config valiku. Lisainformatsiooni leiate .)
See parameeter võimaldab meil käitada — pod'id, mida ei hallata Kubernetes API kaudu. Staatilisi pod'e kasutatakse harva, kuid need on väga mugavad klastri kiireks üles seadmiseks, just seda me vajame. Ignorerime selle valjuhäälse hoiatuse (veel kord, ärge käitage seda tootmises!) ja vaatame, kas suudame pod'i käivitada.
Esmalt loome katalooge staatiliste pod'ide jaoks ja käivitame kubelet:
$ mkdir pods
$ sudo ./kubelet --pod-manifest-path=podsSeejärel, teises terminalis/tmux aknas/või kuskil mujal, loome pod'i manti:
$ cat < pods/hello.yaml
apiVersion: v1
kind: Pod
metadata:
name: hello
spec:
containers:
- image: busybox
name: hello
command: ["echo", "hello world!"]
EOF kubelet algab kirjutama erinevaid hoiatusi ja tundub, et midagi ei toimu. Aga see ei ole tõsi! Vaatame Dockerit:
$ 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 lugesin konteineri manifesti ja andsin Dockerile käsu käivitada paar konteinerit vastavalt meie spetsifikatsioonile. (Kui teid huvitab "pause" konteiner, siis see on Kubernetes'i nipp — lisainfot leiate .) Kubelet käivitab meie konteineri busybox antud käsuga ja taaskäivitab seda lõputult, kuni staatiline pod on kustutatud.
Palju õnne! Me just leiutasime ühe kõige keerulisema viisi teksti terminalis kuvamiseks!
Käivitame etcd
Meie lõppeesmärk on käivitada Kubernetes API, kuid selleks peame esmalt käivitama . Käivitage minimaalne etcd klaster, paigutades selle seadistused kausta pods (näiteks, 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-dataKui olete kunagi töötanud Kubernetesega, peaksid sellised YAML-failid olema teile tuttavad. Siin tuleks märkida ainult kahte punkti:
Oleme mountinud hostide kausta /var/lib/etcd pod'i, et etcd andmed säiliksid pärast taaskäivitamist (kui seda ei tehta, siis klastriseisund kustutatakse iga pod'i taaskäivitamisega, mis ei ole isegi kõige minimaalsema Kubernetes'i installatsiooni jaoks hea).
Me oleme seadnud hostNetwork: true. See parameeter, mis ei ole üllatav, seadistab etcd kasutama hosti võrku sisemise pod'i võrgu asemel (see lihtsustab API-serveri jaoks etcd klastrite leidmist).
Lihtne kontroll näitab, et etcd on tõepoolest localhostis käimas ja salvestab andmeid kettale:
$ 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.walAPI-serveri käivitamine
Kubernetes API-serveri käivitamine on veelgi lihtsam. Ainus parameeter, mida tuleb edastada, --etcd-servers, teeb seda, mida ootate:
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 Asetage see YAML-fail katalooge pods, ja API-server käivitub. Kontrollimine kasutades curl näitab, et Kubernetes API kuulab porti 8080 täieliku juurdepääsuga — autentimist ei nõuta!
$ curl localhost:8080/healthz
ok
$ curl localhost:8080/api/v1/pods
{
"kind": "PodList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/pods",
"resourceVersion": "59"
},
"items": []
}(Ärge käitage seda tootmises! Ma olin natuke üllatunud, et vaikeseade on nii ebaturvaline. Kuid ma arvan, et see on tehtud arenduse ja testimise lihtsustamiseks.)
Ja meeldiv üllatus, et kubectl töötab välja pakendamata ilma igasuguste lisaseadeteta!
$ ./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.Probleem
Kuid kui süveneda, siis tundub, et midagi on valesti:
$ ./kubectl get pod -n kube-system
No resources found in kube-system namespace.Käivitunud staatilised podid on kadunud! Tegelikult ei tuvastata meie kubelet-sõlme üldse:
$ ./kubectl get nodes
No resources found in default namespace.Mis toimub? Kui mäletate, siis mõned lõigud tagasi käivitasime kubeleti äärmiselt väikese käsurea parameetrite kogumiga, seega ei tea kubelet, kuidas API-serveriga ühendust võtta ja oma staatust teavitada. Dokumentatsiooni uurides leidsime sobiva lipu:
--kubeconfig string
Tee faili kubeconfig, milles on määratud, kuidas API-serveritega ühendust võtta. Kui --kubeconfig on olemas, siis lülitub API-serveri režiimi, puudumine --kubeconfig lülitab iseseisva režiimi sisse.
Kogu selle aja oleme teadmata käivitanud kubeleti «iseseisvas režiimis». (Kui me oleksime pedantsed, võiks iseseisvat kubeleti režiimi pidada «minimaalselt elujõuliseks Kuberneteseks», aga see oleks igav). Et «päris» konfiguratsioon töötaks, peame edastama kubeletile kubeconfigi faili, et see teaks, kuidas API-serveriga suhelda. Õnneks on see päris lihtne (kuna meil ei ole autentimise või sertifikaatidega probleeme):
apiVersion: v1
kind: Config
clusters:
- cluster:
server: http://127.0.0.1:8080
name: mink8s
contexts:
- context:
cluster: mink8s
name: mink8s
current-context: mink8s Salvige see kui kubeconfig.yaml, lõpetage protsess kubelet ja käivitage taas vajalike parameetritega:
$ sudo ./kubelet --pod-manifest-path=pods --kubeconfig=kubeconfig.yaml(Muide, kui proovite API-le pöörduda curliga, kui kubelet ei tööta, siis avastate, et see töötab ikka! Kubelet ei ole oma pod'ide «vanem», sarnaselt Docker'ile, ta on rohkem nagu “haldur”. Kubeleti haldatavad konteinerid töötavad, kuni kubelet neid ei peata.)
Mõne minuti pärast kubectl peaks meile näitama pod'id ja sõlmed, nagu ootasime:
$ ./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.6Sel korral tuleb end tõeliselt õnnitleda (ma tean, et olen juba õnnitlenud) — meil on saanud minimaalselt töötav «Kubernetes» klaster, millel on täieõiguslik API!
Käivitame pod'i
Nüüd vaatame, milleks API suuteline on. Alustame nginx pod'iga:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: nginx
name: nginxSiin saame üsna huvitava vea:
$ ./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.Siin näeme, kui kohutavalt poolik meie Kubernetes keskkond on — meil puuduvad teenusekontod. Proovime jälle, luues teenusekonto käsitsi, ja vaatame, mis juhtub:
$ 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 accountIsegi kui me loome teenuse konto käsitsi, ei genereerita autentimistokene. Jätkates katsetamist meie minimalistliku "klastriga", avastame, et enamik kasulikest asjadest, mis tavaliselt automaatselt juhtuvad, on puuduvad. Kubernetes API server on üsna minimalistlik, suurem osa raskest automaatsetest seadistustest toimub erinevates kontrollides ja taustatöödes, mis veel ei tööta.
Saame selle probleemi ületada seadistades valiku automountServiceAccountToken teenuse konto jaoks (kuna me ei pea seda kasutama):
$ 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 13mLõpuks ilmus pod! Kuid tegelikult see ei käivitu, kuna meil pole (scheduler) — veel üks oluline Kubernetes komponent. Jällegi näeme, et Kubernetes API on üllatavalt "idiot" — kui loote pod'i API-s, registreerib see selle, kuid ei ürita välja selgitada, millisel sõlmel seda käivitada.
Tegelikult pole pod'i käivitamiseks planeerijat vaja. Saame käsitsi lisada sõlme manifesti parameetrisse nodeName:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: nginx
name: nginx
nodeName: mink8s
(Asenda mink8s sõlme nimega.) Pärast kustutamist ja rakendamist näeme, et nginx käivitub ja kuulab sise-IP-aadressi:
$ . /kubectl delete pod nginx
pod "nginx" kustutatud
$ . /kubectl apply -f nginx.yaml
pod/nginx loodud
$ . /kubectl get pods -owide
NIMI VALMIS OLEK ÜMBERSTARTIMI KORDAD VANUS IP SÕLM NOMINEERITUD SÕLM VALMIDUSE VÄRAVAD
nginx 1/1 Käib 0 30s 172.17.0.2 mink8s <none> <none>
$ curl -s 172.17.0.2 | head -4
<!DOCTYPE html>
<html>
<head>
<title>Tere tulemast nginx!</title>Kinnitamaks, et võrguühendus pod'ide vahel töötab korralikult, saame käivitada curl teisest pod'ist:
$ cat <<EOS | .\/kubectl apply -f -\napiVersion: v1\nkind: Pod\nmetadata:\n name: curl\nspec:\n containers:\n - image: curlimages\/curl\n name: curl\n command: ["curl", "172.17.0.2"]\n nodeName: mink8s\nEOS\npod\/curl created\n$ .\/kubectl logs curl | head -6\n % Total % Received % Xferd Average Speed Time Time Time Current\n Dload Upload Total Spent Left Speed
<!DOCTYPE html>
<html>
<head>
<title>Tere tulemast nginx!</title>On huvitav uurida seda keskkonda ja vaadata, mis töötab ja mis mitte. Olen avastanud, et ConfigMap ja Secret toimivad oodatult, kuid Service ja Deployment ei tööta.
Edu!
See postitus muutub suureks, seega kavatsema kuulutada võitu ja väita, et see on elujõuline konfiguratsioon, mida võib nimetada "Kubernetes". Kokkuvõtteks: neli binaarfaili, viis käsurea parameetrit ja "ainult" 45 rida YAML (Kubernetes standardite kohaselt mitte nii palju) ja meil töötab üsna palju asju:
- Podid hallatakse tavalise Kubernetes API abil (mõningate trikkidega)
- Saate laadida üles avalikke konteineripilte ja nendega töötada
- Podid jäävad ellu ja taaskäivituvad automaatselt
- Podide vaheline võrk ühe sõlme raames töötab päris hästi
- ConfigMap, Secret ja lihtne salvestuse monteerimine toimib nagu peab
Kuid suur osa sellest, mis teeb Kubernetes tõeliselt kasulikuks, on endiselt puuduv, näiteks:
- Podide planeerija
- Autentimine / autoriseerimine
- Mitu sõlme
- Teenuste võrk
- Klastri sisemine DNS
- Teenusekontode, juurutamiste, pilveteenuste pakkujatega integreerimise ja enamiku teiste "toodete" jaoks, mida Kubernetes pakub, kontrollerid
Kuidas me tõeliselt saime? Kubernetes API, mis töötab iseseisvalt, on tegelikult lihtsalt platvorm konteinerite automatiseerimiseks.Ta ei tee palju – see on erinevate kontrollerite ja operaatorite töö, kes kasutavad API-d – kuid see tagab järjepideva keskkonna automatiseerimiseks.
Lugeda rohkem:
Allikas: habr.com
