Differences

This shows you the differences between two versions of the page.

Link to this comparison view

cc:laboratoare:07 [2021/10/08 12:21]
radu.ciobanu
cc:laboratoare:07 [2021/12/06 12:33] (current)
alexandru.hogea [Secrete în Kubernetes]
Line 1: Line 1:
-===== Laboratorul 07 =====+===== Laboratorul 07 - Secrete, variabile de mediu și persistența datelor în Kubernetes ​=====
  
 +În laboratoarele anterioare am folosit variabilele de mediu direct în fișierele YAML ale pod-urilor. Evident, în cazul datelor sensibile, nu este o idee bună pentru ca oricine are acces la fișierele de configurare YAML să aibă posibilitatea de a vedea variabilele de mediu definite. Problema apare în momentul în care în variabilele de mediu definim nume de utilizatori și parole. ​
 +
 +Cum putem pasa datele sensibile în variabilele de mediu ale unui pod într-un mod sigur? Prin intermediul obiectelor Secrets din Kubernetes.
 +
 +==== Secrete în Kubernetes ====
 +
 +Exemplu de secret în Kubernetes
 +<code yaml>
 +apiVersion: v1
 +data:
 +  POSTGRES_DB:​ bGlicmFyeQ==
 +  POSTGRES_PASSWORD:​ c3R1ZGVudA==
 +  POSTGRES_USER:​ c3R1ZGVudA==
 +kind: Secret
 +metadata:
 +  name: db-secret
 +</​code>​
 +
 +Fișierul de mai sus este un secret care reprezintă variabilele de mediu folosite în podul DB. Puteți observa că perechile cheie-valoare nu sunt în totalitate clare. Mai exact, cheia este vizibilă, dar câmpul de valoare este encodat în format BASE64. **Atenție**,​ BASE64 **nu** este criptare, nu asigură siguranța.
 +
 +Pentru a crea fișierul pentru un secret fără a converti manual string-urile în BASE64, puteți folosi comanda următoare:
 +<code bash>
 +kubectl create secret generic db-secret --from-literal=POSTGRES_USER=student --from-literal=POSTGRES_PASSWORD=student --from-literal=POSTGRES_DB=library --dry-run=client -o yaml > db-secret.
 +</​code>​
 +
 +Creați acest secret:
 +<code bash>
 +kubectl apply -f db-secret.yaml
 +</​code>​
 +Incercati sa vizualizati datele din acest secret:
 +<code bash>
 +kubectl get secret db-secret
 +kubectl describe secret db-secret
 +</​code>​
 +
 +==== Variabile de mediu în Kubernetes ====
 +Cum injectăm aceste date în variabilele de mediu ale podului nostru DB? Să ne uităm pe următorul exemplu:
 +<code yaml>
 +apiVersion: v1
 +kind: Pod
 +metadata:
 +  creationTimestamp:​ null
 +  labels:
 +    run: db
 +  name: db
 +spec:
 +  containers:
 +  - image: axonedge/​lab-k8s-database
 +    name: db
 +    envFrom:
 +      - secretRef:
 +          name: db-secret
 +</​code>​
 +
 +Creați pod-ul și verificați variabilele de mediu. Expuneti pod-ul de DB ca la laboratorul anterior, printr-un serviciu de tipul clusterIP.
 +
 +=== Serviciul de RabbitMQ ===
 +
 +Serviciul de RabbitMQ, fiind unul basic, îl rulăm în continuare ca la laboratorul anterior.
 +<code bash>
 +kubectl run rabbitmq --image=rabbitmq:​3 --port=5672
 +</​code>​
 +
 +și îl expunem printr-un serviciu de tipul ClusterIP:
 +<code yaml>
 +apiVersion: v1
 +kind: Service
 +metadata:
 +  name: rabbitmq-cluster-ip-service
 +spec:
 +  ports:
 +  - port: 5672
 +    protocol: TCP
 +    targetPort: 5672
 +  selector:
 +    run: rabbitmq
 +</​code>​
 +
 +=== Serviciul Procesator ===
 +Asa cum știm, pod-ul de procesator are mai multe variabile de mediu, le puteți vedea mai jos:
 +<code yaml>
 +    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
 +</​code>​
 +
 +Cum putem să injectăm aceste variabile fără să le avem în text clar în fișierul YAML?
 +
 +Putem rezolva această problemă fie prin **configMaps**,​ fie prin **secrets**. Asa cum știm deja, perechile cheie-valoare dintr-un secret **nu** pot fi văzute din interiorul clusterului,​ deci secret rămâne cea mai bună opțiune pentru datele sensibile (''​PGDATABASE'',​ ''​PGUSER'',​ ''​PGPASSWORD''​). În plus, putem folosi configMap pentru variabilele care **nu** sunt sensibile: ''​PGHOST'',​ ''​PGPORT'',​ ''​AMQPURL''​.
 +
 +Așa cum am văzut anterior, creăm un secret cu datele mai sus menționate:​
 +<code bash>
 +kubectl create secret generic proc-secret --from-literal=PGUSER=student --from-literal=PGPASSWORD=student --from-literal=PGDATABASE=library --dry-run=client -o yaml > proc-secret.yaml
 +</​code>​
 +
 +Fișierul YAML este următorul:
 +<code yaml>
 +apiVersion: v1
 +data:
 +  PGDATABASE: bGlicmFyeQ==
 +  PGPASSWORD: c3R1ZGVudA==
 +  PGUSER: c3R1ZGVudA==
 +kind: Secret
 +metadata:
 +  creationTimestamp:​ null
 +  name: proc-secret
 +</​code>​
 +
 +Creați un configMap pentru restul variabilelor (urmăriți exemplul din documentație,​ este foarte similar cu cel de la secret):
 +<code yaml>
 +apiVersion: v1
 +data:
 +  AMQPURL: amqp://​rabbitmq-cluster-ip-service
 +  PGPORT: "​5432"​
 +  PGHOST: db-cluster-ip-service
 +kind: ConfigMap
 +metadata:
 +  name: proc-cmap
 +</​code>​
 +
 +Injectați variabilele în pod:
 +<code yaml>
 +apiVersion: v1
 +kind: Pod
 +metadata:
 +  labels:
 +    run: procesator
 +  name: procesator
 +spec:
 +  containers:
 +  - image: axonedge/​lab-k8s-procesator
 +    name: procesator
 +    envFrom:
 +      - secretRef:
 +          name: proc-secret
 +    env:
 +      - name: AMQPURL
 +        valueFrom:
 +          configMapKeyRef:​
 +            name: proc-cmap
 +            key: AMQPURL
 +      - name: PGPORT
 +        valueFrom:
 +          configMapKeyRef:​
 +            name: proc-cmap
 +            key: PGPORT
 +      - name: PGHOST
 +        valueFrom:
 +          configMapKeyRef:​
 +            name: proc-cmap
 +            key: PGHOST ​      
 +</​code> ​
 +Observați modul în care am injectat variabilele din configMap. Am exemplificat acest mod pentru scopul didactic, ele pot fi injectate la fel ca mai sus la secret.
 +
 +Pentru pod-ul de API, urmăm pașii făcuți pentru procesator. Putem să observăm că datele sensibile sunt aceleași, deci putem să folosim același secret creat la pasul anterior. Restul variabilelor de mediu sunt și ele identice, dar avem în plus variabila ''​PORT''​. Pentru a exemplifica faptul că putem folosi ''​envFrom''​ din mai multe surse, o sa creăm un nou configMap:
 +<code yaml>
 +apiVersion: v1
 +data:
 +  AMQPURL: amqp://​rabbitmq-cluster-ip-service
 +  PGPORT: "​5432"​
 +  PGHOST: db-cluster-ip-service
 +  PORT: "​8000"​
 +kind: ConfigMap
 +metadata:
 +  name: api-cmap
 +</​code>​
 +
 +Acest configMap este identic cu cel de mai sus, dar a fost adăugată variabila ''​PORT''​.
 +Pentru a injecta variabilele de mediu în pod folosim ''​envFrom'',​ ca in fișierul de mai jos:
 +<code yaml>
 +apiVersion: v1
 +kind: Pod
 +metadata:
 +  labels:
 +    run: api
 +  name: api
 +spec:
 +  containers:
 +  - image: axonedge/​lab-k8s-api
 +    name: api
 +    envFrom:
 +      - secretRef:
 +          name: proc-secret
 +      - configMapRef:​
 +          name: api-cmap
 +</​code>​
 +
 +Puteți observa ca am folosit două surse pentru ''​envFrom'',​ o sursă fiind un secret, iar cealaltă sursă fiind un configMap. Astfel, am exeplificat cele mai folosite două metode prin care pot fi injectate variabilele dintr-un configMap într-un pod.
 +
 +=== Temă ===
 +Modificați deployment-ul astfel încât să nu folosim pod-uri, ci să folosim deployment-uri acolo unde este nevoie.
 +
 +==== Persistența datelor ====
 +Adăugați câteva intrări în baza de date. Verificați ca acestea există. Ștergeți podul de DB, creați unul nou și executați o cerere de tip GET. Mai avem intrări în baza de date?
 +
 +Pentru ca datele din baza de date să nu dispară odată cu ștergerea pod-ului, folosim PV (PersistentVolume) și PVC (PersistentVolumeClaims).
 +
 +Un fișier de bază pentru a crea un PersistentVolume găsiti mai jos. Proprietățile pe care le folosim aici sunt destul de intuitive.
 +
 +<code yaml>
 +apiVersion: v1
 +kind: PersistentVolume
 +metadata:
 +    name: mypv
 +spec:
 +  accessModes:​
 +    - ReadWriteMany
 +  capacity:
 +    storage: 1Gi
 +  hostPath:
 +    path: /tmp/data
 +</​code>​
 +
 +Dupa ce creăm acest volum, verificăm că acesta există:
 +<code bash>
 +kubectl get pv # în continuare urmăriți câmpul de status
 +</​code>​
 +
 +Creăm un PVC pe baza următorului fișier de configurare:​
 +<code yaml>
 +apiVersion: v1
 +kind: PersistentVolumeClaim
 +metadata:
 +  name: mypvc
 +spec:
 +  accessModes:​
 +    - ReadWriteMany
 +  resources:
 +    requests:
 +      storage: 1Gi
 +</​code>​
 +
 +După ce am creat și un PVC, verificați din nou atât PV, cât și PVC:
 +<code bash>
 +kubectl get pv # urmăriți câmpul de status
 +kubectl get pvc
 +</​code>​
 +
 +Cum folosim un volum într-un pod? Modificăm fișierul de configurare al pod-ului pentru baza de date astfel încât acesta să folosească noul volum:
 +<code yaml>
 +apiVersion: v1
 +kind: Pod
 +metadata:
 +  creationTimestamp:​ null
 +  labels:
 +    run: db
 +  name: db
 +spec:
 +  containers:
 +  - image: axonedge/​lab-k8s-database
 +    name: db
 +    envFrom:
 +      - secretRef:
 +          name: db-secret
 +    volumeMounts:​
 +      - mountPath: /​var/​lib/​postgresql/​data
 +        name: mypd
 + 
 + 
 +  volumes:
 +  - name: mypd
 +    persistentVolumeClaim:​
 +      claimName: mypvc
 +</​code>​
 +
 +Ștergeți pod-ul de DB creat anterior și creați altul pe baza fișierului de mai sus.
 +Adăugați câteva intrări în baza de date, ștergeți pod-ul și apoi creați altul nou. Putem observa că de data aceasta baza de date nu este goală. ​
  
cc/laboratoare/07.1633684902.txt.gz · Last modified: 2021/10/08 12:21 by radu.ciobanu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0