Tutorial > Introduzione ai Service Kubernetes

Introduzione ai Service Kubernetes

Service Kubernetes

Nello sviluppo di applicazioni cloud, si raccomanda l’adozione di un approccio basato su microservizi distribuiti. I microservizi vengono distribuiti in container Docker e possono essere facilmente gestiti e scalati in ambiente Kubernetes. Uno o più container entrano a far parte della struttura del cluster incapsulati all’interno delle unità di elaborazione di Kubernetes, i Pod, i quali devono essere deployati all’interno del cluster affinché possano essere eseguiti.

Per poter essere accessibili dall’esterno, i Pod deployati devono essere esportati come Servizi Kubernetes.
I Service sono dei servizi che fungono da endpoint, cioè che esportano i Pod in modo da renderli visibili e utilizzabili sia dall’interno che dall’esterno del cluster Kubernetes. Per abilitare il networking tra container e renderli quindi accessibili da altri indirizzi, bisogna esporre i Pod come Service Kubernetes.

Creare un Service Kubernetes

I Service si possono creare, modificare e eliminare tramite kubectl, la command-line tool di K8s.
Il nostro Pod è un server Nginx. Dopo averlo deployato applicando il manifesto YAML tramite il comando:
$ kubectl apply -f ./deployment.yaml
Andiamo prima a verificare l’indirizzo IP del Pod eseguendo:
$ kubectl get pods -l run=nginx-deployment -o yaml | grep podIP
Il comando get pods ritornerà un output del tipo:
Output:

NAME                            READY   STATUS             RESTARTS   AGE
nginx-deployment-754985fdc8     1/1     ImagePullBackOff   0          6h52m
A questo punto andiamo a rendere pubblico il Pod usando il comando:
$ kubectl expose deployment nginx-deployment --type=NodePort --port 8080
In questo caso, l’applicazione accetterà le connessioni interne sulla porta TCP 8080.
Per visualizzare i Service creati basterà eseguire il comando:
$ kubectl get services
Il nostro output sarà simile a:
Output:

NAME               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
hello-kubernetes   ClusterIP   10.244.68.93             80/TCP           3d22h
kubernetes         ClusterIP   10.244.0.1               443/TCP          3d22h
nginx-deployment   NodePort    10.244.168.236           8080:32362/TCP   6h52m
Ora eseguiamo:
$ kubectl describe services/nginx-deployment
E l’output sarà del tipo:
Output:

Name:                     nginx-deployment
Namespace:                default
Labels:                   
Annotations:              
Selector:                 app=nginx
Type:                     NodePort
IP:                       10.244.168.236
Port:                     8080/TCP
TargetPort:               8080/TCP
NodePort:                 32362/TCP
Endpoints:                
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   
Da quì possiamo vedere sia l’indirizzo IP che la porta che fungono da endpoint.

Abbiamo creato un Service Kubernetes e questo ha reso il nostro Pod accessibile dall’interno del cluster.
Comunque, in un ambiente di produzione, affinché l’applicazione possa scalare e possa essere utilizzata da molti utenti, i Pod devono essere replicati. Le repliche garantiscono disponibilità e affidabilità anche in caso di guasto e recovery dei nodi del cluster. Inoltre, per garantire un utilizzo ottimale delle risorse, è necessario che il carico di lavoro assegnato ai nodi venga gestito da un Load Balancer. Gli aspetti di scalabilità e load balancing sono quindi di fondamentale importanza nella messa in opera di applicazioni cloud. Vediamo come questi vengono implementati in Kubernetes.

Scalare i Service tramite Deployment

Scalare un’applicazione Kubernetes significa aumentare il numero di repliche di un deployment all’interno del cluster. Prima di parlare di scalabilità, dobbiamo distinguere tra le due tipologie di applicazioni distribuite di Kubernetes:
  • Applicazioni Stateful: conservano uno stato interno che contiene, ad esempio, le variabili della sessione corrente
  • Applicazioni Stateless: non conservano alcuno stato dell’esecuzione
È intuibile che mantenere dei servizi stateful potrebbe portare a una cattiva gestione delle repliche, in quanto, nel momento in cui si creano più copie dello stesso microservizio, le richieste HTTP andranno a modificare soltanto la replica su cui vengono effettuate le richieste, il che causerebbe problemi di consistenza e di recovery in caso di guasto.
Per questo motivo, Kubernetes permette di gestire le repliche dei servizi e, soprattutto, riesce a scalarle automaticamente, adattando il numero di repliche alla richiesta effettiva.

Esistono diversi modi per replicare i pod:
  • Settando la replica all’interno del deployment stesso, ovvero nel file YAML, andando a specificare il numero di repliche e come queste andranno gestite
  • Definendo un ReplicaSet
  • Duplicando manualmente i Pod
  • Attraverso i Job
  • Attraverso i DaemonSet

Come prima dimostrazione andiamo a usare il primo metodo, per cui modifichiamo il file deployment.yaml come segue:
apiVersion: apps/v1
kind: Deployment
metadata:
    name: nginx-deployment
spec:
    selector:
        matchLabels:
            app: nginx
    replicas: 4
    template:
        metadata:
            labels:
                app: nginx
        spec:
            containers:
                - name: nginx
                  image: nginx:9.0
In alternativa, possiamo modificare il numero di repliche direttamente da terminale:
$ kubectl scale --replicas=4 deployment/nginx-deployment

Output:

deployment.apps/nginx-deployment scaled
E verifichiamo l’esito dello scaling eseguendo:
$ kubectl get deployment

Output:

NAME                READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment    0/4     4            0           50m
oppure:
$ kubectl describe deployment/nginx-deployment

Notiamo che i nuovi Pod non sono ancora pronti per essere usati. Infatti, per rendere disponibili le repliche dobbiamo esporle. Tuttavia, mentre prima usavamo il comando expose, ora dobbiamo implementare il bilanciamento del carico, dal momento che abbiamo istanziato più repliche. Il Load Balancer è il componente cloud che si occupa della distribuzione e dello scheduling dei task sui nodi del cluster, ottimizzando anche l’utilizzazione delle risorse. Vedremo in seguito come implementare il load balancing sul nostro cluster Kubernetes in Aruba Cloud.

In questa serie abbiamo deployato ed esposto un Pod all’interno del nostro cluster per abilitare il networking interno, dopodiché abbiamo fatto scaling andando a creare ed esporre manualmente delle repliche per il nostro Pod. In ogni caso, Kubernetes consente di effettuare auto-scaling, cioè è in grado di determinare automaticamente come bilanciare il carico tra i vari Pod a seconda della richiesta. Nei prossimi capitoli vedremo altri oggetti Kubernetes e più avanti torneremo a parlare di Service e analizzeremo come funzionano il bilanciamento del carico e l’autoscaling in Kubernetes.