Kubernetes

Kubernetes é un orchestratore, cioè un insieme di strumenti che si occupa di gestire un’architettura.

Nodi master e nodi workers

Le principali componenti sono:

  • master: controlla i nodi workers
  • workers: hostano applicazioni nei container

Componenti Nodi Master

I nodi master sono formati da:

  • etcd cluster: database chiave:valore
    • è un registro che contiene tutte le informazioni sul cluster
  • scheduler: affida al nodo giusto il pod più appropriato, a seconda di un certo criterio
  • controller manager
    • gestisce i vari container in Kubernetes. È un processo che monitora continuamente i componenti nel sistema e cerca di far mantenere al sistema un certo stato (es. attivando le repliche).
    • Esistono diversi tipi di controller:
      • node controller: È IL SOLO a comunicare con l’api-server
        • Node monitor period: 5 sec
        • pod eviction timeout: 5 min
        • Node monitor grace: 40 sec
      • replication controller: si assicura che all’interno di un replicaset ci sia un numero di pod sufficienti a garantire lo stato della replica. Se un pod muore lo ricostruisce.
  • kube-api-server: permette di fare qualsiasi cosa attraverso il richiamo alle API.

Componenti Nodi Workers

I nodi workers sono formati da:

  • kubelet: attende e riceve le istruzioni da kube api server
    • si interfaccia con master e workers
  • kube proxy: permette di far comunicare servizi nel cluster
    • ogni volta che viene creato un nuovo servizio, crea sui nodi delle regole per accedervi. È esattamente un forwarder: <ip-servizio: porta-per-connettersi>
  • CRE: container runtime engine (es. container Docker)

Kubectl vs. Minikube

Minikube è un tool per creare una VM e mettere tutti i nodi master e workers in un’unica macchina.

Kubectl: tool per interagire con i nodi. Interagisce con apiserver. I workers si chiamano pods.

Tutto funziona con YAML.

Comandi principali

  1. Tiri su il cluster Kubernetes. Per farlo: minikube start
  2. Scrivi il tuo bel file yaml. Un esempio potrebbe essere:
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
    tier: frontend
spec:
  containers:
  - name: nginx
    image: nginx
  1. Applichi (o in altre parole tiri su) quello che effettivamente hai scritto lo yaml.
  2. Una serie di comandi d’esempio
minikube start
ka pod.yaml
kgpo

kgpo: serve per vedere la lista dei pods

Pod

Che cos’è un pod?

Dalla documentazione di Red Hat: un pod Kubernetes è una raccolta di uno o più container Linux, nonché la più piccola unità di un’applicazione Kubernetes.

La gerarchia (esterno-interno) è:

  • cluster
    • node
      • pod
        • container (es. nginx)
    • node
    • node

Posso avere più container in un solo pod? Sì. Di solito pod e container hanno relation? 1:1

Repliche

Immaginiamo che un bel giorno un pod si rompa: l’utente non avrebbe più accesso al servizio? Ovviamente no!

Kubernetes mette a disposizione un controller chiamato “Replication Controller”.

Nel corso del tempo, si è evoluto fino a chiamarsi: Replica Set.

Il funzionamento è semplice: si determina come qualsiasi altra risorsa Kubernetes (con un file yaml), e vanno indicati il numero di repliche da creare. In questo modo kubernetes effettivamente andrà a creare una copia di quello che è in un certo pod.

Un yaml di esempio:

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: replicaset-2
spec:
  replicas: 2
  selector:
    matchLabels:
      tier: nginx
  template:
    metadata:
      labels:
        tier: nginx
    spec:
      containers:
      - name: nginx
        image: nginx

Deployment

Supponiamo che vogliamo aggiornare un’istanza Kubernetes: non possiamo aggiornare tutti i pod contemporaneamente, vogliamo farlo un po’ per volta, perché altrimenti gli utenti potrebbero sperimentare disservizi.

Vogliamo anche poter fare rollback.

Ci viene in aiuto il deployment, un oggetto Kubernetes che si occupa di gestire questi casi d’uso.

Inoltre, crea già un replica set in automatico.

Infatti, se creiamo un deployment, avremo andando a fare get pods e get replicaset qualcosa.

L’unica cosa che cambia nello yaml è il “kind” che diventa “Deployment”.

Esempio:

kubectl create deployment httpd-frontend --image=httpd:2.4-alpine --replicas=3

Services

I services servono per far comunicare applicazioni sia internamente tra loro che esternamente con gli utenti.

Nodeport

È un servizio che permette di far comunicare host esterni con cluster kubernetes, aprendo una porta speciale.

Si chiama “NodePort” e apre proprio un bridge tra l’utente esterno e il cluster.

apiVersion: v1
kind: Service
metadata:
  name: myapp-service
 
spec:
  type: NodePort
  ports:
    - targetPort: 80
      port: 80
      nodePort: 30008
  selector:
    app: myapp
    type: front-end

Gratis, ci viene dato una sorta di load-balancer: infatti nodeport si occuperà di dirigere il traffico verso il pod più appropriato.

ClusterIP

Supponendo di avere un’architettura del tipo:

  • backend
  • frontend
  • db
  • redis

Devo far comunicare ogni singolo pezzo dell’architettura con l’altro: potrei avere più pod che hanno lo stesso servizio.

Sappiamo però che i nodi potrebbero andare giù in qualsiasi momento, e non hanno IP Fisso: ecco che ci viene in aiuto ClusterIP. Si definisce come Nodeport, l’unica cosa che ovviamente non va definita è Nodeport port.

Con approccio imperativo:

k expose pod redis —port=6379 —name redis-service

C’è un opzione che si chiama --expose=true. Se viene abilitata in fase di creazione del pod, crea anche un servizio ClusterIP associato al pod in questione.z

Load balancer

Dopo che gli assegna un IP pubblico, posso usarlo per accedere al contenuto della macchina

Namespaces

Degli spazi dove vivono i pod. Tipicamente si usa il default se non sono progetti grandi.

Per sapere tutti i “fatti” di un namespace:

kgpo -n=<nome workspace>

Per invece crearne uno nuovo basta fare una nuova unit in yaml.

Approccio dichiarativo vs. imperativo

Approccio dichiarativo vs. imperativo:

  • Imperativo
    • spieghi come bisogna fare le cose
      • usando gli appositi comandi kubectl, kubectl create, kubectl scale ecc
  • Dichiarativo
    • “questo è ciò che devo fare, pensaco tu”
    • yaml che indica cosa aggiornare ecc ecc

Se devi fare operazioni al volo usa l’approccio imperativo.

Se devi fare operazioni complesse usa il dichiarativo.

Piccolo escursus:

  • kubectl run <pod>: CREA un pod
  • kubectl create <dev | service | replicaset>: tutto il resto

Scheduling

Manual scheduling

Per far si che kuber prenda in cosniderazione uno dei nodi e lo peschi, biosgna prima settare una variabile all’interno dello yaml, nodeName: mode01

Label

Per organizzare meglio i pods, possiamo organizzarli attraverso le label.

kgpo --selector env=dev

Resources

Un container può avere assegnato un certo quantitativo di memoria, a patto che hai abbastanza risorse.

Questo non si limita allo storage, ma anche a risorse come il processore.

Errori

  • OOMKilled : out-of-memory
  • CrashLoopback: crashata l’applicazione