Anthos Service Mesh (ASM) è l'installazione gestita di Istio, il service mesh per Kubernetes. Ecco la nostra guida passo passo per configurare un ASM multi-cluster con control plane gestito.

Una guida pratica e passo passo per configurare un Anthos Service Mesh (ASM) multi-cluster con control plane gestito.
Il codice di accompagnamento è disponibile qui: https://github.com/caddac/anthos-examples/tree/main/asm
Un service mesh è un'astrazione che si appoggia a diverse piattaforme di compute – in questo caso i cluster – per semplificare la comunicazione tra servizi, l'osservabilità e la sicurezza. Sposta queste responsabilità a livello di piattaforma e rende più snella l'applicazione. In questo articolo distribuiremo Anthos Service Mesh, ovvero l'installazione gestita di Istio. Istio è un service mesh per Kubernetes, uno strumento potente per ottenere visibilità coerente su osservabilità e sicurezza nelle comunicazioni service-to-service. Con Istio, il risultato si ottiene facendo passare tutto il traffico tra servizi attraverso proxy eseguiti come sidecar dei pod.
I servizi sfruttano i pattern coerenti e trasparenti di Istio per dialogare tra loro, senza doversi preoccupare di come raggiungere un altro servizio, di proteggersi dalle richieste in ingresso o di pubblicare metriche sul traffico inter-servizio. Se ne occupa Istio. Sono funzionalità tanto più preziose in una configurazione multi-cluster, dove l'overhead operativo è ben più elevato.
Adottare un service mesh comporta però anche qualche svantaggio: complessità di setup, consumo di risorse e costi. Istio offre numerose funzionalità e diversi modi per configurarlo, tra cui istioctl, IstioOperator e helm. Anthos Service Mesh con control plane gestito, però, non supporta né l'API IstioOperator né helm.
In questo tutorial creeremo due cluster GKE e vi distribuiremo l'applicazione hello-world di Istio. Installeremo poi un singolo ingress (su un solo cluster) e mostreremo come il traffico venga bilanciato tra i 4 pod hello-world in esecuzione sui due cluster GKE.

Distribuire il terraform
Nella directory asm/infra, aggiorni i valori nel file var_inputs.auto.tfvars.
Esegua plan e apply:
$ terraform init
$ terraform apply
Nota: se l'apply va in errore, riprovi. A volte terraform corre troppo nell'applicare così tante risorse dipendenti tutte insieme. Ho dovuto eseguirlo tre volte per riuscire a creare tutte le risorse.
Sta succedendo parecchio, quindi vediamolo brevemente.
Distribuisce un nuovo progetto GCP e abilita diverse API necessarie [1]. Una nota rapida: la documentazione ufficiale sembra non includere le API sts e anthos, quindi si assicuri di abilitarle.
Distribuisce inoltre una VPC, due subnet con range secondari e una regola firewall che consente la comunicazione. Infine, attiva la funzionalità hub mesh per il progetto.
Ciascun file distribuisce un cluster. Differiscono solo per i nomi dei cluster, le region e i riferimenti alle subnet. Due aspetti da segnalare nella configurazione del cluster. Primo: abbiamo impostato la label mesh_id, così GCP sa a quale mesh appartiene il cluster. Secondo: abbiamo abilitato Workload Identity, che consente ai service account di Kubernetes di operare come service account GCP [2] senza dover scaricare né creare chiavi JSON.
Registriamo il cluster nel fleet usando il nome del cluster come membership id.
Infine, installiamo il control plane gestito. Stiamo usando il control-plane automatico (che sta per "managed"), ma quale revision? Controlli la label revision sul namespace per scoprire quale revision del control plane è in uso [5]. Sì, è davvero così semplice!
A questo punto abbiamo due cluster nello stesso fleet, entrambi con ASM installato tramite control plane gestito. Possiamo quindi iniziare a installare i componenti Istio, anche se la service discovery cross-cluster non è ancora attiva.
Configurare la service discovery cross-cluster
Dobbiamo installare i secret di ogni cluster su tutti gli altri cluster del fleet. Per fortuna esiste uno strumento da riga di comando dedicato: asmcli. Purtroppo non funziona ancora su macOS, quindi conviene eseguirlo dalla cloud console.
Apra la cloud console nel suo progetto: vada nella console GCP e clicchi sul pulsante della cloud console.

