Minimal yashovchan Kubernetes

Maqolaning tarjimasi kurs boshlanishi arafasida tayyorlangan "DevOps amaliyotlari va vositalari".

Minimal yashovchan Kubernetes

Agar siz buni o'qiyotgan bo'lsangiz, Kubernetes haqida biror narsa eshitgan bo'lishingiz mumkin (va bo'lmasa, bu erga qanday keldingiz?) Lekin Kubernetes nima? Bu "Sanoat toifasidagi konteynerlarni orkestrlash"? Yoki "Bulutli mahalliy operatsion tizim"? Bu hatto nimani anglatadi?

Rostini aytsam, men 100% ishonchim komil emas. Ammo, menimcha, ichki qismlarni o'rganish va Kubernetesda uning ko'plab mavhum qatlamlari ostida nima sodir bo'layotganini ko'rish qiziq. Keling, o'yin-kulgi uchun minimal "Kubernetes klasteri" aslida qanday ko'rinishini ko'rib chiqaylik. (Bu ancha oson bo'ladi Kubernetes qiyin yo'l.)

O'ylaymanki, siz Kubernetes, Linux va konteynerlar haqida asosiy bilimga egasiz. Bu yerda biz gaplashadigan hamma narsa faqat tadqiqot/taʼlim maqsadlari uchun, ulardan hech birini ishlab chiqarishga qoʻymang!

haqida umumiy ma'lumot

Kubernetes ko'plab komponentlarni o'z ichiga oladi. Ga binoan Vikipediya, arxitektura quyidagicha ko'rinadi:

Minimal yashovchan Kubernetes

Bu erda kamida sakkizta komponent ko'rsatilgan, ammo biz ularning aksariyatiga e'tibor bermaymiz. Shuni ta'kidlashni istardimki, Kubernetes deb nomlanishi mumkin bo'lgan minimal narsa uchta asosiy komponentdan iborat:

  • kublet
  • kube-apiserver (bu etcd ga bog'liq - uning ma'lumotlar bazasi)
  • konteyner ish vaqti (bu holda Docker)

Keling, hujjatlarda ularning har biri haqida nima deyilganini ko'rib chiqaylik (rus., Ingliz.). Boshida kublet:

Klasterdagi har bir tugun ustida ishlaydigan agent. Bu konteynerlar podda ishlayotganiga ishonch hosil qiladi.

Etarlicha oddiy eshitiladi. Nima haqida konteyner ishlash vaqtlari (konteyner ish vaqti)?

Konteynerning ishlash vaqti - bu konteynerlarni ishga tushirish uchun mo'ljallangan dastur.

Juda ma'lumotli. Ammo agar siz Docker bilan tanish bo'lsangiz, u nima qilishi haqida umumiy tasavvurga ega bo'lishingiz kerak. (Konteynerning ishlash vaqti va kubelet o'rtasidagi mas'uliyatni ajratish tafsilotlari aslida juda nozik va men bu erda ularga kirmayman.)

И API serveri?

API serveri Kubernetes boshqaruv paneli komponenti boʻlib, u Kubernetes API-ni ochib beradi. API serveri Kubernetes boshqaruv panelining mijoz tomonidir

Kubernetes bilan biror narsa qilgan har bir kishi to'g'ridan-to'g'ri yoki kubectl orqali API bilan o'zaro aloqada bo'lishi kerak edi. Bu Kubernetes Kubernetesni - biz hammamiz biladigan va sevadigan YAML tog'larini (?) ishlaydigan infratuzilmaga aylantiradigan miyaning yuragi. API bizning minimal konfiguratsiyamizda bo'lishi kerakligi aniq.

Old shartlar

  • Ildizga kirish huquqiga ega Linux virtual yoki jismoniy mashinasi (men virtual mashinada Ubuntu 18.04 dan foydalanmoqdaman).
  • Va bu hammasi!

Zerikarli o'rnatish

Biz foydalanadigan mashinaga Docker-ni o'rnatishimiz kerak. (Men Docker va konteynerlar qanday ishlashi haqida batafsil ma'lumot bermayman; agar qiziqsangiz, u erda ajoyib maqolalar). Keling, uni faqat bilan o'rnatamiz apt:

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

