Minimaalne töövÔimeline Kubernetes

Artikli tĂ”lge on ettevalmistatud kursuse alguseks „DevOps praktikas ja tööriistades“.

Minimaalne töövÔimeline Kubernetes

Kui sa seda loed, oled tĂ”enĂ€oliselt midagi kuulnud Kubernetesest (ja kui ei ole, siis kuidas sa siia sattusid?). Aga mis Kubernetes tĂ”eliselt on? See on „Tööstuslik tasemel konteinerite orkestreerimine“? ИлО „PilvepĂ”hine operatsioonisĂŒsteem“? Đ§Ń‚ĐŸ ĐČĐŸĐŸĐ±Ń‰Đ” ŃŃ‚ĐŸ Đ·ĐœĐ°Ń‡ĐžŃ‚?

Austades tĂ”de, ma ei ole 100% kindel. Kuid tĂ”enĂ€oliselt on huvitav kaevuda sisemusse ja vaadata, mis tegelikult toimub Kuberneteses selle paljude abstraktsioonikihtide all. Seega, huvi pĂ€rast, vaatame, milline nĂ€eb vĂ€lja minimaalne „Kubernetes klaster“. (See on palju lihtsam kui Kubernetes The Hard Way.)

Olen veendunud, et sul on pÔhitÔed Kubernetesest, Linuxist ja konteineritest selged. KÔik, millest me siin rÀÀgime, on mÔeldud ainult uurimiseks/Ôppimiseks, Àrge kÀitage seda tootmises!

Ülevaade

Kubernetes sisaldab palju komponente. Vastavalt vikipeedia, arhitektuur nÀeb vÀlja jÀrgmine:

Minimaalne töövÔimeline Kubernetes

Siin on nÀidatud vÀhemalt kaheksa komponenti, kuid enamik neist jÀÀb tÀhelepanuta. Soovin kinnitada, et minimaalne asi, mida oleks mÔistlik nimetada Kuberneteseks, koosneb kolmest peamisest komponendist:

  • kubelet
  • kube-apiserver (mis sĂ”ltub etcd-st — oma andmebaasist)
  • konteineri kĂ€itamisrea (selles osas Docker)

Vaatame, mida dokumentatsioon igaĂŒhe kohta ĂŒtleb (rus., ingl). Esmalt kubelet:

Agent, mis töötab igas klastrisÔlmes. Ta jÀlgib, et konteinerid oleksid pod'is kÀivitatud.

KÔlab piisavalt lihtsalt. Kuidas on konteinerite kÀitamisreaga? Konteinerite kÀitamisrea all mÔistetakse programmi, mis on mÔeldud konteinerite kÀitamiseks.

VĂ€ga informatiivne. Kuid kui olete Dockeriga tuttav, peaks teil olema ĂŒldine arusaam sellest, mida see teeb. (Konteinerite kĂ€itamisrea ja kubeleti vastutuse jaotuse detailid on tegelikult ĂŒsna peened ja ma ei sĂŒvene sellesse.)

VĂ€ga informatiivne. Kuid kui olete Dockeriga tutvunud, siis peaksite omama ĂŒldist arusaama sellest, mida see teeb. (Konteinerite tĂ€itmisringi ja kubeleti vahelise vastutuse jaotamise detailid on tegelikult juba ĂŒsna peened ning ma ei hakka neid siin sĂŒvitsi uurima).

JA API-server?

API-server on Kubernetes juhtpaneeli komponent, mis esindab Kubernetes API-d. API-server on Kubernetes juhtpaneeli kliendi osa.

Kellelegi, kes on kunagi Kubernetesega tegelenud, on pidanud API-ga suhtlema kas otse vĂ”i lĂ€bi kubectl. See on sĂŒdameasi, mis teeb Kubernetesest Kubernetes'e — aju, mis muudab kĂ”ik need YAML'id, mida me kĂ”ik tunneme ja armastame (?), töötavaks infrastruktuuriks. Tundub iseenesestmĂ”istetav, et API peaks olema meie minimaalsetes seadetes olemas.

Eeltingimused

  • Virtuaalne vĂ”i fĂŒĂŒsiline Linuxi masin root-juurdepÀÀsuga (kasutan virtuaalmahana Ubuntu 18.04).
  • Ja see on kĂ”ik!

Igav installatsioon

