Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Load balancing e Ingress

Kubernetes: parliamo di load balancing, funzionalità fondamentale quando le applicazioni devono sostenere un carico di richieste variabile
Kubernetes: parliamo di load balancing, funzionalità fondamentale quando le applicazioni devono sostenere un carico di richieste variabile
Link copiato negli appunti

Nella lezione precedente abbiamo imparato a pubblicare un nostro Deployment mediante la componente Service. In questo modo siamo riusciti a rendere disponibili le funzionalità di un workload mediante collegamento in rete. Proprio questa esposizione rappresenta una delle tematiche più calde nella creazione di applicazioni distribuite che, per loro natura, si prestano ad essere raggiunte da remoto sia dall'interno del cluster che dall'esterno.

Un aspetto molto importante però consiste nel curare il cosiddetto load balancing ovvero il bilanciamento del carico. Si tratta di una funzionalità fondamentale quando le applicazioni devono sostenere un carico di richieste variabile che può diventare improvvisamente imponente per determinati lassi di tempo. Teoricamente, un'architettura simile vede un load balancer in ingresso che riceve le richieste e le distribuisce in maniera uniforme tra una serie di "server" che replicano l'applicazione. Tali server possono essere macchine virtuali o fisiche ma nel nostro caso si tratterà di componenti Kubernetes dove le anime operative saranno i Pod. Inoltre, vale la pena ricordare che i load balancer possono essere ad esclusivo uso interno dell'applicazione o esposti verso l'esterno per rispondere alle richieste dell'utenza.

Il bilanciamento del carico in generale offre non solo la distribuzione delle richieste sui vari server ma anche una serie di facoltà correlate come, ad esempio, il continuo monitoraggio dei server e l'individuazione di quelli eventualmente non funzionanti. Ciò è indispensabile per poter distribuire le richieste senza che vadano perse ma al contempo diventa una forma di controllo sulle componenti che stanno gestendo l'applicazione.

Service e Ingress

In Kubernetes, esistono principalmente due modi fondamentali per gestire il load balancing e sono:

  • l'utilizzo di Service, gli stessi incontrati nella lezione precedente, ma con un type impostato al valore LoadBalancer;
  • gli Ingress che rappresentano una componente a sé stante nello scenario di Kubernetes.

In generale, utilizzare il load balancing offerto dai Service potrebbe essere sufficiente tuttavia è spesso necessario ricorrere agli Ingress. La differenza di base tra essi consiste in una diversa collocazione nello stack di rete, infatti i Service eseguono un load balancing a livello TCP quindi non sono in grado di ispezionare i pacchetti al loro interno. Gli Ingress invece lavorano a livello HTTP pertanto in grado di leggere le intestazioni specifiche di questo protocollo applicativo. Inoltre, come vedremo, gli Ingress possono essere considerati uno strumento più articolato in quanto possono essere "programmati" con delle regole per gestire le richieste in base agli indirizzi

Load balancing con i Service

Forniamo un esempio di entrambi i casi. Prepareremo in questo paragrafo un semplice Deployment che andremo poi a pubblicare con un load balancer sia con un Service sia con un Ingress.

Ispiriamoci a quanto già visto nel corso di questa guida attivando, in modalità imperativa, un Web server di tipo NGINX:

$ kubectl create deployment my-server-web --image=nginx
deployment.apps/my-server-web created

Esponiamo il Deployment come sappiamo fare ovvero con un Service solo che questa volta lo imposteremo con type=LoadBalancer:

$ kubectl expose deployment my-server-web --type=LoadBalancer --port=80
service/my-server-web exposed

Eseguendo il tutto su minikube otteniamo quanto dimostrato dalla seguente interrogazione:

$ kubectl get svc
NAME            TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes      ClusterIP      10.96.0.1        <none>        443/TCP        60s
my-server-web   LoadBalancer   10.106.162.229   <pending>     80:30681/TCP   14s

Notiamo che nella colonna EXTERNAL-IP è rimasto il valore pending il che significa che non si è riuscito ad ottenere un indirizzo IP esterno. Ciò perché il nostro è un ambiente di esecuzione di prova mentre se avessimo attivato il tutto su una piattaforma Cloud avremmo ottenuto in pochi secondi un riferimento da contattare direttamente via browser da qualsiasi parte del mondo. Tuttavia, anche in minikube è possibile ottenere connettività per un Service di tipo LoadBalancer ricorrendo ad un tunnel. Eseguendo infatti:

$ minikube tunnel

disporremo di un indirizzo da contattare via rete anche in questo caso: unico accorgimento da adottare consiste nell'eseguire il tunnel in una finestra terminale separata o in background in quanto risulterà bloccante per il prompt. Nel nostro ambiente di prova, applicando un tunnel si ottiene:

$ kubectl get svc
NAME            TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)        AGE
kubernetes      ClusterIP      10.96.0.1        <none>           443/TCP        3m19s
my-server-web   LoadBalancer   10.106.162.229   10.106.162.229   80:30681/TCP   2m33s

che rende possibili interrogazioni dirette come curl 10.106.162.229 per ottenere, nel nostro caso, l'homepage del server NGINX.

Applicazione di un Ingress

Pubblichiamo ora lo stesso Deployment mediante un Ingress. Questo si risolve in un controller in grado di smistare lavoro tra vari Service. Se si sta sperimentando il tutto con minikube, dovremo per prima cosa attivare un apposito add-on:

minikube addons enable ingress

Fermo restando il nostro Deployment, illustrato a inizio esempio, lo esporremo con un Service che in questo caso potrà essere di tipo NodePort (visto che il load balancer sarà l'Ingress):

kubectl expose deployment my-server-web --type=NodePort --port=80

e costruiremo nel file ingress.yaml il nostro Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: my-server-web
                port:
                  number: 80

Notiamo che nell'unica regola (sezione rules) che abbiamo definito associamo un percorso (path: /) con un backend, rappresentato in questo caso dal nostro Service my-server-web.

Attivando il tutto con kubectl apply -f ingress.yaml potremo vedere l'Ingress operativo con:

$ kubectl get ingress
NAME              CLASS   HOSTS   ADDRESS        PORTS   AGE
my-ingress        nginx   *       192.168.49.2   80      14m

ed invocando curl 192.168.49.2 otterremo la risposta da NGINX.

Ciò che rende davvero interessanti gli Ingress è la possibilità di definire una serie di regole articolando meglio la rete di backend raggiungibili. Si provi già in questo caso ad applicare un diverso percorso, ad esempio, con path: /mioserver. Ricaricando il file YAML si vedrà che da questo momento NGINX non sarà più raggiungibile con curl 192.168.49.2 bensì con curl 192.168.49.2/mioserver in virtù dell'annotation impostata nei metadati.

Ti consigliamo anche