[[Kubernetes alapok]]
[[Google Kubernetes Engine]]
=Kubernetes felépítése=[[Openshift basics]]
[[Helm]]
==Logikai építőkockák== * Container:* Pod:* ReplicaSet:* Deployment:* Service:* Endpoint:* Namespace* Network Policies :[[File:ClipCapIt-190330-184913.PNG]] === Namespace ===https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ ==Infrastruktúra elemek== :[[File:ClipCapIt-190330-193336.PNG]] :[[File:ClipCapIt-190313-214212.PNG]] =Telepítés= '''kubectl''' <pre>$ curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl$ chmod +x ./kubectl$ ln -s /home/adam/Programs/Kubernetes/kubectl /usr/local/bin/kubectl</pre> <pre>$ kubectl version --output=yaml</pre> '''Minikube'''<pre>$ curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-"linux-amd64 && $ chmod +x minikube $ ln -s /home/adam/Programs/Kubernetes/minikube /usr/local/bin/minikube</pre> '''kvm2 driver install'''<pre>$ curl -LO https://storage.googleapis.com/minikube/releases/latest/docker-machine-driver-kvm2 \ && sudo install docker-machine-driver-kvm2 /usr/local/bin/ $ minikube version</pre> '''Minikube indítása'''<pre>$ minikube start --vm-driver=kvm2Creating kvm VM (CPUs=2, Memory=2048MB, Disk=20000MB)...- docker- kubernetes master- kubernetes node: kublet😄 minikube v0.35.0 on linux (amd64)🔥 Creating virtualbox VM (CPUs=2, Memory=2048MB, Disk=20000MB) ...</pre> Letölti a minikube.iso image-et a /home/adam/.minikube/cache/iso/ mappába, és innen létrehoz egy kvm vm-et: <pre># virsh list Id Name State---------------------------------------------------- 1 minikube running</pre> ==Minikube parancsok==<pre>$ minikube dashboard </pre> A minikube itt mutatja meg, hogy egy adott service hol érhető el: <pre># minikube service <service-name> --url</pre> Be lehet ssh-zni a vm-be mint a docker-machine ssh nál. <pre># minikube ssh -</pre> A minikube telepítő beállította a kubectl-t is, hogy a minikube-ban futó cluster-re csatlakozzon. Ha listázzuk a kubectl beállításait, láthatjuk a minikube VPN IP címét. <pre># kubectl config viewapiVersion: v1clusters:- cluster: certificate-authority: /root/.minikube/ca.crt server: https://192.168.42.224:8443 name: minikube</pre> ==Nodes== Az összes node listázása. <pre># kubectl get nodesNAME STATUS ROLES AGE VERSIONminikube Ready master 11m v1.13.4</pre>Megfelel a swarm-ban: docker node ls parancsnak. =Pod= :[[File:ClipCapIt-190331-000406.PNG]] A POD-ot úgy kell elképzelni, mint egy egyedi image futtató környezet, tehát nem pusztán egy plusz réteg a docker konténer körül. Ha messziről nézzük, akkor a pod, ha csak egy konténer van benne megfelel egy natív docker konténernek. A docker konténer a Linux virtualizációs eszközökkel teremet egy izolált Linux futtató környezetet az image-nek. Az izolációhoz eszközei: * chroot: fájl rendszer izoláció* chgroup: erőforrás izoláció (CPU, network, IO..)* namespace: process izoláció, a névteren belül futó processzek egy saját sub-tree-t fognak csak látni az eredeti process fából, aminek úgy fogják látni, hogy a gyökere az 1-es process, ami a valóságban egy ága az eredeti process fának. A POD ezen izolációs eszközökkel részben újra gombolja a natív docker konténert, részben meg meghagyja a natív docker funkciókat. Az egy POD-ban futó konténerek közös hálózati névtérbe kerülnek, vagyis osztoznak a hálózati erőforrásokon, viszont minden egyes konténer saját fájlrendszerrel rendelkezik, tehát a fájlrendszer izoláció megegyezik a natív docker konténer futtatással. :[[File:ClipCapIt-190506-194509.PNG]]Ebből következik, hogy a localhost-on az egy POD-ba futó konténerek elérik egymást a megfelelő portokon, minden további hálózati beállítás nélkül tudnak a localhost-on kommunikálni egymással, viszont egymás fájlrendszerét nem tudják olvasni. Az ipari standard szerint egy pod-ba csak egy konténert szokás rakni, így a valóságban általában elmosódik a POD és a natív docker konténer között a különbség, mivel a POD-ban futó egy szem konténer mind hálózati mind fájlrendszer szinten teljesen izolálva fut a külvilágtól. ==Podok készítése== ===Imperative megközelítés===Konténert a legegyszerűbben a '''kubectl run''' paranccsal futtathatunk. Létre fog hozni egy pod-ot és benne el fogja indítani az image-et.<pre>$ kubectl run db --image mongo</pre> ===Deklaratív megközelítés=== <source lang="C++">apiVersion: v1kind: Podmetadata: name: go-demo-2 labels: app: myappspec: containers: - name: db image: mongo:3.3 </source> <pre># kubectl create -f pod-db.yamlpod/go-demo-2 created # kubectl get podNAME READY STATUS RESTARTS AGEgo-demo-2 1/1 Running 0 50s</pre> ==Pod-ok kezelése== Pod-ok listázása<pre># kubectl get podsNAME READY STATUS RESTARTS AGEdb-7fdd878ff9-7v66g 0/1 ContainerCreating 0 66s</pre> Belépés a pod-ban futó konténerekbe: <pre># kubectl exec -it <pod név> /bin/bash</pre> Ha több konténer is van a pod-ban, akkor a -c vel meg kell adni a konténer nevét: <pre># kubectl exec -it -c db dbstack /bin/bash</pre> Ha több konténer is van a pod-ban, akkor a pod neve után meg kell adni a konténer nevét. <pre># kubectl logs dbstack -c db</pre> Minden kubernetes elem listázása: <pre># kubectl get allNAME READY STATUS RESTARTS AGEpod/db-6b5c96c65f-9lxnb 1/1 Running 0 2m46s NAME READY UP-TO-DATE AVAILABLE AGEdeployment.apps/db 1/1 1 1 2m46s NAME DESIRED CURRENT READY AGEreplicaset.apps/db-6b5c96c65f 1 1 1 2m46s</pre> Egy pod összes adatának listázása. Itt külön listában láthatjuk a POD-ban futó összes konténert. Látható, hogy az alábbi POD-ban két konténer is fut: '''db''' és '''api''' néven. <source lang="Python" highlight="13-19">[root@adamDell2 ~]# kubectl describe pod dbstackName: dbstackNamespace: defaultPriority: 0PriorityClassName: <none>Node: minikube/192.168.122.228Start Time: Wed, 13 Mar 2019 21:51:19 +0100Labels: type=stackAnnotations: <none>Status: RunningIP: 172.17.0.5Containers: db: Container ID: docker://c371653e62b4bb1f8a7fb7de4d88452b6de623cf02caa41df9728df15d080481 Image: mongo:3.3 ... api: Container ID: docker://6b64c392a77347ce5e7b36ddfd80f2ef320a0e31d25985f813294d08cacf76b3 Image: vfarcic/go-demo-2</source> A '''get''' paranccsal is ugyan ezt a részletességet érhetjük el a '''-o json''' kapcsolóval. <source lang="xml"># kubectl get pod go-demo-2 -o json{ "apiVersion": "v1", "kind": "Pod", "metadata": { "creationTimestamp": "2019-03-31T21:13:34Z", "labels": { "app": "myapp", "type": "example" }, "name": "go-demo-2", "namespace": "default", "resourceVersion": "133741", "selfLink": "/api/v1/namespaces/default/pods/go-demo-2", "uid": "d7d61cac-53f9-11e9-bdbb-5254008eeeec" }, "spec": { "containers": [ { "image": "mongo:3.3", "imagePullPolicy": "IfNotPresent", "name": "db", "resources": {}, "terminationMessagePath": "/dev/termination-log", "terminationMessagePolicy": "File", "volumeMounts": [ { "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", "name": "default-token-zj4tp", "readOnly": true }...</source> A '''-f''' -el meg lehet adni a leíró fájlt a describe parancsban. Ez minden Kubernetes elemre működik. Ha nem adunk meg a formátumra paramétert, akkor egy szimpla felsorolást kapunk. A végén pedig egy esemény történet van az adott pod-ról. <pre># kubectl describe -f pod-db.yaml Name: dbNamespace: defaultPriority: 0PriorityClassName: <none>Node: minikube/192.168.122.228Start Time: Wed, 13 Mar 2019 20:49:30 +0100Labels: type=db.....Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 21h default-scheduler Successfully assigned default/go-demo-2 to minikube Normal Pulled 21h kubelet, minikube Container image "mongo:3.3" already present on machine Normal Created 21h kubelet, minikube Created container Normal Started 21h kubelet, minikube Started container</pre> ===-o kapcsoló használata==={| class="wikitable"! scope="col"| Név! scope="col"| Leírás|-| -o custom-columns=<spec>|Print a table using a comma separated list of custom columns|-| -o custom-columns-file=<filename>|Print a table using the custom columns template in the <filename> file|-| -o json|Output a JSON formatted API object|-| -o jsonpath=<template> |Print the fields defined in a jsonpath expression|-| -o jsonpath-file=<filename>|Print the fields defined by the jsonpath expression in the <filename> file|-| -o name|Print only the resource name and nothing else|-| -o wide|Output in the plain-text format with any additional information, and for pods, the node name is included|-| -o yaml|Output a YAML formatted API object|} A '''-o json''' kapcsolóval írhatjuk ki JSON -ban a pod infókat. <pre># kubectl get -f pod-db.yaml -o json{ "apiVersion": "v1", "kind": "Pod", "metadata": { "creationTimestamp": "2019-03-13T19:49:30Z", "labels": { "type": "db", "vendor": "MongoLabs" },...</pre> Részletes pod lista. A lényeg itt az IP cím. <pre># kubectl get pods -o wideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESdb 1/1 Running 0 2m39s 172.17.0.2 minikube <none> <none></pre> első pod a listáról: <pre># kubectl get pods -o name | tail -1</pre> <br>===Szűrés===Listázzuk ki JSON-ban a pod részleteket. <source lang="json"> "status": { ... "hostIP": "192.168.122.228",...</source> Szűrni a '''-o jsonpath''' -al lehet. <br>Mindig úgy kell szűrni, hogy a legfelsőbb szintű elem elé teszünk egy .-ot. Majd megadjuk a path-t. <pre># kubectl get -f pod-db.yaml -o jsonpath="{.status.hostIP}"192.168.122.228</pre> Ha egy lista összes elemére akarjuk hogy illeszkedjen a keresés, akkor [*] -ot kell használni. Ha egy konkrét lista elemet akarunk, akkor azt adjuk meg így [1]<br>Pl. az összes konténer nevét így listázhatjuk: <pre># kubectl get -f pod-db.yaml -o jsonpath="{.spec.containers[*].name}"db api</pre> <br>===Címkék===A selector-ok címék alapján működnek. Címke hozzáadása egy node-hoz: <pre># kubectl get nodeNAME STATUS ROLES AGE VERSIONminikube Ready master 22d v1.13.4</pre><pre># kubectl label node minikube disktype=ssdnode/minikube labeled</pre><source lang="java" highlight="6"># kubectl describe node minikubeName: minikubeRoles: masterLabels: beta.kubernetes.io/arch=amd64 beta.kubernetes.io/os=linux disktype=ssd ...</source><source># kubectl get node --show-labelsNAME STATUS ROLES AGE VERSION LABELSminikube Ready master 22d v1.13.4 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,..</source> Szintaxis: <pre># kubectl label <resource type: node, pod, ...> <resource név> <címke neve>=<címke értéke></pre> nodeSelector: labelName: labelvalue Címke felrakása pod-ra: <pre># kubectl label pod go-demo-2 type=examplepod/go-demo-2 labeled</pre><pre># kubectl get pod --show-labelsNAME READY STATUS RESTARTS AGE LABELSgo-demo-2 1/1 Running 1 23h app=myapp,type=example</pre> Címke törlése<pre># kubectl label pod go-demo-2 type-pod/go-demo-2 labeled # kubectl get pod --show-labelsNAME READY STATUS RESTARTS AGE LABELSgo-demo-2 1/1 Running 1 23h app=myapp</pre> <br> ===Health check===<br>* '''readinessProbe''': ezt addig fogja futtatni amíg nem lesz egyszer sikeres, ez után fogja ready-re állítani a konténert. * '''livenessProbe''': Ezzel pedig a konténer egészségét fogja ellenőrizni <source lang="C++">apiVersion: v1kind: Pod...spec: containers: - name: liveness image: k8s.gcr.io/busybox ... readinessProbe: tcpSocket: port: 8080 initialDelaySeconds: 5 periodSeconds: 10 livenessProbe: tcpSocket: port: 8080 initialDelaySeconds: 15 periodSeconds: 20</source> <br> Három változatuk van. * command futtatása* http rest hívás* tcpSocket <br>'''Command'''<br><pre>livenessProbe: exec: command: - cat - /tmp/healthy</pre> <br>'''Http'''<br>* path* port* httpHeaders<pre> livenessProbe: httpGet: path: /healthz port: 8080 httpHeaders: - name: Custom-Header value: Awesome initialDelaySeconds: 3 periodSeconds: 3</pre> <br>'''Socket'''<br><pre>livenessProbe: tcpSocket: port: 8080</pre> <br>{| class="wikitable"! scope="col"| Név! scope="col"| Leírás|-| initialDelaySeconds|ennyi után fogja elkezdeni a próbálkozást|-| periodSeconds|Ilyen sűrűn fogja megpróbálni |-| timeoutSeconds|Ennyi idő után fogja feladni |-| failureTreshold |Ennyi negatív válasz után fogja feladni. |} <br> =ReplicaSets= ==Áttekintés==:[[File:ClipCapIt-190331-231800.PNG]] Arra szolgál, hogy a benne definiált pod lehetőleg mindig annyi példányban fusson, amit defináltunk. Tehát ez továbbra is egy pod-ra vonatkozik, csak annak vezérelni tudjuk most már az életciklusát. A ReplicaSet és a ReplicaController között a selector-ban van a különbség. A Controller-ben csak a = b-vel selector-okat lehet megadni, míg a Set-ben meg lehet adni összetett kifejezéseket is: <pre> selector: matchExpressions: - {key: app, operator: In, values: [soaktestrs, soaktestrs, soaktest]} - {key: teir, operator: NotIn, values: [production]}</pre> A pod-hoz hasonlóan a dekleratív megközelítés szellemében, a replicaSet-et is yaml fájllal kell definiálni: <source lang="C++">apiVersion: apps/v1kind: ReplicaSetmetadata: name: nginx-rsspec: replicas: 2 selector: matchLabels: run: my-nginx template: metadata: labels: run: my-nginx spec: containers: - name: my-nginx image: nginx ports: - containerPort: 80</source> A ReplicaSet leírásában 3 fontos rész van a spec szekción belül: * '''replicas''': megmondja, hogy hány példány kell hogy fusson a pod-ból* '''selector''': megmondja, hogy milyen címkékkel kell hogy a pod rendelkezzen, amire a replicaSet vonatkozik. Mivel a pod és a replicaSet csak lazán csatolt kapcsolatban van, a ReplicaSet csak annyit figyel, hogy minden fusson a replicas részben megadott számú pod, ami rendelkezik olyan címkékkel amiket a selector szekcióba megadtunk (itt tagadni is lehet)* '''template''': Itt definiáljuk a pod-ot. Ez a rész megegyezik a pod yaml fájlnál leírtakkal. A metadata részben adjuk meg a pod címkéit, a spec részbe pedig a konténereket. {{tip|Furcsa hogy ezt a két egymástól független entitást egy fájlban definiáljuk. Simán megcsinálhatjuk, hogy a tempalte szekcióban olyan pod-ot adunk meg, aminek nincs egy olyan címkéje sem, ami illeszkedne a selector részben megadott címkékre, így a replicaSet sosem tudna elindulni. }} ==Selectorok és címkék== A ReplicaSet és majd a Service is a label-ek alapján találnak rá a Pod-okra. A selektorokonak két nagy családja van: * egyenlő, nem egyenlő kifejezések: key=value illetve key!=value* halmaz kifejezések: key in (v1, v2..), key notin (v1,v2..) illetve felírhatunk pusztán a kulcs létezésére ill nem létezésére feltételeket a kulcs értékétől függetlenül: <pre>environment in (production, qa)tier notin (frontend, backend)partition!partition</pre>A példában az utolsó két sor a kulcsra vonatkozik, hogy legyen olyan kulcs amit partition-nek hívnak ill ne legyen olyan kulcs amit partition-nek hívnak. Egy kifejezésben vesszővel lehet AND kapcsolatba hozni a kulcs kifejezéseket. A kubectl parancsokban a '''-l''' -el vagy hosszan '''label''' paraméterben kell megadni a kulcsokat: <pre># kubectl get pod -l app=myapp,type=exampleNAME READY STATUS RESTARTS AGEgo-demo-2 1/1 Running 3 8d</pre> ===Selector===A '''Service''' definíciójában illetve a ReplicaSet elődjében a '''ReplicationController'''-ben még a hagyományos '''selector''' megadást kell használni, a halmazos megadást itt nem szabad használni. <source lang="C++" highlight="9-11">apiVersion: v1kind: Servicemetadata: name: db-svcspec: type: ClusterIP ports: - port: 27017 selector: type: db service: mongo-db</source> A selector-ok után fel kell sorolni a címéket, amik ÉS kapcsolatban vannak. ===matchLabels===A '''deployment'''-ben ill. a '''ReplicaSet'''-ben már a '''matchLabels''' ill a vele ekvivalens '''matchExpressions''' -t kell a címke megadásnál használni.A matchLabels-ben meg lehet adni egyenlőség és set alapú címke definíciókat is. Viszont a '''selector''' kulcsszó után kötelező a '''matchLabels''' használata.<source lang="C++">apiVersion: apps/v1kind: ReplicaSetmetadata: name: rs-dbspec: replicas: 1 selector: matchLabels: type: db service: mongo-db template:</source> <br><br> ==ReplicaSet kezelése== A '''get''' parancsban ReplicaSet esetén az '''rs'''-t kell megadni a '''pod''' helyett: <pre># kubectl get rs -o wideNAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTORgo-demo-2 2 2 2 23s db,api mongo:3.3,vfarcic/go-demo-2 service=go-demo-2,type=backend</pre> Ugyan úgy használhatjuk a '''describe''' parancsot is az rs-el mint a pod esetében: <pre># kubectl describe rs go-demo-2Name: go-demo-2Namespace: defaultSelector: service=go-demo-2,type=backendLabels: <none>Annotations: <none>Replicas: 2 current / 2 desiredPods Status: 2 Running / 0 Waiting / 0 Succeeded / 0 FailedPod Template: Labels: db=mongo language=go service=go-demo-2 type=backend Containers: db: Image: mongo:3.3 Port: <none> Host Port: <none> Environment: <none> Mounts: <none> api: Image: vfarcic/go-demo-2...Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal SuccessfulCreate 112s replicaset-controller Created pod: go-demo-2-6nq9h Normal SuccessfulCreate 112s replicaset-controller Created pod: go-demo-2-5c2sk</pre> <pre># kubectl get pods --show-labelsNAME READY STATUS RESTARTS AGE LABELSgo-demo-2-5c2sk 2/2 Running 0 5m41s db=mongo,language=go,service=go-demo-2,type=backendgo-demo-2-6nq9h 2/2 Running 0 5m41s db=mongo,language=go,service=go-demo-2,type=backend</pre> A pod-ok és az RS között csak lazán csatolt kapcsolat van. Ha '''--cascade=false''' kapcsolóval töröljük az RS-t akkor a podokat meg fogja hagyni. És ha újra létrehozzuk az RS-t ezeket a pod-okat fogja felhasználni. <pre># kubectl delete -f rs/go-demo-2.yml --cascade=false </pre> kubectl apply --> frissíti a konfigurációt. Rárak egy annotációt, és később az alapjén dönti el, hogy mi válozott. Csak akkor lehet használni, ha eleve apply-al hoztuk létre, vagy create --save-confg kapcsolóval. <pre># kubectl create --save-config</pre> kubectl edit: egyenlő azzal, mint ha describe -o yaml -el elmentenénk a konfigot, átírnánk, majd nyomnánk rá egy applay-t. A -o yaml-el meg tudjuk szeretni az eredeti konfigurációs fájlt: <pre># kubectl get rs go-demo-2 -o yaml</pre> <br> =Deployment=...TODO... https://www.mirantis.com/blog/kubernetes-replication-controller-replica-set-and-deployments-understanding-replication-options/ save/ apply ... kubectl rollout status deploy <br> =Networking=https://sookocheff.com/post/kubernetes/understanding-kubernetes-networking-model/ ==Pod szintű kommunikáció==A pod hálózati szempontból nem egy plusz réteg a konténer körül, nem úgy kell elképzelni, mint ha egy konténerben futtatnánk egy másik konténert, sokkal inkább úgy, hogy a POD egy interfésze a konténernek, újra csomagolja a docker konténert és csinál belőle egy "kubernetes konténert". A POD IP címe megegyezik a POD belsejében futó konténer IP címével, amit a Kubernetes oszt ki véletlenszerűen minden egyes POD-nak. A POD-nak akkor is csak egy IP címe van, ha több konténer fut benne.... TODO rajz... TODO: Alapértelmezetten minden pod minden erőforrással kommunikál. Ezt a network policy-val lehet szűkíteni. TODO: namespace: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ ===Konténerek egy pod-ban===... TODO rajz... Ha egy POD belsejében több konténer van, akkor azok osztoznak a hálózati névtérben, tehát ez nem egyenlő azzal, mint ha a lokális gépünkön két konténert elindítanánk egymás mellett, mert ott mind a két konténernek saját hálózati névtere lenne, és alap esetben nem tudnak egymással kommunikálni. Tehát ebből is látszik, hogy a POD a konténer újra csomagolása a hagyományos docker-hez képest, vagyis ha több konténer van egy POD-ban, akkor az olyan mint ha a két image-et egy konténerben "csomagoltuk" volna. A közös POD-ban futó konténerek a localhost-on úgy látják egymást, de ugyan azokon a portokon nem hallgatózhat két konténer, mert akkor port ütközés lesz. A POD tudni fogja a közös névtér ellenére, hogy melyik konténer melyik porton figyel, és a külső kéréseket a megfelelő konténernek fogja továbbítani. <source lang="C++">apiVersion: v1kind: Podmetadata: name: go-demo-2 labels: app: myappspec: containers: - name: my-nginx image: nginx ports: - containerPort: 80 - name: nettest image: amouat/network-utils command: [ "bin/bash" ] args: ["-c", "while true; do echo hello; sleep 10;done"]</source>A network-utils image-ből készülő konténernek végtelen ciklusban adtunk munkát, hogyne álljon le, ahogy létrejön. <pre># kubectl create -f pod-db.yaml pod/go-demo-2 created</pre> Lépjünk be a nettsest konténerbe: <pre># kubectl exec -it -c nettest go-demo-2 /bin/sh#</pre> Majd a localhost-on nézzük meg mit találunk a 80-as porton: <pre># curl localhost:80<!DOCTYPE html><html><head><title>Welcome to nginx!</title></pre>Láthatjuk, hogy annak ellenére választ kapott, hogy valójában a másik konténer hallgatózik a 80-as porton. ===Pod-ok közötti kommunikáció=== Egy Kubernetes cluster-ben minden pod automatikusan tud minden másik POD-al kommunikálni a POD IP címén keresztül. Ez igaz a node-okra is. Minden node elér minden POD-ot és minden POD eléri az összes node-ot a node IP címén annak ellenére, hogy a pod-ok és a node-ok más hálózatban vannak. {{note|Ez a koncepció megfelel a '''docker swarm''' overlay hálózatának, amit a swarm-ban implicit definiálni kell, két swarm service csak akkor látja egymást, ha ugyan azon az overlay hálózaton vannak. (swarm-ban a service egy replicaSet-nek felel meg, nem egyenlő a Kubernetes service objektummal)}} Linux-ban a névterekben lévő virtuális hálózatokat össze lehet kötni a host root hálózatával úgynevezett '''Veth''' (Virtual Ethernet Device) hálózati csatolókkal. Minden pod és a host root hálózata között létrejön egy Veth pár. A Veth párok pedig hálózati híddal (bridge) vannak összekötve a root hálózatban. Ezeket a hálózati beállításokat automatikusan létrehozza a Kubernetes egy cluster-en belül. Ezért éri el minden pod a host gép hálózati interfészeit és viszont. :[[File:ClipCapIt-190506-232813.PNG]]A veth interfészek a root hálózati névtérben Linux Ethernet bridge-el vannak összekötve (Layer 2 kapcsolat). Ezért tud minden pod az összes többi pod-al kommunikálni. A Pod-to-pod kommunikáció node-ok között is működik, de az már hálózatfüggő hogy pontosan hogyan van megvalósítva. Pl. AWS-en erre több lehetőség is van. Hozzunk létre egy nginx pod-ot a kubectl run paranccsal (A run parancs a pod-on kívül létre fog hozni egy ReplicaSet-et és egy Deploymenet-et is. ). <pre># kubectl run webserver --image nginxdeployment.apps/webserver created</pre>Keressük meg az IP címét: <pre># kubectl get pod -o wideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESwebserver-786f555565-gv4m6 1/1 Running 0 103s 172.17.0.7 minikube <none> <none></pre> Hozzunk létre szintén a run paranccsal egy pod-ot amiben a network-utils hálózat tesztelő konténer fog futni. Ezt interaktív üzemmódban fogjuk elindítani, ahogy létrejön a pod a konténer belsejében futó sh shell-hez fogunk kapcsolódni. Ehhez a kubernetes itt is alapértelmezetten létre fog hozni egy deployment-et és egy replicaSet-et. De ez most nem fontos. <pre>$ kubectl run -it netpod --image amouat/network-utils -- sh#</pre>Keressük meg a pod IP címét. <pre># ifconfigeth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:06 inet addr:172.17.0.6</pre> Most a netpod belsejéből kérjük le a webserver pod index.html oldalát: <pre># curl 172.17.0.7<!DOCTYPE html><html><head><title>Welcome to nginx!</title></pre>Láthatjuk hogy a két pod valóban tud egymással kommunikálni. Most ssh-val lépjünk be a minikube node-ra majd onnan szintén kérjük le ezt az oldalt: <pre># minikube ssh _ _ _ _ ( ) ( ) ___ ___ (_) ___ (_)| |/') _ _ | |_ __ /' _ ` _ `\| |/' _ `\| || , < ( ) ( )| '_`\ /'__`\| ( ) ( ) || || ( ) || || |\`\ | (_) || |_) )( ___/(_) (_) (_)(_)(_) (_)(_)(_) (_)`\___/'(_,__/'`\____) $ </pre><pre>$ curl 172.17.0.7<!DOCTYPE html><html><head><title>Welcome to nginx!</title></pre>Látható hogy a node is elérte a pod-ban futó konténert. ===Network policy===https://kubernetes.io/docs/concepts/services-networking/network-policies/ A network policy segítségével lehet korlátozni a pod-ok közötti kommunikációt, ami alapesetben minden pod között adott. <source lang="C++">apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: test-network-policy namespace: defaultspec: podSelector: matchLabels: role: db policyTypes: - Ingress - Egress ingress: - from: - ipBlock: cidr: 172.17.0.0/16 except: - 172.17.1.0/24 - namespaceSelector: matchLabels: project: myproject - podSelector: matchLabels: role: frontend ports: - protocol: TCP port: 6379 egress: - to: - ipBlock: cidr: 10.0.0.0/24 ports: - protocol: TCP port: 5978</source> <br>===DNS feloldás===A service nevére minden POD-ban működik a DNS feloldás. A pod nevére ugyan ez már nem működik. Korábban létrehoztunk egy '''http''' nevű service-t, ami a 80 portot nyitja ki a run=webserver címkével rendelkező pod felé: <pre># kubectl get svcNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEhttp NodePort 10.109.91.148 <none> 80:31997/TCP 29h</pre> Indítsuk el interaktív üzemmódban a korábban már használt network util csomagot tartalmazó konténert: <pre># kubectl run -it netpod --image amouat/network-utils -- sh#</pre> Majd futtassunk egy dig-et a http nevű service-re. Vagy akár curl-al kérjük el a http:80-as porton elérhető tartalmat: <pre># nslookup httpServer: 10.96.0.10Address: 10.96.0.10#53 Name: http.default.svc.cluster.localAddress: 10.109.91.148</pre> <pre># curl http<!DOCTYPE html><html><head><title>Welcome to nginx!</title></pre> ==Service== ===Bevezető=== Láthattuk, hogy egy Kubernetes cluster-en belül az összes pod tud kommunikálni egymással minden további hálózati komponens beiktatása nélkül, amennyiben tudják egymás IP címét. Ez a kommunikáció még akkor is lehetséges, ha a pod-ok külön node-on vannak. Azonban a POD IP címét korántsem tekinthetjük állandónak. A pod ahányszor újra létrejön egy ReplicaSet-ben mindig más és más dinamikus IP címet fog kapni a Kubernetes-től, ezért a POD IP címére nem igazán lehet építeni. Ráadásul, ha egy ReplicaSet-hez több POD példány is tartozik, akkor azt szeretnénk, hogy a ReplicaSet pod-jai load-balanceolva kapják meg a csomagokat, egyáltalán nem fontos, hogy pontosan melyik POD szolgálja ki a kérést az identikits pod-ok közül. A fenti két problémára szolgál megoldással a service. Minden service kap egy virtuális IP címet mikor létrejön, ami a service élete során már nem változik. A service-ekhez pod-okat lehet rendelni. A service-hez rendelt pod-ok elérhetők a service virtuális IP címén keresztül, a service elfedi előlünk a POD dinamikusan változó IP címét, hiába változik meg a POD címe, azt a service leköveti, és meg fogja találni a megfelelő pod-ot. Ha egy service-hez több POD is tartozik, akkor azokhoz load-balance-olva fogja eljuttatni a kéréseket. A load-balancing egy serivce-ben kétféle Linux komponenssel is végrehajtható, ezt a service definiálásakor kell megadni: * iptables: * IPVS (IP Virtual Server): szintén része a Linux kernelnek Ha egy service mögötti pod kommunikálni akar a külvilággal, akkor az üzeneteket a service-nek fogja elküldeni, aki a destination IP-t ki fogja cserélni annak a POD-nak az IP címére, akit eredetileg ...* Pod to Service: Ha egy RepliaSet pod-jaihoz van service definiálva, akkor a pod-ok úgy látják a teljes kommunikáció alatt, hogy ők a service virtuális interfészével kommunikálnak. * Service to Pod: ====Pod to Service kommunikáció====Egy konkrét példán keresztül fogjuk bemutatni, hogy egy pod hogyan tud üzenetet küldeni egy service-nek ami továbbküldi a csomagot a hozzá rendelt pod-nak. Tételezzük föl, hogy létezik egy '''service1''' nevű szolgáltatás, amire a '''pod4''' nevű pod csatlakozik (selectorokon keresztül). A '''service1''' IP virtuális IP címe '''10.109.91.148'''. A mögötte található POD IP címe: '''172.18.0.6'''. A példában a '''pod1''' nevű pod (IP: 172.17.0.5) fog csomagot küldeni a '''service1'''-nek. A '''pod1''' úgy látja, hogy ő kizárólag a '''service1'''-el kommunikál. De a pod4, aki végül meg fogja kapni a csomagokat, ő is úgy fogja látni, hogy kizárólag a service1-től kap csomagokat, csak vele áll kapcsolatban. :[[File:ClipCapIt-190512-162048.PNG]] # A pod1 csomagot akar küldeni a service1-nek. Ebben a forrás IP a POD1 saját címe lesz, a cél IP pedig a service1 virtuális IP címe, ami nem változik. # A POD-ban lévő eth0 interfész fogja megkapni a csomagot. Mivel nem neki szól továbbítani fogja a Virtuális Ethernet eszköz párjának, ami már a node root névterében van. # A '''cbr0''' hálózati híd fogja megkapni a csomagot. Mivel a cél cím (a '''service1''' címe) nem neki szól (ARP protokoll) ezért továbbítani fogja a csomagot a root névtér '''eth0''' alapértelmezett átjárója felé mivel ő nem tud a service létezéséről. # Az '''eth0''' nem kapja meg azonnal a csomagot. A service létrehozásakor a kube-proxy létrehozott egy iptables filtert a '''node1'''-ben. Itt az IPtables szabály hatására a cél IP, ami eddig a service1 virtuális IP címe volt le lesz cserélve a '''service1''' szolgáltatáshoz tartozó '''pod4'''-es pod IP címére dNat szabályokkal, majd a csomag továbbítva lesz az '''eth0'''-nak. # Az eth0 a megfelelő virtuális hálózaton tudni fogja, hogy melyik pod melyik node-on található, így továbbítani fogja a csomagot a '''node2'''-re. # A node2-ön az eth0 interfész továbbítani fogja a csomagot az ottani '''cbr0''' hídnak. Azonban a kube-proxy itt is létrehozott egy IpTables szabályt. Az itten szabály ezúttal a source címet fogja lecserélni a '''service1''' szolgáltatás virtuális IP címére sNat szabályokkal, hogy a '''pod4''' is úgy lássa, hogy ő kizárólag a '''serve1''' szolgáltatással kommunikál. ====Pod to Internet kommunikáció==== :[[File:ClipCapIt-190512-232356.PNG]] * Egress — pod-ok "publikus" internet elérése* Ingress — pod-ok elérése az internetről ===Service definiálása=== A '''containerPort''' csak informatív jellegű a konténer definícióban. Ettől függetlenül bármilyen porot-ot expose-álni lehet később, olyat is ami itt nincs megadva. Ha az expose parancsban nem adunk meg '''--target'''-port-ot akkor a '''-containerPort'''-al megadott portot fogja megosztani. containers: - name: my-nginx image: nginx ports: - containerPort: 80 Az expose paranccsal lehet egy Pod vagy ReplicSet vagy Deployment-hez service-t készíteni implicit (tehát nem dekleratív módon). Meg kell mondani, hogy miből indulunk ki. Mi most egy replicaSet-ből, ezért az rs után megadtuk a ReplicaSet nevét. Utána meg kell adni a service nevét, a portot, amit ki akarunk nyitni, valamint a típust. <pre># kubectl expose rs nginx-rs --name=http --port=80 --type=NodePort --target-port=80</pre> Típusok: * NodePort: a külvilágból is elérhető lesz, minden egyes node-on --> clientIP típust is létrehoz, így a többi node is eléri ezt automatikusan* ClusterIP: csak a cluster-en belülről * ExternalName: ehhez cloud szolgáltató kell, pl aws* LoadBalancer Háromféle port érdekes a '''NodePort''' típusú service esetetén, amiből az expose paranccsal csak kettőt lehet megadni: * port: ezen a porton érhető el a service a cluster-en belül. Ennek nincs köze ahhoz hogy a cluster-n kivül hol érhető el a szolgáltatás. Ha nem adjuk meg, akkor ugyan az lesz mint a target-port* target-port: ez azt mondja meg, hogy a pod-on/container-en belül hol hallgatózik a service. Ha nem adjuk meg külön, akkor a -containerPort -ból szedni. * nodePort: na ezt nem lehet itt megadni. Azt mondja meg, hogy a cluster-en kívül hol lesz elérhető a szolgálatás. Ha nem adjuk meg akkor random választ. <pre># kubectl get svc http -o wideNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTORhttp NodePort 10.98.187.168 <none> 80:32730/TCP 8m3s run=my-nginx</pre> Az itt mutatott IP cím a belső virtuális cím ami csak a Kubernetes cluster-en belül érvényes. A konténernek sincs ilyen 10.X.X.X-es tartományú IP címe, ez egy Kubernetes belső dolog. Láthatjuk, hogy a service belső IP címe 80 (ezt adtuk meg a --port -nál, bármi lehetett volna, szabadon választható) és ehhez rendelte hozzá a külső portot: 32730Ez a port az összes node publikus IP -én elérhető. <pre># kubectl get node -o wideNAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIMEminikube Ready master 7d1h v1.13.4 192.168.122.228 <none> Buildroot 2018.05 4.15.0 docker://18.6.2 ^^^^^^</pre> Az expose autómatikusan legyártja a service definíciót a ReplicaSet-ből, amiből kiindultunk. A végerdmény az alábbi: <pre># kubectl get svc http -o yamlapiVersion: v1kind: Servicemetadata: name: httpspec: ports: - nodePort: 32730 port: 80 protocol: TCP targetPort: 80 selector: run: my-nginx type: NodePort</pre>A service és a ReplicaSet semmilyen kapcsolatban nincsenek egymással. Mind a kettő a selector-okkal találják meg a POD-okat. A pod-ok úgynevezett Endpoint-okon keresztül ajálják ki a portokat a service-ek számára. Rövidítése ep. Tehát itt a 80-as port megegyezik a target-port-nál megadott értékkel. # kubectl get ep NAME ENDPOINTS AGEhttp 172.17.0.7:80 23m ------------------------------ A service-ek neve bekerül a DNS-be, és feloldja a Kubernetes a konténerek számára a belső virtuális IP címmel. Ha van egy ClusterIP típusú service-ünk a db-svc névvel, akkor a cluster-ben minden egyes konténerben ezt fel fogja oldani a service IP címére: 10.111.222.165. A service meg a felsorolt Enpoints-okon éri el a konténert. <pre># kubectl describe svc db-svcName: db-svcNamespace: defaultLabels: <none>Annotations: <none>Selector: service=mongo-db,type=dbType: ClusterIPIP: 10.111.222.165Port: <unset> 27017/TCPTargetPort: 27017/TCPEndpoints: 172.17.0.2:27017</pre> A service round-rubin módon választ a végpontok között. De csak azoknak küld csomagot, amiben a livenessProbe. sikeresen futott le. Korábban userpase-el ment a kommunikácó, most már iptabels szabályokkal, ami sokkal gyorsabb, viszont nem tudja deketálni ha egy pod kiesett. Erre kell a livenessProbe Lépjünk be egy harmadik konténerbe, amire nincs rákötve a service: # kubectl exec -it rs-db-api-m6hkf /bin/sh / # nslookup db-svcName: db-svcAddress 1: 10.111.222.165 db-svc.default.svc.cluster.local / # nc -vz db-svc 27017db-svc (10.111.222.165:27017) open Publikus port lekrédezése: PORT=$(kubectl get svc svc-api -o jsonpath="{.spec.ports[0].nodePort}" Tehát nem kell a -o json ahhoz hogy tudjunk szűrni. -------------------------Nem muszáj hogy selector-a legyen egy szolgáltatásnak. Készíthetünk serlector nélküli service-t, ami automatikusan egyik pod-ra sem fog ezért rákerülni, majd készíthetünk hozzá manuálisan egy endpoint-ot: <pre>kind: EndpointsapiVersion: v1metadata: name: my-servicesubsets: - addresses: - ip: 1.2.3.4 ports: - port: 9376</pre> <br> ==Endpoints==Az endpoint-ok teremtenek kapcsolatot a service és a hozzá tartozó pod példányok között. Minden egyes pod-hoz ami illeszkedik a service selector-ára a service létrehozásakor automatikusan létrejön egy endpoint. Az endpoint tartalmazza a POD IP címét amivel a service-hez csatlakozik. Ez az IP cím a konténerben lévő eth0 interfész IP címe. Egy service-hez legalább egy darab Enpoints Kubernetes objektum tartozik, ami leírja az összes végpontot / pod. Endpoints objektumot manuálisan is létre lehet hozni vagy módosítani, de tipikusan ezt a service kezeli. Ha megnézzük az ep definícióját, akkor ott fel van sorolva az összes pod aki részt vesz a service-ben. Látható, hogy két pod van jelenleg . Az is ki van listázva, hogy mi a belső IP címük és hogy melyik node-on vannak. <pre># kubectl get ep http -o yamlapiVersion: v1kind: Endpointsmetadata: creationTimestamp: "2019-03-17T19:49:12Z" name: http namespace: default resourceVersion: "84822" selfLink: /api/v1/namespaces/default/endpoints/http uid: bd23a709-48ed-11e9-8d39-5254008eeeecsubsets:- addresses: - ip: 172.17.0.7 nodeName: minikube targetRef: kind: Pod name: nginx-rs-wtzmm namespace: default resourceVersion: "73593" uid: 1820549d-48d9-11e9-8d39-5254008eeeec notReadyAddresses: - ip: 172.17.0.8 nodeName: minikube targetRef: kind: Pod name: nginx-rs-jkvx7 namespace: default resourceVersion: "84820" uid: 1c547797-48ee-11e9-8d39-5254008eeeec ports: - port: 80</pre> ... <br> ==Ingress== A service-ekkel önmagukban az a baj, hogy egy Kubernetes klaszterben egy porton csak egy service hallgatózhat. nodePort esetén ezen a porton bármelyik node-ról elérhető a service. Ahhoz egy ugyanazon a porton több szolgáltatást is elérhessünk a klaszeren kívülről szükségünk van az úgynevezett '''ingress controller'''-e. Az ingress komponens végezhet SSL terminálást, név alapú virtuális hosting-ot, és load-balanc-olást. Tipikusan HTTP és HTTPS protokollokat használ. Az ingress beékelődik a külvilág és Kubernetes servcie-ek közé. Az ingress objektum nem része a Kubernetes-nek, a Kubernetes csak egy API-t biztosít. Számtalan ingress implementáció érhető el, pl:* HAproxy * nginx* Traefik (https://docs.traefik.io/user-guide/kubernetes/) ami Docker swarm-hoz is biztosít Layer 7-es sticky session load balancer-t. <br>{{note|Swarm -ban Ingress-nek egy kicsit mást hívnak. Swarm-ban két fő hálózati típus van. Az egyik az '''overly''' hálózat, ahol az overly hálózatra kapcsolódó konténerek (swarm service) elérik egymást. A másik az '''Ingress''' hálózat, ahova publikálhatunk swarm szolgáltatásokat megadott portokon. A swarm klaszter bármelyik node-ján a megadott porton elérhető lesz a szolgáltatás. Ha több konténer is van a szolgáltatásban, akkor az ingress load-balance-olni fog. Tehát a Kubernetes service keveréke a swarm overlay és swarm ingress hálózatnak, de a Kubernetes ingress komponensnek semmi köze a swarm ingress hálózathoz. }} :[[File:ClipCapIt-190517-200014.PNG]] Az ingress kontroller is egy pod-ként fog futni a Kubernetes klaszterben. Ha több node is van a klaszerben, akkor minden egyes node-ra fell kell telepíteni. Ugyan pod-ként fut, de az ingress egy sepciális pod a '''kube-system''' névtérben (tehát a natúr get pod parancs nem listázza ki). Az ingress pod az ingress implementáció telepítése közben jön létre. Létre jön minden egyes node-on (virtuális gépen) egy külön ethernet interfész az ingress számára: <pre>eth0 Link encap:Ethernet HWaddr 52:54:00:8E:EE:EC inet addr:192.168.122.228 Bcast:192.168.122.255 Mask:255.255.255.0 eth1 Link encap:Ethernet HWaddr 52:54:00:54:0F:3C inet addr:192.168.42.224 Bcast:192.168.42.255 Mask:255.255.255.0</pre>Az első interfész lett az ingress számára létrehozva. A '''minikube ip''' parancs a második (.224) IP címet fogja visszaadni, míg az ingress példányokhoz az első IP cím (.228) lesz feltüntetve. Az ingress kontroller kizárólag a saját interfészén fog hallgatózni, jelen esetbe a 228-on. ===Installálás minikube-ba===<pre># minikube addons list...- ingress: disabled...</pre> <pre># minikube addons enable ingress✅ ingress was successfully enabled</pre> Ahhoz hogy listázni tudjuk az nginx pud-ját meg kell adni implicit a -n kapcsolóval a '''kube-system''' névteret. Alap esetben minden a default névtérbe kerül és ha külön nem adjuk meg, akkor mindig a default tartalmát listázza. <pre># kubectl get pods -n kube-system NAME READY STATUS RESTARTS AGE...nginx-ingress-controller-7c66d668b-wnqsk 0/1 ContainerCreating 0 3s</pre> ===Ingress definiálása===Az Ingress objektum formátuma az alábbi. Bármilyen ingress implementációt is választunk, a dekleratív leíró fájl szabványos kell legyen. Az egyetlen olyan elem, ahol az implementáció specifikus paramétereket adhatjuk meg, az a '''annotations''' szekció. Ha az adott implementációnak vannak egyedi beállításai, akkor azokat itt kell megadni. Láthatjuk hogy itt két nginx-es beállítást is használtunk. Az ingress kontroller http path és http hostnév alapján is tud route-olni vagy a kettőt együtt is használhatjuk. Az alábbi példában nem adtuk meg hostnevet. A -http -> paths listában kell felsorolni az URL path-okat, amire az adott service-t kötni szeretnénk. Majd a backend szekcióban meg kell adni az adott service kubernetes nevét és belső portájt. Vagyis nodePort típusú service esetén nem azt a portot kell megadni, ahol a node-on el lehet érni, és nem is azt a portot ahol a pod hallgatózik, hanem a service saját portját. Nekünk van egy http nevű service-ünk, ami a 80-as porton hallgatózik. A node-on kívülről a 31997-es porton érhető el. Az ingress kontrollerben a /app1-es path-t erre a service-re akarjuk rákötni. A http service-ünkhöz egy nginx-es image-et tartalmazó pod van kötve. <pre># kubectl get svcNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEhttp NodePort 10.109.91.148 <none> 80:31997/TCP 5d6h</pre> {{warning|Az ingress kontroller ugyan azt a path-t fogja továbbítani az alkalmazásnak, amit megadunk a routingban. Tehát nem fogja automatikusan a / (root)-ra irányítani a kérést. A lenti példában tehát az nginx szerver a /app1-et kapná meg, amilyen URL alapértelmezetten nem létezik.}} A "'''nginx.ingress.kubernetes.io/rewrite-target: /'''" paraméterrel mondhatjuk meg, hogy minden alkalmazáshoz a /-ra irányítsa a kérést a path paraméterben megadott érték helyett. <source lang="C++">apiVersion: extensions/v1beta1kind: Ingressmetadata: name: demo-inggress annotations: kubernetes.io/ingress.class: "nginx" ingress.kubernetes.io/ssl-redirect: "false" nginx.ingress.kubernetes.io/ssl-redirect: "false" nginx.ingress.kubernetes.io/rewrite-target: /spec: rules: - http: paths: - path: /app1 backend: serviceName: http servicePort: 31997</source> <pre># kubectl create -f demo-ingress.yml ingress.extensions/demo-inggress created</pre> <pre># kubectl get ingressNAME HOSTS ADDRESS PORTS AGEdemo-inggress * 192.168.122.228 80 6m59s</pre> :[[File:ClipCapIt-190517-212050.PNG]] * path alapú routolás* domain név alapú routolás* default rout:<pre>curl -I -H "Host: mydomain.com" \"http://http://192.168.122.224/app2/"</pre> <br> ===Ingress konfigurációs fájl===Az ingress kontroller figyeli az API szerveren történt változásokat. Ha új ingress objektumot jegyez be ott a kliens, akkor átkonfigurálja a load-balancer-t jelen esetben az nginx szervert. A változásokat beírja a '''/etc/nginx/nginx.conf''' fájlba. Ha belépünk az nginx pod-ba interaktív módban (bash-t futtatva) akkor megnézhetjük a fenti ingress definíció hatására létrejött konfigurációt. <pre># kubectl exec -it -n kube-system nginx-ingress-controller-7c66d668b-wnqsk /bin/sh$$ cat nginx.conf</pre><source>... ## start server _ server { server_name _ ; listen 80 default_server reuseport backlog=511; location ~* "^/app1\/?(?<baseuri>.*)" { set $namespace "default"; set $ingress_name "demo-inggress"; set $service_name "http"; set $service_port "80"; set $location_path "/app1"; ... rewrite "(?i)/app1/(.*)" /$1 break; rewrite "(?i)/app1$" / break; proxy_pass http://upstream_balancer; }</source> ===Compare to swarm===A Deployment, ReplicaSet és Service Kubernetes komponenseknek megvan az ekvivalens párja Docker Swarm-ban. A Docker swarm megoldása ráadásul sokkal felhasználó barátabb, a leíró fájl sokkal tömörebb és egyszerűbb. Azonban a szabványosított Ingress API megoldás teljesen hiányzok a swarm-ból, minden gyártó (Ngnix, Traefic, Docker flow proxy) egyedi módon oldotta meg. Ezzel ellentétben a Kubernetes-ben egy teljesen szabványosított megoldás van, tehát itt egyértelműen a Kubrnetes a nyerő. <br> =Volumes= A volume a konténer számára egy kívülről felcsatolt fájl vagy mappa. A volume a POD születésekor jön létre, és a POD megszűnésével törlődik. A Kubernetes számtalan volume típust támogat: https://kubernetes.io/docs/concepts/storage/volumes/A volume-ok pod szinten kell definiálni, és a definíciónak két része van. A POD .spec.volumes szekciójában kell definiálni a volume forrását (pl hostPath típus esetén a hostVM-en a source mappa/fájl/socket helyét), és a POD .spec.containers.volumeMounts szekciójában kell megadni a konténer számára a mount pontot.A Kubernetes számtalan volume típust támogat, többek között: * hostPath* secret* nfs* awsElasticBlockStore* azureDisk / azureFilestb '''Forrás definíciója:''' <br>A volumes listában fel kell sorolni minden egyes volume-ont. A volume definíciója a névvel kezdődik (ezzel fogunk rá hivatkozni a mount pont megadásánál). Ezt követi a típus megadása. <pre>spec: ... volumes: - name: myFileMount hostPath: path: /hostVM/somefile type: File</pre> <pre>....spec: containers: - name: xxx ... volumeMounts: - mountPath: /home/mydirectory name: myFileMount</pre> {{note|A volume definiálása valamelyest eltér a docker swarm megközelítéstől, bár a volume ... . Docker stack fájlban is két részre osztható a volume definíciója. A stack fájlban globálisan definiálhatjuk a volume típusát és forrását, majd a swarm service definícióban adhatjuk meg a mount pontont, pont mint Kubernetes-ben. }} source types:* File* FileOrCreate* Directory* DirectoryOrCreate* Socket* CharDevice* BlockDevice <pre>apiVersion: v1kind: PersistentVolumemetadata: name: nfsspec: capacity: storage: 1Mi accessModes: - ReadWriteMany nfs: server: nfs-server.default.svc.cluster.local path: "/"</pre>