Quando la console compare nella parte inferiore dello schermo, esegua i seguenti comandi:
$ curl https://storage.googleapis.com/csm-artifacts/asm/asmcli\_1.13 > asmcli
$ chmod +x asmcli
_$ ./asmcli create-mesh ${GOOGLE_CLOUD_PROJECT} _
_${GOOGLE_CLOUD_PROJECT}/us-west1/${GOOGLE_CLOUD_PROJECT}-cluster1 _
${GOOGLE_CLOUD_PROJECT}/us-east1/${GOOGLE_CLOUD_PROJECT}-cluster2

Una nota rapida: se utilizza cluster privati, sono necessari ulteriori passaggi per abilitare la service discovery cross-cluster [6][7].
Distribuire le app e i componenti Istio
Dalla directory asm/manifests possiamo installare le app per testare il mesh. Sul cluster 1 installeremo l'app helloworld e i componenti Istio per l'ingress.
Inizi recuperando i context dei cluster:
export PROJECT_ID=<gcp_project_id>
gcloud container clusters get-credentials ${PROJECT_ID}-cluster1 --region us-west1 --project ${PROJECT_ID}
gcloud container clusters get-credentials ${PROJECT_ID}-cluster2 --region us-east1 --project ${PROJECT_ID}
Installi il cluster 1 con:
kubectl apply -k manifests/ --context=gke_${PROJECT_ID}_us-west1_${PROJECT_ID}-cluster1
E il cluster 2 con:
kubectl apply -k manifests/app/ --context=gke_${PROJECT_ID}_us-east1_${PROJECT_ID}-cluster2

Verificare il risultato
Dopo qualche minuto dovrebbe essere tutto attivo e potrà controllare il risultato.
Verifichi che tutti i pod helloworld siano in esecuzione su entrambi i cluster:
$ export PROJECT_ID=<gcp_project_id>
$ kubectl get pods -n helloworld
--context=gke_${PROJECT_ID}_us-west1_${PROJECT_ID}-cluster1
$ kubectl get pods -n helloworld
--context=gke_${PROJECT_ID}_us-east1_${PROJECT_ID}-cluster2

Verifichi che il deployment ingress-gateway sia in esecuzione sul cluster 1:
$ kubectl get deploy -n asm-gateways --context=gke_${PROJECT_ID}_us-west1_${PROJECT_ID}-cluster1

Verifichi che il service ingress-gateway abbia un IP esterno sul cluster 1:
$ kubectl get svc -n asm-gateways --context=gke_${PROJECT_ID}_us-west1_${PROJECT_ID}-cluster1

Verifichi infine il bilanciamento del carico cross-cluster interrogando più volte l'endpoint pubblico. Noterà che la versione e il pod id cambiano man mano che vengono raggiunti pod diversi. Dovrebbe ottenere 4 pod id distinti e 2 versioni differenti.

$ curl /hello

Personalizzazione e consultazione dei log
Abilitare i log di debug di envoy
L'abbiamo già fatto nella fase di deploy della configurazione asm. Dia un'occhiata al file asm/manifests/gateways/asm-config.yaml. La ConfigMap che abbiamo distribuito configura i proxy envoy per scrivere gli access log su stdout. Allo stesso modo è possibile abilitare altre opzioni [3].
Log del control plane
Anche con il control plane gestito è possibile consultarne i log. Si trovano in Logs Explorer, sotto la risorsa "Istio Control Plane".
Riferimenti
- https://cloud.google.com/service-mesh/docs/managed/auto-control-plane-with-fleet#before_you_begin
- https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity
- https://cloud.google.com/service-mesh/docs/managed/enable-managed-anthos-service-mesh-optional-features
- https://cloud.google.com/service-mesh/docs/managed/auto-control-plane-with-fleet
- https://cloud.google.com/service-mesh/docs/managed/select-a-release-channel#how_to_select_a_release_channel
- https://cloud.google.com/service-mesh/docs/unified-install/gke-install-multi-cluster#private-clusters-endpoint
- https://cloud.google.com/service-mesh/docs/unified-install/gke-install-multi-cluster#private-clusters-authorized-network