Shundan so'ng biz Kubernetes ikkiliklarini olishimiz kerak. Aslida, bizning "klasterimiz" ni dastlabki ishga tushirish uchun bizga faqat kerak kubelet, chunki boshqa server komponentlarini ishga tushirish uchun biz foydalanishimiz mumkin kubelet. Klasterimiz ishlagandan so'ng u bilan o'zaro ishlash uchun biz ham foydalanamiz 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

Agar biz shunchaki yugursak nima bo'ladi kubelet?

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

kubelet root sifatida ishlashi kerak. Juda mantiqiy, chunki u butun tugunni boshqarishi kerak. Keling, uning parametrlarini ko'rib chiqaylik:

$ ./kubelet -h
<слишком много строк, чтобы разместить здесь>
$ ./kubelet -h | wc -l
284

Voy, juda ko'p variantlar! Yaxshiyamki, bizga ulardan faqat ikkitasi kerak. Mana bizni qiziqtirgan parametrlardan biri:

--pod-manifest-path string

Statik pods uchun fayllarni o'z ichiga olgan katalogga yo'l yoki statik podlarni tavsiflovchi faylga yo'l. Nuqtalar bilan boshlangan fayllar e'tiborga olinmaydi. (QO'SHILGAN: Bu parametr --config opsiyasi orqali Kubeletga uzatiladigan konfiguratsiya faylida o'rnatilishi kerak. Qo'shimcha ma'lumot uchun qarang. kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file .)

Ushbu parametr bizni ishga tushirishga imkon beradi statik podalar — Kubernetes API orqali boshqarilmaydigan pods. Statik podalar kamdan-kam qo'llaniladi, lekin ular klasterni tezda ko'tarish uchun juda qulaydir va bu bizga kerak bo'lgan narsadir. Biz bu katta ogohlantirishni e'tiborsiz qoldiramiz (yana buni ishlab chiqarishda ishlatmang!) va podni ishga tushirishimiz mumkinligini bilib olamiz.

Avval biz statik pods uchun katalog yaratamiz va ishga tushiramiz kubelet:

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

Keyin, boshqa terminalda/tmux oynasida/nima bo'lishidan qat'iy nazar, biz pod manifestini yaratamiz:

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

kubelet ba'zi ogohlantirishlarni yozishni boshlaydi va hech narsa sodir bo'lmaganga o'xshaydi. Ammo bu unday emas! Keling, Dockerni ko'rib chiqaylik:

