Satt að segja er ég ekki 100% viss. En ég held að það sé áhugavert að grafa ofan í sig innri hliðina og sjá hvað er raunverulega að gerast í Kubernetes undir mörgum lögum af abstraktum. Svo bara til gamans skulum við kíkja á hvernig lágmarks „Kubernetes þyrping“ lítur út í raun og veru. (Þetta verður miklu auðveldara en Kubernetes erfiða leiðin.)
Ég geri ráð fyrir að þú hafir grunnþekkingu á Kubernetes, Linux og gámum. Allt sem við tölum um hér er eingöngu til rannsóknar/náms, ekki setja neitt af því í framleiðslu!
Skoða
Kubernetes inniheldur marga hluti. Samkvæmt wikipedia, arkitektúrinn lítur svona út:
Það eru að minnsta kosti átta þættir sýndir hér, en við munum hunsa flesta þeirra. Ég vil taka fram að lágmarkshluturinn sem hægt er að kalla Kubernetes með sanngjörnum hætti samanstendur af þremur meginþáttum:
kúbelet
kube-apiserver (sem fer eftir etcd - gagnagrunninum hans)
keyrslutími gáma (Docker í þessu tilfelli)
Við skulum sjá hvað skjölin segja um hvert þeirra (rus., Enska.). Í fyrstu kúbelet:
Umboðsmaður í gangi á hverjum hnút í þyrpingunni. Það tryggir að ílát séu í gangi í belgnum.
Hljómar nógu einfalt. Hvað um keyrslutíma gáma (keyrslutími gáma)?
Gámakeyrsla er forrit sem er hannað til að keyra gáma.
Mjög fræðandi. En ef þú þekkir Docker, þá ættir þú að hafa almenna hugmynd um hvað það gerir. (Upplýsingarnar um aðskilnað ábyrgðar milli keyrslutíma gáma og kubelet eru í raun frekar lúmskur og ég mun ekki fara út í þær hér.)
И API þjónn?
API Server er Kubernetes stjórnborðshlutinn sem afhjúpar Kubernetes API. API þjónninn er biðlarahlið Kubernetes stjórnborðsins
Allir sem hafa einhvern tíma gert eitthvað með Kubernetes hafa þurft að hafa samskipti við API annað hvort beint eða í gegnum kubectl. Þetta er hjarta þess sem gerir Kubernetes Kubernetes - heilann sem breytir fjöllum YAML sem við öll þekkjum og elskum (?) í starfandi innviði. Það virðist augljóst að API ætti að vera til staðar í lágmarks stillingum okkar.
Forsendur
Linux sýndar- eða líkamleg vél með rótaraðgangi (ég er að nota Ubuntu 18.04 á sýndarvél).
Og það er allt!
Leiðinleg uppsetning
Við þurfum að setja upp Docker á vélinni sem við munum nota. (Ég ætla ekki að fara í smáatriði um hvernig Docker og gámar virka; ef þú hefur áhuga, þá er dásamlegar greinar). Við skulum bara setja það upp með apt:
Eftir það þurfum við að fá Kubernetes tvöfaldana. Reyndar, fyrir fyrstu kynningu á „þyrpingunni“ okkar þurfum við aðeins kubelet, þar sem við getum notað aðra miðlarahluti til að keyra kubelet. Til að hafa samskipti við klasann okkar eftir að hann er í gangi munum við líka nota kubectl.
kubelet verður að keyra sem rót. Alveg rökrétt þar sem hann þarf að stjórna öllum hnútnum. Við skulum skoða breytur þess:
$ ./kubelet -h
<слишком много строк, чтобы разместить здесь>
$ ./kubelet -h | wc -l
284
Vá, svo margir möguleikar! Sem betur fer þurfum við aðeins nokkra af þeim. Hér er ein af breytunum sem við höfum áhuga á:
--pod-manifest-path string
Slóð að möppunni sem inniheldur skrár fyrir static pods, eða slóð að skrá sem lýsir static pods. Skrár sem byrja á punktum eru hunsaðar. (ÚTLAÐIÐ: Þessi valkostur verður að vera stilltur í stillingarskránni sem send er til Kubelet með --config valkostinum. Fyrir frekari upplýsingar, sjá kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file .)
Þessi valkostur gerir okkur kleift að keyra kyrrstæður belg — belg sem ekki er stjórnað í gegnum Kubernetes API. Stöðugir fræbelgir eru sjaldan notaðir, en þeir eru mjög þægilegir til að ala upp klasa fljótt og þetta er nákvæmlega það sem við þurfum. Við munum hunsa þessa stóru viðvörun (aftur, ekki keyra þetta í framleiðslu!) og sjá hvort við getum komið belgnum í gang.
Fyrst munum við búa til möppu fyrir kyrrstæður belg og keyra kubelet:
kubelet byrjar að skrifa nokkrar viðvaranir og svo virðist sem ekkert sé að gerast. En það er ekki satt! Við skulum líta á 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 Ég las belgskrána og gaf Docker skipunina um að ræsa nokkra gáma í samræmi við forskriftir okkar. (Ef þú ert að spá í "hlé" ílátið, þá er það Kubernetes hakk - sjáðu þetta blogg.) Kubelet mun ræsa gáminn okkar busybox með tilgreindri skipun og mun endurræsa hana endalaust þar til kyrrstöðubelgnum er eytt.
Óska þér til hamingju. Við komum bara með eina af ruglingslegustu leiðunum til að senda texta í flugstöðina!
Ræsa etcd
Lokamarkmið okkar er að keyra Kubernetes API, en til að gera það þurfum við fyrst að keyra osfrv. Byrjum á lágmarks etcd klasa með því að setja stillingar hans í pods möppuna (til dæmis, pods/etcd.yaml):
Ef þú hefur einhvern tíma unnið með Kubernetes ættu þessar YAML skrár að vera kunnuglegar fyrir þig. Hér eru aðeins tvö atriði sem vert er að benda á:
Við höfum sett upp hýsilmöppuna /var/lib/etcd í belgnum þannig að etcd gögnin varðveitist eftir endurræsingu (ef það er ekki gert mun klasaástandið eyðast í hvert skipti sem belgurinn er endurræstur, sem mun ekki vera gott fyrir jafnvel lágmarks Kubernetes uppsetningu).
Við höfum sett upp hostNetwork: true. Þessi stilling, sem kemur ekki á óvart, stillir etcd til að nota hýsingarnetið í stað innra nets hólfsins (þetta mun auðvelda API þjóninum að finna etcd þyrpinguna).
Einföld athugun sýnir að etcd er örugglega í gangi á localhost og vistar gögn á 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.wal
Ræsir API þjóninn
Það er enn auðveldara að keyra Kubernetes API netþjón. Eina færibreytan sem þarf að fara framhjá er --etcd-servers, gerir það sem þú býst við:
Settu þessa YAML skrá í möppuna pods, og API þjónninn mun ræsa. Athugar með curl sýnir að Kubernetes API er að hlusta á port 8080 með algjörlega opnum aðgangi - engin auðkenning krafist!
(Aftur, ekki keyra þetta í framleiðslu! Ég var svolítið hissa á því að sjálfgefin stilling er svo óörugg. En ég býst við að þetta sé til að auðvelda þróun og prófun.)
Og, skemmtilega á óvart, kubectl virkar út úr kassanum án frekari stillinga!
$ ./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.
vandamálið
En ef þú kafar aðeins dýpra virðist eitthvað vera að fara úrskeiðis:
$ ./kubectl get pod -n kube-system
No resources found in kube-system namespace.
Kyrrstæðu belgirnir sem við bjuggum til eru horfnir! Reyndar er kubelet hnúturinn okkar alls ekki uppgötvaður:
$ ./kubectl get nodes
No resources found in default namespace.
Hvað er að? Ef þú manst fyrir nokkrum málsgreinum síðan, þá byrjuðum við kubelet með mjög einföldu setti af skipanalínubreytum, þannig að kubelet veit ekki hvernig á að hafa samband við API þjóninn og láta hann vita um ástand hans. Eftir að hafa rannsakað skjölin finnum við samsvarandi fána:
--kubeconfig string
Slóðin að skránni kubeconfig, sem tilgreinir hvernig á að tengjast API þjóninum. Framboð --kubeconfig virkjar API netþjónsstillingu, nr --kubeconfig virkjar ótengda stillingu.
Allan þennan tíma, án þess að vita af því, vorum við að keyra kúbelet í „ótengdum ham“. (Ef við værum pedantísk gætum við hugsað um sjálfstæðan kúbelet sem „lágmarks lífvænlegar Kubernetes“, en það væri mjög leiðinlegt). Til að láta "raunverulega" stillingarnar virka, þurfum við að senda kubeconfig skrána til kubelet svo það viti hvernig á að tala við API þjóninn. Sem betur fer er það frekar einfalt (þar sem við erum ekki með nein auðkenningar- eða vottorðsvandamál):
(Við the vegur, ef þú reynir að fá aðgang að API í gegnum curl þegar kubelet er ekki í gangi, muntu komast að því að það er enn í gangi! Kubelet er ekki „foreldri“ fræbelgja sinna eins og Docker, það er meira eins og „stýring“ púkinn.“ Gámar sem stjórnað er af kubelet munu halda áfram að keyra þar til kubelet stöðvar þá.)
Eftir nokkrar mínútur kubectl ætti að sýna okkur belg og hnúta eins og við búumst við:
$ ./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
Við skulum virkilega óska okkur til hamingju í þetta skiptið (ég veit að ég hef nú þegar óskað okkur til hamingju) - við erum með lágmarks Kubernetes "þyrping" í gangi með fullkomlega virku API!
Við ræsum undir
Nú skulum við sjá hvað API er fær um. Byrjum á nginx pod:
$ ./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.
Hér sjáum við hversu grátlega ófullkomið Kubernetes umhverfi okkar er - við höfum enga reikninga fyrir þjónustu. Við skulum reyna aftur með því að búa til þjónustureikning handvirkt og sjá hvað gerist:
$ 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
Jafnvel þegar við stofnuðum þjónustureikninginn handvirkt er auðkenningartáknið ekki búið til. Þegar við höldum áfram að gera tilraunir með mínimalíska „þyrpinguna“ okkar, munum við komast að því að flest það gagnlega sem gerist venjulega sjálfkrafa mun vanta. Kubernetes API þjónninn er frekar naumhyggjulegur, þar sem flestar þungar lyftingar og sjálfvirkar stillingar eiga sér stað í ýmsum stjórnendum og bakgrunnsverkum sem eru ekki enn í gangi.
Við getum unnið í kringum þetta vandamál með því að velja valkostinn automountServiceAccountToken fyrir þjónustureikninginn (þar sem við þurfum samt ekki að nota hann):
$ 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
Loksins er belgurinn kominn! En í raun mun það ekki byrja vegna þess að við höfum ekki skipuleggjandi (dagskrá) er annar mikilvægur hluti af Kubernetes. Aftur sjáum við að Kubernetes API er furðu "heimskulegt" - þegar þú býrð til Pod í API, skráir það það, en reynir ekki að finna út hvaða hnút á að keyra það á.
Reyndar þarftu ekki tímaáætlun til að keyra pod. Þú getur handvirkt bætt hnút við upplýsingaskrána í færibreytunni nodeName:
(Skiptu út mink8s að nafni hnútsins.) Eftir að hafa eytt og notað, sjáum við að nginx er byrjað og er að hlusta á innri IP tölu:
$ ./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>
Til að ganga úr skugga um að netið á milli belgjanna virki rétt, getum við keyrt krullu úr öðrum belg:
$ 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>
Það er ansi áhugavert að grafast fyrir um þetta umhverfi og sjá hvað virkar og hvað ekki. Ég komst að því að ConfigMap og Secret virka eins og búist var við, en Service og Deployment ekki.
Árangur!
Þessi færsla er að verða löng, svo ég ætla að lýsa yfir sigri og segja að þetta sé raunhæf uppsetning sem hægt er að kalla „Kubernetes“. Til að draga saman: fjórar tvöfaldar, fimm skipanalínubreytur og „aðeins“ 45 línur af YAML (ekki það mikið miðað við staðla Kubernetes) og við höfum alveg nokkra hluti sem virka:
Bekkjum er stjórnað með venjulegu Kubernetes API (með nokkrum innbrotum)
Þú getur hlaðið upp og stjórnað opinberum gámamyndum
Pods halda lífi og endurræsa sig sjálfkrafa
Netkerfi milli fræbelgja innan sama hnút virkar nokkuð vel
ConfigMap, Secret og einföld geymsluuppsetning virkar eins og búist var við
En margt af því sem gerir Kubernetes sannarlega gagnlegt vantar enn, eins og:
Pod Scheduler
Auðkenning/heimild
Margir hnútar
Þjónustunet
Klustað innra DNS
Stýringar fyrir þjónustureikninga, dreifingu, samþættingu við skýjaveitur og flest annað góðgæti sem Kubernetes kemur með
Svo hvað fengum við eiginlega? Kubernetes API, sem keyrir eitt og sér, er í raun bara vettvangur fyrir gáma sjálfvirkni. Það gerir ekki mikið - það er starf fyrir ýmsa stýringar og rekstraraðila sem nota API - en það veitir stöðugt umhverfi fyrir sjálfvirkni.