Masinale, mida me kasutame, tuleb installida Docker. (Ma ei hakka detailselt rÀÀkima, kuidas Docker ja konteinerid töötavad; kui see huvitab, on olemas suurepÀrased artiklid). Lihtsalt installime selle koos apt:

$ sudo apt install docker.io
$ sudo systemctl start docker

PĂ€rast seda peame saama Kubernetes'e binaarid. Tegelikult on meie “klastri” esialgseks kĂ€ivitamiseks vajalik ainult kubelet, sest teiste serveri komponentide kĂ€itamiseks saame kasutada kubelet. Meie klastri suhtlemiseks pĂ€rast selle tööle hakkamist kasutame samuti 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. See on loogiline, kuna sel on vaja hallata kogu sÔlme. Vaadake, millised on tema parameetrid:

$ ./kubelet -h

$ ./kubelet -h | wc -l
284

Vau, kui palju valikuid! Õnneks vajame ainult mĂ”nda neist. Siin on ĂŒks parameeter, mis meid huvitab:

--pod-manifest-path string

Kaust, mis sisaldab staatiliste podide faile, vĂ”i faili, mis sisaldab staatiliste podide kirjeldust. Failid, mis algavad punktiga, jĂ€etakse tĂ€helepanuta. (AEGUNUD: see parameeter tuleks seadistada konfigureerimisfailis, mis edastatakse Kubeletile valiku —config kaudu. Lisateabe jaoks vaadake. kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file .)

See parameeter vĂ”imaldab meil kĂ€ivitada staatilisi pode — podid, mida ei haldata Kubernetes API kaudu. Staatilisi pode kasutatakse harva, kuid need on vĂ€ga mugavad klastrite kiireks ĂŒlesehitamiseks, mida meil on vaja. Ignoreerime seda valjuhÀÀlset hoiatust (jĂ€llegi, Ă€rge kĂ€itage seda tootmises!) ja vaatame, kas suudame poda kĂ€ivitada.

Esmalt loome staatiliste podide katalooge ja kÀivitame kubelet:

$ mkdir pods
$ sudo ./kubelet --pod-manifest-path=pods

SeejÀrel teises terminalis/tmuxis/veel kusagil loome poda manifesti:

$ cat < pods/hello.yaml
apiVersion: v1
kind: Pod
metadata:
  name: hello
spec:
  containers:
  - image: busybox
    name: hello
    command: ["echo", "hello world!"]
EOF

kubelet alustab mÔningate hoiatuste kirjutamist ja tundub, et mitte midagi ei toimu. Kuid see pole 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 podi manifesti ja andsin Docker’ile kĂ€su kĂ€ivitada paar konteinerit vastavalt meie spetsifikatsioonile. (Kui teid huvitab konteiner “pause”, siis see on Kubernetes’i hĂ€kkimine — tĂ€iendavad ĂŒksikasjad leiate selles blogis.) Kubelet kĂ€ivitab meie konteineri busybox mÀÀratud kĂ€suga ja taaskĂ€ivitab selle pidevalt, kuni staatiline pod on eemaldatud.

Palju Ă”nne! Me mĂ”tlesime vĂ€lja ĂŒhe kĂ”ige keerukama viisi teksti terminalis kuvamiseks!

KĂ€ivitame etcd

