Questo documento ti guida attraverso un deployment blu/verde di un'applicazione store di esempio in due cluster GKE. I deployment blu/verde sono una strategia efficace per eseguire la migrazione delle tue applicazioni a nuovi cluster GKE con un rischio minimo. Spostando gradualmente il traffico dal cluster attuale (blu) al nuovo cluster (verde), puoi convalidare il nuovo ambiente in produzione prima di eseguire un cutover completo.
In questo tutorial utilizzerai un'applicazione store di esempio per simulare uno scenario reale in cui un servizio di acquisti online è di proprietà e gestito da team separati e viene eseguito il deployment in un parco risorse di cluster GKE condivisi.
Prima di iniziare
I gateway multi-cluster richiedono una certa preparazione dell'ambiente prima di poter essere implementati. Prima di procedere, segui i passaggi descritti in Prepara l'ambiente per i gateway multi-cluster:
Eseguire il deployment dei cluster GKE.
Registra i cluster in un parco risorse (se non sono già registrati).
Abilita i controller dei servizi multi-cluster e dei gateway multi-cluster.
Infine, esamina le limitazioni e i problemi noti del GKE Gateway Controller prima di utilizzarlo nel tuo ambiente.
Routing blu/verde multi-cluster con Gateway
Le GatewayClass gke-l7-global-external-managed-*, gke-l7-regional-external-managed-* e gke-l7-rilb-* hanno molte funzionalità avanzate di routing del traffico, tra cui suddivisione del traffico, corrispondenza delle intestazioni, manipolazione delle intestazioni, mirroring del traffico e altro ancora. In questo esempio, mostrerai come utilizzare la suddivisione del traffico basata sul peso per controllare esplicitamente la proporzione del traffico tra due cluster GKE.
Questo esempio illustra alcuni passaggi realistici che un proprietario di un servizio dovrebbe seguire per spostare o espandere la propria applicazione in un nuovo cluster GKE. L'obiettivo dei deployment blu-verde è ridurre il rischio attraverso più passaggi di convalida che confermano che il nuovo cluster funziona correttamente. Questo esempio illustra quattro fasi del deployment:
- 100% - Canary basato su intestazione: utilizza il routing delle intestazioni HTTP per inviare solo traffico di test o sintetico al nuovo cluster.
- 100% - Traffico di mirroring: esegui il mirroring del traffico utente nel cluster canary. In questo modo, viene testata la capacità del cluster canary copiando il 100% del traffico utente in questo cluster.
- 90%-10%: Canary con una suddivisione del traffico del 10% per esporre lentamente il nuovo cluster al traffico in tempo reale.
- 0%-100%: esegui il cutover completo al nuovo cluster con l'opzione di tornare indietro se vengono rilevati errori.
Questo esempio è simile al precedente, ma esegue il deployment di un gateway multi-cluster interno. In questo modo viene eseguito il deployment di un bilanciatore del carico delle applicazioni interno, accessibile solo privatamente dall'interno del VPC. Utilizzerai i cluster e la stessa applicazione di cui hai eseguito il deployment nei passaggi precedenti, ma ne eseguirai il deployment tramite un gateway diverso.
Prerequisiti
L'esempio seguente si basa su alcuni dei passaggi descritti in Deployment di un gateway multi-cluster esterno. Assicurati di aver completato i seguenti passaggi prima di procedere con questo esempio:
Deployment di un'applicazione demo
Questo esempio utilizza i cluster
gke-west-1egke-west-2che hai già configurato. Questi cluster si trovano nella stessa regione perché la GatewayClassgke-l7-rilb-mcè a livello di regione e supporta solo i backend dei cluster nella stessa regione.Esegui il deployment del servizio e degli oggetti ServiceExport necessari su ogni cluster. Se hai eseguito il deployment di servizi e ServiceExport dall'esempio precedente, hai già eseguito il deployment di alcuni di questi.
kubectl apply --context gke-west-1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store-west-1-service.yaml kubectl apply --context gke-west-2 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store-west-2-service.yamlEsegue il deployment di un insieme simile di risorse in ogni cluster:
service/store created serviceexport.net.gke.io/store created service/store-west-2 created serviceexport.net.gke.io/store-west-2 created
Configurazione di una subnet solo proxy
Se non l'hai ancora fatto, configura una subnet solo proxy per ogni regione in cui esegui il deployment dei gateway interni. Questa subnet viene utilizzata per fornire indirizzi IP interni ai proxy del bilanciatore del carico e deve essere configurata con un --purpose impostato solo su REGIONAL_MANAGED_PROXY.
Devi creare una subnet solo proxy prima di creare i gateway che gestiscono i bilanciatori del carico delle applicazioni interni. Ogni regione di una rete Virtual Private Cloud (VPC) in cui utilizzi i bilanciatori del carico delle applicazioni interni deve avere una subnet solo proxy.
Il comando gcloud compute networks subnets create crea una subnet solo proxy.
gcloud compute networks subnets create SUBNET_NAME \
--purpose=REGIONAL_MANAGED_PROXY \
--role=ACTIVE \
--region=REGION \
--network=VPC_NETWORK_NAME \
--range=CIDR_RANGE
Sostituisci quanto segue:
SUBNET_NAME: il nome della subnet solo proxy.REGION: la regione della subnet solo proxy.VPC_NETWORK_NAME: il nome della rete VPC che contiene la subnet.CIDR_RANGE: l'intervallo di indirizzi IP principale della subnet. Devi utilizzare una subnet mask non superiore a/26in modo che siano disponibili almeno 64 indirizzi IP per i proxy nella regione. La subnet mask consigliata è/23.
Deployment del gateway
Il seguente gateway viene creato dalla GatewayClass gke-l7-rilb-mc, che è un gateway interno a livello di regione che può avere come target solo i cluster GKE nella stessa regione.
Applica il seguente manifest
Gatewayal cluster di configurazione,gke-west-1in questo esempio:cat << EOF | kubectl apply --context gke-west-1 -f - kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: internal-http namespace: store spec: gatewayClassName: gke-l7-rilb-mc listeners: - name: http protocol: HTTP port: 80 allowedRoutes: kinds: - kind: HTTPRoute EOFVerifica che il gateway sia stato avviato correttamente. Puoi filtrare solo gli eventi di questo gateway con il seguente comando:
kubectl get events --field-selector involvedObject.kind=Gateway,involvedObject.name=internal-http --context=gke-west-1 --namespace storeIl deployment del gateway è andato a buon fine se l'output è simile al seguente:
LAST SEEN TYPE REASON OBJECT MESSAGE 5m18s Normal ADD gateway/internal-http store/internal-http 3m44s Normal UPDATE gateway/internal-http store/internal-http 3m9s Normal SYNC gateway/internal-http SYNC on store/internal-http was a success
Canary basato su intestazione
La canary basata su intestazione consente al proprietario del servizio di trovare corrispondenze con il traffico di test sintetico che non proviene da utenti reali. Questo è un modo semplice per verificare che il networking di base dell'applicazione funzioni senza esporre direttamente gli utenti.
Applica il seguente manifest
HTTPRouteal cluster di configurazione,gke-west-1in questo esempio:cat << EOF | kubectl apply --context gke-west-1 -f - kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: internal-store-route namespace: store labels: gateway: internal-http spec: parentRefs: - kind: Gateway namespace: store name: internal-http hostnames: - "store.example.internal" rules: # Matches for env=canary and sends it to store-west-2 ServiceImport - matches: - headers: - name: env value: canary backendRefs: - group: net.gke.io kind: ServiceImport name: store-west-2 port: 8080 # All other traffic goes to store-west-1 ServiceImport - backendRefs: - group: net.gke.io kind: ServiceImport name: store-west-1 port: 8080 EOFUna volta eseguito il deployment, questa risorsa HTTPRoute configura il seguente comportamento di routing:
- Le richieste interne a
store.example.internalsenza l'intestazione HTTPenv: canaryvengono indirizzate ai podstorenel clustergke-west-1 - Le richieste interne a
store.example.internalcon l'intestazione HTTPenv: canaryvengono indirizzate ai podstorenel clustergke-west-2
Verifica che la risorsa HTTPRoute funzioni correttamente inviando traffico all'indirizzo IP del gateway.
- Le richieste interne a
Recupera l'indirizzo IP interno da
internal-http.kubectl get gateways.gateway.networking.k8s.io internal-http -o=jsonpath="{.status.addresses[0].value}" --context gke-west-1 --namespace storeSostituisci VIP nei passaggi seguenti con l'indirizzo IP che ricevi come output.
Invia una richiesta al gateway utilizzando l'intestazione HTTP
env: canary. In questo modo, confermerai che il traffico viene indirizzato agke-west-2. Utilizza un client privato nello stesso VPC dei cluster GKE per verificare che le richieste vengano instradate correttamente. Il seguente comando deve essere eseguito su una macchina che ha accesso privato all'indirizzo IP del gateway, altrimenti non funzionerà.curl -H "host: store.example.internal" -H "env: canary" http://VIPL'output conferma che la richiesta è stata gestita da un pod del cluster
gke-west-2:{ "cluster_name": "gke-west-2", "host_header": "store.example.internal", "node_name": "gke-gke-west-2-default-pool-4cde1f72-m82p.c.agmsb-k8s.internal", "pod_name": "store-5f5b954888-9kdb5", "pod_name_emoji": "😂", "project_id": "agmsb-k8s", "timestamp": "2021-05-31T01:21:55", "zone": "us-west1-a" }
Mirroring del traffico
Questa fase invia il traffico al cluster previsto, ma ne esegue anche il mirroring al cluster canary.
L'utilizzo del mirroring è utile per determinare l'impatto del carico di traffico sulle prestazioni dell'applicazione senza influire in alcun modo sulle risposte ai client. Potrebbe non essere necessario per tutti i tipi di implementazioni, ma può essere utile quando si implementano modifiche di grandi dimensioni che potrebbero influire sulle prestazioni o sul carico.
Applica il seguente manifest
HTTPRouteal cluster di configurazione,gke-west-1in questo esempio:cat << EOF | kubectl apply --context gke-west-1 -f - kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: internal-store-route namespace: store labels: gateway: internal-http spec: parentRefs: - kind: Gateway namespace: store name: internal-http hostnames: - "store.example.internal" rules: # Sends all traffic to store-west-1 ServiceImport - backendRefs: - name: store-west-1 group: net.gke.io kind: ServiceImport port: 8080 # Also mirrors all traffic to store-west-2 ServiceImport filters: - type: RequestMirror requestMirror: backendRef: group: net.gke.io kind: ServiceImport name: store-west-2 port: 8080 EOFUtilizzando il tuo client privato, invia una richiesta al gateway
internal-http. Utilizza il percorso/mirrorin modo da poter identificare in modo univoco questa richiesta nei log dell'applicazione in un passaggio successivo.curl -H "host: store.example.internal" http://VIP/mirrorL'output conferma che il client ha ricevuto una risposta da un pod nel cluster
gke-west-1:{ "cluster_name": "gke-west-1", "host_header": "store.example.internal", "node_name": "gke-gke-west-1-default-pool-65059399-ssfq.c.agmsb-k8s.internal", "pod_name": "store-5f5b954888-brg5w", "pod_name_emoji": "🎖", "project_id": "agmsb-k8s", "timestamp": "2021-05-31T01:24:51", "zone": "us-west1-a" }Ciò conferma che il cluster principale risponde al traffico. Devi comunque confermare che il cluster di cui stai eseguendo la migrazione riceva il traffico sottoposto a mirroring.
Controlla i log dell'applicazione di un pod
storenel clustergke-west-2. I log dovrebbero confermare che il pod ha ricevuto il traffico sottoposto a mirroring dal bilanciatore del carico.kubectl logs deployment/store --context gke-west-2 -n store | grep /mirrorQuesto output conferma che anche i pod nel cluster
gke-west-2ricevono le stesse richieste, ma le loro risposte a queste richieste non vengono inviate al client. Gli indirizzi IP visualizzati nei log sono gli IP interni del bilanciatore del carico che comunicano con i tuoi pod.Found 2 pods, using pod/store-5c65bdf74f-vpqbs [2023-10-12 21:05:20,805] INFO in _internal: 192.168.21.3 - - [12/Oct/2023 21:05:20] "GET /mirror HTTP/1.1" 200 - [2023-10-12 21:05:27,158] INFO in _internal: 192.168.21.3 - - [12/Oct/2023 21:05:27] "GET /mirror HTTP/1.1" 200 - [2023-10-12 21:05:27,805] INFO in _internal: 192.168.21.3 - - [12/Oct/2023 21:05:27] "GET /mirror HTTP/1.1" 200 -
Suddivisione traffico
La suddivisione del traffico è uno dei metodi più comuni per implementare un nuovo codice o eseguire il deployment in nuovi ambienti in modo sicuro. Il proprietario del servizio imposta una percentuale esplicita di traffico che viene inviata ai backend canary, che in genere rappresenta una quantità molto ridotta del traffico complessivo, in modo che il successo dell'implementazione possa essere determinato con un livello di rischio accettabile per le richieste degli utenti reali.
La suddivisione del traffico con una minoranza del traffico consente al proprietario del servizio di ispezionare l'integrità dell'applicazione e le risposte. Se tutti i segnali sono positivi, possono procedere al cutover.
Applica il seguente manifest
HTTPRouteal cluster di configurazione,gke-west-1in questo esempio:cat << EOF | kubectl apply --context gke-west-1 -f - kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: internal-store-route namespace: store labels: gateway: internal-http spec: parentRefs: - kind: Gateway namespace: store name: internal-http hostnames: - "store.example.internal" rules: - backendRefs: # 90% of traffic to store-west-1 ServiceImport - name: store-west-1 group: net.gke.io kind: ServiceImport port: 8080 weight: 90 # 10% of traffic to store-west-2 ServiceImport - name: store-west-2 group: net.gke.io kind: ServiceImport port: 8080 weight: 10 EOFUtilizzando il tuo client privato, invia una richiesta curl continua al gateway
internal- http.while true; do curl -H "host: store.example.internal" -s VIP | grep "cluster_name"; sleep 1; doneL'output sarà simile al seguente, a indicare che è in corso una suddivisione del traffico 90/10.
"cluster_name": "gke-west-1", "cluster_name": "gke-west-1", "cluster_name": "gke-west-1", "cluster_name": "gke-west-1", "cluster_name": "gke-west-1", "cluster_name": "gke-west-1", "cluster_name": "gke-west-1", "cluster_name": "gke-west-1", "cluster_name": "gke-west-2", "cluster_name": "gke-west-1", "cluster_name": "gke-west-1", ...
Cutover del traffico
L'ultima fase della migrazione blu/verde consiste nel passare completamente al nuovo cluster e rimuovere quello precedente. Se il proprietario del servizio stesse effettivamente eseguendo l'onboarding di un secondo cluster in un cluster esistente, quest'ultimo passaggio sarebbe diverso, poiché il passaggio finale prevederebbe il traffico verso entrambi i cluster. In questo scenario, è consigliabile un singolo ServiceImport store con pod di entrambi i cluster gke-west-1 e gke-west-2. In questo modo, il bilanciatore del carico può decidere dove indirizzare il traffico per un'applicazione attiva-attiva, in base a prossimità, integrità e capacità.
Applica il seguente manifest
HTTPRouteal cluster di configurazione,gke-west-1in questo esempio:cat << EOF | kubectl apply --context gke-west-1 -f - kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: internal-store-route namespace: store labels: gateway: internal-http spec: parentRefs: - kind: Gateway namespace: store name: internal-http hostnames: - "store.example.internal" rules: - backendRefs: # No traffic to the store-west-1 ServiceImport - name: store-west-1 group: net.gke.io kind: ServiceImport port: 8080 weight: 0 # All traffic to the store-west-2 ServiceImport - name: store-west-2 group: net.gke.io kind: ServiceImport port: 8080 weight: 100 EOFUtilizzando il tuo client privato, invia una richiesta curl continua al gateway
internal- http.while true; do curl -H "host: store.example.internal" -s VIP | grep "cluster_name"; sleep 1; doneL'output sarà simile al seguente, a indicare che tutto il traffico ora va a
gke-west-2."cluster_name": "gke-west-2", "cluster_name": "gke-west-2", "cluster_name": "gke-west-2", "cluster_name": "gke-west-2", ...
Questo passaggio finale completa una migrazione completa dell'applicazione blu-verde da un cluster GKE a un altro cluster GKE.
Esegui la pulizia
Dopo aver completato gli esercizi di questo documento, segui questi passaggi per rimuovere le risorse ed evitare addebiti indesiderati sul tuo account:
Annulla la registrazione dei cluster dal parco risorse se non è necessario registrarli per un altro scopo.
Disattiva la funzionalità
multiclusterservicediscovery:gcloud container fleet multi-cluster-services disableDisabilita Ingress multi-cluster:
gcloud container fleet ingress disableDisabilita le API:
gcloud services disable \ multiclusterservicediscovery.googleapis.com \ multiclusteringress.googleapis.com \ trafficdirector.googleapis.com \ --project=PROJECT_ID
Risoluzione dei problemi
Nessun upstream integro
Sintomo:
Il seguente problema potrebbe verificarsi quando crei un gateway, ma non riesci ad accedere ai servizi di backend (codice di risposta 503):
no healthy upstream
Motivo:
Questo messaggio di errore indica che il controllo di integrità non riesce a trovare servizi di backend integri. È possibile che i servizi di backend siano integri, ma potrebbe essere necessario personalizzare i controlli di integrità.
Soluzione temporanea:
Per risolvere il problema, personalizza il controllo di integrità in base ai requisiti della tua applicazione (ad esempio /health) utilizzando un HealthCheckPolicy.
Passaggi successivi
- Scopri di più sul controller Gateway.