This is an old revision of the document!
In laboratorul trecut am vazut cum putem deploya o aplicatie distribuita sub forma Pod-uri de kubernetes, folosind comenzi de kubectl. Rularea comenzilor manual este primul pas pentru invatare, insa nu este recomandat la nivel de productie. Pentru productie, precum si in cazul Docker Swarm, este indicata folosirea configuratiilor declarative.
Kubernetes ofera suport pentru rularea configuratiilor declarative de tip .yaml. In acest laborator vom explora cum este posibil.
Fisierele YAML pot fi scrise de la 0, sau pot fi generate prin rularea uscata a pod-urilor.
#Exemplu oficial de fisier YAML apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80
Pentru a genera fișiere YAML plecand de la o comanda imperativa putem folosi flag-urile –dry-run=client -o yaml
. Exemplu: kubectl run nginx –image=nginx –dry-run=client -o yaml
Orice fișier YAML are 4 componente importante:
Pentru a face deploy la unul (sau mai multe) obiecte dintr-un fisier YAML folosim următoarea comandă: kubectl apply -f myfile.yaml
kubectl create
, kubectl upate
, kubectl delete
, dar este indicat sa folositi direct kubectl apply
, care combina create, replace si delete. Aceasta reprezinta cel mai avansat model de aplicare a unei configuratii declarative.
kubectl apply
se poate da si pe un folder care contine fisiere .yaml sau pe un url care pointeaza catre un fisier .yaml
În fișierul YAML generat de comanda anterioară, putem observa că în câmpul metadata
, pe lângă atributul name
, avem și atributul labels
:
metadata: creationTimestamp: null labels: run: nginx name: nginx
Aceste labels sunt perechi de tipul cheie-valoare care sunt folosite pentru identificarea obiectelor din Kubernetes. În exemplul de mai sus, avem perechea run=nginx
. Această pereche poate fi folosită de către un label selector pentru a referi acest obiect (mai multe detalii în continuare).
Spre deosebire de nume, label-urile nu asigură unicitate. În general, ne așteptăm ca mai multe obiecte să aibă aceleași label-uri.
Asa cum am spus anterior, cu ajutorul unor Label Selectors putem identifica numite seturi de obiecte în Kubernetes. Un exemplu relevant este expunerea unui pod printr-un serviciu. În cadrul laboratorului trecut, ați expus poduri cu ajutor unor servicii de tipul ClusterIp și NodePort. De unde știe serviciul ClusterIp ce nod să expuna? (hint: kubectl describe myservice #cautati label selectors
).
Un exemplu comun de utilizare a labels și labels selectors prin intermediul fișierelor de configurare YAML este următorul:
kubectl run nginx –image=nginx –port=8080 –dry-run=client -o yaml >vtest.yaml
Adăugați podului următorul label:
app: myapp
Creați pod-ul:
kubectl apply -f test.yaml. kubectl describe pod nginx # analizate label-urile podului.
Pentru a expune acest pod trebuie creat un serviciu de tipul ClusterIP care să selecteze podul nostru prin intermediul label selectors. Un fișier de configurare YAML pentru acest serviciu este următorul:
apiVersion: v1 kind: Service metadata: creationTimestamp: null name: nginx spec: ports: - port: 80 protocol: TCP targetPort: 80 selector: app: myapp #select the pod/pods status: loadBalancer: {}
Observați că nu am definit tipul de serviciu, astfel Kubernetes a creat by default un serviciu de tipul ClusterIP. Verificați faptul că podul nginx este expus.
In exemplul precedent am scris definitia unui Pod in YAML. De obicei, nu veti dori sa lucrati cu pod-uri, ci cu un obiect care controleaza starea de viata a pod-urilor, precum un deployment
.
Deployment-ul are o sintaxa putin mai grea:
#Exemplu oficial de fisier YAML apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: selector: matchLabels: app: nginx replicas: 2 # tells deployment to run 2 pods matching the template template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80
Faceti referire la aplicatia propusa in laboratorul trecut. Vom reface rezolvarea, folosind fisiere YAML pentru declararea pod-urilor si a serviciilor.
dry-run
Generare fișier YAML pentru containerul DB:
kubectl run db --image=axonedge/lab-k8s-database --dry-run=client -o yaml > db-pod.yaml
Deschidem fisierul YAML și adăugam câmpul env în spec:
spec: containers: - image: axonedge/lab-k8s-database name: db env: - name: POSTGRES_USER value: student - name: POSTGRES_PASSWORD value: student - name: POSTGRES_DB value: library
Creăm un fișier YAML pentru un serviciu care expune pod-ul creat anterior:
apiVersion: v1 kind: Service metadata: name: db-cluster-ip-service spec: ports: - port: 5432 protocol: TCP targetPort: 5432 selector: run: db
Cum pod-ul de RabbitMq este unul basic, Îl puteam crea direct cu metoda imperativă:
kubectl run rabbitmq --image=rabbitmq:3 --port=5672
Copiați fisierul pentru serivicul anterior si modificați-l astfel încât acesta să folosească portul 5672 și să expună pod-ul de RabbitMQ:
apiVersion: v1 kind: Service metadata: name: rabbitmq-cluster-ip-service spec: ports: - port: 5672 protocol: TCP targetPort: 5672 selector: run: rabbitmq
Creați serviciul:
kubectl create -f serviciu-rabbitmq.yaml
Generați un fișier YAML pentru pod-ul de procesator:
kubectl run procesator --image=axonedge/lab-k8s-procesator --dry-run=client -o yaml > procesator-pod.yaml
Adăugați variabilele de mediu necesare:
env: - name: PORT value: "8000" - name: PGHOST value: db-cluster-ip-service - name: PGDATABASE value: library - name: PGPORT value: "5432" - name: PGUSER value: student - name: PGPASSWORD value: student - name: AMQPURL value: amqp://rabbitmq-cluster-ip-service
Generați fișierul YAML pentru acest pod:
kubectl run api --image=axonedge/lab-k8s-api --dry-run=client -o yaml > api-pod.yaml
Adăugați variabilele de mediu:
env: - name: PORT value: "8000" - name: PGHOST value: db-cluster-ip-service - name: PGDATABASE value: library - name: PGPORT value: "5432" - name: PGUSER value: student - name: PGPASSWORD value: student - name: AMQPURL value: amqp://rabbitmq-cluster-ip-service
Scrieți un fișier de configurare pentru serviciul nodeport:
apiVersion: v1 kind: Service metadata: name: api-nodeport-service spec: ports: - port: 8000 protocol: TCP targetPort: 8000 selector: run: api #select the pod/pods type: NodePort
Cu aceasta teorie pusa in practica, am reusit sa acoperim o parte consistenta din baza kubernetes. Cu toate acestea, inca nu am terminat. La laboratorul urmator vom invata sa folosim stocare persistenta, secrete si configurari.
Adaptati configuratiile facute astazi, transformand pod-urile in deployment-uri. Api-ul ar trebui sa aiba 2 replici, clientul de rabbit 3 si baza de date 1.