Este documento mostra como realizar as seguintes tarefas:
- Implemente aplicações distribuídas globalmente expostas através do GKE Gateway e do Cloud Service Mesh.
- Exponha uma aplicação a vários clientes combinando o Cloud Load Balancing com a Cloud Service Mesh.
- Integre balanceadores de carga com uma malha de serviços implementada em várias Google Cloud regiões.
Este guia de implementação destina-se a administradores da plataforma. Também se destina a profissionais avançados que executam o Cloud Service Mesh. As instruções também funcionam para o Istio no GKE.
Arquitetura
O diagrama seguinte mostra a topologia de entrada predefinida de uma malha de serviços, ou seja, um balanceador de carga de TCP/UDP externo que expõe os proxies de gateway de entrada num único cluster:
Este guia de implementação usa recursos do Gateway do Google Kubernetes Engine (GKE). Especificamente, usa um gateway de vários clusters para configurar o equilíbrio de carga de várias regiões em frente de vários clusters do Autopilot distribuídos por duas regiões.
O diagrama anterior mostra como os dados fluem através de cenários de entrada na nuvem e de entrada na malha. Para mais informações, consulte a explicação do diagrama de arquitetura no documento de arquitetura de referência associado.
Objetivos
- Implemente um par de clusters do GKE Autopilot na mesma frota. Google Cloud
- Implemente uma malha de serviços na nuvem baseada no Istio na mesma frota.
- Configure um balanceador de carga através do GKE Gateway para terminar o tráfego HTTPS público.
- Direcionar o tráfego HTTPS público para aplicações alojadas pelo Cloud Service Mesh que são implementadas em vários clusters e regiões.
- Implemente a aplicação de exemplo whereami nos dois clusters do Autopilot.
Otimização de custos
Neste documento, usa 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 custos com base na sua utilização projetada,
use a calculadora de preços.
Quando terminar as tarefas descritas neste documento, pode evitar a faturação contínua eliminando os recursos que criou. Para mais informações, consulte o artigo Limpe.
Antes de começar
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator
(
roles/resourcemanager.projectCreator
), which contains theresourcemanager.projects.create
permission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
-
In the Google Cloud console, activate Cloud Shell.
Executa todos os comandos do terminal para esta implementação a partir do Cloud Shell.
Defina o seu Google Cloud projeto predefinido:
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 quer usar para esta implementaçã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`
No Cloud Shell, crie um novo ficheiro
kubeconfig
. Este passo garante que não cria um conflito com o seu ficheirokubeconfig
(predefinido) existente.touch edge2mesh_mr_kubeconfig export KUBECONFIG=${WORKDIR}/edge2mesh_mr_kubeconfig
Defina as variáveis de ambiente que são usadas quando cria os clusters do GKE e os recursos nos mesmos. Modifique as opções de região predefinidas para se adequarem aos 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 Google Cloud que são usadas ao longo deste 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 privados em
CLUSTER_1_REGION
. Use a flag--async
para evitar esperar que o primeiro cluster seja aprovisionado e registado 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 registe 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
Certifique-se de que os clusters estão em execução. Pode demorar até 20 minutos até que todos os clusters estejam em execução:
gcloud container clusters list
O resultado é semelhante ao seguinte:
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
Reúna as credenciais para
CLUSTER_1_NAME
.Criou-o de forma assíncrona para poder executar comandos adicionais enquanto o cluster era aprovisionado.CLUSTER_1_NAME
gcloud container clusters get-credentials ${CLUSTER_1_NAME} \ --region ${CLUSTER_1_REGION}
Para esclarecer os nomes dos contextos do Kubernetes, mude o nome 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}
No Cloud Shell, ative o Cloud Service Mesh na frota:
gcloud container fleet mesh enable
Ative a gestão automática do plano de controlo e do plano de dados:
gcloud container fleet mesh update \ --management automatic \ --memberships ${CLUSTER_1_NAME},${CLUSTER_2_NAME}
Aguarde cerca de 20 minutos. Em seguida, verifique se o estado do plano de controlo é
ACTIVE
:gcloud container fleet mesh describe
O resultado é semelhante ao seguinte:
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'
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 uma etiqueta de espaço de nomes aos espaços de nomes
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 é semelhante ao seguinte:
namespace/asm-ingress labeled
Etiquetar os espaços de nomes
asm-ingress
comistio-injection=enabled
indica ao Cloud Service Mesh que injete automaticamente proxies Envoy sidecar quando um pod é implementado.Gere um certificado autoassinado para utilização futura:
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 encriptação entre o equilibrador de carga e os gateways de entrada da malha de serviços. Também permite a compatibilidade com protocolos baseados em HTTP/2, como o gRPC. As instruções sobre como anexar o certificado autoassinado aos gateways de entrada são fornecidas mais adiante em Crie recursos de endereço IP externo, registo DNS e certificado TLS.
Para mais informações sobre os requisitos do certificado do gateway de entrada, consulte o artigo Encriptação do equilibrador de carga para os back-ends.
Crie um segredo do Kubernetes em cada cluster para armazenar o certificado autossinado:
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 fazer a integração com o Application Load Balancer externo, crie uma variante do 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 a ambos os clusters:
kubectl --context ${CLUSTER_1_NAME} apply -k ${WORKDIR}/asm-ig/variant kubectl --context ${CLUSTER_2_NAME} apply -k ${WORKDIR}/asm-ig/variant
- Permite que o balanceador de carga se dirija aos pods do gateway de entrada em vários clusters.
- Permite que os pods do gateway de entrada encaminhem pedidos para serviços em execução na malha de serviços.
No Cloud Shell, ative os serviços em vários clusters (MCS) para a frota:
gcloud container fleet multi-cluster-services enable
Conceda ao MCS as autorizações de IAM necessárias ao projeto ou à 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 ficheiro 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 ficheiro YAML
ServiceExport
a ambos os clusters:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/svc_export.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/svc_export.yaml
Se receber a seguinte mensagem de erro, aguarde alguns momentos para que as definições de recursos personalizados (CRDs) do MCS sejam instaladas. Em seguida, volte a executar os comandos para aplicar o
ServiceExport
ficheiro YAML a ambos os 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
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 GKE Gateway. Permite que o endereço IP permaneça o mesmo, mesmo que o balanceador de carga externo seja recriado.
Obtenha 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 fácil de usar para o endereço IP do gateway, tem de ter um registo DNS público.
Pode usar qualquer fornecedor de DNS e esquema de automatização que quiser. Esta implementação usa os Endpoints em vez de criar uma zona DNS gerida. O Endpoints fornece um registo de DNS gerido pela Google gratuito para um endereço IP externo.
Execute o seguinte comando para criar um ficheiro YAML denominado
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 ficheiro
dns-spec.yaml
define o registo de DNS público no formatofrontend.endpoints.PROJECT_ID.cloud.goog
, em quePROJECT_ID
é o identificador exclusivo do seu projeto.Implemente o ficheiro
dns-spec.yaml
para criar a entrada DNS. Este processo demora alguns minutos.gcloud endpoints services deploy ${WORKDIR}/dns-spec.yaml
Crie um certificado com o Gestor de certificados para o nome da entrada DNS que criou no passo anterior:
gcloud certificate-manager certificates create mcg-cert \ --domains="frontend.endpoints.PROJECT_ID.cloud.goog"
É usado um certificado TLS gerido pela Google para terminar os pedidos de clientes recebidos no balanceador de carga.
Crie um mapa de certificados:
gcloud certificate-manager maps create mcg-cert-map
O equilibrador de carga faz referência ao certificado através da entrada do mapa de certificados que cria no passo seguinte.
Crie uma entrada de mapeamento de certificados para o certificado que criou anteriormente nesta secçã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"
- Crie uma política de segurança do Cloud Armor com regras.
- Crie uma política que permita ao equilibrador de carga verificar a capacidade de resposta dos pods do gateway de entrada através do
ServiceExport
ficheiro YAML que criou anteriormente. - Use a API GKE Gateway para criar um recurso de balanceador de carga.
- Use o recurso personalizado
GatewayClass
para definir o tipo de equilibrador de carga específico. - 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 Cloud Armor:
gcloud compute security-policies create edge-fw-policy \ --description "Block XSS attacks"
Crie uma regra para a 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 ficheiro YAML para a política de segurança e faça referência ao
ServiceExport
ficheiro YAML através de um ficheiro 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 Cloud Armor a ambos os 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 ficheiro YAML personalizado que permita ao balanceador de carga realizar verificações de funcionamento no ponto final de funcionamento do Envoy (porta
15021
no caminho/healthz/ready
) dos pods do gateway de entrada em ambos os 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 ficheiro YAML personalizado que criou no passo anterior a ambos os 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 equilíbrio 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 autorizações de 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 ficheiro YAML do equilibrador de carga através de um recurso personalizado do Gateway que faça referência ao
gke-l7-global-external-managed-mc
gatewayClass
e ao endereço IP estático que 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 ficheiro YAML
frontend-gateway
a ambos os clusters. Apenas o cluster de configuraçãoCLUSTER_1_NAME
é autoritário, a menos que designe um cluster de configuração diferente como autoritário:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-gateway.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-gateway.yaml
Crie um
HTTPRoute
ficheiro YAML denominadodefault-httproute.yaml
que instrui o recurso Gateway a enviar pedidos para os 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 ficheiro
HTTPRoute
YAML que criou no passo 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 fazer redirecionamentos de HTTP para HTTP(S), crie um
HTTPRoute
ficheiro YAML adicional denominadodefault-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 ficheiro YAML de redirecionamento a ambos os clusters:
HTTPRoute
kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/default-httproute-redirect.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/default-httproute-redirect.yaml
Inspeccione o recurso Gateway para verificar o progresso da implementação do equilibrador de carga:
kubectl --context=${CLUSTER_1_NAME} describe gateway external-http -n asm-ingress
A saída mostra as informações que introduziu nesta secção.
No Cloud Shell, crie os namespaces para um whereami
frontend
e um whereamibackend
em ambos os 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 whereami
backend
: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 whereami
backend
a ambos os 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 whereami
frontend
: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 whereami
frontend
a ambos os 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 ficheiro YAML para encaminhar pedidos para o whereami
frontend
:VirtualService
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 ficheiro YAML
frontend-vs
a ambos os 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 implementou o
frontend-vs.yaml
em ambos os clusters, tente chamar o ponto final público dos seus clusters:curl -s https://frontend.endpoints.PROJECT_ID.cloud.goog | jq
O resultado é semelhante ao seguinte:
{ "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" }
-
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 apenas ativa o encaminhamento local para o serviço
frontend
. Também precisa de uma configuração adicional que processe o back-end. Aplique o ficheiro YAML
frontend-dr
a ambos os 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
DestinationRule
ficheiro YAML que ative o balanceamento de carga de localidade para a comutação por falha regional para o serviçobackend
:cat << EOF > ${WORKDIR}/backend-dr.yaml apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: 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 ficheiro YAML
backend-dr
a ambos os 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 ficheiros YAML
DestinationRule
aplicados a ambos os clusters, os pedidos permanecem locais para o cluster para o qual o pedido é encaminhado.Para testar a ativação pós-falha do serviço
frontend
, reduza o número de réplicas para o gateway de entrada no cluster principal.Do ponto de vista do equilibrador de carga multirregional, esta ação simula uma falha do cluster. Faz com que esse cluster falhe as verificações de funcionamento do equilibrador de carga. Este exemplo usa o cluster em
CLUSTER_1_REGION
. Só deve ver respostas do cluster emCLUSTER_2_REGION
.Reduza o número de réplicas para o gateway de entrada no cluster principal para zero e chame o ponto final público para verificar se os pedidos foram transferidos para o outro cluster:
kubectl --context=${CLUSTER_1_NAME} -n asm-ingress scale --replicas=0 deployment/asm-ingressgateway
O resultado deve ser semelhante ao seguinte:
$ 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 encaminhamento de tráfego típico, 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 para o 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
provêm da região principalus-central1
através do balanceador de carga e se as respostas do serviçobackend
provêm da região secundáriaus-east4
.O resultado também deve 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 encaminhamento de tráfego típico:
kubectl --context=${CLUSTER_1_NAME} -n backend scale --replicas=3 deployment/whereami-backend
- 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.
No Cloud Shell, elimine 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
Elimine os recursos do GKE Gateway:
kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/frontend-gateway.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/frontend-gateway.yaml
Elimine 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
Elimine as exportações de serviços:
kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/svc_export.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/svc_export.yaml
Elimine os recursos do 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
Elimine os recursos do Certificate Manager:
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
Elimine a entrada de DNS dos pontos finais:
gcloud --project=PROJECT_ID endpoints services delete "frontend.endpoints.PROJECT_ID.cloud.goog" --quiet
Elimine o endereço IP estático:
gcloud --project=PROJECT_ID compute addresses delete mcg-ip --global --quiet
Elimine os clusters do GKE Autopilot. Este passo demora vários 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
- Saiba mais sobre as funcionalidades oferecidas pelo GKE Gateway que pode usar com a sua malha de serviços.
- Saiba mais sobre os diferentes tipos de Cloud Load Balancing disponíveis para o GKE.
- Saiba mais sobre as funcionalidades e as funções oferecidas pela Cloud Service Mesh.
- Para ver mais arquiteturas de referência, diagramas e práticas recomendadas, explore o Centro de arquitetura na nuvem.
- Alex Mattson | Application Specialist Engineer
- Mark Chilvers | Application Specialist Engineer
- Abdelfettah Sghiouar | Cloud Developer Advocate
- Greg Bray | Customer Engineer
- Paul Revello | Arquiteto de soluções na nuvem
- Valavan Rajakumar | Key Enterprise Architect
Crie clusters do GKE
Nesta secção, cria clusters do GKE para alojar as aplicações e a infraestrutura de apoio, que cria mais tarde neste guia de implementação.
Instale uma malha de serviço
Nesta secção, configura a malha de serviços na nuvem gerida com a API Fleet. A utilização da API Fleet para ativar o Cloud Service Mesh oferece uma abordagem declarativa para aprovisionar uma malha de serviços.
Implemente um balanceador de carga de aplicações externo e crie gateways de entrada
Nesta secção, implementa um Application Load Balancer externo através do controlador do GKE Gateway e cria gateways de entrada para ambos os clusters. Os recursos gateway
e gatewayClass
automatizam o aprovisionamento
do equilibrador de carga e da verificação de funcionamento do back-end. Para fornecer a terminação TLS no balanceador de carga, crie recursos do Gestor de certificados e anexe-os ao balanceador de carga. Além disso, usa pontos finais para aprovisionar automaticamente um nome DNS público para a aplicação.
Instale um gateway de entrada em ambos os clusters
Como prática recomendada de segurança, recomendamos que implemente o gateway de entrada num espaço de nomes diferente do plano de controlo da malha.
Exponha pods de gateway de entrada ao balanceador de carga através de um serviço em vários clusters
Nesta secção, exporta os pods do gateway de entrada através de um recurso personalizado.ServiceExport
Tem de exportar os pods do gateway de entrada
através de um recurso personalizado ServiceExport
pelos seguintes motivos:
Crie recursos de endereço IP externo, registo de DNS e certificado TLS
Nesta secção, cria recursos de rede que suportam os recursos de balanceamento de carga que cria mais tarde nesta implementação.
Crie políticas de serviço de back-end e recursos do balanceador de carga
Nesta secção, conclui as seguintes tarefas:
Implemente a aplicação de amostra whereami
Este guia usa a app
whereami
como uma aplicação de exemplo para fornecer feedback direto sobre os clusters que estão a
responder a pedidos. A secção seguinte configura duas implementações separadas de whereami em ambos os clusters: uma implementação frontend
e uma implementação backend
.
A implementação frontend
é a primeira carga de trabalho a receber o pedido. Em seguida, chama a implementação backend
.
Este modelo é usado para demonstrar uma arquitetura de aplicação de vários serviços.
Os serviços frontend
e backend
são implementados em ambos os clusters.
Se executar o comando curl
algumas vezes, vai ver que as respostas (tanto de frontend
como de backend
) provêm de regiões diferentes. Na respetiva resposta, o balanceador de carga está a fornecer georouting. Isto significa que o balanceador de carga está a encaminhar pedidos do cliente para o cluster ativo mais próximo, mas os pedidos continuam a chegar aleatoriamente. Quando os pedidos vão ocasionalmente de uma região para outra, aumenta a latência e o custo.
Na secção seguinte, implementa o equilíbrio de carga de localidade na malha de serviços para manter os pedidos locais.
Ative e teste o equilíbrio de carga de localidade para o whereami
Nesta secção, implementa o equilíbrio de carga de localidade na malha de serviços para manter os pedidos locais. Também realiza alguns testes para ver como o whereami processa vários cenários de falha.
Quando faz um pedido ao serviço whereami frontend
, o balanceador de carga envia o pedido para o cluster com a latência mais baixa relativamente ao cliente. Isto significa que os pods de gateway de entrada na malha equilibram os pedidos de carga para os pods whereami frontend
em ambos os clusters. Esta secção
resolve esse problema ativando o balanceamento de carga de localidade na malha.
Agora, tem um balanceador de carga HTTP(S) global que funciona como um front-end para a sua aplicação multirregional alojada na malha de serviços.
Limpar
Para evitar incorrer em cobranças na sua Google Cloud conta pelos recursos usados nesta implementação, elimine o projeto que contém os recursos ou mantenha o projeto e elimine os recursos individuais.
Elimine o projeto
Elimine os recursos individuais
Se quiser manter o Google Cloud projeto que usou nesta implementação, elimine os recursos individuais:
O que se segue?
Colaboradores
Autores:
Outros colaboradores: