Минималды өміршең кубернеттер

Мақаланың аудармасы курстың басталу қарсаңында дайындалды «DevOps тәжірибелері мен құралдары».

Минималды өміршең кубернеттер

Егер сіз мұны оқып жатсаңыз, сіз Кубернетес туралы бірдеңе естіген шығарсыз (және егер олай болмаса, бұл жерге қалай келдіңіз?) Бірақ Кубернетес деген не? Бұл «Өнеркәсіптік деңгейдегі контейнерлердің оркестрі»? Немесе «Бұлтты жергілікті операциялық жүйе»? Бұл тіпті нені білдіреді?

Шынымды айтсам, мен 100% сенімді емеспін. Бірақ менің ойымша, ішкі бөліктерді қазып алу және оның көптеген абстракция қабаттарының астында Кубернетесте не болып жатқанын көру қызықты. Ендеше, көңіл көтеру үшін минималды «Кубернетес кластері» қалай көрінетінін қарастырайық. (Бұл қарағанда әлдеқайда оңай болады Кубернетес қиын жол.)

Сізде Kubernetes, Linux және контейнерлер туралы негізгі біліміңіз бар деп ойлаймын. Бұл жерде біз айтатын барлық нәрсе тек зерттеу/оқу мақсаттарына арналған, олардың ешқайсысын өндіріске салмаңыз!

қайта қарау

Kubernetes құрамында көптеген компоненттер бар. Сәйкес Wikipedia, архитектурасы келесідей:

Минималды өміршең кубернеттер

Мұнда кемінде сегіз компонент көрсетілген, бірақ біз олардың көпшілігін елемейміз. Мен Кубернетес деп атауға болатын ең аз нәрсе үш негізгі компоненттен тұратынын айтқым келеді:

  • кубелет
  • kube-apiserver (ол etcd-ге байланысты - оның дерекқоры)
  • контейнердің жұмыс уақыты (бұл жағдайда Docker)

Олардың әрқайсысы туралы құжаттамада не айтылғанын көрейік (rus., Ағылшын.). Алғашқыда кубелет:

Кластердегі әрбір түйінде жұмыс істейтін агент. Ол контейнерлердің подводта жұмыс істеп тұрғанын қамтамасыз етеді.

Қарапайым естіледі. Не туралы контейнердің жұмыс уақыты (контейнердің жұмыс уақыты)?

Контейнердің орындалу уақыты – контейнерлерді іске қосуға арналған бағдарлама.

Өте мазмұнды. Бірақ егер сіз Docker-пен таныс болсаңыз, онда сізде оның не істейтіні туралы жалпы түсінік болуы керек. (Контейнердің жұмыс уақыты мен кубелет арасындағы жауапкершілікті бөлудің егжей-тегжейлері өте нәзік және мен бұл жерде оларға кірмеймін.)

И API сервері?

API сервері Kubernetes API интерфейсін ашатын Kubernetes басқару тақтасының құрамдас бөлігі болып табылады. API сервері Kubernetes басқару тақтасының клиенттік жағы болып табылады

Kubernetes-пен бірдеңе жасаған кез келген адам API-мен тікелей немесе kubectl арқылы өзара әрекеттесуге мәжбүр болды. Бұл Кубернетес Кубернетесті - бәріміз білетін және жақсы көретін YAML тауларын (?) жұмыс инфрақұрылымына айналдыратын мидың жүрегі. API біздің минималды конфигурациямызда болуы керек екені анық сияқты.

Алғы шарттар

  • Түбірлік қатынасы бар Linux виртуалды немесе физикалық машинасы (мен виртуалды машинада Ubuntu 18.04 пайдаланамын).
  • Міне, бәрі де!

Жалықтырғыш орнату

Біз қолданатын құрылғыға Docker орнатуымыз керек. (Мен Docker және контейнерлер қалай жұмыс істейтіні туралы егжей-тегжейлі айтып бермеймін; егер сізді қызықтырса, бар тамаша мақалалар). Онымен бірге орнатайық apt:

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

