Este documento orienta você em uma implantação azul-verde de um aplicativo store
de exemplo em dois clusters do GKE. As implantações azul-verde são uma estratégia eficaz para migrar seus aplicativos para novos clusters do GKE com risco mínimo. Ao mudar gradualmente o tráfego do cluster atual (azul) para o novo cluster (verde), é possível validar o novo ambiente em produção antes de fazer uma migração completa.
Neste tutorial, você usa um aplicativo store de amostra para simular um cenário real em que um serviço de compras on-line é de propriedade e operado por equipes separadas e implantado em uma frota de clusters compartilhados do GKE.
Antes de começar
Os gateways de vários clusters precisam de preparação do ambiente para serem implantados. Antes de continuar, siga as etapas em Preparar o ambiente para gateways de vários clusters:
Implante cluster do GKE.
Registre os clusters em uma frota, se ainda não tiver feito isso.
Ative os controladores do gateway de vários clusters e do serviço de vários clusters.
Por fim, analise as limitações e problemas conhecidos do GKE Gateway controller antes de usá-lo no seu ambiente.
Roteamento azul-verde com vários clusters usando o Gateway
O GatewayClasses gke-l7-global-external-managed-*, gke-l7-regional-external-managed-* e gke-l7-rilb-* tem muitos recursos avançados de roteamento de tráfego,
incluindo divisão de tráfego, correspondência de cabeçalho, manipulação de cabeçalho, espelhamento de
tráfego e muito mais. Neste exemplo, mostraremos como usar a divisão de tráfego
baseada em peso para controlar explicitamente a proporção de tráfego em dois
clusters do GKE.
Este exemplo mostra algumas etapas realistas que um proprietário de serviço faria ao mover ou expandir o aplicativo para um novo cluster do GKE. O objetivo das implantações azul-verde é reduzir o risco por meio de várias etapas de validação que confirmam se o novo cluster está funcionando corretamente. Este exemplo mostra quatro etapas de implantação:
- 100%-Canário baseado em cabeçalho: use o roteamento de cabeçalho HTTP para enviar apenas tráfego de teste ou sintético no novo cluster.
- 100%-Espelhar o tráfego: espelha o tráfego de usuários para o cluster canário. Isso testa a capacidade do cluster canário copiando 100% do tráfego do usuário para esse cluster.
- 90%-10%: canário de uma divisão de tráfego de 10% para expor lentamente o novo cluster para o tráfego em tempo real.
- 0%-100%: mude totalmente para o novo cluster com a opção de reverter se os erros observados.
Este exemplo é semelhante ao anterior, mas implanta um gateway interno de vários clusters. Ele implanta um balanceador de carga de aplicativo interno que só pode ser acessado de maneira particular dentro da VPC. Você usará os mesmos clusters e o mesmo aplicativo implantados nas etapas anteriores, mas irá implantá-los em um Gateway diferente.
Pré-requisitos
O exemplo a seguir se baseia em algumas das etapas de Como implantar um gateway externo de vários clusters. Certifique-se de ter concluído as seguintes etapas antes de continuar com este exemplo:
Como implantar um aplicativo de demonstração
Neste exemplo, usamos os clusters
gke-west-1egke-west-2que você já configurou. Esses clusters estão na mesma região porque o GatewayClassgke-l7-rilb-mcé regional e só aceita back-ends de cluster na mesma região.Implantar o Service e o ServiceExports necessários em cada cluster. Se você implantou os Services e ServiceExports do exemplo anterior, então já implantou alguns deles.
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.yamlEle implanta um conjunto semelhante de recursos em cada cluster:
service/store created serviceexport.net.gke.io/store created service/store-west-2 created serviceexport.net.gke.io/store-west-2 created
Como configurar uma sub-rede somente proxy
Se você ainda não tiver feito isso, configure uma sub-rede somente proxy para cada região em que os gateways internos estão sendo implantados. Essa sub-rede é usada
para fornecer endereços IP internos aos proxies do balanceador de carga e precisa ser
configurada com --purpose definido apenas como REGIONAL_MANAGED_PROXY.
Crie uma sub-rede apenas de proxy antes de criar gateways que gerenciem balanceadores de carga de aplicativo internos. Cada região de uma rede de nuvem privada virtual (VPC) em que você usa balanceadores de carga de aplicativos internos precisa ter uma sub-rede apenas de proxy.
O comando
gcloud compute networks subnets create cria uma sub-rede somente proxy.
gcloud compute networks subnets create SUBNET_NAME \
--purpose=REGIONAL_MANAGED_PROXY \
--role=ACTIVE \
--region=REGION \
--network=VPC_NETWORK_NAME \
--range=CIDR_RANGE
Substitua:
SUBNET_NAME: o nome da sub-rede somente proxy.REGION: a região da sub-rede somente proxy.VPC_NETWORK_NAME: o nome da rede VPC que contém a sub-rede.CIDR_RANGE: o intervalo de endereços IP principal da sub-rede. Use uma máscara de sub-rede de até/26de comprimento para que ao menos 64 endereços IP estejam disponíveis para os proxies na região. A máscara de sub-rede recomendada é/23.
Como implantar o gateway
O gateway a seguir é criado com base no GatewayClass gke-l7-rilb-mc, que é
um gateway interno regional que só pode segmentar clusters do GKE na
mesma região.
Aplique o manifesto
Gatewayao cluster de configuração, neste exemplogke-west-1: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 EOFConfira se o gateway foi criado. É possível filtrar apenas os eventos desse gateway com o seguinte comando:
kubectl get events --field-selector involvedObject.kind=Gateway,involvedObject.name=internal-http --context=gke-west-1 --namespace storeA implantação do gateway foi bem-sucedida se a saída for semelhante a esta:
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
Canário com base em cabeçalho
O canário baseado em cabeçalho permite que o proprietário do serviço corresponda ao tráfego de teste sintético que não vem de usuários reais. Isso facilita a validação de que a rede básica do aplicativo está funcionando sem expor os usuários diretamente.
Aplique o manifesto
HTTPRouteao cluster de configuração, neste exemplogke-west-1: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 EOFDepois de implantado, esse HTTPRoute configura o seguinte comportamento de roteamento:
- Solicitações internas para
store.example.internalsem o cabeçalho HTTPenv: canarysão roteadas para podsstoreno clustergke-west-1 - Solicitações internas para
store.example.internalcom o cabeçalho HTTPenv: canarysão roteadas para podsstoreno clustergke-west-2
Envie tráfego para o endereço IP do gateway para validar o funcionamento correto do HTTPRoute.
- Solicitações internas para
Recupere o endereço IP interno de
internal-http.kubectl get gateways.gateway.networking.k8s.io internal-http -o=jsonpath="{.status.addresses[0].value}" --context gke-west-1 --namespace storeSubstitua VIP nas etapas a seguir pelo endereço IP que você recebe como saída.
Envie uma solicitação para o gateway usando o cabeçalho HTTP
env: canary. Isso confirmará que o tráfego está sendo roteado paragke-west-2. Use um cliente particular na mesma VPC que os clusters do GKE para confirmar se as solicitações estão sendo roteadas corretamente. O comando a seguir precisa ser executado em uma máquina que tenha acesso particular ao endereço IP do gateway. Caso contrário, ela não funcionará.curl -H "host: store.example.internal" -H "env: canary" http://VIPA saída confirma que a solicitação foi exibida por um pod do 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" }
Espelhamento do tráfego
Esse estágio envia o tráfego para o cluster pretendido, mas também espelha esse tráfego para o cluster canário.
Usar o espelhamento é útil para determinar como a carga do tráfego afetará o desempenho do aplicativo sem afetar as respostas aos clientes. Talvez não seja necessário para todos os tipos de lançamentos, mas pode ser útil ao implementar grandes alterações que podem afetar o desempenho ou a carga.
Aplique o manifesto
HTTPRouteao cluster de configuração, neste exemplogke-west-1: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 EOFUsando seu cliente particular, envie uma solicitação para o gateway
internal-http. Use o caminho/mirrorpara identificar exclusivamente essa solicitação nos registros do aplicativo em uma etapa posterior.curl -H "host: store.example.internal" http://VIP/mirrorA resposta confirma que o cliente recebeu uma resposta de um pod no 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" }Isso confirma que o cluster principal está respondendo ao tráfego. Você ainda precisa confirmar se o cluster para o qual está migrando está recebendo tráfego espelhado.
Verifique os registros do aplicativo de um pod
storeno clustergke-west-2. Os registros precisam confirmar que o pod recebeu tráfego espelhado do balanceador de carga.kubectl logs deployment/store --context gke-west-2 -n store | grep /mirrorEssa saída confirma que os pods no cluster
gke-west-2também estão recebendo as mesmas solicitações. No entanto, as respostas a essas solicitações não são enviadas de volta ao cliente. Os endereços IP vistos nos registros são os dos endereços IP internos do balanceador de carga que estão se comunicando com seus pods.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 -
Divisão de tráfego
A divisão de tráfego é um dos métodos mais comuns de lançar novo código ou implantar em novos ambientes com segurança. O proprietário do serviço define uma porcentagem explícita de tráfego enviada para os back-ends canários, que geralmente é uma quantidade muito pequena do tráfego geral. Assim, o sucesso do lançamento pode ser determinado com uma quantidade aceitável de risco para solicitações reais de usuários.
Fazer uma divisão de tráfego com uma minoria de tráfego permite que o proprietário do serviço inspecione a integridade do aplicativo e as respostas. Se todos os sinais parecerem íntegros, eles poderão prosseguir para a transição completa.
Aplique o manifesto
HTTPRouteao cluster de configuração, neste exemplogke-west-1: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 EOFUsando seu cliente particular, envie uma solicitação curl contínua para o gateway
internal- http.while true; do curl -H "host: store.example.internal" -s VIP | grep "cluster_name"; sleep 1; doneA saída será semelhante a esta, indicando que está ocorrendo uma divisão de tráfego de 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", ...
Redução do tráfego
A última etapa da migração azul-verde é totalmente transferida para o novo
cluster e remove o antigo. Se o proprietário do serviço estivesse realmente integrando
um segundo cluster a um cluster existente, essa última etapa seria diferente,
porque a etapa final teria o tráfego fluindo para os dois clusters. Nesse cenário, é
recomendado um único ServiceImport store que tenha pods dos clusters
gke-west-1 e gke-west-2. Isso permite que o balanceador de carga tome a decisão de
onde o tráfego deve ir para um aplicativo ativo-ativo, com base em proximidade,
integridade e capacidade.
Aplique o manifesto
HTTPRouteao cluster de configuração, neste exemplogke-west-1: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 EOFUsando seu cliente particular, envie uma solicitação curl contínua para o gateway
internal- http.while true; do curl -H "host: store.example.internal" -s VIP | grep "cluster_name"; sleep 1; doneA saída será semelhante a esta, indicando que todo o tráfego está indo agora para
gke-west-2."cluster_name": "gke-west-2", "cluster_name": "gke-west-2", "cluster_name": "gke-west-2", "cluster_name": "gke-west-2", ...
Essa etapa final conclui uma migração completa de aplicativos azul-verde de um cluster do GKE para outro cluster do GKE.
Limpar
Depois de concluir os exercícios neste documento, siga estas etapas para remover os recursos e evitar cobranças indesejadas na conta:
Cancele o registro dos clusters da frota se eles não precisarem ser registrados para outra finalidade.
Desative o recurso
multiclusterservicediscovery:gcloud container fleet multi-cluster-services disableDesativar a Entrada de vários clusters:
gcloud container fleet ingress disableDesative as APIs:
gcloud services disable \ multiclusterservicediscovery.googleapis.com \ multiclusteringress.googleapis.com \ trafficdirector.googleapis.com \ --project=PROJECT_ID
Solução de problemas
Nenhum upstream íntegro
Sintoma:
O seguinte problema pode ocorrer quando você cria um gateway mas não pode acessar os serviços de back-end (código de resposta 503):
no healthy upstream
Motivo:
Esta mensagem de erro indica que a sondagem da verificação de integridade não consegue encontrar a integridade dos serviços de back-end. É possível que os serviços de back-end estejam íntegros, mas talvez seja necessário personalizar as verificações de integridade.
Alternativa:
Para resolver esse problema, personalize a verificação de integridade com base nas condições
(por exemplo, /health) usando um HealthCheckPolicy.
A seguir
- Saiba mais sobre o controlador de gateway.