Minimaalselt elujÔuline Kubernetes

Artikli tÔlge on koostatud kursuse alguse eelÔhtul «DevOps praktikad ja tööriistad».

Minimaalselt elujÔuline Kubernetes

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 „Tööstuslik konteinerite orkestreerimine“? ИлО „PilvepĂ”hine operatsioonisĂŒsteem“? Đ§Ń‚ĐŸ ĐČĐŸĐŸĐ±Ń‰Đ” ŃŃ‚ĐŸ Đ·ĐœĐ°Ń‡ĐžŃ‚?

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 Kubernetes The Hard Way.)

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 vikipeediale, nÀeb arhitektuur vÀlja jÀrgmiselt:

Minimaalselt elujÔuline Kubernetes

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 (ru., en.). 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.)

ma saan kasutada 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 suurepÀrased artiklid). 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
284

Vau, nii palju valikuid! Õnneks vajame ainult mĂ”nda neist. Siin on ĂŒks meile huvitav parameeter:

--pod-manifest-path string

Teekond 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 kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file .)

See parameeter vĂ”imaldab meil kĂ€itada staatilisi pod'e — 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=pods

SeejÀ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 selles blogis.) 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 etcd. 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-data

Kui 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.wal

API-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.6

Sel 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: nginx

Siin 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 account

Isegi 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          13m

LĂ”puks ilmus pod! Kuid tegelikult see ei kĂ€ivitu, kuna meil pole planeerijat (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 &lt;&lt;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.

Uurige kursusest lÀhemalt tasuta veebiseminaril.

Lugeda rohkem:

Allikas: habr.com

Osta usaldusvÀÀrne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid | ProHoster