Осыдан кейін біз Kubernetes екілік файлдарын алуымыз керек. Шын мәнінде, біздің «кластердің» алғашқы іске қосылуы үшін бізге қажет kubelet, өйткені біз басқа сервер құрамдастарын іске қосу үшін пайдалана аламыз kubelet. Кластер іске қосылғаннан кейін онымен әрекеттесу үшін біз де қолданамыз 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

Біз жай ғана жүгірсек не болады kubelet?

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

kubelet түбір ретінде іске қосылуы керек. Өте қисынды, өйткені ол бүкіл түйінді басқаруы керек. Оның параметрлерін қарастырайық:

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

Уау, көптеген нұсқалар! Бақытымызға орай, бізге олардың бірнешеуі ғана керек. Міне, бізді қызықтыратын параметрлердің бірі:

--pod-manifest-path string

Статикалық қосқыштарға арналған файлдарды қамтитын каталогқа жол немесе статикалық қосқыштарды сипаттайтын файлға жол. Нүктелерден басталатын файлдар еленбейді. (ТОҚТАДЫ: бұл опция Kubelet жүйесіне --config опциясы арқылы жіберілген конфигурация файлында орнатылуы керек. Қосымша ақпаратты қараңыз. kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file .)

Бұл опция бізге іске қосуға мүмкіндік береді статикалық түйіршіктер — Kubernetes API арқылы басқарылмайтын бөлімдер. Статикалық бағандар сирек пайдаланылады, бірақ олар кластерді жылдам көтеру үшін өте ыңғайлы және бұл бізге қажет нәрсе. Біз бұл үлкен ескертуді елемейміз (қайтадан, бұны өндірісте іске қоспаңыз!) және подкастты іске қоса алатынымызды көреміз.

Алдымен біз статикалық қосқыштар үшін каталог жасаймыз және іске қосамыз kubelet:

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

Содан кейін басқа терминалда/tmux терезесінде/қандай болса да, біз подманифест жасаймыз:

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

kubelet кейбір ескертулерді жаза бастайды және ештеңе болмаған сияқты. Бірақ бұл олай емес! Докерді қарастырайық:

$ 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 Мен подманифестті оқыдым және Docker-ке біздің сипаттамаларымызға сәйкес бірнеше контейнерді іске қосу пәрменін бердім. (Егер сізді «кідірту» контейнері туралы қызықтыратын болсаңыз, бұл Kubernetes бұзуы - қараңыз осы блог.) Кубелет біздің контейнерді іске қосады busybox көрсетілген пәрменмен және статикалық подкаст жойылмайынша оны шексіз қайта іске қосады.

Өзіңізді құттықтаңыз. Біз терминалға мәтін шығарудың ең түсініксіз тәсілдерінің бірін ойлап таптық!

Іске қосу және т.б

