All'interno di questo capitolo della rubrica dedicata a Kubernetes, parleremo di come impostare una semplice applicazione stateless andando ad analizzare due esempi che, nel corso della rubrica, possano dare uno sbocco verso idee più avanzate impresentabili tramite un infrastruttura di base discussa all'interno di questo capitolo. Prima di sporcarci le mani con il terminal e con un pò di codice, andiamo ad identificare cosa sia un'applicazione stateless e su come esse possano contribuire per l'esecuzione di processi in vari contesti.
V. Capitoli
1. Introduzione a Kubernetes: cos'è, infrastruttura su cui si basa, vantaggi, caratteristiche e nomenclatura.
2. Architettura di Kubernetes: Architettura Cluster, Container, Pods, Admin Cluster, Storage e Scheduling.
3. Configurazione di un ambiente Kubernetes: Set up, configurazione dei container, dei pods ed esecuzione di applicazioni.
4. Creazione della prima applicazione su Kubernetes: Hello MiniKube!
5. Creazione di un'applicazione stateless su Kubernetes
(*) La rubrica potrebbe subire delle estensioni in caso il progetto riceva un buon feedback.
1. Introduzione
Per poter creare un applicazione di tipo stateless abbiamo bisogno di alcune componenti che non sono state utilizzate per l'infrastruttura di base del capitolo precedente.
La prima cosa da fare è registrarsi ad uno dei servizi di cloud provider di rete come Google Kubernetes Engine (Cloud provider ad-hoc per Kubernetes su tecnologie basate su Google Cloud) oppure su AWS (se si vuole avere un ambiente più familiare e dinamico)
La mia opinione sulla scelta verte verso Google Kubernetes Engine, anche se AWS è comunque una valida alternativa.
Un'altro aspetto da considerare è il Load Balancer Esterno che bisogna configurarlo per il Cloud Provider scelto.
IMPORTANTE: Se usate GKE o AWS (Amazon EKS) dovete configurare kubectl per il cloud provider scelto. Tutte le informazioni sono riportate nella documentazione ufficiale dei due cloud provider.
2. Load Balancer
Ciò che andremo a fare è creare un Load Balancer Esterno. Bisogna sapere che appena si ha il deploy di un servizio su un cluster in modo tale da poter accederci anche da esterno (quindi l'ambiente di esecuzione si estende anche al di fuori del cluster), si ha una configurazione di default del load balancer. Esso ha il compito di comunicare con l'esterno attraverso un IP esposto su una porta specifica in modo da gestirne le operazioni all'interno del nodo del cluster da e verso nodi esterni.
Per poter configurare un Load Balancer esterno si ha sempre bisogno del comando kubectl
Puoi verificare la presenza di questi comandi andando a digitare:
Codice:
kubectl --version && minikube --version
Se non si hanno errori dovuti all'assenza di questo comando, seguite il capitolo 3 della rubrica che troverete a questo link.
2.1 File di configurazione
Per prima cosa bisogna accedere all'interno della directory principale di Kubernetes ed entrare all'interno del file di configurazione dei servizi
- Il tipo del file è come segue:
Codice:
type: LoadBalancer
Il file di configurazione del servizio, dovrebbe avere i seguenti campi di default (ovviamente il nome del servizio è un esempio)
Codice:
apiVersion: v1
kind: Service
metadata:
name: example-service
spec:
selector:
app: example
ports:
- port: 8765
targetPort: 9376
type: LoadBalancer
In alternativa, se non si ha un file di configurazione dei servizi, si può generare uno con il comando:
Codice:
kubectl expose rc example --port=8765 --target-port=9376 \
--name=example-service --type=LoadBalancer
In cui rc sta per il replication controller che è nominato con "example", ovviamente siete liberi di decidere il nome del vostro RC senza alcun vincolo.
- Dopo aver analizzato il LoadBalancer o averlo generato con kubectl, bisogna trovare l'IP di ingresso del LoadBalancer, ossia l'IP di comunicazione esterna del servizio localizzato sui nodi del nostro cluster. Per farlo basta digitare il comando:
Codice:
kubectl describe services example-service
Producendo un output come:
Codice:
Name: example-service
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=example
Type: LoadBalancer
IP: 10.67.252.103
LoadBalancer Ingress: 192.0.2.89
Port: <unnamed> 80/TCP
NodePort: <unnamed> 32445/TCP
Endpoints: 10.64.0.4:80,10.64.1.5:80,10.64.2.4:80
Session Affinity: None
Events: <none>
Analizziamo ora i campi:
1. Name - Identifica il nome del servizio
2. Namespace - Identifica il namespace di configurazione del servizio, dato che non abbiamo mai manipolato i servizi né in questo capitolo e neanche in quelli precedenti, si ha il namespace di default
3. Labels & Annotations: Sono delle annotazioni che servono per identificare lo scope del servizio sotto un punto di vista formale, non hanno nessuna valenza sul sistema se non quello di informare il programmatore o all'amministratore del sistema su come usare tale servizio.
4. Selector: Identifica il nome del nostro RC
5. Tipo: LoadBalancer
IP: Dove è localizzato fisicamente, ossia in quale store è presente il servizio in modo da poterlo richiamare all'interno del contesto distribuito (ovviamente si ha trasparenza di locazione, quindi l'utente finale non sa realmente dove si trovi tale servizio, per lui è come se fosse sul suo PC)
6. LoadBalancer Ingress: IP di ingresso al cluster per la comunicazione esterna
7. Port: Porta di ingresso/Protocollo di comunicazione di rete del cluster
8. NodePort: Dato che siamo su un cluster, bisogna definire anche la porta del nodo in cui è localizzato il servizio, ovviamente è un nodo appartenente allo stesso cluster.
Le altre informazioni non sono al momento rilevanti
- Dato che noi eseguiamo i servizi tramite minikube (come anche nel capitolo precedente), siamo in grado di filtrare i dati di configurazione e poterci ricavare l'IP direttamente tramite il comando:
Codice:
minikube service example-service --url
2. Creare una prima applicazione stateless
Dopo aver configurato il LoadBalancer, possiamo ora sporcarci le mani.
Gli obiettivi da raggiungere per poter creare una applicazione stateless di base che giri su Kubernetes sono:
1. Eseguire 5 istanze di una applicazione Hello-World in dei pods
2. Creare un oggetto Service che espone le istanze verso un indirizzo IP esterno (quello del LoadBalancer)
3. Usare il servizio per accedere alle applicazioni in runtime mantenute nei pods
2.1 Eseguire Hello-World in 5 istanze differenti nel cluster
Le applicazioni Hello-World vengono eseguite all'interno dei pods localizzati in nodi del cluster, per poter effettuare tale operazione, abbiamo bisogno di un file di configurazione YAML che dia indicazione su cosa vogliamo fare:
Codice:
# \service\load-balancer-hello-world.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: load-balancer-hello-world
name: hello-world
spec:
replicas: 5
selector:
matchLabels:
app.kubernetes.io/name: load-balancer-hello-world
template:
metadata:
labels:
app.kubernetes.io/name: load-balancer-hello-world
spec:
containers:
- image: gcr.io/google-samples/node-hello:1.0
name: hello-world
ports:
- containerPort: 8080
- Successivamente alla configurazione, andiamo ad applicare tale struttura di esecuzione su Kubernetes utilizzando kubectl
Codice:
kubectl apply -f https://k8s.io/examples/service/load-balancer-example.yaml
Il seguente comando non fa altro che creare il Deployment andando ad associarlo al ReplicaSet che, nel nostro caso, ha 5 pods collegati.
Per visualizzare il campo di configurazione del ReplicaSet basta visualizzare il documento precedente e analizzare nel campo spec:
Codice:
replicas: <number-of-pods>
- Per verificare che il Deployment è avvenuto correttamente:
1. Verifichiamo lo stato del Deployment
Codice:
kubectl get deployments hello-world
kubectl describe deployments hello-world
2. Verifichiamo le informazioni relative al ReplicaSet
Codice:
kubectl get replicasets
kubectl describe replicasets
- Successivamente, andiamo a creare un oggetto Service che esponga il deployment
Codice:
kubectl expose deployment hello-world --type=LoadBalancer --name=my-service
NOTA: Il campo relativo al name del deployment si può analizzare nel file di configurazione YAML sopra indicato.
- Per verificare che il servizio sia attivo, andiamo ad eseguire:
Codice:
kubectl get services my-service
Si avrà un output simile a:
Codice:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-service LoadBalancer 10.3.245.137 104.198.205.71 8080/TCP 54s
NOTA: Se si visualizza nel campo EXTERNAL-IP la voce <pending> significa che dovete attendere 1 minuto e rieseguire il comando per verificare il servizio (a volte si ha una latenza di attivazione molto elevata, non è il nostro caso ma in situazioni in cui si ha un ReplicaSet elevato o applicazioni molto grandi, si risentono gli effetti sull'attivazione ma mai sulle prestazioni)
- Per analizzare tutte le informazioni del servizio:
Codice:
kubectl describe services my-service
Si avranno informazioni simile a:
Codice:
Name: my-service
Namespace: default
Labels: app.kubernetes.io/name=load-balancer-example
Annotations: <none>
Selector: app.kubernetes.io/name=load-balancer-example
Type: LoadBalancer
IP: 10.3.245.137
LoadBalancer Ingress: 104.198.205.71
Port: <unset> 8080/TCP
NodePort: <unset> 32377/TCP
Endpoints: 10.0.0.6:8080,10.0.1.6:8080,10.0.1.7:8080 + 2 more...
Session Affinity: None
Events: <none>
Da questo output possiamo venire a conoscenza di informazioni fondamentali:
1. IP e porte esterne: Rappresentato dal campo del LoadBalancer Ingress, nel caso indicato è 104.198.205.71, per le porte da utilizzare abbiamo quelle del cluster indicate dal campo Port e quelle del nodo indicato con il campo NodePort che, nel nostro caso, sono rispettivamente 8080 e 32377
2. Nome del servizio: Definito dal campo name
3. Endpoints: Indicati dal campo con lo stesso nome, nel nostro caso alcuni Endpoints sono 10.0.0.6:8080,10.0.1.6:8080,10.0.1.7:8080, essi indicano gli indirizzi interni dei vari pods in cui è eseguita l'applicazione Hello-World
NOTA: Gli Endpoints hanno sempre come riferimento la porta del cluster, nel nostro caso la 8080
- Per verificare gli indirizzi interni dei pods basta eseguire:
Codice:
kubectl get pods --output=wide
Cosi da ottenere un output simile a:
Codice:
NAME ... IP NODE
hello-world-2895499144-1jaz9 ... 10.0.1.6 gke-cluster-1-default-pool-e0b8d269-1afc
hello-world-2895499144-2e5uh ... 10.0.1.8 gke-cluster-1-default-pool-e0b8d269-1afc
hello-world-2895499144-9m4h1 ... 10.0.0.6 gke-cluster-1-default-pool-e0b8d269-5v7a
hello-world-2895499144-o4z13 ... 10.0.1.7 gke-cluster-1-default-pool-e0b8d269-1afc
hello-world-2895499144-segjf ... 10.0.2.5 gke-cluster-1-default-pool-e0b8d269-cpuc
Per accedere alle applicazioni stateless ci avvaliamo di un comando shell molto noto: curl
Se non avete scaricato curl, basta farlo da apt:
Codice:
sudo apt install curl
- Eseguiamo ora l'invocazione verso l'IP esterno del cluster sulla porta esposta per accedere all'applicazione
Codice:
curl http://<external-ip>:<port>
In cui <external-ip> è l'IP esterno definito dal campo LoadBalancer Ingress e il campo <port> è uguale alla porta definita dalla voce Port nel file di configurazione
- Nel nostro caso avremo (tratto dal file di configurazione riportato sopra):
Codice:
curl http://104.198.205.71:8080
- L'output di questo comando sarà quello del programma in runtime sul pods:
Codice:
Hello Kubernetes!
NOTA: Ovviamente è possibile accederci anche tramite web browser con lo stesso indirizzo IP associato alla medesima porta.
3. Pulire l'applicazione di prova
Dato che questa è un'applicazione di prova, si può benissimo ripulire il contenuto dei pods e del sistema in generale, ossia andremo a cancellare il deployment e il servizio creati precedentemente andando ad eseguire:
Codice:
kubectl delete services my-service && kubectl delete deployment hello-world
Nella documentazione ufficiale ci sta un esempio carino su come creare un guestbook mantenuto su kubernetes. Per accedere al tutorial basta andare al seguente link
Fonti:
Documentazione Ufficiale di Kubernetes: https://kubernetes.io/docs/home/