Meie lÔppeesmÀrk on kÀivitada Kubernetes API, kuid kÔigepealt peame kÀivitama etcd. Alustame minimaalset etcd klastri kÀivitamist, paigutades selle seaded pods katalooge (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 Kubernetes’ega, peaksid sellised YAML-failid olema teile tuttavad. Siinkohal tasub mĂ€rkida ainult kahte punkti:

Oleme mountinud hosti kausta /var/lib/etcd Konteineris peab olema seadistatud nii, et etcd andmed salvestataks pÀrast taaskÀivitamist (kui seda ei tehta, siis klastris olek kustutatakse igal taaskÀivitamisel, mis pole soovitatav isegi Kubernetes'i minimaalsete seadistuste puhul).

Oleme installinud hostNetwork: true. See parameeter, nagu ikka, seadistab etcd kasutama hosti vÔrgustikku ja mitte konteineri sisemist vÔrgustikku (see lihtsustab API-serveril etcd klastri leidmist).

Lihtne kontroll nÀitab, et etcd töötab tÔeliselt localhost'is 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. Ainsaks parameetriks, mis tuleb edastada, on --etcd-servers, mis teeb just 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 kausta pods, ja API-server kĂ€ivitub. Kontrollimine lĂ€bi curl nĂ€itab, et Kubernetes API kuulab porti 8080, millel on tĂ€ielik juurdepÀÀs — 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! Olin veidi ĂŒllatunud, et vaikeseaded on nii ebaturvalised. Ent ma arvan, et see on tehtud arenduse ja testimise lihtsustamiseks.)

Ja miski jĂ€i ĂŒllatuseks, kubectl töötab kohe ilma 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
Default nimiet sisaldab ressursse.

Probleem

Aga kui sĂŒgavamale kaevata, siis tundub, et midagi on valesti:

$ ./kubectl get pod -n kube-system
Kube-sĂŒsteemi nimiehetes pole ressursse.

Loome kokku pandud pod'id on kadunud! Tegelikult ei tuvastata meie kubelet-sĂ”lme ĂŒleĂŒldse:

$ ./kubectl get nodes
Ei ole ressursse leitud vaike nimivÀli.

Mis on siis? Kui te mĂ€letate, siis me kĂ€ivitasime kubeleti vĂ€ga lihtsa kĂ€surea parameetrite kogumiga, mistĂ”ttu kubelet ei tea, kuidas ĂŒhenduda API-serveriga ja edastada sellele oma olekut. Dokumentatsiooni uurides leiame vastava lipu:

--kubeconfig string

Faili tee kubeconfig, kus on kirjas, kuidas ĂŒhenduda API-serveriga. Lipu olemasolu --kubeconfig lĂŒlitab API-serveri reĆŸiimi sisse, samas kui selle puudumine --kubeconfig lĂŒlitab sisse iseseisva reĆŸiimi.

Kogu selle aja oleme, teadmata, kĂ€ivitanud kubeleti „iseseisvas reĆŸiimis“. (Kui oleksime pedantsed, vĂ”iks iseseisvat kubeleti reĆŸiimi pidada „minimaalselt elujĂ”uliseks Kuberneteseks“, aga see oleks vĂ€ga igav.) Et „pĂ€ris“ konfiguratsioon töötaks, peame andma kubeletile kubeconfig faili, et ta teaks, kuidas suhelda API-serveriga. Õnneks on see ĂŒsna 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

Salvesta see kui kubeconfig.yaml, tapa protsess kubelet ja taaskÀivita vajalike parameetritega:

$ sudo ./kubelet --pod-manifest-path=pods --kubeconfig=kubeconfig.yaml

(Üks asi veel, kui proovite API-le juurde pÀÀseda curl'in lĂ€bi, kui kubelet ei tööta, avastate, et see töötab endiselt! Kubelet ei ole oma pod'ide 'vanem', nagu Docker, rohkem nagu 'demon'. Kubeleti haldavad konteinerid jÀÀvad tööle, kuni kubelet neid peatab.)

MÔne minuti jooksul kubectl peaksime nÀgema pod'e ja sÔlmi, nagu ootame:

$ ./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

TĂ€naseks peaksime end tĂ”eliselt kiitma (ma tean, et olen juba kiitnud) — meil on töötav minimaalne 'kubernetes' klaster, millel on tĂ€isfunktsionaalne API!

KĂ€ivitame pod'i

NĂŒĂŒd vaatame, milleks API vĂ”imeline on. Alustame nginx pod'iga:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - image: nginx
    name: nginx

Siin saame ĂŒsna huvitava veateate:

$ ./kubectl apply -f nginx.yaml
Serverist tulenev viga (Forbidden): viga "nginx.yaml" loomisel: podid "nginx" on
keelatud: teenuse konto "default" otsimisel ilmnes viga: teenuse konto
"default" ei leitud
$ ./kubectl get serviceaccounts
Default nimiosas ressursse ei leitud.

Siin nĂ€eme, kui kohutavalt puudulik on meie Kubernetes keskkond — meil puuduvad teenuse kontod. Proovime uuesti, luues teenuse konto kĂ€sitsi, ja vaatame, mis juhtub:

$ cat <<EOS | ./kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  name: default
  namespace: default
EOS
teenusekonto/default loodud
$ ./kubectl apply -f nginx.yaml
Serverist tulenev viga (ServerTimeout): viga "nginx.yaml" loomisel: API
tokenit teenuse konto "default" jaoks ei leitud, proovige uuesti pÀrast
selle automaatset loomist ja teenuse kontole lisamist.

Isegi kui me loome teenuse konto kĂ€sitsi, ei genereerita autentimistokenit. JĂ€tkates katsetamist meie minimalistlikus „klastris“, leiame, et enamus kasulikest asjadest, mis tavaliselt automaatselt juhtuvad, on puudu. Kubernetes API server on ĂŒsna minimalistlik, enamus rasketest automaatsetest seadistustest toimub erinevates kontrollerites ja taustatöödel, mis veel ei töötata.

Saame selle probleemi ĂŒletada, seadistades valiku automountServiceAccountToken teenuse konto jaoks (sest me ei pea seda kasutama):

$ cat <<EOS | ./kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  name: default
  namespace: default
automountServiceAccountToken: false
EOS
serviceaccount/default konfigureeritud
$ ./kubectl apply -f nginx.yaml
pod/nginx loodud
$ ./kubectl get pods
NIMI    VALMIS   OLEK    UUESTI KÄIVITUSED   VANUS
nginx   0/1     Ootel   0          13m

LĂ”puks on pod olemas! Kuid tegelikult ei kĂ€ivitu see, kuna meil puudub planeerija (scheduler) — veel ĂŒks oluline komponent Kuberneteses. JĂ€lle, me nĂ€eme, et Kubernetes API on ĂŒllatavalt "loll" — kui lood podi API-s, registreerib see selle, kuid ei pĂŒĂŒa vĂ€lja selgitada, millisel sĂ”lmel seda kĂ€ivitada.

Tegelikult ei ole podi kÀivitamiseks planeerijat vajalik. Saad 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 delete ja apply nÀeme, et nginx on kÀivitatud ja kuulab sisemist IP-aadressi:

$ ./kubectl delete pod nginx
pod "nginx" kustutatud
$ ./kubectl apply -f nginx.yaml
pod/nginx loodud
$ ./kubectl get pods -owide
NIMI    VALMIS   SEISUND    TÄISTAMINE   VANUS   IP           NOOD     NOMINEERITUD NOOD   VALMIDUSE KÜSJAD
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 podide vahel töötab Ă”igesti, saame kĂ€ivitada curl teisest podist:

$ cat &lt;&lt;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>Tere tulemast nginx!</title>

On ĂŒsna huvitav selles keskkonnas ringi kaevata ja vaadata, mis töötab ja mis mitte. Olen leidnud, et ConfigMap ja Secret toimivad ootuspĂ€raselt, kuid Service ja Deployment mitte.

Edu!

See postitus muutub pikaks, seetÔttu kavatsen kuulutada vÔitu ja öelda, et see on kasutatav konfiguratsioon, mida vÔib nimetada "Kubernetes". KokkuvÔttes: neli binaarfaili, viis kÀsurea parameetrit ja "ainult" 45 rida YAML (Kubernetes'e standardite jÀrgi mitte nii palju) ning meil töötab mitmeid asju:

  • Pod'e haldatakse tavalise Kubernetes API kaudu (mĂ”ne nipiga)
  • VĂ”ib ĂŒles laadida avalikke konteineripilte ja neid hallata
  • Pod'id pĂŒsivad elus ja taaskĂ€ivituvad automaatselt
  • VĂ”rk pod'ide vahel samas sĂ”lmes töötab ĂŒsna hĂ€sti
  • ConfigMap, Secret ja kĂ”ige lihtsam salvestusruumi mountimine toimivad nagu peab

Kuid enamik sellest, mis teeb Kubernetes'est tÔeliselt kasuliku, on endiselt puudulik, nÀiteks:

  • Pod'ide planeerija
  • Autentimine / autoriseerimine
  • Mitu sĂ”lme
  • Teenuste vĂ”rk
  • Klastri sisemine DNS
  • Teenused, nagu serverite kontrollerid, juurutused, integreerimine pilveteenuse pakkujatega ja enamik teisi kasulikke funktsioone, mida Kubernetes pakub.

Kuid mis me tegelikult saime? Kubernetes API, mis töötab iseseisvalt, on tegelikult lihtsalt platvorm. konteinerite automatiseerimiseks.See ei tee palju – see on erinevate kontrollerite ja operaatorite töö, kes kasutavad API-d, – aga see tagab jĂ€rjepideva keskkonna automatiseerimiseks.

Tutvuge kursuse kohta tasuta veebinaris.

Loe edasi:

Allikas: habr.com

Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster