Este documento mostra como realizar as seguintes tarefas:
- Implante aplicativos distribuídos globalmente e expostos pelo gateway do GKE e pelo Cloud Service Mesh.
- Exponha um aplicativo a vários clientes combinando o Cloud Load Balancing com o Cloud Service Mesh.
- Integre balanceadores de carga a uma malha de serviço implantada em várias regiões do Google Cloud.
Este guia de implantação é destinado a administradores de plataforma. Ele também é destinado a profissionais avançados que executam o Cloud Service Mesh. As instruções também funcionam para o Istio no GKE.
Arquitetura
O diagrama a seguir mostra a topologia de entrada padrão de uma malha de serviços: um balanceador de carga TCP/UDP externo que expõe os proxies do gateway de entrada em um cluster único:
Este guia de implantação usa recursos do gateway do Google Kubernetes Engine (GKE). Especificamente, ele usa um gateway de vários clusters para configurar o balanceamento de carga em várias regiões na frente de vários clusters do Autopilot distribuídos em duas regiões.
O diagrama anterior mostra como os dados fluem pelos cenários de entrada de nuvem e entrada de malha. Para mais informações, consulte a explicação do diagrama de arquitetura no documento de arquitetura de referência associado.
Objetivos
- Implante um par de clusters do GKE Autopilot no Google Cloud na mesma frota.
- Implante uma malha de serviço do Cloud baseada no Istio na mesma frota.
- Configure um balanceador de carga usando o gateway do GKE para encerrar o tráfego HTTPS público.
- Direcione o tráfego HTTPS público para aplicativos hospedados pelo Cloud Service Mesh implantados em vários clusters e regiões.
- Implante o aplicativo de exemplo whereami nos dois clusters do Autopilot.
Otimização de custos
Neste documento, você usará os seguintes componentes faturáveis do Google Cloud:
- Google Kubernetes Engine
- Cloud Load Balancing
- Cloud Service Mesh
- Multi Cluster Ingress
- Google Cloud Armor
- Certificate Manager
- Cloud Endpoints
Para gerar uma estimativa de custo baseada na projeção de uso deste tutorial, use a calculadora de preços.
Ao concluir as tarefas descritas neste documento, é possível evitar o faturamento contínuo excluindo os recursos criados. Saiba mais em Limpeza.
Antes de começar
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
In the Google Cloud console, activate Cloud Shell.
Todos os comandos de terminal desta implantação são executados a partir do Cloud Shell.
Defina seu projeto padrão do Google Cloud:
export PROJECT=YOUR_PROJECT export PROJECT_NUMBER=$(gcloud projects describe PROJECT_ID --format="value(projectNumber)") gcloud config set project PROJECT_ID
Substitua
PROJECT_ID
pelo ID do projeto que você quer usar nesta implantação.Crie um diretório de trabalho:
mkdir -p ${HOME}/edge-to-mesh-multi-region cd ${HOME}/edge-to-mesh-multi-region export WORKDIR=`pwd`
Criar clusters do GKE
Nesta seção, você cria clusters do GKE para hospedar os aplicativos e a infraestrutura de suporte, que serão criados mais adiante neste guia de implantação.
No Cloud Shell, crie um novo arquivo
kubeconfig
. Esta etapa garante que você não crie conflitos com seu arquivokubeconfig
(padrão) atual.touch edge2mesh_mr_kubeconfig export KUBECONFIG=${WORKDIR}/edge2mesh_mr_kubeconfig
Defina as variáveis de ambiente usadas ao criar os clusters do GKE e os recursos neles. Modifique as opções de região padrão de acordo com seus objetivos.
export CLUSTER_1_NAME=edge-to-mesh-01 export CLUSTER_2_NAME=edge-to-mesh-02 export CLUSTER_1_REGION=us-central1 export CLUSTER_2_REGION=us-east4 export PUBLIC_ENDPOINT=frontend.endpoints.PROJECT_ID.cloud.goog
Ative as APIs do Google Cloud usadas neste guia:
gcloud services enable \ container.googleapis.com \ mesh.googleapis.com \ gkehub.googleapis.com \ multiclusterservicediscovery.googleapis.com \ multiclusteringress.googleapis.com \ trafficdirector.googleapis.com \ certificatemanager.googleapis.com
Crie um cluster do GKE Autopilot com nós particulares em
CLUSTER_1_REGION
. Use a flag--async
para evitar a espera pelo provisionamento e registro do primeiro cluster na frota:gcloud container clusters create-auto --async \ ${CLUSTER_1_NAME} --region ${CLUSTER_1_REGION} \ --release-channel rapid --labels mesh_id=proj-${PROJECT_NUMBER} \ --enable-private-nodes --enable-fleet
Crie e registre um segundo cluster do Autopilot em
CLUSTER_2_REGION
:gcloud container clusters create-auto \ ${CLUSTER_2_NAME} --region ${CLUSTER_2_REGION} \ --release-channel rapid --labels mesh_id=proj-${PROJECT_NUMBER} \ --enable-private-nodes --enable-fleet
Verifique se os clusters estão sendo executados. Pode levar até 20 minutos até que todos os clusters estejam em execução:
gcloud container clusters list
O resultado será assim:
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS edge-to-mesh-01 us-central1 1.27.5-gke.200 34.27.171.241 e2-small 1.27.5-gke.200 RUNNING edge-to-mesh-02 us-east4 1.27.5-gke.200 35.236.204.156 e2-small 1.27.5-gke.200 RUNNING
Colete as credenciais para
CLUSTER_1_NAME
. Você criouCLUSTER_1_NAME
de forma assíncrona para executar outros comandos enquanto o cluster estava provisionado.gcloud container clusters get-credentials ${CLUSTER_1_NAME} \ --region ${CLUSTER_1_REGION}
Para esclarecer os nomes dos contextos do Kubernetes, renomeie-os para os nomes dos clusters:
kubectl config rename-context gke_PROJECT_ID_${CLUSTER_1_REGION}_${CLUSTER_1_NAME} ${CLUSTER_1_NAME} kubectl config rename-context gke_PROJECT_ID_${CLUSTER_2_REGION}_${CLUSTER_2_NAME} ${CLUSTER_2_NAME}
Instalar uma malha de serviço
Nesta seção, você configurará o Cloud Service Mesh gerenciado com a API Fleet. O uso da API Fleet para ativar o Cloud Service Mesh oferece uma abordagem declarativa para provisionar uma malha de serviço.
No Cloud Shell, ative o Cloud Service Mesh na frota:
gcloud container fleet mesh enable
Ative o gerenciamento automático do plano de controle e do plano de dados:
gcloud container fleet mesh update \ --management automatic \ --memberships ${CLUSTER_1_NAME},${CLUSTER_2_NAME}
Espere aproximadamente 20 minutos. Em seguida, verifique se o status do plano de controle é
ACTIVE
:gcloud container fleet mesh describe
O resultado será assim:
createTime: '2023-11-30T19:23:21.713028916Z' membershipSpecs: projects/603904278888/locations/us-central1/memberships/edge-to-mesh-01: mesh: management: MANAGEMENT_AUTOMATIC projects/603904278888/locations/us-east4/memberships/edge-to-mesh-02: mesh: management: MANAGEMENT_AUTOMATIC membershipStates: projects/603904278888/locations/us-central1/memberships/edge-to-mesh-01: servicemesh: controlPlaneManagement: details: - code: REVISION_READY details: 'Ready: asm-managed-rapid' implementation: ISTIOD state: ACTIVE dataPlaneManagement: details: - code: OK details: Service is running. state: ACTIVE state: code: OK description: |- Revision ready for use: asm-managed-rapid. All Canonical Services have been reconciled successfully. updateTime: '2024-06-27T09:00:21.333579005Z' projects/603904278888/locations/us-east4/memberships/edge-to-mesh-02: servicemesh: controlPlaneManagement: details: - code: REVISION_READY details: 'Ready: asm-managed-rapid' implementation: ISTIOD state: ACTIVE dataPlaneManagement: details: - code: OK details: Service is running. state: ACTIVE state: code: OK description: |- Revision ready for use: asm-managed-rapid. All Canonical Services have been reconciled successfully. updateTime: '2024-06-27T09:00:24.674852751Z' name: projects/e2m-private-test-01/locations/global/features/servicemesh resourceState: state: ACTIVE spec: {} updateTime: '2024-06-04T17:16:28.730429993Z'
Implantar um balanceador de carga de aplicativo externo e criar gateways de entrada
Nesta seção, você implanta um balanceador de carga de aplicativo externo pelo
GKE Gateway Controller e cria gateways de entrada para os dois
clusters. Os recursos gateway
e gatewayClass
automatizam o provisionamento
do balanceador de carga e da verificação de integridade do back-end. Para fornecer terminação TLS no balanceador de carga, crie recursos do Gerenciador de certificados e anexe-os ao balanceador de carga. Além disso, use os
Endpoints para provisionar automaticamente um nome DNS público ao aplicativo.
Instalar um gateway de entrada nos dois clusters
Como prática recomendada de segurança, recomendamos que você implante o gateway de entrada em um namespace diferente do plano de controle de malha.
No Cloud Shell, crie um namespace
asm-ingress
dedicado em cada cluster:kubectl --context=${CLUSTER_1_NAME} create namespace asm-ingress kubectl --context=${CLUSTER_2_NAME} create namespace asm-ingress
Adicione um rótulo ao namespace
asm-ingress
:kubectl --context=${CLUSTER_1_NAME} label namespace asm-ingress istio-injection=enabled kubectl --context=${CLUSTER_2_NAME} label namespace asm-ingress istio-injection=enabled
O resultado será assim:
namespace/asm-ingress labeled
Rotular os namespaces
asm-ingress
comistio-injection=enabled
instrui o Cloud Service Mesh a injetar automaticamente os proxies sidecar do Envoy quando um pod é implantado.Gere um certificado autoassinado para uso futuro:
openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 \ -subj "/CN=frontend.endpoints.PROJECT_ID.cloud.goog/O=Edge2Mesh Inc" \ -keyout ${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.key \ -out ${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.crt
O certificado oferece uma camada adicional de criptografia entre o balanceador de carga e os gateways de entrada da malha de serviço. Ele também é compatível com protocolos baseados em HTTP/2, como o gRPC. As instruções sobre como anexar o certificado autoassinado aos gateways de entrada serão fornecidas mais adiante em Criar recursos de endereço IP externo, registro DNS e certificado TLS.
Para mais informações sobre os requisitos do certificado do gateway de entrada, consulte Criptografia do balanceador de carga para os back-ends.
Crie um secret do Kubernetes em cada cluster para armazenar o certificado autoassinado:
kubectl --context ${CLUSTER_1_NAME} -n asm-ingress create secret tls \ edge2mesh-credential \ --key=${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.key \ --cert=${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.crt kubectl --context ${CLUSTER_2_NAME} -n asm-ingress create secret tls \ edge2mesh-credential \ --key=${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.key \ --cert=${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.crt
Para integrar com o balanceador de carga de aplicativo externo, crie uma variante kustomize para configurar os recursos do gateway de entrada:
mkdir -p ${WORKDIR}/asm-ig/base cat <<EOF > ${WORKDIR}/asm-ig/base/kustomization.yaml resources: - github.com/GoogleCloudPlatform/anthos-service-mesh-samples/docs/ingress-gateway-asm-manifests/base EOF mkdir ${WORKDIR}/asm-ig/variant cat <<EOF > ${WORKDIR}/asm-ig/variant/role.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: asm-ingressgateway namespace: asm-ingress rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get", "watch", "list"] EOF cat <<EOF > ${WORKDIR}/asm-ig/variant/rolebinding.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: asm-ingressgateway namespace: asm-ingress roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: asm-ingressgateway subjects: - kind: ServiceAccount name: asm-ingressgateway EOF cat <<EOF > ${WORKDIR}/asm-ig/variant/service-proto-type.yaml apiVersion: v1 kind: Service metadata: name: asm-ingressgateway namespace: asm-ingress spec: ports: - name: status-port port: 15021 protocol: TCP targetPort: 15021 - name: http port: 80 targetPort: 8080 appProtocol: HTTP - name: https port: 443 targetPort: 8443 appProtocol: HTTP2 type: ClusterIP EOF cat <<EOF > ${WORKDIR}/asm-ig/variant/gateway.yaml apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: asm-ingressgateway namespace: asm-ingress spec: servers: - port: number: 443 name: https protocol: HTTPS hosts: - "*" # IMPORTANT: Must use wildcard here when using SSL, as SNI isn't passed from GFE tls: mode: SIMPLE credentialName: edge2mesh-credential EOF cat <<EOF > ${WORKDIR}/asm-ig/variant/kustomization.yaml namespace: asm-ingress resources: - ../base - role.yaml - rolebinding.yaml patches: - path: service-proto-type.yaml target: kind: Service - path: gateway.yaml target: kind: Gateway EOF
Aplique a configuração do gateway de entrada aos dois clusters:
kubectl --context ${CLUSTER_1_NAME} apply -k ${WORKDIR}/asm-ig/variant kubectl --context ${CLUSTER_2_NAME} apply -k ${WORKDIR}/asm-ig/variant
Expor pods de gateway de entrada ao balanceador de carga usando um serviço de vários clusters
Nesta seção, você exporta os pods de gateway de entrada usando um recurso personalizado ServiceExport
. É necessário exportar os pods de gateway de entrada
por um recurso personalizado ServiceExport
pelos seguintes motivos:
- Permite que o balanceador de carga aborde os pods de gateway de entrada em vários clusters.
- Permite que os pods do gateway de entrada façam solicitações de proxy para serviços em execução na malha de serviço.
No Cloud Shell, ative os serviços de vários clusters (MCS) para a frota:
gcloud container fleet multi-cluster-services enable
Conceda ao MCS as permissões do IAM necessárias para o projeto ou a frota:
gcloud projects add-iam-policy-binding PROJECT_ID \ --member "serviceAccount:PROJECT_ID.svc.id.goog[gke-mcs/gke-mcs-importer]" \ --role "roles/compute.networkViewer"
Crie o arquivo YAML
ServiceExport
:cat <<EOF > ${WORKDIR}/svc_export.yaml kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: asm-ingressgateway namespace: asm-ingress EOF
Aplique o arquivo YAML
ServiceExport
aos dois clusters:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/svc_export.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/svc_export.yaml
Se você receber a mensagem de erro a seguir, aguarde alguns instantes para que as definições de recursos personalizados (CRDs) do MCS sejam instaladas. Em seguida, execute novamente os comandos para aplicar o arquivo YAML
ServiceExport
aos dois clusters.error: resource mapping not found for name: "asm-ingressgateway" namespace: "asm-ingress" from "svc_export.yaml": no matches for kind "ServiceExport" in version "net.gke.io/v1" ensure CRDs are installed first
Criar recursos de endereço IP externo, registro DNS e certificado TLS
Nesta seção, você cria recursos de rede que são compatíveis com os recursos de balanceamento de carga que serão criados mais adiante nesta implantação.
No Cloud Shell, reserve um endereço IP externo estático:
gcloud compute addresses create mcg-ip --global
Um endereço IP estático é usado pelo recurso de gateway do GKE. Ele permite que o endereço IP permaneça o mesmo, mesmo que o balanceador de carga externo seja recriado.
Acesse o endereço IP estático e armazene-o como uma variável de ambiente:
export MCG_IP=$(gcloud compute addresses describe mcg-ip --global --format "value(address)") echo ${MCG_IP}
Para criar um mapeamento estável e legível por humanos para o endereço IP do Gateway, é preciso ter um registro DNS público.
Use o provedor de DNS e o esquema de automação que quiser. Nesta implantação, usamos os Endpoints em vez de criar uma zona de DNS gerenciada. Os Endpoints fornecem um registro DNS gerenciado pelo Google gratuito para um endereço IP externo.
Execute o comando abaixo para criar um arquivo YAML chamado
dns-spec.yaml
:cat <<EOF > ${WORKDIR}/dns-spec.yaml swagger: "2.0" info: description: "Cloud Endpoints DNS" title: "Cloud Endpoints DNS" version: "1.0.0" paths: {} host: "frontend.endpoints.PROJECT_ID.cloud.goog" x-google-endpoints: - name: "frontend.endpoints.PROJECT_ID.cloud.goog" target: "${MCG_IP}" EOF
O arquivo
dns-spec.yaml
define o registro DNS público no formatofrontend.endpoints.PROJECT_ID.cloud.goog
, em quePROJECT_ID
é o identificador exclusivo do projeto.Implante o arquivo
dns-spec.yaml
para criar a entrada DNS. Esse processo leva alguns minutos.gcloud endpoints services deploy ${WORKDIR}/dns-spec.yaml
Crie um certificado usando o Gerenciador de certificados para o nome da entrada DNS criado na etapa anterior:
gcloud certificate-manager certificates create mcg-cert \ --domains="frontend.endpoints.PROJECT_ID.cloud.goog"
Um certificado TLS gerenciado pelo Google é usado para encerrar solicitações de clientes de entrada no balanceador de carga.
Criar um mapa de certificado:
gcloud certificate-manager maps create mcg-cert-map
O balanceador de carga faz referência ao certificado pela entrada do mapa de certificado criada na próxima etapa.
Crie uma entrada de mapa de certificados para o certificado que você criou anteriormente nesta seção:
gcloud certificate-manager maps entries create mcg-cert-map-entry \ --map="mcg-cert-map" \ --certificates="mcg-cert" \ --hostname="frontend.endpoints.PROJECT_ID.cloud.goog"
Criar políticas de serviço de back-end e recursos de balanceador de carga
Nesta seção, você vai realizar as seguintes tarefas:
- Crie uma política de segurança do Google Cloud Armor com regras.
- Crie uma política que permita que o balanceador de carga verifique a capacidade de resposta dos pods do gateway de entrada usando o arquivo YAML
ServiceExport
que você criou anteriormente. - Use a API Gateway do GKE para criar um recurso de balanceador de carga.
- Use o recurso personalizado
GatewayClass
para definir o tipo específico de balanceador de carga. - Ative o balanceamento de carga de vários clusters para a frota e designe um dos clusters como o cluster de configuração da frota.
No Cloud Shell, crie uma política de segurança do Google Cloud Armor:
gcloud compute security-policies create edge-fw-policy \ --description "Block XSS attacks"
Crie uma regra para sua política de segurança:
gcloud compute security-policies rules create 1000 \ --security-policy edge-fw-policy \ --expression "evaluatePreconfiguredExpr('xss-stable')" \ --action "deny-403" \ --description "XSS attack filtering"
Crie um arquivo YAML para a política de segurança e faça referência ao arquivo YAML
ServiceExport
usando um arquivo YAMLServiceImport
correspondente:cat <<EOF > ${WORKDIR}/cloud-armor-backendpolicy.yaml apiVersion: networking.gke.io/v1 kind: GCPBackendPolicy metadata: name: cloud-armor-backendpolicy namespace: asm-ingress spec: default: securityPolicy: edge-fw-policy targetRef: group: net.gke.io kind: ServiceImport name: asm-ingressgateway EOF
Aplique a política do Google Cloud Armor aos dois clusters:
kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/cloud-armor-backendpolicy.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/cloud-armor-backendpolicy.yaml
Crie um arquivo YAML personalizado que permita que o balanceador de carga realize verificações de integridade no endpoint de integridade do Envoy (porta
15021
no caminho/healthz/ready
) dos pods de gateway de entrada nos dois clusters:cat <<EOF > ${WORKDIR}/ingress-gateway-healthcheck.yaml apiVersion: networking.gke.io/v1 kind: HealthCheckPolicy metadata: name: ingress-gateway-healthcheck namespace: asm-ingress spec: default: config: httpHealthCheck: port: 15021 portSpecification: USE_FIXED_PORT requestPath: /healthz/ready type: HTTP targetRef: group: net.gke.io kind: ServiceImport name: asm-ingressgateway EOF
Aplique o arquivo YAML personalizado que você criou na etapa anterior aos dois clusters:
kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/ingress-gateway-healthcheck.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/ingress-gateway-healthcheck.yaml
Ative o balanceamento de carga de vários clusters para a frota e designe
CLUSTER_1_NAME
como o cluster de configuração:gcloud container fleet ingress enable \ --config-membership=${CLUSTER_1_NAME} \ --location=${CLUSTER_1_REGION}
Conceda as permissões do IAM para o controlador de gateway na frota:
gcloud projects add-iam-policy-binding PROJECT_ID \ --member "serviceAccount:service-${PROJECT_NUMBER}@gcp-sa-multiclusteringress.iam.gserviceaccount.com" \ --role "roles/container.admin"
Crie o arquivo YAML do balanceador de carga usando um recurso personalizado do Gateway que referencia o
gke-l7-global-external-managed-mc
gatewayClass
e o endereço IP estático que você criou anteriormente:cat <<EOF > ${WORKDIR}/frontend-gateway.yaml kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: external-http namespace: asm-ingress annotations: networking.gke.io/certmap: mcg-cert-map spec: gatewayClassName: gke-l7-global-external-managed-mc listeners: - name: http # list the port only so we can redirect any incoming http requests to https protocol: HTTP port: 80 - name: https protocol: HTTPS port: 443 allowedRoutes: kinds: - kind: HTTPRoute addresses: - type: NamedAddress value: mcg-ip EOF
Aplique o arquivo YAML
frontend-gateway
aos dois clusters. SomenteCLUSTER_1_NAME
é autoritativo, a menos que você designe um cluster de configuração diferente como autoritativo:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-gateway.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-gateway.yaml
Crie um arquivo YAML
HTTPRoute
chamadodefault-httproute.yaml
que instrua o recurso Gateway a enviar solicitações aos gateways de entrada:cat << EOF > ${WORKDIR}/default-httproute.yaml apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: default-httproute namespace: asm-ingress spec: parentRefs: - name: external-http namespace: asm-ingress sectionName: https rules: - backendRefs: - group: net.gke.io kind: ServiceImport name: asm-ingressgateway port: 443 EOF
Aplique o arquivo YAML
HTTPRoute
criado na etapa anterior a ambos os clusters:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/default-httproute.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/default-httproute.yaml
Para realizar redirecionamentos HTTP para HTTP(S), crie outro arquivo YAML
HTTPRoute
chamadodefault-httproute-redirect.yaml
:cat << EOF > ${WORKDIR}/default-httproute-redirect.yaml kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-to-https-redirect-httproute namespace: asm-ingress spec: parentRefs: - name: external-http namespace: asm-ingress sectionName: http rules: - filters: - type: RequestRedirect requestRedirect: scheme: https statusCode: 301 EOF
Aplique o arquivo YAML de redirecionamento
HTTPRoute
aos dois clusters:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/default-httproute-redirect.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/default-httproute-redirect.yaml
Inspecione o recurso Gateway para verificar o progresso da implantação do balanceador de carga:
kubectl --context=${CLUSTER_1_NAME} describe gateway external-http -n asm-ingress
A saída mostra as informações que você inseriu nesta seção.
Implantar o aplicativo de exemplo whereami
Este guia usa o
whereami
como um aplicativo de exemplo para fornecer feedback direto sobre quais clusters estão
respondendo às solicitações. A seção a seguir configura duas implantações separadas do
whereami nos dois clusters: uma implantação frontend
e uma backend
.
A implantação frontend
é a primeira carga de trabalho a receber a solicitação. Em seguida,
ela chama a implantação backend
.
Esse modelo é usado para demonstrar uma arquitetura de aplicativo multiserviço.
Os serviços frontend
e backend
são implantados nos dois clusters.
No Cloud Shell, crie os namespaces para um
frontend
e umbackend
do whereami nos dois clusters e ative a injeção de namespace:kubectl --context=${CLUSTER_1_NAME} create ns frontend kubectl --context=${CLUSTER_1_NAME} label namespace frontend istio-injection=enabled kubectl --context=${CLUSTER_1_NAME} create ns backend kubectl --context=${CLUSTER_1_NAME} label namespace backend istio-injection=enabled kubectl --context=${CLUSTER_2_NAME} create ns frontend kubectl --context=${CLUSTER_2_NAME} label namespace frontend istio-injection=enabled kubectl --context=${CLUSTER_2_NAME} create ns backend kubectl --context=${CLUSTER_2_NAME} label namespace backend istio-injection=enabled
Crie uma variante do Kustomize para o
backend
do whereami:mkdir -p ${WORKDIR}/whereami-backend/base cat <<EOF > ${WORKDIR}/whereami-backend/base/kustomization.yaml resources: - github.com/GoogleCloudPlatform/kubernetes-engine-samples/quickstarts/whereami/k8s EOF mkdir ${WORKDIR}/whereami-backend/variant cat <<EOF > ${WORKDIR}/whereami-backend/variant/cm-flag.yaml apiVersion: v1 kind: ConfigMap metadata: name: whereami data: BACKEND_ENABLED: "False" # assuming you don't want a chain of backend calls METADATA: "backend" EOF cat <<EOF > ${WORKDIR}/whereami-backend/variant/service-type.yaml apiVersion: "v1" kind: "Service" metadata: name: "whereami" spec: type: ClusterIP EOF cat <<EOF > ${WORKDIR}/whereami-backend/variant/kustomization.yaml nameSuffix: "-backend" namespace: backend commonLabels: app: whereami-backend resources: - ../base patches: - path: cm-flag.yaml target: kind: ConfigMap - path: service-type.yaml target: kind: Service EOF
Aplique a variante
backend
do whereami aos dois clusters:kubectl --context=${CLUSTER_1_NAME} apply -k ${WORKDIR}/whereami-backend/variant kubectl --context=${CLUSTER_2_NAME} apply -k ${WORKDIR}/whereami-backend/variant
Crie uma variante do Kustomize para o
frontend
do whereami:mkdir -p ${WORKDIR}/whereami-frontend/base cat <<EOF > ${WORKDIR}/whereami-frontend/base/kustomization.yaml resources: - github.com/GoogleCloudPlatform/kubernetes-engine-samples/quickstarts/whereami/k8s EOF mkdir whereami-frontend/variant cat <<EOF > ${WORKDIR}/whereami-frontend/variant/cm-flag.yaml apiVersion: v1 kind: ConfigMap metadata: name: whereami data: BACKEND_ENABLED: "True" BACKEND_SERVICE: "http://whereami-backend.backend.svc.cluster.local" EOF cat <<EOF > ${WORKDIR}/whereami-frontend/variant/service-type.yaml apiVersion: "v1" kind: "Service" metadata: name: "whereami" spec: type: ClusterIP EOF cat <<EOF > ${WORKDIR}/whereami-frontend/variant/kustomization.yaml nameSuffix: "-frontend" namespace: frontend commonLabels: app: whereami-frontend resources: - ../base patches: - path: cm-flag.yaml target: kind: ConfigMap - path: service-type.yaml target: kind: Service EOF
Aplique a variante
frontend
do whereami aos dois clusters:kubectl --context=${CLUSTER_1_NAME} apply -k ${WORKDIR}/whereami-frontend/variant kubectl --context=${CLUSTER_2_NAME} apply -k ${WORKDIR}/whereami-frontend/variant
Crie um arquivo YAML
VirtualService
para encaminhar solicitações para ofrontend
do whereami:cat << EOF > ${WORKDIR}/frontend-vs.yaml apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: whereami-vs namespace: frontend spec: gateways: - asm-ingress/asm-ingressgateway hosts: - 'frontend.endpoints.PROJECT_ID.cloud.goog' http: - route: - destination: host: whereami-frontend port: number: 80 EOF
Aplique o arquivo YAML
frontend-vs
aos dois clusters:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-vs.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-vs.yaml
Agora que você implantou
frontend-vs.yaml
nos dois clusters, tente chamar o endpoint público deles:curl -s https://frontend.endpoints.PROJECT_ID.cloud.goog | jq
O resultado será assim:
{ "backend_result": { "cluster_name": "edge-to-mesh-02", "gce_instance_id": "8396338201253702608", "gce_service_account": "e2m-mcg-01.svc.id.goog", "host_header": "whereami-backend.backend.svc.cluster.local", "metadata": "backend", "node_name": "gk3-edge-to-mesh-02-pool-2-675f6abf-645h", "pod_ip": "10.124.0.199", "pod_name": "whereami-backend-7cbdfd788-8mmnq", "pod_name_emoji": "📸", "pod_namespace": "backend", "pod_service_account": "whereami-backend", "project_id": "e2m-mcg-01", "timestamp": "2023-12-01T03:46:24", "zone": "us-east4-b" }, "cluster_name": "edge-to-mesh-01", "gce_instance_id": "1047264075324910451", "gce_service_account": "e2m-mcg-01.svc.id.goog", "host_header": "frontend.endpoints.e2m-mcg-01.cloud.goog", "metadata": "frontend", "node_name": "gk3-edge-to-mesh-01-pool-2-d687e3c0-5kf2", "pod_ip": "10.54.1.71", "pod_name": "whereami-frontend-69c4c867cb-dgg8t", "pod_name_emoji": "🪴", "pod_namespace": "frontend", "pod_service_account": "whereami-frontend", "project_id": "e2m-mcg-01", "timestamp": "2023-12-01T03:46:24", "zone": "us-central1-c" }
Se você executar o comando curl
algumas vezes, verá que as respostas (de frontend
e backend
) vêm de regiões diferentes. Em resposta,
o balanceador de carga está fornecendo o roteamento geográfico. Isso significa que o balanceador de carga está roteando solicitações do cliente para o cluster ativo mais próximo, mas as solicitações ainda estão sendo enviadas aleatoriamente. Quando as solicitações vão de uma região para outra, isso aumenta a latência e o custo.
Na próxima seção, você vai implementar o balanceamento de carga de localidade no Service Mesh para manter as solicitações locais.
Ativar e testar o balanceamento de carga de localidade para o whereami
Nesta seção, você vai implementar o balanceamento de carga de localidade na malha de serviço para manter as solicitações locais. Você também realiza alguns testes para conferir como o whereami processa vários cenários de falha.
Quando você faz uma solicitação para o serviço frontend
do whereami, o balanceador de carga
envia a solicitação para o cluster com a menor latência em relação ao
cliente. Isso significa que os pods de gateway de entrada dentro do balanceamento de carga de malha solicita pods frontend
do whereami nos dois clusters. Esta seção
vai resolver esse problema ativando o balanceamento de carga de localidade na malha.
No Cloud Shell, crie um arquivo YAML
DestinationRule
que ative o failover regional de balanceamento de carga de localidade para o serviçofrontend
:cat << EOF > ${WORKDIR}/frontend-dr.yaml apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: frontend namespace: frontend spec: host: whereami-frontend.frontend.svc.cluster.local trafficPolicy: connectionPool: http: maxRequestsPerConnection: 0 loadBalancer: simple: LEAST_REQUEST localityLbSetting: enabled: true outlierDetection: consecutive5xxErrors: 1 interval: 1s baseEjectionTime: 1m EOF
O exemplo de código anterior só ativa o roteamento local para o serviço
frontend
. Você também precisa de uma configuração extra que processe o back-end.Aplique o arquivo YAML
frontend-dr
aos dois clusters:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-dr.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-dr.yaml
Crie um arquivo YAML
DestinationRule
que ative o failover regional de balanceamento de carga de localidade para o serviçobackend
:cat << EOF > ${WORKDIR}/backend-dr.yaml apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: n ame: backend namespace: backend spec: host: whereami-backend.backend.svc.cluster.local trafficPolicy: connectionPool: http: maxRequestsPerConnection: 0 loadBalancer: simple: LEAST_REQUEST localityLbSetting: enabled: true outlierDetection: consecutive5xxErrors: 1 interval: 1s baseEjectionTime: 1m EOF
Aplique o arquivo YAML
backend-dr
aos dois clusters:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/backend-dr.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/backend-dr.yaml
Com os dois conjuntos de arquivos YAML
DestinationRule
aplicados aos dois clusters, as solicitações permanecem locais para o cluster para o qual a solicitação é roteada.Para testar o failover do serviço
frontend
, reduza o número de réplicas do gateway de entrada no cluster principal.Do ponto de vista do balanceador de carga multirregional, essa ação simula uma falha de cluster. Isso faz com que o cluster falhe nas verificações de integridade do balanceador de carga. Este exemplo usa o cluster em
CLUSTER_1_REGION
. Você só vai ver respostas do cluster emCLUSTER_2_REGION
.Reduza o número de réplicas do gateway de entrada no cluster principal para zero e chame o endpoint público para verificar se as solicitações falharam no outro cluster:
kubectl --context=${CLUSTER_1_NAME} -n asm-ingress scale --replicas=0 deployment/asm-ingressgateway
A saída será semelhante a esta:
$ curl -s https://frontend.endpoints.PROJECT_ID.cloud.goog | jq { "backend_result": { "cluster_name": "edge-to-mesh-02", "gce_instance_id": "2717459599837162415", "gce_service_account": "e2m-mcg-01.svc.id.goog", "host_header": "whereami-backend.backend.svc.cluster.local", "metadata": "backend", "node_name": "gk3-edge-to-mesh-02-pool-2-675f6abf-dxs2", "pod_ip": "10.124.1.7", "pod_name": "whereami-backend-7cbdfd788-mp8zv", "pod_name_emoji": "🏌🏽♀", "pod_namespace": "backend", "pod_service_account": "whereami-backend", "project_id": "e2m-mcg-01", "timestamp": "2023-12-01T05:41:18", "zone": "us-east4-b" }, "cluster_name": "edge-to-mesh-02", "gce_instance_id": "6983018919754001204", "gce_service_account": "e2m-mcg-01.svc.id.goog", "host_header": "frontend.endpoints.e2m-mcg-01.cloud.goog", "metadata": "frontend", "node_name": "gk3-edge-to-mesh-02-pool-3-d42ddfbf-qmkn", "pod_ip": "10.124.1.142", "pod_name": "whereami-frontend-69c4c867cb-xf8db", "pod_name_emoji": "🏴", "pod_namespace": "frontend", "pod_service_account": "whereami-frontend", "project_id": "e2m-mcg-01", "timestamp": "2023-12-01T05:41:18", "zone": "us-east4-b" }
Para retomar o roteamento de tráfego normal, restaure as réplicas do gateway de entrada para o valor original no cluster:
kubectl --context=${CLUSTER_1_NAME} -n asm-ingress scale --replicas=3 deployment/asm-ingressgateway
Simule uma falha no serviço
backend
reduzindo o número de réplicas na região principal para 0:kubectl --context=${CLUSTER_1_NAME} -n backend scale --replicas=0 deployment/whereami-backend
Verifique se as respostas do serviço
frontend
vêm da região principalus-central1
pelo balanceador de carga e se as respostas do serviçobackend
vêm da região secundáriaus-east4
.A saída também precisa incluir uma resposta para o serviço
frontend
da região principal (us-central1
) e uma resposta para o serviçobackend
da região secundária (us-east4
), conforme esperado.Restaure as réplicas do serviço de back-end para o valor original para retomar o roteamento de tráfego típico:
kubectl --context=${CLUSTER_1_NAME} -n backend scale --replicas=3 deployment/whereami-backend
Agora você tem um balanceador de carga HTTP(S) global que serve como front-end para seu aplicativo multirregional hospedado pela malha de serviço.
Limpar
Para evitar cobranças na sua conta do Google Cloud pelos recursos usados na implantação, exclua o projeto ou mantenha o projeto e exclua cada um dos recursos.
Excluir o projeto
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
Excluir recursos individuais
Se você quiser manter o projeto do Google Cloud usado nesta implantação, exclua os recursos individuais:
No Cloud Shell, exclua os recursos
HTTPRoute
:kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/default-httproute-redirect.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/default-httproute-redirect.yaml kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/default-httproute.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/default-httproute.yaml
Exclua os recursos do gateway do GKE:
kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/frontend-gateway.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/frontend-gateway.yaml
Exclua as políticas:
kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/ingress-gateway-healthcheck.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/ingress-gateway-healthcheck.yaml kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/cloud-armor-backendpolicy.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/cloud-armor-backendpolicy.yaml
Exclua as exportações de serviço:
kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/svc_export.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/svc_export.yaml
Excluir os recursos do Google Cloud Armor:
gcloud --project=PROJECT_ID compute security-policies rules delete 1000 --security-policy edge-fw-policy --quiet gcloud --project=PROJECT_ID compute security-policies delete edge-fw-policy --quiet
Exclua os recursos do Gerenciador de certificados:
gcloud --project=PROJECT_ID certificate-manager maps entries delete mcg-cert-map-entry --map="mcg-cert-map" --quiet gcloud --project=PROJECT_ID certificate-manager maps delete mcg-cert-map --quiet gcloud --project=PROJECT_ID certificate-manager certificates delete mcg-cert --quiet
Exclua a entrada DNS do Endpoints:
gcloud --project=PROJECT_ID endpoints services delete "frontend.endpoints.PROJECT_ID.cloud.goog" --quiet
Exclua o endereço IP estático:
gcloud --project=PROJECT_ID compute addresses delete mcg-ip --global --quiet
Exclua os clusters do GKE Autopilot. Essa etapa leva alguns minutos.
gcloud --project=PROJECT_ID container clusters delete ${CLUSTER_1_NAME} --region ${CLUSTER_1_REGION} --quiet gcloud --project=PROJECT_ID container clusters delete ${CLUSTER_2_NAME} --region ${CLUSTER_2_REGION} --quiet
A seguir
- Saiba mais sobre mais recursos oferecidos pelo Gateway do GKE que podem ser usados com sua malha de serviço.
- Saiba mais sobre os diferentes tipos de balanceamento de carga na nuvem disponíveis para o GKE.
- Saiba mais sobre os recursos e as funcionalidades oferecidas pelo Cloud Service Mesh.
- Para mais arquiteturas de referência, diagramas e práticas recomendadas, confira a Central de arquitetura do Cloud.
Colaboradores
Autores:
- Alex Mattson | Engenheiro especialista em aplicativos
- Mark Chilvers | Engenheiro especialista em aplicativos
Outros colaboradores:
- Abdelfettah Sghiouar | Mediador de desenvolvedores de nuvem
- Greg Bray | Engenheiro de clientes
- Paul Revello | Arquiteto de soluções de nuvem
- Valavan Rajakumar | Arquiteto corporativo fundamental