ĂversĂ€ttningen av artikeln Ă€r framtagen inför kursstarten .

Om du lĂ€ser detta har du förmodligen hört talas om Kubernetes (och om inte, hur kom du hit?). Men vad Ă€r egentligen Kubernetes? Det Ă€r ? ĐлО ? ЧŃĐŸ ĐČĐŸĐŸĐ±ŃĐ” ŃŃĐŸ Đ·ĐœĐ°ŃĐžŃ?
Ărligt talat Ă€r jag inte 100 % sĂ€ker. Men jag tror det Ă€r intressant att grĂ€va ner i detaljerna och se vad som verkligen hĂ€nder i Kubernetes under dess mĂ„nga abstraktionslager. SĂ„ för intressets skull, lĂ„t oss titta pĂ„ hur en minimal âKubernetes-klusterâ faktiskt ser ut. (Det kommer att bli mycket enklare Ă€n .)
Jag antar att du har grundlÀggande kunskaper om Kubernetes, Linux och containrar. Allt vi kommer att diskutera hÀr Àr bara avsett för utforskning/lÀrande, kör inget av detta i produktion!
Ăversikt
Kubernetes innehÄller mÄnga komponenter. Enligt , ser arkitekturen ut pÄ följande sÀtt:

HÀr visas Ätminstone Ätta komponenter, men de flesta av dem kommer vi att ignorera. Jag vill pÄstÄ att den minimi- enhet som rimligt kan kallas Kubernetes bestÄr av tre huvudkomponenter:
- kubelet
- kube-apiserver (som beror pĂ„ etcd â dess databas)
- container runtime (i det hÀr fallet Docker)
LÄt oss se vad som sÀgs om var och en av dem i dokumentationen (., .). Först kubelet:
Agenten som kör pÄ varje nod i klustret. Den ser till att containrarna körs i podden.
Det lÄter ganska enkelt. Vad sÀgs om container runtime? Container-runtime Àr ett program avsett för att köra containrar.
Mycket informativt. Men om du Àr bekant med Docker, borde du ha en generell förstÄelse för vad det gör. (Detaljerna kring ansvarsfördelningen mellan container runtime och kubelet Àr faktiskt ganska subtila och jag kommer inte att gÄ in pÄ dem hÀr.)
API-servern
Och API-servern Àr en komponent av Kubernetes kontrollplan som presenterar Kubernetes API. API-servern Àr klientsidan av Kubernetes kontrollplan.?
Vem som helst som nĂ„gonsin har gjort nĂ„got med Kubernetes har behövt interagera med API:et antingen direkt eller via kubectl. Det Ă€r hjĂ€rtat av vad som gör Kubernetes till Kubernetes â hjĂ€rnan som omvandlar de mĂ€ngder YAML som vi alla kĂ€nner till och Ă€lskar (?) till fungerande infrastruktur. Det verkar uppenbart att API:t mĂ„ste finnas med i vĂ„r minimala konfiguration.
För alla som nĂ„gonsin har arbetat med Kubernetes har det varit nödvĂ€ndigt att interagera med API:et, antingen direkt eller via kubectl. Det Ă€r hjĂ€rtat i vad som gör Kubernetes till Kubernetes â hjĂ€rnan som omvandlar de mĂ€ngder av YAML som vi alla kĂ€nner till och Ă€lskar (?) till en fungerande infrastruktur. Det verkar uppenbart att API:et mĂ„ste finnas med i vĂ„r minimala konfiguration.
FörutsÀttningar
- En virtuell eller fysisk Linux-maskin med root-Ätkomst (jag anvÀnder Ubuntu 18.04 pÄ en virtuell maskin).
- Och det Àr allt!
TrÄkig installation
PÄ maskinen vi ska anvÀnda behöver vi installera Docker. (Jag kommer inte att gÄ in pÄ detaljer om hur Docker och containrar fungerar; om du Àr intresserad finns det ). LÄt oss bara installera det med apt:
$ sudo apt install docker.io
$ sudo systemctl start docker DÀrefter behöver vi hÀmta Kubernetes-binÀrerna. För att starta vÄr "kluster" behöver vi faktiskt bara kubelet, eftersom vi kan anvÀnda kubeletför att köra andra serverkomponenter. För att interagera med vÄrt kluster nÀr det vÀl Àr igÄng, kommer vi ocksÄ att anvÀnda 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 Vad hÀnder om vi bara kör kubelet?
$ ./kubelet
F0609 04:03:29.105194 4583 server.go:254] mkdir /var/lib/kubelet: permission denied kubelet mÄste köras som root. Ganska logiskt, eftersom den behöver hantera hela noden. LÄt oss titta pÄ dess alternativ:
$ ./kubelet -h
$ ./kubelet -h | wc -l
284Oj, sÄ mÄnga alternativ! Som tur Àr behöver vi bara ett par av dem. HÀr Àr ett av alternativen som intresserar oss:
--pod-manifest-path stringSökvĂ€g till katalogen som innehĂ„ller filer för statiska pods, eller sökvĂ€gen till en fil med beskrivning av statiska pods. Filer som börjar med punkter ignoreras. (URDATERAD: detta alternativ bör stĂ€llas in i konfigurationsfilen som överförs till Kubelet via alternativet âconfig. För mer information se. .)
Detta alternativ gör att vi kan köra â pods som inte hanteras via Kubernetes API. Statiska pods anvĂ€nds sĂ€llan, men de Ă€r mycket praktiska för att snabbt sĂ€tta upp ett kluster, vilket Ă€r precis vad vi behöver. Vi kommer att ignorera denna varning (igen, kör inte detta i produktion!) och se om vi kan köra en pod.
Först kommer vi att skapa en katalog för statiska pods och köra kubelet:
$ mkdir pods
$ sudo ./kubelet --pod-manifest-path=podsSedan, i ett annat terminalfönster/tmux/eller nÄgon annanstans, kommer vi att skapa manifestet för podden:
$ cat < pods/hello.yaml
apiVersion: v1
kind: Pod
metadata:
name: hello
spec:
containers:
- image: busybox
name: hello
command: ["echo", "hello world!"]
EOF kubelet börjar skriva nÄgra varningar och det verkar som att inget hÀnder. Men sÄ Àr det inte! LÄt oss titta pÄ 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 lĂ€ste manifestet för podden och gav Docker kommandot att starta ett par containrar enligt vĂ„r specifikation. (Om du Ă€r intresserad av containern âpauseâ, sĂ„ Ă€r det en Kubernetes-hack â detaljer kan lĂ€sas i .) Kubelet kommer att starta vĂ„r container busybox med det angivna kommandot och kommer att starta om det oĂ€ndligt, sĂ„ lĂ€nge den statiska podden inte tas bort.
Grattis! Vi har just kommit pÄ ett av de mest invecklade sÀtten att skriva ut text i terminalen!
Startar etcd
VÄrt slutgiltiga mÄl Àr att starta Kubernetes API, men för det behöver vi först starta . LÄt oss starta en minimal etcd-kluster och placera dess instÀllningar i katalogen pods (till exempel, 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-dataOm du nÄgonsin har arbetat med Kubernetes, bör liknande YAML-filer vara bekanta för dig. HÀr Àr det bara tvÄ saker att notera:
Vi har monterat vÀrddatorns mapp /var/lib/etcd i podden sÄ att etcd-data sparas efter omstart (om detta inte görs kommer klustrets tillstÄnd att raderas vid varje omstart av podden, vilket inte Àr bra ens för en minimal Kubernetes-installation).
Vi har stÀllt in hostNetwork: true. Denna parameter, vilket inte Àr förvÄnande, konfigurerar etcd att anvÀnda vÀrd-nÀtverket istÀllet för poddens interna nÀtverk (detta kommer att göra det lÀttare för API-servern att hitta etcd-klustret).
En enkel kontroll visar att etcd verkligen körs pÄ localhost och sparar data pÄ 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.walStarta API-servern
Att starta Kubernetes API-servern Àr Ànnu enklare. Det enda parameter som mÄste anges, --etcd-servers, gör vad du förvÀntar dig:
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 Placera den hĂ€r YAML-filen i katalogen pods, och API-servern startar. Kontroll med curl visar att Kubernetes API lyssnar pĂ„ port 8080 med fullstĂ€ndig öppen Ă„tkomst â autentisering krĂ€vs inte!
$ curl localhost:8080/healthz
ok
$ curl localhost:8080/api/v1/pods
{
"kind": "PodList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/pods",
"resourceVersion": "59"
},
"items": []
}(à terigen, kör inte detta i produktion! Jag blev lite överraskad över att standardinstÀllningen Àr sÄ osÀker. Men jag antar att det Àr för att underlÀtta utveckling och testning.)
Och en trevlig överraskning, kubectl fungerar direkt utan nÄgra ytterligare instÀllningar!
$ ./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.Problemet
Men om vi grÀver lite djupare verkar det som att nÄgot gÄr snett:
$ ./kubectl get pod -n kube-system
No resources found in kube-system namespace.De statiska poddar vi skapade Àr borta! Faktisk, vÄr kubelet-nod kan inte ens hittas:
$ ./kubectl get nodes
No resources found in default namespace.Vad Àr problemet? Om ni kommer ihÄg, i nÄgra stycken tillbaka körde vi kubelet med ett mycket enkelt set av kommandoradsparametrar, sÄ kubelet vet inte hur man ska kontakta API-servern och rapportera sitt tillstÄnd. Genom att studera dokumentationen hittar vi den relevanta flaggan:
--kubeconfig string
SökvÀg till filen kubeconfig, som anger hur man ansluter till API-servern. NÀrvaro av --kubeconfig aktiverar API-serverlÀge, frÄnvaro av --kubeconfig aktiverar fristÄende lÀge.
Under hela den hÀr tiden, utan att veta om det, har vi kört kubelet i "autonomt lÀge". (Om vi var pedantiska skulle vi kunna betrakta kubelets autonoma lÀge som "minimalt livskraftig Kubernetes", men det skulle vara vÀldigt trÄkigt). För att fÄ den "riktiga" konfigurationen att fungera behöver vi överföra kubeconfig-filen till kubelet sÄ att den vet hur man kommunicerar med API-servern. Lyckligtvis Àr detta ganska enkelt (eftersom vi inte har problem med autentisering eller certifikat):
apiVersion: v1
kind: Config
clusters:
- cluster:
server: http://127.0.0.1:8080
name: mink8s
contexts:
- context:
cluster: mink8s
name: mink8s
current-context: mink8s Spara detta som kubeconfig.yaml, döda processen kubelet och starta om med nödvÀndiga parametrar:
$ sudo ./kubelet --pod-manifest-path=pods --kubeconfig=kubeconfig.yaml(Förresten, om du försöker komma Ät API:et via curl nÀr kubelet inte kör, kommer du att upptÀcka att det fortfarande fungerar! Kubelet Àr inte "förÀlder" till sina pods, liknande Docker, det liknar mer en "hanterande demon". De containrar som hanteras av kubelet kommer att fortsÀtta köra tills kubelet stoppar dem.)
Efter nÄgra minuter kubectl bör det visa oss pods och noder, precis som vi förvÀntade oss:
$ ./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 21h v1.18.5 10.70.10.228 Ubuntu 18.04.4 LTS 4.15.0-109-generic docker://19.3.6LĂ„t oss verkligen gratulera oss den hĂ€r gĂ„ngen (jag vet att jag redan har gratulerat) â vi har fĂ„tt en minimal "kluster" Kubernetes som fungerar med en fullt fungerande API!
Vi startar en pod
Nu ska vi se vad API:et kan göra. LÄt oss börja med en nginx-pod:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: nginx
name: nginxHÀr kommer vi att fÄ ett ganska intressant felmeddelande:
$ ./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 ser vi hur fruktansvĂ€rt ofullstĂ€ndig vĂ„r Kubernetes-miljö Ă€r â vi har inga tjĂ€nstekonton. LĂ„t oss försöka igen, genom att skapa ett tjĂ€nstekonto manuellt, och se vad som hĂ€nder:
$ 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Ăven nĂ€r vi skapade servicekontot manuellt, skapas ingen autentiseringstoken. NĂ€r vi fortsĂ€tter att experimentera med vĂ„r minimalistiska "kluster" kommer vi att upptĂ€cka att de flesta anvĂ€ndbara saker som vanligtvis sker automatiskt kommer att saknas. Kubernetes API-servern Ă€r ganska minimalistisk, och det mesta av de tunga automatiska instĂ€llningarna sker i olika kontrollanter och bakgrundsuppgifter som Ă€nnu inte körs.
Vi kan kringgÄ detta problem genom att stÀlla in alternativet automountServiceAccountToken för servicekontot (eftersom vi ÀndÄ inte behöver anvÀnda det):
$ 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 13mTill slut dyker podden upp! Men den kommer faktiskt inte att starta, eftersom vi inte har nĂ„gon (scheduler) â en annan viktig komponent av Kubernetes. Igen ser vi att Kubernetes API Ă€r förvĂ„nansvĂ€rt "dum" â nĂ€r du skapar en pod i API:et registrerar det den, men försöker inte rĂ€kna ut pĂ„ vilken nod den ska köras.
För att starta en pod behövs faktiskt ingen planerare. Du kan manuellt lÀgga till noden i manifestet i parameter nodeName:
apiversion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: nginx
name: nginx
nodeName: mink8s
(ErsÀtt mink8s med nodens namn.) Efter delete och apply ser vi att nginx har startat och lyssnar pÄ det interna IP-adressen:
$ .\/kubectl delete pod nginx
pod "nginx" raderad
$ .\/kubectl apply -f nginx.yaml
pod/nginx skapad
$ .\/kubectl get pods -owide
NAMN KLAR STATUS OMSTARTNINGAR ÅLDER IP NOD NOMINERAD NOD LÄSNINGS GATAN
nginx 1/1 Körning 0 30s 172.17.0.2 mink8s <none> <none>
$ curl -s 172.17.0.2 | head -4
<!DOCTYPE html>
<html>
<head>
<title>Välkommen till nginx!</title>För att sĂ€kerstĂ€lla att nĂ€tverket mellan poddar fungerar korrekt kan vi köra curl frĂ„n en annan podd:
$ kat <<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 skapad
$ .\/kubectl logs curl | head -6
% Total % Mottagen % Xferd Genomsnittlig Hastighet Tid Tid Tid Aktuell
Dload Ladda Upp Totalt Tillbringad Kvar Hastighet
<!DOCTYPE html>
<html>
<head>
<title>Välkommen till nginx!</title>Det Ă€r ganska intressant att grĂ€va i denna miljö och se vad som fungerar och vad som inte gör det. Jag har upptĂ€ckt att ConfigMap och Secret fungerar som förvĂ€ntat, men Service och Deployment gör det inte.
FramgÄng!
Detta inlĂ€gg blir lĂ„ngt, sĂ„ jag tĂ€nker avsluta och sĂ€ga att detta Ă€r en livskraftig konfiguration som kan kallas âKubernetesâ. Sammanfattningsvis: fyra binĂ€rfiler, fem kommandoradsparametrar och âbaraâ 45 rader YAML (inte sĂ„ mycket i Kubernetes standarder) och vi har fĂ„tt mĂ„nga saker att fungera:
- Pods hanteras med hjÀlp av det vanliga Kubernetes API:et (med nÄgra hacks)
- Det gÄr att ladda upp offentliga containerbilder och hantera dem
- Pods förblir aktiva och startas automatiskt om
- NĂ€tverket mellan pods inom en nod fungerar ganska bra
- ConfigMap, Secret och enklast montering av lagring fungerar som det ska
Men mycket av det som gör Kubernetes verkligen anvÀndbart saknas fortfarande, till exempel:
- Pod-schemalÀggare
- Autentisering / auktorisation
- Flera noder
- TjÀnsternÀtverk
- Klonens interna DNS
- Kontroller för tjÀnstekonton, distributioner, integrationer med molnleverantörer och de flesta andra "funktioner" som Kubernetes medför
Vad har vi egentligen fĂ„tt? Kubernetes API:et som fungerar pĂ„ egen hand Ă€r faktiskt bara en plattform för automatisering av containrar. Det gör inte mycket â det Ă€r jobbet för olika kontroller och operatörer som anvĂ€nder API:et â men det ger en konsekvent miljö för automatisering.
LĂ€sa mer:
KĂ€lla: habr.com
