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 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 shopping online è di proprietà e gestito da team separati e viene implementato in una flotta di cluster GKE condivisi.
Prima di iniziare
I gateway multicluster richiedono una preparazione dell'ambiente prima di poter essere implementati. Prima di procedere, segui i passaggi descritti in Prepara l'ambiente per i gateway multi-cluster:
Esegui il deployment dei cluster GKE.
Registra i cluster in un parco risorse (se non lo sono già).
Abilita i controller del servizio multi-cluster e del gateway multi-cluster.
Infine, esamina le limitazioni e i problemi noti del controller GKE Gateway 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 di traffico tra due cluster GKE.
Questo esempio illustra alcuni passaggi realistici che un proprietario del servizio eseguirebbe 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 il corretto funzionamento del nuovo cluster. Questo esempio illustra quattro fasi di deployment:
- 100% - Canary basato sull'intestazione: Utilizza il routing delle intestazioni HTTP per inviare solo traffico di test o sintetico al nuovo cluster.
- 100% - Traffico mirror: Duplica il traffico degli utenti nel cluster canary. In questo modo viene testata la capacità del cluster canary copiando il 100% del traffico utenti in questo cluster.
- 90%-10%: Canary a traffic split del 10% per esporre lentamente il nuovo cluster al traffico reale.
- 0%-100%: Esegui il cutover completo al nuovo cluster con la possibilità di tornare indietro in caso di errori.
Questo esempio è simile al precedente, tranne per il fatto che viene eseguito il deployment di un gateway multicluster interno. Viene eseguito il deployment di un bilanciatore del carico delle applicazioni interno accessibile privatamente solo dall'interno del VPC. Utilizzerai i cluster e la stessa applicazione che hai eseguito il deployment nei passaggi precedenti, ma eseguirai il deployment tramite un gateway diverso.
Prerequisiti
L'esempio seguente si basa su alcuni 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égke-l7-rilb-mcGatewayClass è regionale e supporta solo i backend dei cluster nella stessa regione.Esegui il deployment dei servizi e delle ServiceExport necessari su ogni cluster. Se hai eseguito il deployment di Services e ServiceExports dell'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 stai eseguendo 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.
Prima di creare gateway che gestiscono bilanciatori del carico delle applicazioni interni, devi creare una subnet solo proxy. 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 regionale 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 è riuscito 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 sull'intestazione
Il canarying basato sull'intestazione consente al proprietario del servizio di abbinare 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 implementata, questa HTTPRoute configura il seguente comportamento di routing:
- Le richieste interne a
store.example.internalsenza l'intestazione HTTPenv: canaryvengono indirizzate ai podstoresul clustergke-west-1. - Le richieste interne a
store.example.internalcon l'intestazione HTTPenv: canaryvengono indirizzate ai podstoresul clustergke-west-2
Verifica che 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 successivi con l'indirizzo IP che ricevi come output.
Invia una richiesta al gateway utilizzando l'intestazione HTTP
env: canary. In questo modo verificherai che il traffico venga 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 con 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" }
Specchio stradale
Questa fase invia il traffico al cluster di destinazione, ma lo duplica anche nel cluster canary.
L'utilizzo del mirroring è utile per determinare in che modo il carico di traffico influirà sulle prestazioni dell'applicazione senza influire in alcun modo sulle risposte ai tuoi clienti. Potrebbe non essere necessario per tutti i tipi di implementazione, ma può essere utile quando si implementano modifiche di grandi dimensioni che potrebbero influire sul rendimento 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/mirrorper 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 primario risponde al traffico. Devi comunque confermare che il cluster a cui stai eseguendo la migrazione riceve il traffico mirroring.
Controlla i log dell'applicazione di un pod
storenel clustergke-west-2. I log devono confermare che il pod ha ricevuto il traffico sottoposto a mirroring dal bilanciamento del carico.kubectl logs deployment/store --context gke-west-2 -n store | grep /mirrorQuesto output conferma che anche i pod del 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 quelli degli indirizzi 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 nuovo codice o eseguire il deployment in nuovi ambienti in modo sicuro. Il proprietario del servizio imposta una percentuale esplicita di traffico inviato ai backend canary, che in genere è una quantità molto piccola 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.
L'esecuzione di una suddivisione del traffico con una minoranza del traffico consente al proprietario del servizio di ispezionare l'integrità dell'applicazione e le risposte. Se tutti gli indicatori sembrano integri, possono procedere al cutover completo.
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 a questo, a indicare che si sta verificando 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", ...
Trasferimento 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 stava effettivamente eseguendo l'onboarding
di un secondo cluster in un cluster esistente, questo ultimo passaggio sarebbe diverso
in quanto il passaggio finale prevederebbe il traffico verso entrambi i cluster. In questo scenario, è consigliabile un singolo store ServiceImport con pod provenienti dai cluster gke-west-1 e gke-west-2. In questo modo, il bilanciatore del carico può decidere
dove deve andare il traffico per un'applicazione active-active, 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 a questo, a indicare che tutto il traffico ora è diretto 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 blue-green da un cluster GKE a un altro cluster GKE.
Esegui la pulizia
Dopo aver completato gli esercizi descritti in 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 devono essere registrati 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:
Quando crei un gateway, ma non riesci ad accedere ai servizi di backend (codice di risposta 503), potrebbe verificarsi il seguente problema:
no healthy upstream
Motivo:
Questo messaggio di errore indica che il probe di 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 del gateway.