Lágmarks raunhæfur Kubernetes

Þýðing á greininni var unnin í aðdraganda námskeiðsins „DevOps venjur og verkfæri“.

Lágmarks raunhæfur Kubernetes

Ef þú ert að lesa þetta hefurðu líklega heyrt eitthvað um Kubernetes (og ef ekki, hvernig endaðir þú hér?) En hvað er Kubernetes nákvæmlega? Þetta „Hljómsveit á gámum í iðnaðarflokki“? Eða "Cloud-native stýrikerfi"? Hvað þýðir þetta jafnvel?

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:

Lágmarks raunhæfur Kubernetes

Þ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:

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

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.

$ 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

Hvað gerist ef við hlaupum bara kubelet?

$ ./kubelet
F0609 04:03:29.105194    4583 server.go:254] mkdir /var/lib/kubelet: permission denied

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:

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

Síðan, í annarri flugstöð/tmux glugga/hvað sem er, munum við búa til pod manifest:

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

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):

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

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ð:

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

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!

$ curl localhost:8080/healthz
ok
$ curl localhost:8080/api/v1/pods
{
  "kind": "PodList",
  "apiVersion": "v1",
  "metadata": {
    "selfLink": "/api/v1/pods",
    "resourceVersion": "59"
  },
  "items": []
}

(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):

apiVersion: v1
kind: Config
clusters:
- cluster:
    server: http://127.0.0.1:8080
  name: mink8s
contexts:
- context:
    cluster: mink8s
  name: mink8s
current-context: mink8s

Vista þetta sem kubeconfig.yaml, drepa ferlið kubelet og endurræstu með nauðsynlegum breytum:

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

(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:

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

Hér fáum við frekar áhugaverða villu:

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

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

(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.

Lærðu meira um námskeiðið í ókeypis vefnámskeiðinu.

Lestu meira:

Heimild: www.habr.com

Bæta við athugasemd