Біздің түпкі мақсатымыз - Kubernetes API іске қосу, бірақ ол үшін алдымен іске қосу керек және т.б.. Ең аз etcd кластерін оның параметрлерін pods каталогына орналастыру арқылы бастайық (мысалы, 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

Егер сіз Kubernetes-пен жұмыс істеген болсаңыз, бұл YAML файлдары сізге таныс болуы керек. Мұнда назар аударатын екі жай ғана бар:

Біз хост қалтасын орнаттық /var/lib/etcd қайта іске қосқаннан кейін etcd деректері сақталады (егер бұл орындалмаса, блок қайта іске қосылған сайын кластер күйі жойылады, бұл тіпті минималды Kubernetes орнатуы үшін де жақсы болмайды).

Біз орнаттық hostNetwork: true. Бұл параметр, таңқаларлық емес, etcd параметрін подкасттың ішкі желісінің орнына хост желісін пайдалану үшін конфигурациялайды (бұл API серверіне etcd кластерін табуды жеңілдетеді).

Қарапайым тексеру, etcd шынымен де жергілікті хостта жұмыс істейтінін және деректерді дискіге сақтайтынын көрсетеді:

$ 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 серверін іске қосу

Kubernetes API серверін іске қосу оңайырақ. Өткізілуі керек жалғыз параметр --etcd-servers, сіз күткен нәрсені жасайды:

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

Бұл YAML файлын каталогқа орналастырыңыз pods, және API сервері іске қосылады. -мен тексерілуде curl Kubernetes API толығымен ашық қол жетімділікпен 8080 портында тыңдайтынын көрсетеді - аутентификация қажет емес!

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

(Қайтадан, бұны өндірісте іске қоспаңыз! Әдепкі параметрдің соншалықты қауіпті екеніне таң қалдым. Бірақ бұл әзірлеуді және тестілеуді жеңілдету үшін деп ойлаймын.)

Және, жағымды тосын сый, kubectl қораптан тыс қосымша параметрлерсіз жұмыс істейді!

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

проблема

Бірақ егер сіз сәл тереңірек қазсаңыз, бірдеңе дұрыс емес сияқты:

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

Біз жасаған статикалық блоктар жоғалды! Шын мәнінде, біздің кубелет түйіні мүлдем ашылмаған:

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

Не болды? Бірнеше абзац бұрын есіңізде болса, біз kubelet-ті пәрмен жолы параметрлерінің өте қарапайым жиынтығымен бастадық, сондықтан kubelet API серверімен қалай байланысу керектігін және оның күйі туралы хабарлауды білмейді. Құжаттаманы зерттегеннен кейін біз сәйкес жалаушаны табамыз:

--kubeconfig string

Файлға апаратын жол kubeconfig, ол API серверіне қосылу жолын көрсетеді. Қол жетімділік --kubeconfig API сервер режимін қосады, жоқ --kubeconfig офлайн режимін қосады.

Осы уақыт ішінде біз білмей, кубелетті «офлайн режимінде» іске қостық. (Егер біз педантикалық болсақ, біз автономды кубелетті «ең аз өміршең Кубернетес» деп ойлай аламыз, бірақ бұл өте қызық болар еді). «Нақты» конфигурация жұмыс істеуі үшін API серверімен қалай сөйлесу керектігін білу үшін kubeconfig файлын kubelet-ке беру керек. Бақытымызға орай, бұл өте қарапайым (себебі бізде аутентификация немесе сертификат мәселесі жоқ):

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

Мынадай сақтаңыз kubeconfig.yaml, процесті өлтіріңіз kubelet және қажетті параметрлермен қайта іске қосыңыз:

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

(Айтпақшы, егер сіз kubelet іске қосылмаған кезде API интерфейсіне curl арқылы қол жеткізуге тырыссаңыз, оның әлі де жұмыс істеп тұрғанын көресіз! Kubelet Docker сияқты оның түйіндерінің «ата-анасы» емес, ол «басқару» сияқты. демон.» Кубелет басқаратын контейнерлер кубелет оларды тоқтатқанша жұмысын жалғастырады.)

Бірнеше минуттан кейін kubectl Біз күткендей бізге бөтелкелер мен түйіндерді көрсету керек:

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

Осы жолы өзімізді шын жүректен құттықтап көрейік (мен өзімді құттықтағанымды білемін) - бізде толық жұмыс істейтін API бар минималды Kubernetes «кластері» бар!

астында іске қосамыз

Енді API не істей алатынын көрейік. Nginx подводынан бастайық:

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

Мұнда біз өте қызықты қатені аламыз:

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

Мұнда біз Kubernetes ортасының қаншалықты толық емес екенін көреміз - бізде қызметтерге тіркелгі жоқ. Қызмет тіркелгісін қолмен жасау арқылы әрекетті қайталап көрейік және не болатынын көрейік:

$ 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

Қызмет тіркелгісін қолмен жасаған кезде де, аутентификация таңбалауышы жасалмайды. Біз минималистік «кластерімізбен» тәжірибе жасауды жалғастыра отырып, әдетте автоматты түрде болатын пайдалы нәрселердің көпшілігі жоқ болатынын көреміз. Kubernetes API сервері өте минималистік, ауыр жүк көтеру және автоматты конфигурацияның көпшілігі әртүрлі контроллерлерде және әлі іске қосылмаған фондық тапсырмаларда орындалады.

Опцияны орнату арқылы бұл мәселені шешуге болады automountServiceAccountToken қызмет тіркелгісі үшін (өйткені біз оны бәрібір пайдаланудың қажеті жоқ):

$ 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

Ақырында, бөтелке пайда болды! Бірақ іс жүзінде ол басталмайды, өйткені бізде жоқ жоспарлаушы (жоспарлаушы) - Кубернетестің тағы бір маңызды құрамдас бөлігі. Тағы да біз Kubernetes API таңқаларлық «мылқау» екенін көреміз - API ішінде Pod жасағанда, ол оны тіркейді, бірақ оны қай түйінде іске қосу керектігін анықтауға тырыспайды.

Шындығында, подкастты іске қосу үшін жоспарлаушы қажет емес. Параметрдегі манифестке түйінді қолмен қосуға болады nodeName:

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

(Ауыстыру mink8s түйіннің атауына.) Жою және қолданғаннан кейін nginx іске қосылғанын және ішкі IP мекенжайын тыңдап жатқанын көреміз:

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

Қоспалар арасындағы желінің дұрыс жұмыс істеп тұрғанына көз жеткізу үшін, біз басқа подводтан curl іске қоса аламыз:

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

Бұл ортаны қазып, не жұмыс істейтінін және не істемейтінін көру өте қызықты. Мен ConfigMap және Secret күткендей жұмыс істейтінін байқадым, бірақ Service және Deployment жұмыс істемейді.

Жетістік!

Бұл пост ұзарып барады, сондықтан мен жеңісті жариялаймын және бұл «Кубернетес» деп атауға болатын өміршең конфигурация. Қорытындылау үшін: төрт екілік, бес пәрмен жолы параметрі және «тек» 45 YAML жолы (жоқ Kubernetes стандарттары бойынша көп) және бізде жұмыс істейтін бірнеше нәрсе бар:

  • Қондырғылар кәдімгі Kubernetes API арқылы басқарылады (бірнеше бұзулармен)
  • Қоғамдық контейнер кескіндерін жүктеп салуға және басқаруға болады
  • Қоспалар тірі қалады және автоматты түрде қайта іске қосылады
  • Бір түйіндегі подкасттар арасындағы желі өте жақсы жұмыс істейді
  • ConfigMap, құпия және қарапайым сақтауды орнату күткендей жұмыс істейді

Бірақ Kubernetes-ті шынымен пайдалы ететін көптеген нәрселер әлі де жоқ, мысалы:

  • Под жоспарлаушы
  • Аутентификация/авторизация
  • Бірнеше түйін
  • Қызметтер желісі
  • Кластерленген ішкі DNS
  • Қызмет тіркелгілеріне арналған контроллерлер, орналастырулар, бұлттық провайдерлермен біріктіру және Kubernetes әкелетін басқа да жақсылықтардың көпшілігі

Сонымен, біз шынымен не алдық? Kubernetes API өзі жұмыс істейді, бұл шын мәнінде тек платформа контейнерлік автоматтандыру. Бұл көп нәрсе жасамайды - бұл API қолданатын әртүрлі контроллерлер мен операторларға арналған жұмыс - бірақ ол автоматтандыру үшін тұрақты ортаны қамтамасыз етеді.

Курс туралы қосымша ақпаратты тегін вебинардан алыңыз.

Толығырақ:

Ақпарат көзі: www.habr.com

пікір қалдыру