Düzünü desəm, 100% əmin deyiləm. Ancaq məncə, daxili hissələrə baxmaq və Kubernetesdə çoxlu abstraksiyalar təbəqəsi altında həqiqətən nə baş verdiyini görmək maraqlıdır. Sadəcə əylənmək üçün gəlin minimal “Kubernetes klasteri”nin əslində necə göründüyünə nəzər salaq. (Bu, daha asan olacaq Kubernetes Çətin Yol.)
Güman edirəm ki, Kubernetes, Linux və konteynerlər haqqında əsas biliklərə sahibsiniz. Burada danışdığımız hər şey yalnız tədqiqat/öyrənmə məqsədləri üçündür, heç birini istehsalata qoymayın!
Review
Kubernetes bir çox komponentdən ibarətdir. görə Vikipediya, memarlıq belə görünür:
Burada göstərilən ən azı səkkiz komponent var, lakin biz onların əksəriyyətinə məhəl qoymayacağıq. Bildirmək istəyirəm ki, əsaslı şəkildə Kubernetes adlandırıla bilən minimum şey üç əsas komponentdən ibarətdir:
kubelet
kube-apiserver (etcd-dən asılıdır - onun verilənlər bazası)
konteyner işləmə vaxtı (bu halda Docker)
Gəlin görək sənədlərdə onların hər biri haqqında nə deyilir (rus., İngilis dili.). Əvvəlcə kubelet:
Klasterdəki hər bir qovşaqda işləyən agent. Konteynerlərin podda işlədiyinə əmin olur.
Kifayət qədər sadə səslənir. Nə haqqında konteyner işləmə müddətləri (konteyner işləmə müddəti)?
Konteynerin işləmə müddəti konteynerləri işə salmaq üçün nəzərdə tutulmuş proqramdır.
Çox məlumatlandırıcıdır. Ancaq Docker ilə tanışsınızsa, onun nə etdiyi barədə ümumi təsəvvürünüz olmalıdır. (Konteynerin işləmə vaxtı ilə kubelet arasında məsuliyyətlərin ayrılmasının təfərrüatları əslində olduqca incədir və mən burada onlara daxil olmayacağam.)
И API server?
API Server Kubernetes API-ni ifşa edən Kubernetes idarəetmə paneli komponentidir. API serveri Kubernetes idarəetmə panelinin müştəri tərəfidir
Kubernetes ilə heç bir iş görmüş hər kəs ya birbaşa, ya da kubectl vasitəsilə API ilə əlaqə saxlamalı olub. Bu, Kubernetes Kubernetes-i - hamımızın bildiyimiz və sevdiyimiz (?) YAML dağlarını işləyən infrastruktura çevirən beyinin ürəyidir. Aydın görünür ki, API bizim minimal konfiqurasiyamızda olmalıdır.
İlkin şərtlər
Linux virtual və ya kök çıxışı olan fiziki maşın (Mən virtual maşında Ubuntu 18.04 istifadə edirəm).
Və hamısı!
Darıxdırıcı quraşdırma
İstifadə edəcəyimiz maşına Docker quraşdırmalıyıq. (Docker və konteynerlərin necə işlədiyi barədə təfərrüata varmaq fikrində deyiləm; əgər maraqlanırsınızsa, orada gözəl məqalələr). Onunla quraşdıraq apt:
Bundan sonra biz Kubernetes ikili fayllarını almalıyıq. Əslində, "klasterimizin" ilkin işə salınması üçün bizə yalnız lazımdır kubelet, çünki digər server komponentlərini işə salmaq üçün istifadə edə bilərik kubelet. Çalışdıqdan sonra klasterimizlə qarşılıqlı əlaqə yaratmaq üçün biz də istifadə edəcəyik kubectl.
kubelet kök kimi işləməlidir. Tamamilə məntiqlidir, çünki o, bütün nodu idarə etməlidir. Onun parametrlərinə baxaq:
$ ./kubelet -h
<слишком много строк, чтобы разместить здесь>
$ ./kubelet -h | wc -l
284
Vay, çoxlu seçim! Xoşbəxtlikdən, onlardan yalnız bir neçəsinə ehtiyacımız var. Bizi maraqlandıran parametrlərdən biri budur:
--pod-manifest-path string
Statik podlar üçün faylları ehtiva edən kataloqa yol və ya statik podları təsvir edən fayla gedən yol. Nöqtələrlə başlayan fayllar nəzərə alınmır. (İSTƏNİLMİŞDİR: Bu seçim --config seçimi ilə Kubelet-ə ötürülən konfiqurasiya faylında quraşdırılmalıdır. Əlavə məlumat üçün baxın. kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file .)
Bu seçim bizə qaçmağa imkan verir statik qabıqlar — Kubernetes API vasitəsilə idarə olunmayan podlar. Statik podlar nadir hallarda istifadə olunur, lakin onlar klasteri sürətlə qaldırmaq üçün çox əlverişlidir və bu, bizə lazım olan şeydir. Biz bu böyük xəbərdarlığa məhəl qoymayacağıq (yenidən bunu istehsalda işə salmayın!) və podun işə salınıb-çalışdıra bilməyəcəyimizə baxın.
Əvvəlcə statik podlar üçün kataloq yaradacağıq və işə başlayacağıq kubelet:
kubelet bəzi xəbərdarlıqlar yazmağa başlayır və sanki heç nə baş vermir. Amma bu doğru deyil! Docker-ə baxaq:
$ 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 Mən pod manifestini oxudum və Dockerə spesifikasiyalarımıza uyğun olaraq bir neçə konteyneri işə salmağı əmr etdim. (Əgər "fasilə" konteyneri ilə maraqlanırsınızsa, bu, Kubernetes hackidir - baxın bu blog.) Kubelet konteynerimizi işə salacaq busybox göstərilən əmrlə və statik pod silinənə qədər onu qeyri-müəyyən müddətə yenidən başladır.
Özünüzü təbrik edin. Biz indicə terminala mətn çıxarmağın ən qarışıq yollarından birini tapdıq!
Başla və s
Bizim əsas məqsədimiz Kubernetes API-ni işə salmaqdır, lakin bunu etmək üçün ilk öncə işə salmalıyıq və s. Parametrlərini pods kataloquna yerləşdirməklə minimal etcd klasterinə başlayaq (məsələn, pods/etcd.yaml):
Əgər əvvəllər Kubernetes ilə işləmisinizsə, bu YAML faylları sizə tanış olmalıdır. Burada yalnız iki məqamı qeyd etmək lazımdır:
Biz host qovluğunu quraşdırdıq /var/lib/etcd podda belə ki, etcd məlumatları yenidən başladıldıqdan sonra qorunsun (əgər bu edilmədikdə, pod hər dəfə yenidən işə salındıqda klaster vəziyyəti silinəcək, bu, hətta minimal Kubernetes quraşdırması üçün də yaxşı olmayacaq).
Quraşdırmışıq hostNetwork: true. Təəccüblü deyil ki, bu parametr podun daxili şəbəkəsi əvəzinə host şəbəkəsindən istifadə etmək üçün etcd-ni konfiqurasiya edir (bu, API serverinin etcd klasterini tapmasını asanlaşdıracaq).
Sadə bir yoxlama, etcd-nin həqiqətən localhost-da işlədiyini və məlumatları diskdə saxladığını göstərir:
$ 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 serverinin işə salınması
Kubernetes API serverini idarə etmək daha asandır. Qəbul edilməli olan yeganə parametrdir --etcd-servers, gözlədiyinizi edir:
Bu YAML faylını qovluğa yerləşdirin pods, və API server başlayacaq. ilə yoxlanılır curl Kubernetes API-nin tamamilə açıq girişlə 8080 portunu dinlədiyini göstərir - autentifikasiya tələb olunmur!
(Yenə də, bunu istehsalda işə salmayın! Defolt parametrin bu qədər etibarsız olması məni bir az təəccübləndirdi. Amma bunun inkişafı və sınaqları asanlaşdırmaq üçün olduğunu təxmin edirəm.)
Və xoş sürpriz, kubectl heç bir əlavə parametr olmadan qutudan çıxır!
$ ./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.
problem
Ancaq bir az daha dərin qazsanız, bir şey səhv gedir:
$ ./kubectl get pod -n kube-system
No resources found in kube-system namespace.
Yaratdığımız statik podlar getdi! Əslində kubelet qovşağımız ümumiyyətlə aşkar edilmir:
$ ./kubectl get nodes
No resources found in default namespace.
Nə məsələdir? Bir neçə paraqrafı xatırlayırsınızsa, biz kubelet-i son dərəcə sadə komanda xətti parametrləri dəsti ilə işə saldıq, ona görə də kubelet API serveri ilə necə əlaqə saxlayacağını və ona vəziyyəti barədə məlumat verəcəyini bilmir. Sənədləri öyrəndikdən sonra müvafiq bayrağı tapırıq:
--kubeconfig string
Fayla gedən yol kubeconfig, API serverinə necə qoşulacağını müəyyən edir. Mövcudluq --kubeconfig API server rejimini aktivləşdirir, yox --kubeconfig oflayn rejimi işə salır.
Bütün bu müddət ərzində, bilmədən kubeleti “oflayn rejimdə” işlədirdik. (Əgər biz pedantik olsaydıq, müstəqil kubelet haqqında "minimum canlı Kubernetes" kimi düşünə bilərdik, lakin bu, çox darıxdırıcı olardı). "Real" konfiqurasiyanın işləməsi üçün kubeconfig faylını kubeletə ötürməliyik ki, o API serveri ilə necə danışacağını bilsin. Xoşbəxtlikdən bu, olduqca sadədir (çünki autentifikasiya və ya sertifikatlarla bağlı heç bir problemimiz yoxdur):
(Yeri gəlmişkən, kubelet işləmədikdə API-yə curl vasitəsilə daxil olmağa çalışsanız, onun hələ də işlədiyini görəcəksiniz! Kubelet Docker kimi podların “valideyn”i deyil, daha çox “nəzarət” kimidir. daemon.” Kubelet tərəfindən idarə olunan konteynerlər kubelet onları dayandırana qədər işləməyə davam edəcək.)
Bir neçə dəqiqəyə kubectl Bizə gözlədiyimiz kimi pod və qovşaqları göstərməlidir:
$ ./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
Gəlin bu dəfə özümüzü həqiqətən təbrik edək (özümüzü artıq təbrik etdiyimi bilirəm) - tam funksional API ilə işləyən minimal Kubernetes "klasterimiz" var!
altında işə salırıq
İndi API-nin nəyə qadir olduğuna baxaq. Nginx pod ilə başlayaq:
$ ./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.
Burada biz Kubernetes mühitimizin nə qədər natamam olduğunu görürük - xidmətlər üçün hesablarımız yoxdur. Gəlin əl ilə xidmət hesabı yaradaraq yenidən cəhd edək və nə baş verdiyini görək:
$ 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
Xidmət hesabını əl ilə yaratsaq belə, autentifikasiya nişanı yaradılmır. Minimalist "klasterimiz"lə təcrübə aparmağa davam etdikcə, adətən avtomatik olaraq baş verən faydalı şeylərin əksəriyyətinin itkin olacağını görəcəyik. Kubernetes API serveri olduqca minimalistdir, ağır yük qaldırma və avtomatik konfiqurasiyanın əksəriyyəti müxtəlif nəzarətçilərdə və hələ işləməyən fon işlərində baş verir.
Seçimi təyin etməklə bu problemi həll edə bilərik automountServiceAccountToken xidmət hesabı üçün (çünki biz hər halda ondan istifadə etmək məcburiyyətində qalmayacağıq):
$ 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
Nəhayət, pod göründü! Amma əslində başlamayacaq, çünki bizdə yoxdur planlaşdırıcı (planlayıcı) Kubernetes-in digər vacib komponentidir. Yenə də görürük ki, Kubernetes API təəccüblü dərəcədə “laldır” – siz API-də Pod yaratdığınız zaman onu qeyd edir, lakin onu hansı node üzərində işlətəcəyini anlamağa çalışmır.
Əslində, podu işə salmaq üçün planlaşdırıcıya ehtiyacınız yoxdur. Parametrdə manifestə əl ilə node əlavə edə bilərsiniz nodeName:
(Əvəz edin mink8s qovşağın adına.) Sildikdən və tətbiq etdikdən sonra nginx-in işə düşdüyünü və daxili IP ünvanını dinlədiyini görürük:
$ ./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>
Podlar arasındakı şəbəkənin düzgün işlədiyinə əmin olmaq üçün başqa bir poddan curl işlədə bilərik:
$ 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 mühiti qazmaq və nəyin işlədiyini və nəyin olmadığını görmək olduqca maraqlıdır. Mən tapdım ki, ConfigMap və Secret gözlənildiyi kimi işləyir, lakin Service və Deployment yox.
Uğurlar!
Bu yazı uzanır, ona görə də qələbəni elan edəcəyəm və bunun "Kubernetes" adlandırıla bilən etibarlı konfiqurasiya olduğunu söyləyəcəyəm. Xülasə etmək üçün: dörd binar, beş komanda xətti parametri və "yalnız" 45 YAML sətri (yox Kubernetes standartlarına görə bu qədər) və bizdə işləyən bir neçə şey var:
Podlar adi Kubernetes API istifadə edərək idarə olunur (bir neçə hack ilə)
Siz ictimai konteyner şəkillərini yükləyə və idarə edə bilərsiniz
Podlar canlı qalır və avtomatik olaraq yenidən başlayır
Eyni node daxilində podlar arasında şəbəkə olduqca yaxşı işləyir
ConfigMap, Gizli və sadə saxlama montajı gözlənildiyi kimi işləyir
Lakin Kubernetes-i həqiqətən faydalı edən şeylərin çoxu hələ də yoxdur, məsələn:
Pod Planlayıcısı
Doğrulama/avtorizasiya
Çoxlu qovşaqlar
Xidmətlər şəbəkəsi
Kümelənmiş daxili DNS
Xidmət hesabları, yerləşdirmələr, bulud provayderləri ilə inteqrasiya və Kubernetes-in gətirdiyi digər üstünlüklərin əksəriyyəti üçün nəzarətçilər
Beləliklə, əslində nə əldə etdik? Öz-özünə işləyən Kubernetes API həqiqətən sadəcə bir platformadır konteyner avtomatlaşdırılması. Bu, çox şey etmir - bu API istifadə edən müxtəlif nəzarətçilər və operatorlar üçün bir işdir - lakin avtomatlaşdırma üçün ardıcıl mühit təmin edir.