En este documento, se muestra cómo completar las siguientes tareas:
- Implementar aplicaciones distribuidas globalmente expuestas a través de GKE Gateway y Cloud Service Mesh.
- Exponer una aplicación a varios clientes mediante la combinación de Cloud Load Balancing con Cloud Service Mesh
- Integra los balanceadores de cargas con una malla de servicios implementada en varias Google Cloud regiones.
Esta guía de implementación está dirigida a los administradores de la plataforma. También está dirigido a profesionales avanzados que ejecutan Cloud Service Mesh. Las instrucciones también funcionan para Istio on GKE.
Arquitectura
En el siguiente diagrama, se muestra la topología de entrada predeterminada de una malla de servicios: un balanceador de cargas de TCP/UDP externo que expone los proxies de puerta de enlace de entrada en un solo clúster:
En esta guía de implementación, se usan recursos de puerta de enlace de Google Kubernetes Engine (GKE). Específicamente, usa una puerta de enlace de varios clústeres para configurar el balanceo de cargas multirregional frente a varios clústeres de Autopilot que se distribuyen en dos regiones.
En el diagrama anterior, se muestra cómo fluyen los datos a través de situaciones de entrada de la nube y entrada de la malla. Para obtener más información, consulta la explicación del diagrama de arquitectura en el documento de arquitectura de referencia asociado.
Objetivos
- Implementa un par de clústeres de GKE Autopilot en Google Cloud en la misma flota.
- Implementar una Cloud Service Mesh basada en Istio en la misma flota
- Configurar un balanceador de cargas a través de la puerta de enlace de GKE para finalizar el tráfico HTTPS público.
- Dirigir el tráfico de HTTPS público a las aplicaciones alojadas en Cloud Service Mesh que se implementan en varios clústeres y regiones.
- Implementar la aplicación de muestra whereami en ambos clústeres de Autopilot.
Optimización de costos
En este documento, usarás los siguientes componentes facturables de Google Cloud:
- Google Kubernetes Engine
- Cloud Load Balancing
- Cloud Service Mesh
- Multi Cluster Ingress
- Google Cloud Armor
- Certificate Manager
- Cloud Endpoints
Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios.
Cuando completes las tareas que se describen en este documento, podrás borrar los recursos que creaste para evitar que se te siga facturando. Para obtener más información, consulta Realiza una limpieza.
Antes de comenzar
-
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.createpermission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
-
In the Google Cloud console, activate Cloud Shell.
Ejecuta todos los comandos de terminal de esta implementación desde Cloud Shell.
Configura tu proyecto Google Cloud predeterminado:
export PROJECT=YOUR_PROJECT export PROJECT_NUMBER=$(gcloud projects describe PROJECT_ID --format="value(projectNumber)") gcloud config set project PROJECT_IDReemplaza
PROJECT_IDpor el ID del proyecto que deseas usar para esta implementación.Cree un directorio de trabajo:
mkdir -p ${HOME}/edge-to-mesh-multi-region cd ${HOME}/edge-to-mesh-multi-region export WORKDIR=`pwd`En Cloud Shell, crea un archivo
kubeconfignuevo. Con este paso te aseguras de no causar un conflicto con el archivokubeconfig(predeterminado) existente.touch edge2mesh_mr_kubeconfig export KUBECONFIG=${WORKDIR}/edge2mesh_mr_kubeconfigDefine las variables de entorno que se usan cuando se crean los clústeres de GKE y los recursos que contienen. Modifica las opciones de región predeterminadas para que se adapten a tus 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.googHabilita las APIs de Google Cloud que se usan en esta guía:
gcloud services enable \ container.googleapis.com \ mesh.googleapis.com \ gkehub.googleapis.com \ multiclusterservicediscovery.googleapis.com \ multiclusteringress.googleapis.com \ trafficdirector.googleapis.com \ certificatemanager.googleapis.comCrea un clúster de GKE Autopilot con nodos privados en
CLUSTER_1_REGION. Usa la marca--asyncpara evitar esperar a que el primer clúster se aprovisione y se registre en la flota: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-fleetCrea y registra un segundo clúster de Autopilot en
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-fleetAsegúrate de que los clústeres estén en ejecución. Puede tomar hasta 20 minutos hasta que todos los clústeres estén en ejecución:
gcloud container clusters listEl resultado es similar a este:
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
Recopila las credenciales para
CLUSTER_1_NAME. CreasteCLUSTER_1_NAMEde forma asíncrona para poder ejecutar comandos adicionales mientras se aprovisiona el clúster.gcloud container clusters get-credentials ${CLUSTER_1_NAME} \ --region ${CLUSTER_1_REGION}Para aclarar los nombres de los contextos de Kubernetes, cámbialos por los nombres de los clústeres:
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}En Cloud Shell, habilita Cloud Service Mesh en la flota:
gcloud container fleet mesh enableHabilita la administración automática del plano de control y del plano de datos:
gcloud container fleet mesh update \ --management automatic \ --memberships ${CLUSTER_1_NAME},${CLUSTER_2_NAME}Espera alrededor de 20 minutos. Luego, verifica que el estado del plano de control sea
ACTIVE:gcloud container fleet mesh describeEl resultado es similar a este:
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'En Cloud Shell, crea un espacio de nombres
asm-ingressdedicado en cada clúster:kubectl --context=${CLUSTER_1_NAME} create namespace asm-ingress kubectl --context=${CLUSTER_2_NAME} create namespace asm-ingressAgrega una etiqueta de espacio de nombres al espacio de nombres
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=enabledEl resultado es similar a este:
namespace/asm-ingress labeled
Si etiquetas los espacios de nombres
asm-ingressconistio-injection=enabled, se indica a Cloud Service Mesh que inserte de manera automática proxies de sidecar de Envoy cuando se implementa un Pod.Genera un certificado autofirmado para usarlo en el 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.crtEl certificado proporciona una capa adicional de encriptación entre el balanceador de cargas y las puertas de enlace de entrada de la malla de servicios. También habilita la compatibilidad con protocolos basados en HTTP/2, como gRPC. Las instrucciones para adjuntar el certificado autofirmado a las puertas de enlace de entrada se proporcionan más adelante en Crea recursos de dirección IP externa, registro de DNS y certificado TLS.
Para obtener más información sobre los requisitos del certificado de puerta de enlace de entrada, consulta Encriptación del balanceador de cargas a los backends.
Crea un Secret de Kubernetes en cada clúster para almacenar el certificado autofirmado:
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.crtPara integrarla al balanceador de cargas de aplicaciones externo, crea una variante de kustomize para configurar los recursos de la puerta de enlace 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 EOFAplica la configuración de la puerta de enlace de entrada a ambos clústeres:
kubectl --context ${CLUSTER_1_NAME} apply -k ${WORKDIR}/asm-ig/variant kubectl --context ${CLUSTER_2_NAME} apply -k ${WORKDIR}/asm-ig/variant- Permite que el balanceador de cargas dirija los Pods de la puerta de enlace de entrada en varios clústeres.
- Permite que los Pods de la puerta de enlace de entrada envíen solicitudes de proxy a los servicios que se ejecutan dentro de la malla de servicios.
En Cloud Shell, habilita los servicios de varios clústeres (MCS) para la flota:
gcloud container fleet multi-cluster-services enableOtorga al MCS los permisos de IAM necesarios para el proyecto o la flota:
gcloud projects add-iam-policy-binding PROJECT_ID \ --member "serviceAccount:PROJECT_ID.svc.id.goog[gke-mcs/gke-mcs-importer]" \ --role "roles/compute.networkViewer"Crea el archivo YAML
ServiceExport:cat <<EOF > ${WORKDIR}/svc_export.yaml kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: asm-ingressgateway namespace: asm-ingress EOFAplica el archivo YAML de
ServiceExporta ambos clústeres:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/svc_export.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/svc_export.yamlSi recibes el siguiente mensaje de error, espera unos momentos para que se instalen las definiciones de recursos personalizados (CRD) de MCS. Luego, vuelve a ejecutar los comandos para aplicar el archivo YAML
ServiceExporta ambos clústeres.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 firstEn Cloud Shell, reserva una dirección IP externa estática:
gcloud compute addresses create mcg-ip --globalEl recurso de GKE Gateway usa una dirección IP estática. Permite que la dirección IP siga siendo la misma, incluso si se vuelve a crear el balanceador de cargas externo.
Obtén la dirección IP estática y almacénala como una variable de entorno:
export MCG_IP=$(gcloud compute addresses describe mcg-ip --global --format "value(address)") echo ${MCG_IP}Para crear una asignación estable y fácil de usar para la dirección IP de Ingress, debes tener un registro DNS público.
Puedes usar el proveedor de DNS y el esquema de automatización que desees. En esta implementación, se usa Endpoints en lugar de crear una zona del DNS administrada. Endpoints proporciona un registro DNS administrado por Google gratuito para una dirección IP externa.
Ejecuta el siguiente comando para crear un archivo YAML llamado
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}" EOFEl archivo
dns-spec.yamldefine el registro DNS público en el formatofrontend.endpoints.PROJECT_ID.cloud.goog, en el quePROJECT_IDes tu identificador de proyecto único.Implementa el archivo
dns-spec.yamlpara crear la entrada de DNS. Este proceso tarda unos minutos.gcloud endpoints services deploy ${WORKDIR}/dns-spec.yamlCrea un certificado con el Administrador de certificados para el nombre de entrada de DNS que creaste en el paso anterior:
gcloud certificate-manager certificates create mcg-cert \ --domains="frontend.endpoints.PROJECT_ID.cloud.goog"Se usa un certificado TLS administrado por Google para finalizar las solicitudes entrantes de los clientes en el balanceador de cargas.
Crea un mapa de certificados:
gcloud certificate-manager maps create mcg-cert-mapEl balanceador de cargas hace referencia al certificado a través de la entrada del mapa de certificados que creas en el siguiente paso.
Crea una entrada de mapa de certificados para el certificado que creaste anteriormente en esta sección:
gcloud certificate-manager maps entries create mcg-cert-map-entry \ --map="mcg-cert-map" \ --certificates="mcg-cert" \ --hostname="frontend.endpoints.PROJECT_ID.cloud.goog"- Crea una política de seguridad de Cloud Armor con reglas.
- Crea una política que permita que el balanceador de cargas verifique la capacidad de respuesta de los Pods de la puerta de enlace de entrada a través del archivo YAML
ServiceExportque creaste antes. - Usa la API de Gateway de GKE para crear un recurso de balanceador de cargas.
- Usa el recurso personalizado
GatewayClasspara establecer el tipo específico de balanceador de cargas. - Habilita el balanceo de cargas de varios clústeres para la flota y designa uno de los clústeres como el clúster de configuración para la flota.
En Cloud Shell, crea una política de seguridad de Cloud Armor:
gcloud compute security-policies create edge-fw-policy \ --description "Block XSS attacks"Crea una regla para la política de seguridad:
gcloud compute security-policies rules create 1000 \ --security-policy edge-fw-policy \ --expression "evaluatePreconfiguredExpr('xss-stable')" \ --action "deny-403" \ --description "XSS attack filtering"Crea un archivo YAML para la política de seguridad y haz referencia al archivo YAML
ServiceExporta través de un archivo YAMLServiceImportcorrespondiente: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 EOFAplica la política de Cloud Armor a ambos clústeres:
kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/cloud-armor-backendpolicy.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/cloud-armor-backendpolicy.yamlCrea un archivo YAML personalizado que permita que el balanceador de cargas realice verificaciones de estado en el extremo de estado de Envoy (puerto
15021en la ruta de acceso/healthz/ready) de los Pods de la puerta de enlace de entrada en ambos clústeres: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 EOFAplica el archivo YAML personalizado que creaste en el paso anterior a ambos clústeres:
kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/ingress-gateway-healthcheck.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/ingress-gateway-healthcheck.yamlHabilita el balanceo de cargas de varios clústeres para la flota y designa
CLUSTER_1_NAMEcomo el clúster de configuración:gcloud container fleet ingress enable \ --config-membership=${CLUSTER_1_NAME} \ --location=${CLUSTER_1_REGION}Otorga permisos de IAM para el controlador de puerta de enlace en la flota:
gcloud projects add-iam-policy-binding PROJECT_ID \ --member "serviceAccount:service-${PROJECT_NUMBER}@gcp-sa-multiclusteringress.iam.gserviceaccount.com" \ --role "roles/container.admin"Crea el archivo YAML del balanceador de cargas a través de un recurso personalizado de puerta de enlace que haga referencia a
gke-l7-global-external-managed-mcgatewayClassy a la dirección IP estática que creaste antes: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 EOFAplica el archivo YAML de
frontend-gatewaya ambos clústeres. SoloCLUSTER_1_NAMEes autoritativo, a menos que designes otro clúster de configuración como autoritativo:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-gateway.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-gateway.yamlCrea un archivo YAML
HTTPRoutellamadodefault-httproute.yamlque indique al recurso de Gateway que envíe solicitudes a las puertas de enlace 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 EOFAplica el archivo YAML
HTTPRouteque creaste en el paso anterior a ambos clústeres:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/default-httproute.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/default-httproute.yamlPara realizar redireccionamientos de HTTP a HTTP(S), crea un archivo
HTTPRouteYAML adicional llamadodefault-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 EOFAplica el archivo YAML de redireccionamiento
HTTPRoutea ambos clústeres:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/default-httproute-redirect.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/default-httproute-redirect.yamlInspecciona el recurso Gateway para verificar el progreso de la implementación del balanceador de cargas:
kubectl --context=${CLUSTER_1_NAME} describe gateway external-http -n asm-ingressEn el resultado, se muestra la información que ingresaste en esta sección.
En Cloud Shell, crea los espacios de nombres para un
frontendy unbackendde Donami en ambos clústeres y habilita la inserción de espacios de nombres: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=enabledCrea una variante de kustomize para el 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 EOFAplica la variante
backendde whereami a ambos clústeres:kubectl --context=${CLUSTER_1_NAME} apply -k ${WORKDIR}/whereami-backend/variant kubectl --context=${CLUSTER_2_NAME} apply -k ${WORKDIR}/whereami-backend/variantCrea una variante de kustomize para el 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 EOFAplica la variante
frontendde whereami a ambos clústeres:kubectl --context=${CLUSTER_1_NAME} apply -k ${WORKDIR}/whereami-frontend/variant kubectl --context=${CLUSTER_2_NAME} apply -k ${WORKDIR}/whereami-frontend/variantCrea un archivo YAML
VirtualServicepara enrutar las solicitudes alfrontendde 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 EOFAplica el archivo YAML de
frontend-vsa ambos clústeres:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-vs.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-vs.yamlAhora que implementaste
frontend-vs.yamlen ambos clústeres, intenta llamar al extremo público de tus clústeres:curl -s https://frontend.endpoints.PROJECT_ID.cloud.goog | jqEl resultado es similar a este:
{ "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" }En Cloud Shell, crea un archivo YAML
DestinationRuleque permita la conmutación por error regional del balanceo de cargas de localidad al serviciofrontend: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 EOFLa muestra de código anterior solo habilita el enrutamiento local para el servicio
frontend. También necesitas una configuración adicional que controle el backend.Aplica el archivo YAML de
frontend-dra ambos clústeres:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-dr.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-dr.yamlCrea un archivo YAML
DestinationRuleque habilite la conmutación por error regional del balanceo de cargas de localidad al serviciobackend: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 EOFAplica el archivo YAML de
backend-dra ambos clústeres:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/backend-dr.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/backend-dr.yamlCon ambos conjuntos de archivos YAML de
DestinationRuleaplicados a ambos clústeres, las solicitudes permanecen locales al clúster al que se enrutan.Para probar la conmutación por error del servicio
frontend, reduce la cantidad de réplicas de la puerta de enlace de entrada en el clúster principal.Desde la perspectiva del balanceador de cargas multirregional, esta acción simula una falla del clúster. Esto hace que el clúster falle en las verificaciones de estado del balanceador de cargas. En este ejemplo, se usa el clúster en
CLUSTER_1_REGION. Solo deberías ver respuestas del clúster enCLUSTER_2_REGION.Reduce a cero la cantidad de réplicas de la puerta de enlace de entrada en el clúster principal y llama al extremo público para verificar que las solicitudes hayan conmutado por error al otro clúster:
kubectl --context=${CLUSTER_1_NAME} -n asm-ingress scale --replicas=0 deployment/asm-ingressgatewayEl resultado debe parecerse al siguiente:
$ 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 reanudar el enrutamiento de tráfico típico, restablece las réplicas de la puerta de enlace de entrada al valor original en el clúster:
kubectl --context=${CLUSTER_1_NAME} -n asm-ingress scale --replicas=3 deployment/asm-ingressgatewaySimula una falla para el servicio
backendreduciendo la cantidad de réplicas en la región principal a 0:kubectl --context=${CLUSTER_1_NAME} -n backend scale --replicas=0 deployment/whereami-backendVerifica que las respuestas del servicio
frontendprovengan de la región principalus-central1a través del balanceador de cargas y que las respuestas del serviciobackendprovengan de la región secundariaus-east4.El resultado también debe incluir una respuesta para el servicio
frontendde la región principal (us-central1) y una respuesta para el serviciobackendde la región secundaria (us-east4), como se esperaba.Restablece las réplicas del servicio de backend al valor original para reanudar el enrutamiento de tráfico 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.
En Cloud Shell, borra los recursos de
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.yamlBorra los recursos de la puerta de enlace de GKE:
kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/frontend-gateway.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/frontend-gateway.yamlBorra las 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.yamlBorra las exportaciones de servicio:
kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/svc_export.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/svc_export.yamlBorra los recursos de 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 --quietBorra los recursos de 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 --quietBorra la entrada de DNS de Endpoints:
gcloud --project=PROJECT_ID endpoints services delete "frontend.endpoints.PROJECT_ID.cloud.goog" --quietBorra la dirección IP estática:
gcloud --project=PROJECT_ID compute addresses delete mcg-ip --global --quietBorra los clústeres de GKE Autopilot. Este paso tarda varios 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- Obtén más información sobre las otras funciones que ofrece GKE Gateway que puedes usar con la malla de servicios.
- Obtén más información sobre los distintos tipos de Cloud Load Balancing disponibles para GKE.
- Obtén información sobre las características y funciones que ofrece Cloud Service Mesh.
- Para obtener más información sobre las arquitecturas de referencia, los diagramas y las prácticas recomendadas, explora Cloud Architecture Center.
- Alex Mattson | Ingeniero especialista en aplicaciones
- Mark Chilvers | Ingeniero especialista en aplicaciones
- Abdelfettah Sghiouar | Representante de desarrolladores de Cloud
- Greg Bray | Ingeniero de Atención al cliente
- Paul Revello | Arquitecto de Soluciones de Cloud
- Valavan Rajakumar | Arquitecto empresarial clave
Crea clústeres de GKE
En esta sección, crearás clústeres de GKE para alojar las aplicaciones y la infraestructura de asistencia, que crearás más adelante en esta guía de implementación.
Instala una malla de servicios
En esta sección, debes configurar Cloud Service Mesh administrado con la API de Fleet. El uso de la API de la flota para habilitar Cloud Service Mesh proporciona un enfoque declarativo a fin de aprovisionar una malla de servicios.
Implementa un balanceador de cargas de aplicaciones externo y crea puertas de enlace de entrada
En esta sección, implementarás un balanceador de cargas de aplicaciones externo a través de GKE Gateway Controller y crearás puertas de enlace de entrada para ambos clústeres. Los recursos gateway y gatewayClass automatizan el aprovisionamiento del balanceador de cargas y la verificación de estado del backend. Para proporcionar la finalización de TLS en el balanceador de cargas, crea recursos del Administrador de certificados y adjúntalos al balanceador de cargas. Además, debes usar Endpoints para aprovisionar de forma automática un nombre de DNS público para la aplicación.
Instala una puerta de enlace de entrada en ambos clústeres
Como práctica recomendada de seguridad, te recomendamos que implementes la puerta de enlace de entrada en un espacio de nombres diferente en el plano de control de malla.
Expón los Pods de la puerta de enlace de entrada al balanceador de cargas mediante un servicio de varios clústeres
En esta sección, exportarás los Pods de la puerta de enlace de entrada a través de un recurso personalizado ServiceExport. Debes exportar los Pods de la puerta de enlace de entrada a través de un recurso personalizado ServiceExport por los siguientes motivos:
Crea recursos de dirección IP externa, registro DNS y certificado TLS
En esta sección, crearás recursos de redes que admitan los recursos de balanceo de cargas que crearás más adelante en esta implementación.
Crea políticas de servicio de backend y recursos de balanceador de cargas
En esta sección, completarás las siguientes tareas:
Implementa la aplicación de ejemplo de Whereami
En esta guía, se usa whereami como una aplicación de ejemplo para proporcionar comentarios directos sobre qué clústeres responden a las solicitudes. En la siguiente sección, se configuran dos implementaciones separadas de whereami en ambos clústeres: una implementación de frontend y una implementación de backend.
La implementación de frontend es la primera carga de trabajo en recibir la solicitud. Luego, llama a la implementación de backend.
Este modelo se usa para demostrar una arquitectura de aplicación de varios servicios.
Los servicios frontend y backend se implementan en ambos clústeres.
Si ejecutas el comando curl varias veces, verás que las respuestas (tanto de frontend como de backend) provienen de diferentes regiones. En su respuesta, el balanceador de cargas proporciona el enrutamiento geográfico. Esto significa que el balanceador de cargas está enrutando las solicitudes del cliente al clúster activo más cercano, pero las solicitudes siguen llegando de forma aleatoria. Cuando las solicitudes ocasionalmente van de una región a otra, aumentan la latencia y el costo.
En la siguiente sección, implementarás el balanceo de cargas de localidad en la malla de servicios para mantener las solicitudes locales.
Habilita y prueba el balanceo de cargas de localidad para whereami
En esta sección, implementarás el balanceo de cargas por localidad en la malla de servicios para mantener las solicitudes locales. También debes realizar algunas pruebas para ver cómo whereami maneja varias situaciones de falla.
Cuando realizas una solicitud al servicio frontend de whereami, el balanceador de cargas envía la solicitud al clúster con la latencia más baja en relación con el cliente. Esto significa que los Pods de la puerta de enlace de entrada dentro de la malla balancean las solicitudes de carga a los Pods de whereami frontend en ambos clústeres. En esta sección, se abordará ese problema habilitando el balanceo de cargas por localidad dentro de la malla.
Ahora tienes un balanceador de cargas de HTTP(S) global que funciona como frontend en tu aplicación multirregional alojada en la malla de servicios.
Limpia
Para evitar que se apliquen cargos a tu Google Cloud cuenta por los recursos usados en esta implementación, borra el proyecto que contiene los recursos o conserva el proyecto y borra los recursos individuales.
Borra el proyecto
Borra los recursos individuales
Si deseas conservar el proyecto Google Cloud que usaste en esta implementación, borra los recursos individuales:
¿Qué sigue?
Colaboradores
Autores:
Otros colaboradores: