INTRODUZIONE
In questo articolo andremo a deployare su Google Cloud Platform un architettura molto comune nel mondo Enterprise. L esempio sara’ composto da:
- Servizio Spring boot che espone un API REST deployato su una VM di Google Cloud
- Il servizio utilizzerà’ un database Mysql con soluzione AS Service offerto da Google Cloud Sql
La soluzione finale e’ illustrata nel seguente immagine
codice sorgente servizio
Il codice sorgente dell applicazione che andremo a deployare e’ molto banale e lo trovatoe pubblicato al seguente REPO.
Partiamo dall’ application.properties del progetto che lo trovato compilato con le settings per girare in locale l applicazione.
# loggin props spring.application.name=hello-ws logging.level.root = DEBUG logging.level.web = DEBUG logging.level.it.italiancoders = DEBUG logging.level.sql = DEBUG logging.level.org.hibernate.SQL=DEBUG #logging.file.path=C:\\logs #logging.file.name=${logging.file.path}\\app.log spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/demo_db spring.datasource.username=root spring.datasource.password=<PASSWORD> spring.jpa.hibernate.ddl-auto=create hello.message = Ciao Mondo
Sostanzialmente l applicazione utilizza un Database Mysql su cui salva il messaggio di hello world identificato dalla propieta’ hello.message .
Infine trovate il controller HelloController il quale espone una API REST in GET e dal path /hello la quale ritorna banalmente il messaggio di hello world letto dal database.
Per comodità’ abbiamo preparato anche l immagine docker che andremo a deployare sulla nostra VM.
FROM openjdk:8-jdk-alpine EXPOSE 8080 COPY target/demo.jar demo.jar ENTRYPOINT ["java", "-jar", "demo.jar"]
Abbiamo pubblicato l immagine del servizio su Docker Hub: dariofrongillo/demo-gcloud.
Se volete testare sulla vostra macchina tale applicazione basterà’ che vi installiate un database mysql con all’interno un database con il nome demo-db o tirando su il database con docker, ad es:
docker run -p 3306:3306 --name hb-mysql-exampl -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=demo-db -d mysql
deploy su google cloud
Andiamo adesso a configurare l ambiente su Google Cloud della nostra demo. Nei seguenti step do per scontato che:
- Siete iscritti a Google Cloud
- Conosciate un minimo i servizi di Compute Engine e di Cloud Sql di Google Cloud
creazione progetto
Creiamo innanzitutto un nuovo progetto Google Cloud dal nome italiancoders-demo
I progetti Google Cloud costituiscono la base per la creazione, l’abilitazione e l’utilizzo di tutti i servizi Google Cloud, compresa la gestione delle API, l’abilitazione della fatturazione, l’aggiunta e la rimozione di collaboratori e la gestione delle autorizzazioni per le risorse di Google Cloud. Per maggiori info su cosa e’ un progetto in google cloud vi rimando alla seguente pagina.
creazione database
Inizieremo con la creazione del nostro database MySql su google cloud. Utilizzeremo Cloud Sql il quale fornisce database relazionali come MySql, PostgreSQL, Sql Server in modalità’ As A Service ovvero come servizio gestito completamente da Google. In breve basterà’ configurare dalla console di google cloud il nostro Database e Cloud Sql automatizzerà’ backup, replica, failover per garantire HA e provisioning dello storage.
Per creare il nostro database MySql, cerchiamo nella console la voce Cloud Sql e procediamo con la creazione del nostro Database MySql.
Modifichiamo anche la questione connettività’ impostandola a Privata.
Su questo punto conviene spendere due parole; vedo molto spesso configurare la connettività’ pubblica aprendo al mondo il database anche quando non serve ( il CIDR 0.0.0.0/0 e’ da persone malvage 😛 ). Nell architettura disegnata nella immagine ad inizio articolo si evince che il database e’ utilizzato solo all’ interno della infrastruttura Cloud e quindi di conseguenza possiamo rendere disponibile il DB solo all’interno della rete privata VPC del nostro progetto di cui farà’ parte anche la VM su cui girerà’ la nostra Spring Boot Application. Se avete bisogno di connettervi dalla vostra macchina per magari far girare script o fare alcune verifiche potete impostare la connettività’ pubblica ma senza autorizzare nessuna rete esterna. Per connettervi potrete usare il Cloud Sql Proxy che instaura per voi una connessione sicura verso il database. Leggi il seguente ARTICOLO per saperne di piu’.
Nelle altre configurazioni potrete anche impostare il tipo di macchina, storage, backup recovery, HA che in questo articolo non specificheremo. A questo punto potremo verificare l istanza di My Sql creata.
La seguente immagine mostra l esito di creazione del nostro servizio My Sql il quale ha il seguente IP e Connection Name:
- 10.19.192.3
- italiancoders-demo:europe-west2:demo-db
creazione vm
A questo punto andiamo a creare la VM su cui deployeremo il nostro servizio Spring.
Colleghiamoci in SSH alla macchina e innanzitutto verifichiamo che essa sia in grado di collegarsi al’ istanza DB My Sql. Dalla console Attraverso il bottone Connect e’ possibile collegarsi in SSH dal browser.
Procediamo quindi a installare un client Mysql sulla VM e verifichiamo che riusciamo a connetterci al DB utilizzando l IP privato dell istanza.
sudo apt-get update ... sudo apt-get install -y default-mysql-client ... mysql -h 10.19.192.3 -u root -p ... MySQL [(none)]> ...
Come possiamo vedere la VM riesce a connettersi al DB facendo parte entrambi della medesima VPC. A questo punto possiamo procedere a deployare la nostra applicazione Spring sulla nostra macchina
INSTALLIAMO DOCKER
La mia VM monta un Debian 10; Per installare Docker potete fare riferimento a questo ARTICOLO.
lanciamo la nostra applicazione
Se lanciassimo l immagine dariofrongillo/demo-gcloud senza specificare nessuna opzione essa lancerebbe la nostra applicazione con i puntamenti specificati nel application properties del jar ( il quale contiene i puntamenti di sviluppo). Spring offre una feature molto versatile per esternalizzare le application properties: Spring a Runtime va a cercare se e’ presente nel path da dove viene lanciato il jar un file application.properties in una subfolder dal nome config, se e’ presente tale file verrà’ caricato. Andremo quindi a creare nella VM una folder /config su cui monteremo un volume docker che punterà’ alla folder /config all’interno del container. Creiamo quindi la folder config e una seconda folder logs che fungera’ da contenitore dei logs ( anche su questa folder monteremo un volume docker).
mkdir logs mkdir config
Andiamo a preparare in locale l application properties che caricheremo nella folder config della VM
# loggin props spring.application.name=hello-ws logging.level.root = DEBUG logging.level.web = DEBUG logging.level.it.italiancoders = DEBUG logging.level.sql = DEBUG logging.level.org.hibernate.SQL=DEBUG logging.file.path=/logs logging.file.name=${logging.file.path}/app.log spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:google:mysql://italiancoders-demo:europe-west2:demo-db/demo_db spring.datasource.username=root spring.datasource.password=<PASSWORD> spring.jpa.hibernate.ddl-auto=create hello.message = Ciao Mondo
A questo punto possiamo caricare il file application.properties appena creato nella folder config della VM utilizzando la funzionalita’ Upload File della shell virtuale del nostro browser ( ricordiamo di fare una move per spostare l application.properties dentro la folder config).
A questo punto possiamo lanciare la nostra applicazione
sudo docker run -p 8080:8080 -d -v "$(pwd)/config":/config -v "$(pwd)/logs":/logs dariofrongillo/demo-gcloud
Possiamo vedere dai log contenuti nella folder /logs che l applicazione e’ correttamente running.
creiamo il servizio http load balanced
Nella precedente sezione abbiamo lanciato la nostra applicazione Spring che girerà’ sulla porta 8080 della VM. Potremmo aprire il firewall della porta 8080 al mondo intero per permettere ai client esterni di interrogare tale API. Questa non e’ l opzione più corretta; Cosa accadrebbe se il carico della nostra applicazione e’ troppo alto e avessimo bisogno di avviare una seconda VM da utilizzare per bilanciare il carico dell API ? La soluzione che utilizzeremo, come evidenziato nel immagine ad inizio articolo, prevede di esporre su Internet il componente Load Balancer . Il Cloud Load Balancer di Google ci porta numerosi vantaggi. Può fornire un bilanciamento del carico semplice e scalabile per oltre un milione di query al secondo. Può anche scaricare l’overhead SSL dalle VM, instradare le query nella migliore regione per gli utenti in base sia alla posizione che alla disponibilità e supportare protocolli moderni come HTTP / 2 e QUIC.
Per questa esercitazione, si sfrutta un’altra caratteristica chiave: il proxy globale della connessione IP. Questa funzione fornisce un unico indirizzo IP usato dai client i quali possono quindi connettersi alle risorse ospitate su indirizzi IP privati ovunque in Google Cloud. Questa configurazione aiuta a proteggere le istanze dagli attacchi DDoS e dagli attacchi diretti. Inoltre, consente funzionalità come Google Cloud Armor per una sicurezza ancora maggiore.
Gli step che dobbiamo seguire sono:
- Creare una regola firewall per consentire l’accesso alla nostra VM da parte del load balancer
- Allocare un indirizzo IPv4 statico e globale per il load balancer
- Creazione di un instance group che raccoglierà’ le tue istanze.
firewall
Dal menu firewall andiamo a creare la regola allow-lb-and-healthcheck per consentire il traffico dal load balancer alla VM.
In breve abbiamo aperto per i CIDR del load balancer la porta 8080 a tutte le VM che usano il tag network allow-lb-and-healthcheck. Quindi dopo aver creato questa regola del Firewall occorre aggiornare la VM e applicare sulla istanza demo-vm il tag allow-lb-and-healthcheck.
creazione istance group
I servizi di load balancing di Google Cloud richiedono che i gruppi di istanze fungano da backend per il traffico. In questo tutorial useremo i gruppi gestiti manualmente ma e’ anche possibile utilizzare istance group gestiti in maniera automatica per sfruttare funzionalità quali il ridimensionamento automatico, la correzione automatica, la distribuzione regionale (multi-zona) e l’aggiornamento automatico. Ecco la nostra configurazione dell Istance Group
In breve abbiamo configurato :
- un gruppo dal nome hello-vm-group composto da una singola VM: la nostra demo-vm. Se un domani avessimo bisogno di scalare potremmo inserire nel gruppo altre VM per bilanciare il carico.
- una port name mapping: endpoint-port la quale rappresenta la porta 8080 sulla quale il load balancing dovra’ inoltrare il traffico
load balancing: configurazione backend e health check
Andiamo quindi a creare il servizio backend del nostro load balancer che riferirà’ al gruppo di VM identificato dall istance group appena creato.
In breve abbiamo configurato
- Named Port che il load balancing utilizza per indirizzare il traffico verso il gruppo
- health check, che esegue il polling delle istanze per vedere se sono integre. Il load balancing del carico invia il traffico solo a istanze integre. Per semplicità’ abbiamo usato di nuovo l api /hello. Per completezza occorre usare l endpoint esposto da Spring Actuator per monitorare lo stato di salute dell’applicazione.
- Servizio di backend collegato all istance group creato nello step precedente
load balancing: host e regole di path
Nella configurazione del servizio di Load Balancing ci e’ permesso di definire le regole che sulla base delle URL delle richieste verranno utilizzate per dirottare le richieste all istance group di riferimento. In questo esercizio, poiché non si utilizza l’inoltro basato sul contenuto, la mappa URL contiene solo la mappatura predefinita.
load balancing: configurazione frontend
Il frontend del Google Load Balancing sara’ l interfaccia esposta su internet che i vostri client interrogheranno per accedere alle vostre API.
Fate attenzione sulla selezione della tipologia dell IP; se selezionate l opzione Ephemeral significa che l IP potrebbe cambiare con il tempo. Nel mio esempio ho riservato un IP statico. Nello screen abbiamo configurato il frontend in attesa sulla porta 80.
riepilogo configurazione
Abbiamo quindi configurato il load balancer per esporre ai client l interfaccia all IP 34.102.186.80 e porta 80. Tutte le richieste verranno redirette al backend hello-backend-service che e’ collegato al gruppo di istanze VM hello-vm-group che in questo momento riferisce ad una sola VM: hello vm. A questo punto possiamo testare dal nostro browser accedendo all URL http://34.102.186.80/hello il quale mostrerà’ la risposta attesa: Ciao Mondo.