il nostro primo deploy sy k8s
Ciao a tutti coders,
inizio con la citazione di un amico
Kubernetes e’ come il sesso tra adolescenti, tutti ne
parlano ma pochi lo fanno
Scherzi a parte Kubernetes e’ oramai il presente da un po di tempo e sara’ sempre di più il futuro che sembra remare in maniera decisa sul mondo dei software cloud ready.
scopo dell articolo
Lo scopo di questo articolo non e’ spiegare Kubernetes ( abbreviato successivamente con l acronimo K8s) in quanto pure io sono alle prime armi su K8s e trovo comunque veramente riduttivi gli articoli che tentano di spiegare K8s in poche righe. Kubernetes e’ una piattaforma che ha bisogno di essere studiata con attenzione. Segnalo le seguenti fonti su cui sto studiando Kubernetes magari vi possono essere d aiuto
Lo scopo di questo articolo e’ un esercizio che ha il fine di deployare una architettura a microservizi in versione semplificata su un cluster Kubernetes di sviluppo. Andremo infatti a deployare i microservizi sotto descritti su un cluster mono-nodo che gira in locale.
prerequisti
Per poter comprendere questo articolo occorre:
- avere le basi di Kubernetes e Docker.
- avere un cluster kubernetes configurato in locale (puoi utilizzare minikube o docker desktop)
- avere le basi di Spring Boot
- conoscenza dei principi di un architettura a microservizi
tutorial Post e Commenti
L’ esercizio che andremo a realizzare e’ una versione molto semplificata di un social network basato su una architettura a microservizi. L obbiettivo e’ quello di realizzare delle API per pubblicare e gestire Post e Commenti come in un social network. Di seguito le API che offriremo ai nostri client:
- GET /posts: Ritorna una lista di Post
- GET /posts/{id}: Ritorna il Post con id specificato
- POST /posts: Aggiunge un post come da richiesta nel body
- PUT/posts/{id}: Aggiorna il Post con id specificato come da richiesta nel body
- DELETE /posts/{id}: Elimina il Post con id specificato
- GET /posts/{id}/comments: Ritorna i commenti del Post con id specificato
- POST /posts/{id}/comments: Aggiunge il commento al Post con id specificato come da commento riportato nel body
La soluzione implementata e’ molto banale e non gestisci autenticazione/autorizzazione. Il motivo e’ quello di posizionare il focus dell articolo sul deploy su kubernetes di due semplici microservizi. Siete liberi di raffinare la soluzione forkando il mio repository.
architettura SOFTWARE
Andremo a sviluppare un architettura con le seguenti caratteristiche
- Infrastruttura su Kubernetes: Deployeremo i nostri microservizi su un cluster K8s con un singolo nodo e cercheremo di risolvere i problemi di service discovery e load balancing lato server/infrastruttura con K8s anziché’ Spring Cloud. Questa e’ veramente una grossa novità’ per gli sviluppatori Spring, i quali si potranno concentrare esclusivamente sulla logica business del microservizio che stanno sviluppando, poiche’ service discovery, load balancing, circuit breaker saranno realizzati in maniera trasparente configurando opportunamente l’infrastruttura di K8s. In questo modo:
- il codice del singolo microservizio e’ più semplice
- l architettura e’ più facilmente scalabile
- l architettura e’ finalmente poliglotta e quindi per lo sviluppo di un singolo microservizio non siamo piu’ obbligati ad utilizzare Java e Spring ma bensi’ il team sceglierà’ lo stack che ritiene più opportuno a risolvere i problemi di un microservizio
- Servizi sviluppati: divideremo il dominio in due microservizi: post-ws e comment-ws . Trattasi di una scelta puramente didattica, in un contesto reale con quasi certezza implementerei post e commenti all’interno del solito microservizio.
- ogni microservizio avrà’ un database mysql dedicato per lo storage dei dati del proprio dominio
- scaleremo il carico dei due microservizi tirando su istanze del microservizio e bilanciando il carico in maniera round robin
- Il microservizio Post-ws oltre a gestire in autonomia le richieste inerenti ai Post, fara’ da orchestratore del microservizio Comment-ws andando a contattare il microservizio comment-ws quando ha bisogno dei dati relativi ai commenti e aggregando quindi i dati di propria competenza con quelli dei commenti. Non e’ una soluzione pulitissima; di solito in letteratura si risolve questo problema sviluppando un terzo microservizio ( aggregator pattern) o aggregando i dati di diversi microservizi sul gateway.
Ecco una anteprima dell architettura che tireremo sul nostro cluster kubernetes che per semplicità’ sara’ composto da un solo nodo.
step 0: codice sorgente
Trovate il codice sorgente di questo esercizio sul mio REPO
All’interno del repo trovate le seguenti cartelle:
- post-ws: codice sorgente microservizio post
- comment-ws: codice sorgente microservizio comment
- k8s: file yaml contenenti le dichiarazioni per creare gli object kubernetes che compongono la nostra architettura.
POST-WS
Il codice sorgente del microservice Post lo trovate al seguente URL
Analizziamo le properties del microservizio post-ws e la sua immagine docker.
Ho due profili di application properties: dev e docker. Dev lo utilizzo quando sviluppo in locale mentre docker e’ quello che utilizzo per buildare la mia immagine docker.
application.properties
Carico a runtime le properties del profilo passato come variabile d ambiente SPRING_PROFILE o se non presente carico il profilo dev ( profilo utilizzato per sviluppare in locale con puntamenti statici al db e agli altri servizi che girano in locale)
spring.profiles.active=${SPRING_PROFILE:dev}
application.docker
server.port = 8080 spring.application.name= post-ws instance.instance-id=${spring.application.name}:${spring.application.istance_id:${random.value}} logging.level.org.springframework=INFO logging.level.it.italiancoders.postws=INFO logging.level.com.zaxxer=DEBUG logging.level.root=ERROR #show sql statement logging.level.org.hibernate.SQL=debug #show sql values logging.level.org.hibernate.type.descriptor.sql=trace spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver #$ docker run -p 3307:3306 --name hb-mysql-example -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=post_db -d mysql spring.datasource.url=jdbc:mysql://${MYSQL_HOST_POST_DB}:${MYSQL_PORT_POST_DB}/post_db spring.datasource.username=${MYSQL_ROOT_USERNAME_POST_DB} spring.datasource.password=${MYSQL_ROOT_PASSWORD_POST_DB} spring.jpa.hibernate.ddl-auto=create #service discovery info comments_ws.ip=${COMMENT_WS_IP} comments_ws.port=${COMMENT_WS_PORT}
Come si evince dal file di properties, utilizziamo le Environment variables per gestire i valori delle configurazioni come indirizzi e porte dei servizi che utilizzerà’ il nostro microservizio:
- configurazione e indirizzi del db mysql utilizzato per storage dei dati relativi ad un Post.
- indirizzo e porta del microservizio Comment-ws: Abbiamo seguito il principio di singola responsabilita’: il servizio post-ws gestisce in autonomia solo i Post; Quando sono richiesti i commenti sara’ necessario invocare il microservizio comment-ws. Servirà’ quindi conoscere l IP e la porta del microservizio comment-ws. I più’ attenti si staranno già chiedendo come mai un singolo IP? Se ho 4 istanze running del microservizio Comment-ws come faccio a gestire il tutto con un unico indirizzo IP? Abbiate un attimo pazienza. Nella sezione dedicata ai service kubernetes vi spieghero’ come risolveremo il problema di service discovery e load balancing in questo esercizio.
Infine riportiamo l immagine docker del microservizio Post-ws.
FROM openjdk:8-jdk-alpine EXPOSE 8080 COPY target/post-ws.jar post-ws.jar ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=docker", "post-ws.jar"]
COMMENT WS
Il codice sorgente del microservice Comment lo trovate al seguente URL
Vale quanto detto dal microservizio Comment-ws. Riporto per completezza l application properties e il Dockerfile.
application.properties
application.docker.properties
Dockerfile
spring.profiles.active=${SPRING_PROFILE:dev}
server.port = 8081 spring.application.name= comment-ws instance.instance-id=${spring.application.name}:${spring.application.istance_id:${random.value}} logging.level.org.springframework=INFO logging.level.it.italiancoders.postws=INFO logging.level.com.zaxxer=DEBUG logging.level.root=ERROR #show sql statement logging.level.org.hibernate.SQL=debug #show sql values logging.level.org.hibernate.type.descriptor.sql=trace spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver #$ docker run -p 3307:3306 --name hb-mysql-example -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=comment_db -d mysql spring.datasource.url=jdbc:mysql://${MYSQL_HOST_COMMENT_DB}:${MYSQL_PORT_COMMENT_DB}/comment_db spring.datasource.username=${MYSQL_ROOT_USERNAME_COMMENT_DB} spring.datasource.password=${MYSQL_ROOT_PASSWORD_COMMENT_DB} spring.jpa.hibernate.ddl-auto=create
FROM openjdk:8-jdk-alpine EXPOSE 8081 COPY target/comment-ws.jar comment-ws.jar ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=docker", "comment-ws.jar"]
CONFIGURAZIONE K8S
Prima di passare alla configurazione di Kubernetes (pod, controller, ecc.), È importante comprendere il modello dichiarativo di Kubernetes. Kubernetes ha anche modalità imperative, ma ci concentreremo sul modello dichiarativo e sugli stati desiderati. Se vuoi saperne di più ti suggerisco il seguente articolo. In breve andremo a scrivere dei file YAML che descriveranno lo stato desiderato dell’applicazione: quale immagine Docker dovrebbe essere eseguita, quale strategia di ridimensionamento usare e quali porte / servizi esporre. Queste informazioni vengono inviate al server kube-api attraverso il comando
kubectl apply -f <fileconfig>
e il master node distribuisce il lavoro per garantire che il cluster corrisponda allo stato desiderato. Questa configurazione viene archiviata in etcd e il carico di lavoro viene distribuito nel cluster. Infine, Kubernetes verificherà costantemente se lo stato corrente del cluster corrisponde al comportamento desiderato definito dal programmatore. Quindi, se un pod muore, Kubernetes ne fara’ partire un altro per garantire lo stato desiderato nel cluster.
Anche se tutto ciò sembra semplice, è un potente schema che rende Kubernetes molto utile. Tu (il programmatore) devi solo specificare lo stato desiderato, e Kubernetes si prenderà cura di tutto il resto (invece di aver eseguito comandi specifici per raggiungere questo obiettivo come nei modelli imperativi).
Nella soluzione di questo articolo utilizzeremo i seguenti tipi di oggetti kubernetes:
- pod
- service
- persitent volume e persitent volume claim
- secret
- ingress
Faro’ una brevissima panoramica degli object di K8s che utilizzeremo
POD
Iniziamo con l analizzare il componente POD.
I pod sono le unità distribuibili più piccole che possono essere create e gestite in Kubernetes.
Un Pod è un gruppo di uno o più container con memoria / rete condivisa e una specifica su come eseguire i container. Nessun pod può esistere senza un container. Ma ci possono essere pod a container singolo o pod a container multiplo a seconda dell’applicazione che implementiamo. Un’altra piccola cosa da ricordare sui Pod è che sono “mortali” o meglio hanno un ciclo di vita a 3 fasi
In attesa → In esecuzione → Riuscito / Non riuscito
Questo è simile a Born → Living → Dead. Non ci sarà risurrezione; nessuna rinascita. Se un Pod è morto senza aver completato il suo compito, verrà creato un nuovo Pod per sostituire il Pod morto. La cosa più importante è che l’IP di questo nuovo pod saranno diversi dal pod morto. In aggiunta possiamo configurare Kubernates per creare piu’ di un istanza replica di un Pod per poter scalar orizzontalmente la nostra architettura.
service
Come ho detto prima, i pod sono mortali. Quando un pod muore, ne nasce uno nuovo per prendere il suo posto. Non ha pero’ lo stesso indirizzo IP di quello morto.
Pensa quindi allo scenario del nostro tutorial. Dal microservizio Post-ws per chiamare il servizio Comment-ws abbiamo bisogno dell IP e porta di quest’ultimo. Supponiamo di aver utilizzato l’IP del Comment-ws all’interno del codice del servizio Post-ws. Ci troviamo di fronte a tre problemi:
- Dobbiamo prima deployare il micro servizio comment-ws e prendere il suo IP.
- Non siamo in grado di gestire piu’ istanze del microservizio comment-ws
- Se il pod Commen-ws muore, K8s ri-creera’ il Pod con un nuovo IP
Insomma la gestione diventa parecchio problematica; per questo abbiamo bisogno di un nuovo Object i service.
esempio servizio frontend che deve contattare il pod backend configurato per avere diverse repliche ( https://medium.com/javarevisited/kubernetes-step-by-step-with-spring-boot-docker-gke-35e9481f6d5f). Medesima situazione di quella proposta in questo articolo
Come si evince dal immagine sopra il service ha un proprio indirizzo IP e DNS che sono stabili. Quindi utilizzeremo questa soluzione anche per il nostro esercizio per permettere ad un Pod di collegarsi ad un altro Pod (quindi sia per invocare i microservizi tra loro che per il collegamento al db). Il singolo pod Post-ws utilizzerà come indirizzo IP dei Commenti il DNS del servizio che gestisce i Pod del Comment-ws. Quando una richiesta arriva al Servizio di comment-ws, esso bilancerà’ le richieste tra le diverse repliche del comment-ws. Concludo dicendo che l’uso dell object Service ci offre altri molti vantaggi, come l’inoltro di richieste solo a pod sani, il bilanciamento del carico, il rollback delle versioni, ecc. Ma il vantaggio più importante di un servizio è il disaccoppiamento dei componenti del sistema.
Andiamo a leggere i file yaml contenenti le configurazione dei pod e service per i nostri due microservizi post-ws e comment-ws
comment-ws
comment-ws-deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: comment-ws-deployment spec: replicas: 4 selector: matchLabels: component: comment-ws template: metadata: labels: component: comment-ws spec: containers: - name: comment-ws image: dariofrongillo/comment-ws:1.0.1 ports: - containerPort: 8081 env: - name: MYSQL_ROOT_USERNAME_COMMENT_DB value: root - name: MYSQL_ROOT_PASSWORD_COMMENT_DB valueFrom: secretKeyRef: name: dbpassword key: MYSQL_ROOT_PASSWORD_COMMENT_DB - name: MYSQL_HOST_COMMENT_DB value: mysql-comment-cluster-ip-service - name: MYSQL_PORT_COMMENT_DB value: '3306' - name: SPRING_PROFILE value: docker
Il nostro deployment dichiara a K8s
- di volere 4 repliche del pod comment-ws
- il pod conterra al suo interno un solo container con immagine dariofrongillo/comment-ws:1.0.1
- per le label vi consiglio di leggere il seguente LINK. Le labels sono dei metadata che possono essere associati a qualsiasi oggetto Kubernates. Consentono di etichettare oggetti, in modo da poterli facilmente recuperare, ricercare ed interrogare. In un ambiente composto da numersosi pods, le label sono sicuramente un ottimo strumento per poter raggruppare e individuare facilmente un’insieme di pods. In pratica, sono un ottimo strumento per organizzare i pods.
comment-ws-cluster-ip-services.yaml
apiVersion: v1 kind: Service metadata: name: comment-ws-cluster-ip-service spec: type: ClusterIP selector: component: comment-ws ports: - port: 8081 targetPort: 8081
Lo yaml definisce il servizio che gestisce i pod che hanno labels comment-ws. Grazie a label e selector K8s riesce quindi a realizzare la service discovery.
Abbiamo utilizzato un tipo specifico di servizio kubernetes, ClusterIp: questo tipo espone il servizio su un IP interno al cluster. La scelta di questo valore rende il servizio raggiungibile solo all’interno del cluster. Questo è il tipo di servizio predefinito. I nostri servizi non saranno raggiungibili direttamente da fuori del cluster perciò’ abbiamo utilizzato questo tipo.
Quindi il microservizio post-ws potra interrogare uno dei pod running sparando una richiesta al service di comment ws al seguente indirizzo http://comment-ws-cluster-ip-service:8081 . Sara’ compito del servizio bilanciare le richieste ai pod running di comment-ws.
post-ws
Il concetto per configurare post-ws e il suo service e’ il medesimo.
Al seguente URL trovate il deployment file del pod post-ws mentre a questo URL la configurazione del suo servizio.
database
Configurare un database su un cluster con repliche e alta affidabilità’ e’ sempre un operazione ardua. Se non si ha le giuste competenze nel team valutare sempre la possibilità’ di utilizzare un database as service come ad esempio RDS di AWS o Cloud Sql di Google Cloud per l ambiente di produzione.
L’ esempio di questo articolo e’ un deploy su un cluster K8S di un solo nodo adatta ad un ambiente di sviluppo e test. Pertanto ci faremo alcuni “sconti” nella configurazione degli storage. Prima di creare i Pod dei nostri due database mysql e i loro relativi volumi andremo a creare un Secret per salvare le due password dei nostri db mysql.
secret
Un secret è un oggetto che contiene una piccola quantità di dati sensibili come una password, un token o una chiave. Tali informazioni possono essere lette dai nostri Pod. Nel nostro esempio con la cli di kubectl andremo a creare il secret con il seguente comando
kubectl create secret generic dbpassword --from-literal MYSQL_ROOT_PASSWORD_POST_DB=password123 --from-literal MYSQL_ROOT_PASSWORD_COMMENT_DB=password123
Ad esempio, come visto sopra, il pod comment-ws e’ stato definito con una env MYSQL_ROOT_COMMENT-DB presa dal secret dbpassword appena creato
- name: MYSQL_ROOT_PASSWORD_COMMENT_DB valueFrom: secretKeyRef: name: dbpassword key: MYSQL_ROOT_PASSWORD_COMMENT_DB
persistent volume e persistent volume claim
Lo storage dei container tramite il file system root di un contenitore è effimera e può scomparire dopo la cancellazione e la creazione del contenitore. Per fornire una posizione “durabile” in cui archiviare i dati e prevenirne la perdita, è possibile creare e utilizzare volumi persistenti per archiviare i dati all’esterno dei contenitori. Per risolvere questi problemi introduciamo due nuovi oggetti di K8S: Persitent Volume e Persistent Volume Claim.
Un PersistentVolume (PV) è un pezzo di storage nel cluster che è stato fornito da un administrator o dinamicamente fornito usando le Storage Classes. È quindi una risorsa nel cluster proprio come un nodo è una risorsa cluster. I PV hanno un ciclo di vita indipendente da ogni singolo Pod che utilizza il PV. Questo oggetto acquisisce i dettagli dell’implementazione dell’archiviazione, che sia NFS, iSCSI o un sistema di archiviazione specifico del provider cloud.
Un PersistentVolumeClaim (PVC) è una richiesta di archiviazione da parte di un utente. È simile ad un Pod. Infatti come i pod consumano risorse di un nodo, i PVC consumano PV. I pod possono richiedere livelli specifici di risorse (CPU e memoria). I Claims possono richiedere dimensioni e modalità di accesso specifiche (ad es. Possono essere montati una volta in lettura / scrittura o molte volte in sola lettura).
I concetti attorno ai volumi persistenti sono sicuramente uno dei topic più complessi da apprendere quindi vi rimando al LINK per una spiegazione dettagliata.
Nel nostro esercizio abbiamo creato:
- due volumi persistenti hostPath. Kubernetes supporta hostPath per lo sviluppo e il test su un cluster a nodo singolo. Un hostPath PersistentVolume utilizza un file o una directory sul nodo per emulare l’archiviazione collegata alla rete. Essendo il nostro cluster composto da un nodo questa configurazione é sufficiente.
- due persistent volume claim che utilizzeranno i pod utilizzano per richiedere l’archiviazione fisica.
mysql-pv.yaml
apiVersion: v1 kind: PersistentVolume metadata: name: mysql-pv-volume-1 labels: type: local-1 spec: storageClassName: manual capacity: storage: 1Gi accessModes: - ReadWriteOnce hostPath: path: "/mnt/data-pv1" --- apiVersion: v1 kind: PersistentVolume metadata: name: mysql-pv-volume-2 labels: type: local-2 spec: storageClassName: manual capacity: storage: 1Gi accessModes: - ReadWriteOnce hostPath: path: "/mnt/data-pv2" --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-pv-claim-post-ws spec: storageClassName: manual accessModes: - ReadWriteOnce resources: requests: storage: 1Gi --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-pv-claim-comment-ws spec: storageClassName: manual accessModes: - ReadWriteOnce resources: requests: storage: 1Gi
Una nota: In un cluster di produzione, non utilizzare hostPath come volumi. Un administrator in produzione dovrebbe eseguire il provisioning di una risorsa di rete come un disco persistente di Google Compute Engine, una condivisione NFS o un volume di Amazon Elastic Block Store.
pod database
A questo punto, possiamo dichiarare i deployment file dei due database utilizzati dai microservice post e comment e i service necessari per poter accedere ai database tramire il loro DNS. Riporto solo la configurazione del pod del database dei post; il deployment yaml del database dei commenti e il relativo service li trovate nel repository del progetto.
mysql-post-db-deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: mysql-post-db-deployment spec: replicas: 1 selector: matchLabels: component: mysql-post strategy: type: Recreate template: metadata: labels: component: mysql-post spec: volumes: - name: mysql-persistent-storage persistentVolumeClaim: claimName: mysql-pv-claim-post-ws containers: - name: mysql image: mysql:5.6 ports: - containerPort: 3306 volumeMounts: - name: mysql-persistent-storage mountPath: /var/lib/mysql env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: dbpassword key: MYSQL_ROOT_PASSWORD_POST_DB - name: MYSQL_DATABASE value: post_db
mysql-post-db-cluster-ip-service.yaml
apiVersion: v1 kind: Service metadata: name: mysql-post-cluster-ip-service spec: type: ClusterIP selector: component: mysql-post ports: - port: 3306 targetPort: 3306
ingress
I service di tipo ClusterIp espongono il servizio su un IP interno al cluster e pertanto i nostri microservizi, come giusto che sia, non sono raggiungibili al di fuori del cluster. Date un occhio di nuovo all immagine dell architettura del nostro esercizio. Abbiamo bisogno di rendere accessibili all’ esterno le API del microservizio Post-ws. Per fare questo abbiamo bisogno di configurare Ingress: un object di K8s che gestisce gli accessi esterni al cluster ai servizi interni al cluster come nel nostro caso il service dei Post.
internet | [ Ingress ] --|-----|-- [ Services ]
Nel nostro esempio abbiamo utilizzato Nginx Ingress. Esistono diversi modi per installare Nginx Ingress nel proprio cluster e alcuni di questi dipendono dal vostro OS. Trovate le istruzioni di setup a questo LINK. La mia macchina di sviluppo ha Windows come OS e ho installato il cluster K8s con Docker for Desktop e pertanto mi e’ bastato eseguire il seguente comando
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-0.32.0/deploy/static/provider/cloud/deploy.yaml
Una volta installato ingress potete verificare se tutto e’ andato a buon fine eseguendo
kubectl get pods -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --watch
Una volta installato ingress occorre configurare le route da applicare inviando a K8s lo yaml di configurazione
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress-service annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/rewrite-target: /$1 spec: rules: - http: paths: - path: /post-ws/?(.*) backend: serviceName: post-ws-cluster-ip-service servicePort: 8080
In questo modo abbiamo configurato ingress per redirigere tutte le richieste http che iniziano con /post-ws al service di post-ws e a rimuovere infine tale prefisso. Pertanto nel mio esempio la seguente richiesta
http://localhost/post-ws/posts verra’ gestita all interno del cluster con il seguente URL http://post-ws-cluster-ip-service:8080/posts
applichiamo le configurazioni e testiamo il tutto
Abbiamo descritto tutti i file yaml da applicare sul nostro cluster K8S. Li trovate cmq disponibili al seguente URL. Dopo aver installato Ingress Nginx e creato il secret dei database potete comunque inviare tutte le configurazioni in un colpo solo passando al comando apply la folder contente i file yaml
kubectl apply -f k8s/
Potrete verificare i deployments e service applicati a k8s
PS C:\Users\Dario> kubectl get deployments NAME READY UP-TO-DATE AVAILABLE AGE comment-ws-deployment 4/4 4 4 8d mysql-comment-db-deployment 1/1 1 1 8d mysql-post-db-deployment 1/1 1 1 8d post-ws-deployment 3/3 3 3 8d PS C:\Users\Dario> kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE comment-ws-cluster-ip-service ClusterIP 10.106.126.10 <none> 8081/TCP 8d kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 8d mysql-comment-cluster-ip-service ClusterIP 10.108.191.13 <none> 3306/TCP 8d mysql-post-cluster-ip-service ClusterIP 10.106.147.220 <none> 3306/TCP 8d post-ws-cluster-ip-service ClusterIP 10.107.179.55 <none> 8080/TCP 8d
e potrete verificare lo stato dei vostri Pod in modo da assicurarvi che siano tutti Running
PS C:\Users\Dario> kubectl get pods NAME READY STATUS RESTARTS AGE comment-ws-deployment-6fbd48c545-78cgh 1/1 Running 0 8d comment-ws-deployment-6fbd48c545-9tfzh 1/1 Running 0 8d comment-ws-deployment-6fbd48c545-m6rfg 1/1 Running 0 8d comment-ws-deployment-6fbd48c545-v46gl 1/1 Running 0 8d mysql-comment-db-deployment-5bd584f666-vjggt 1/1 Running 0 8d mysql-post-db-deployment-686cd9d966-j8x2s 1/1 Running 0 8d post-ws-deployment-589864f477-6fx8q 1/1 Running 0 8d post-ws-deployment-589864f477-md5zq 1/1 Running 0 8d post-ws-deployment-589864f477-qd47z 1/1 Running 0 8d
Se per caso un Pod non e’ Running ed e’ in errore, potrete consulare i log di quest ultimo in modo da capire la causa del malfunzionamento con il comando
kubectl logs <podname>
Una volta assicurato che tutto sia Running potrete iniziare ad inviare Richieste Http alla nostra applicazione che gira su K8s ricordandoci che abbiamo configurato Ingress con il prefisso /post-ws. Ad esempio
GET localhost/post-ws/posts response 200 []
conclusioni
In questo articolo abbiamo configurato un cluster con un singolo nodo utile per sviluppare e testare la nostra applicazione Social di esempio. La soluzione proposta va’ sicuramente migliorata ed estesa in quanto non abbiamo gestito:
- monitoring
- tracing
- circuit breaker
- autenticazione e autorizzazione
Raffineremo con queste features la nostra soluzione nei prossimi articoli.
https://italiancoders.it/esempio-di-un-deploy-di-un-architettura-a-microservizi-su-kubernetes/