$ 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 Men pod manifestini o'qib chiqdim va Dockerga bizning spetsifikatsiyalarimizga muvofiq bir nechta konteynerlarni ishga tushirish buyrug'ini berdim. (Agar siz "pauza" konteyneri haqida qiziqayotgan bo'lsangiz, bu Kubernetes xackidir - qarang. bu blog.) Kubelet bizning konteynerimizni ishga tushiradi busybox belgilangan buyruq bilan va statik pod o'chirilgunga qadar uni cheksiz muddatga qayta ishga tushiradi.

O'zingizni tabriklang. Biz faqat terminalga matn chiqarishning eng chalkash usullaridan birini topdik!

Ishga tushirish va boshqalar

Bizning yakuniy maqsadimiz Kubernetes API-ni ishga tushirishdir, lekin buning uchun avval ishga tushirishimiz kerak va boshqalar. Minimal etcd klasterini uning sozlamalarini pods katalogiga joylashtirish orqali boshlaylik (masalan, 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

Agar siz hech qachon Kubernetes bilan ishlagan bo'lsangiz, ushbu YAML fayllari sizga tanish bo'lishi kerak. Bu erda faqat ikkita fikrni ta'kidlash kerak:

Biz xost papkasini o'rnatdik /var/lib/etcd qayta ishga tushirilgandan so'ng etcd ma'lumotlari saqlanib qolishi uchun podkada (agar bu bajarilmasa, pod har safar qayta ishga tushirilganda klaster holati o'chiriladi, bu hatto minimal Kubernetes o'rnatilishi uchun ham yaxshi bo'lmaydi).

Biz o'rnatdik hostNetwork: true. Bu sozlama, ajablanarli emas, etcd ni podning ichki tarmog'i o'rniga xost tarmog'idan foydalanish uchun sozlaydi (bu API serveriga etcd klasterini topishni osonlashtiradi).

Oddiy tekshirish shuni ko'rsatadiki, etcd haqiqatan ham localhost-da ishlaydi va ma'lumotlarni diskda saqlaydi:

$ 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 server ishga tushirilmoqda

Kubernetes API serverini ishga tushirish yanada oson. O'tish kerak bo'lgan yagona parametr --etcd-servers, siz kutgan narsani qiladi:

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

Ushbu YAML faylini katalogga joylashtiring pods, va API server ishga tushadi. bilan tekshirish curl Kubernetes API 8080 portni butunlay ochiq kirish bilan tinglayotganini ko'rsatadi - autentifikatsiya talab qilinmaydi!

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

(Yana, buni ishlab chiqarishda ishlatmang! Standart sozlama juda xavfli ekanligi meni hayratda qoldirdi. Lekin men buni ishlab chiqish va sinovdan o‘tkazishni osonlashtirish uchun qilingan deb o‘ylayman.)

Va yoqimli ajablanib, kubectl hech qanday qo'shimcha sozlamalarsiz ishlaydi!

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

muammo

Ammo agar siz biroz chuqurroq qazsangiz, biror narsa noto'g'ri ketayotganga o'xshaydi:

$ ./kubectl get pod -n kube-system
No resources found in kube-system namespace.

Biz yaratgan statik podlar yo'qoldi! Aslida, bizning kubelet tugunimiz umuman topilmagan:

$ ./kubectl get nodes
No resources found in default namespace.

Nima bo'ldi? Agar bir necha paragraflar oldin esingizda bo'lsa, biz kubeletni juda oddiy buyruq qatori parametrlari to'plami bilan boshladik, shuning uchun kubelet API serveri bilan qanday bog'lanishni va uning holati haqida uni xabardor qilishni bilmaydi. Hujjatlarni o'rganib chiqqandan so'ng biz tegishli bayroqni topamiz:

--kubeconfig string

Faylga yo'l kubeconfig, bu API serveriga qanday ulanishni belgilaydi. Mavjudligi --kubeconfig API server rejimini yoqadi, yo'q --kubeconfig oflayn rejimini yoqadi.

Bu vaqt davomida biz bilmagan holda kubeletni "oflayn rejimda" ishga tushirdik. (Agar biz pedantik bo'lganimizda, biz mustaqil kubeletni "minimal hayotiy Kubernetes" deb o'ylashimiz mumkin edi, lekin bu juda zerikarli bo'lar edi). "Haqiqiy" konfiguratsiya ishlashi uchun biz kubeconfig faylini kubeletga o'tkazishimiz kerak, shunda u API serveri bilan qanday gaplashishni biladi. Yaxshiyamki, bu juda oddiy (chunki bizda autentifikatsiya yoki sertifikat bilan bog'liq muammolar yo'q):

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

Buni shunday saqlang kubeconfig.yaml, jarayonni o'ldiring kubelet va kerakli parametrlar bilan qayta ishga tushiring:

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

(Aytgancha, agar siz kubelet ishlamayotgan vaqtda API-ga curl orqali kirishga harakat qilsangiz, u hali ham ishlayotganini ko'rasiz! Kubelet Docker kabi podslarining "ota-onasi" emas, u ko'proq "boshqaruv" ga o'xshaydi. daemon." Kubelet tomonidan boshqariladigan konteynerlar kubelet ularni to'xtatmaguncha ishlashda davom etadi.)

Bir necha daqiqadan so'ng kubectl Biz kutganimizdek, bizga podalar va tugunlarni ko'rsatishi kerak:

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

Keling, bu safar o'zimizni chin dildan tabriklaylik (men allaqachon o'zimizni tabriklaganimni bilaman) - bizda to'liq ishlaydigan API bilan ishlaydigan minimal Kubernetes "klasteri" bor!

Biz ostida ishga tushiramiz

Endi API nimaga qodirligini ko'rib chiqamiz. Nginx podidan boshlaylik:

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

Bu erda biz juda qiziq xatoga duch kelamiz:

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

Bu erda biz Kubernetes muhitimiz qanchalik to'liq emasligini ko'ramiz - bizda xizmatlar uchun hisoblar yo'q. Xizmat hisobini qo'lda yaratish orqali qayta urinib ko'raylik va nima sodir bo'lishini ko'ramiz:

$ 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

Xizmat hisobini qo'lda yaratganimizda ham, autentifikatsiya belgisi yaratilmaydi. Minimalistik "klasterimiz" bilan tajriba o'tkazishda davom etar ekanmiz, odatda avtomatik ravishda sodir bo'ladigan foydali narsalarning ko'pchiligi yo'qolishini topamiz. Kubernetes API serveri juda minimalist bo'lib, og'ir yuklarni ko'tarish va avtomatik sozlashning aksariyati hali ishlamayotgan turli kontrollerlar va fon ishlarida sodir bo'ladi.

Variantni o'rnatish orqali bu muammoni hal qilishimiz mumkin automountServiceAccountToken xizmat hisobi uchun (chunki biz undan foydalanishimiz shart emas):

$ 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

Nihoyat, pod paydo bo'ldi! Lekin aslida u boshlamaydi, chunki bizda yo'q rejalashtiruvchi (rejalashtiruvchi) Kubernetesning yana bir muhim komponentidir. Shunga qaramay, biz Kubernetes API hayratlanarli darajada "soqov" ekanligini ko'ramiz - APIda Pod yaratganingizda, u uni ro'yxatdan o'tkazadi, lekin uni qaysi tugunda ishga tushirishni aniqlashga urinmaydi.

Aslida, podkastni ishga tushirish uchun rejalashtiruvchi kerak emas. Parametrdagi manifestga tugunni qo'lda qo'shishingiz mumkin nodeName:

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

(Almashtirish mink8s tugun nomiga.) Oʻchirish va qoʻllashdan soʻng biz nginx ishga tushganini va ichki IP manzilni tinglayotganini koʻramiz:

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

Qopqoqlar orasidagi tarmoq to'g'ri ishlayotganiga ishonch hosil qilish uchun biz boshqa poddan curl ishga tushirishimiz mumkin:

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

Bu muhitni qazish va nima ishlayotganini va nima bo'lmasligini ko'rish juda qiziq. Men ConfigMap va Secret kutilganidek ishlayotganini topdim, lekin Xizmat va Deployment ishlamayapti.

Uspex!

Bu post uzoq davom etmoqda, shuning uchun men g'alabani e'lon qilmoqchiman va bu "Kubernetes" deb nomlanishi mumkin bo'lgan hayotiy konfiguratsiya ekanligini aytmoqchiman. Xulosa qilish uchun: to'rtta ikkilik, beshta buyruq qatori parametrlari va "faqat" 45 qator YAML (emas) Kubernetes standartlari bo'yicha) va bizda juda ko'p narsa ishlaydi:

  • Podlar oddiy Kubernetes API yordamida boshqariladi (bir nechta xakerlar bilan)
  • Siz ommaviy konteyner rasmlarini yuklashingiz va boshqarishingiz mumkin
  • Podlar tirik qoladi va avtomatik ravishda qayta ishga tushadi
  • Xuddi shu tugun ichidagi podlar o'rtasidagi tarmoq juda yaxshi ishlaydi
  • ConfigMap, maxfiy va oddiy saqlashni o'rnatish kutilganidek ishlaydi

Ammo Kubernetes-ni haqiqatan ham foydali qiladigan ko'p narsalar hali ham etishmayapti, masalan:

  • Pod Scheduler
  • Autentifikatsiya/avtorizatsiya
  • Bir nechta tugunlar
  • Xizmatlar tarmog'i
  • Klasterli ichki DNS
  • Xizmat hisoblari uchun kontrollerlar, joylashtirishlar, bulutli provayderlar bilan integratsiya va Kubernetes keltiradigan ko'pgina boshqa yaxshiliklar

Xo'sh, biz aslida nimani oldik? O'z-o'zidan ishlaydigan Kubernetes API haqiqatan ham shunchaki platformadir konteynerni avtomatlashtirish. Bu ko'p narsa qilmaydi - bu API-dan foydalanadigan turli kontrollerlar va operatorlar uchun ishdir - lekin u avtomatlashtirish uchun izchil muhitni ta'minlaydi.

Kurs haqida ko'proq ma'lumotni bepul vebinarda o'qing.

Batafsil:

Manba: www.habr.com

a Izoh qo'shish