En este documento se explica cómo llevar a cabo las siguientes tareas:
- Despliega aplicaciones distribuidas en todo el mundo expuestas a través de GKE Gateway y Cloud Service Mesh.
- Expón una aplicación a varios clientes combinando Cloud Load Balancing con Cloud Service Mesh.
- Integra los balanceadores de carga con una malla de servicios desplegada en varias Google Cloud regiones.
Esta guía de implementación está dirigida a los administradores de plataformas. 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 carga TCP/UDP externo que expone los proxies de la puerta de enlace de entrada en un solo clúster:
En esta guía de implementación se usan recursos de Gateway de Google Kubernetes Engine (GKE). En concreto, usa una gateway multiclúster para configurar el balanceo de carga multirregional delante de varios clústeres Autopilot distribuidos en dos regiones.
En el diagrama anterior se muestra cómo fluyen los datos en los casos de entrada en la nube y de entrada en 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
- Despliega un par de clústeres de Autopilot de GKE en Google Cloud en la misma flota.
- Despliega un Cloud Service Mesh basado en Istio en la misma flota.
- Configura un balanceador de carga con GKE Gateway para terminar el tráfico HTTPS público.
- Dirige el tráfico HTTPS público directamente a las aplicaciones alojadas por Cloud Service Mesh que se han desplegado en varios clústeres y regiones.
- Despliega la aplicación de ejemplo whereami en ambos clústeres de Autopilot.
Optimización de costes
En este documento, se utilizan 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 costes basada en el uso previsto,
utiliza la calculadora de precios.
Cuando termines las tareas que se describen en este documento, puedes evitar que se te siga facturando eliminando los recursos que has creado. Para obtener más información, consulta la sección Limpiar.
Antes de empezar
-
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.
Todos los comandos de terminal de este despliegue se ejecutan desde Cloud Shell.
Configura tu Google Cloud proyecto predeterminado:
export PROJECT=YOUR_PROJECT export PROJECT_NUMBER=$(gcloud projects describe PROJECT_ID --format="value(projectNumber)") gcloud config set project PROJECT_IDSustituye
PROJECT_IDpor el ID del proyecto que quieras usar en esta implementación.Crea 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
kubeconfig. De esta forma, te aseguras de que no se produzca un conflicto con el archivokubeconfig(predeterminado) que ya tienes.touch edge2mesh_mr_kubeconfig export KUBECONFIG=${WORKDIR}/edge2mesh_mr_kubeconfigDefine las variables de entorno que se usan al crear los clústeres de GKE y los recursos que contienen. Modifica las opciones de región predeterminadas para adaptarlas a tus necesidades.
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 Autopilot de GKE con nodos privados en
CLUSTER_1_REGION. Usa la marca--asyncpara no tener que esperar a que se aprovisione el primer clúster 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 se estén ejecutando. Puede tardar hasta 20 minutos en que todos los clústeres se ejecuten:
gcloud container clusters listEl resultado debería ser similar al siguiente:
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
Recoge las credenciales de
CLUSTER_1_NAME.Has creadoCLUSTER_1_NAMEde forma asíncrona para poder ejecutar comandos adicionales mientras se aprovisionaba 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ámbiales el nombre por el 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 gestió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 unos 20 minutos. A continuación, comprueba que el estado del plano de control sea
ACTIVE:gcloud container fleet mesh describeEl resultado debería ser similar al siguiente:
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-ingressAñade una etiqueta de espacio de nombres a los espacios de nombres de
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 debería ser similar al siguiente:
namespace/asm-ingress labeled
Al etiquetar los espacios de nombres
asm-ingressconistio-injection=enabled, se indica a Cloud Service Mesh que inserte automáticamente proxies sidecar de Envoy cuando se despliegue un pod.Genera un certificado autofirmado para usarlo más adelante:
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 cifrado entre el balanceador de carga y las pasarelas de entrada de la malla de servicios. También permite la compatibilidad con protocolos basados en HTTP/2, como gRPC. Las instrucciones sobre cómo adjuntar el certificado autofirmado a las pasarelas de entrada se proporcionan más adelante en Crear recursos de dirección IP externa, registro DNS y certificado TLS.
Para obtener más información sobre los requisitos del certificado de la pasarela de entrada, consulta Cifrado del balanceador de carga a los back-ends.
Crea un secreto 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 integrar un balanceador de carga de aplicación externo, crea una variante de kustomize para configurar los recursos de pasarela 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 pasarela 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 carga se dirija a los pods de la pasarela de entrada en varios clústeres.
- Permite que los pods de la puerta de enlace de entrada proxyicen las solicitudes a los servicios que se ejecutan en la malla de servicios.
En Cloud Shell, habilita los servicios de varios clústeres (MCS) en la flota:
gcloud container fleet multi-cluster-services enableConcede a MCS los permisos de gestión de identidades y accesos necesarios en 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
ServiceExportYAML:cat <<EOF > ${WORKDIR}/svc_export.yaml kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: asm-ingressgateway namespace: asm-ingress EOFAplica el archivo
ServiceExportYAML a 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 instantes a que se instalen las definiciones de recursos personalizados (CRDs) de MCS. A continuación, vuelve a ejecutar los comandos para aplicar el archivo
ServiceExportYAML a 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 la pasarela de GKE usa una dirección IP estática. Permite que la dirección IP siga siendo la misma, aunque se vuelva a crear el balanceador de carga externo.
Obtén la dirección IP estática y almacénala como 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 recordar a la dirección IP de tu pasarela, debes tener un registro DNS público.
Puedes usar el proveedor de DNS y el esquema de automatización que quieras. Esta implementación usa Endpoints en lugar de crear una zona DNS gestionada. Endpoints proporciona un registro DNS gestionado 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 con el formatofrontend.endpoints.PROJECT_ID.cloud.goog, dondePROJECT_IDes el identificador único de tu proyecto.Implementa el archivo
dns-spec.yamlpara crear la entrada DNS. Este proceso tarda unos minutos.gcloud endpoints services deploy ${WORKDIR}/dns-spec.yamlCrea un certificado con Gestor de certificados para el nombre de entrada DNS que has creado en el paso anterior:
gcloud certificate-manager certificates create mcg-cert \ --domains="frontend.endpoints.PROJECT_ID.cloud.goog"Se usa un certificado TLS gestionado por Google para finalizar las solicitudes de clientes entrantes en el balanceador de carga.
Crea un mapa de certificados:
gcloud certificate-manager maps create mcg-cert-mapEl balanceador de carga hace referencia al certificado a través de la entrada del mapa de certificados que crees en el siguiente paso.
Crea una entrada de mapa de certificados para el certificado que has creado 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 al balanceador de carga comprobar la capacidad de respuesta de los pods de la puerta de enlace de entrada a través del archivo YAML
ServiceExportque has creado anteriormente. - Usa la API Gateway de GKE para crear un recurso de balanceador de carga.
- Usa el recurso personalizado
GatewayClasspara definir el tipo de balanceador de carga específico. - Habilita el balanceo de carga entre varios clústeres en la flota y designa uno de los clústeres como clúster de configuración de 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
ServiceExportmediante 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 al balanceador de carga realizar comprobaciones del estado en el endpoint de comprobación del estado de Envoy (puerto
15021en la ruta/healthz/ready) de los pods de la puerta de enlace de entrada de 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 has creado 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 carga entre clústeres para la flota y designa
CLUSTER_1_NAMEcomo clúster de configuración:gcloud container fleet ingress enable \ --config-membership=${CLUSTER_1_NAME} \ --location=${CLUSTER_1_REGION}Concede permisos de gestión de identidades y accesos al controlador de Gateway 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 carga mediante un recurso personalizado Gateway que haga referencia a
gke-l7-global-external-managed-mcgatewayClassy a la dirección IP estática que has creado 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 EOFAplica el archivo
frontend-gatewayYAML a ambos clústeres. SoloCLUSTER_1_NAMEtiene autoridad, a menos que designes otro clúster de configuración como autoridad:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-gateway.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-gateway.yamlCrea un archivo
HTTPRouteYAML llamadodefault-httproute.yamlque indique al recurso Gateway que envíe solicitudes a las pasarelas 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 has creado 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 redirecciones de HTTP a HTTP(S), cree 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
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 comprobar el progreso de la implementación del balanceador de carga:
kubectl --context=${CLUSTER_1_NAME} describe gateway external-http -n asm-ingressEl resultado muestra la información que has introducido en esta sección.
En Cloud Shell, crea los espacios de nombres de whereami
frontendy whereamibackenden ambos clústeres y habilita la inyecció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
backendde 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 EOFAplica la variante whereami
backenda 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
frontendde 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 EOFAplica la variante whereami
frontenda 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 dirigir las solicitudes a whereamifrontend: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
frontend-vsYAML a 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 has implementado
frontend-vs.yamlen ambos clústeres, intenta llamar al endpoint público de tus clústeres:curl -s https://frontend.endpoints.PROJECT_ID.cloud.goog | jqEl resultado debería ser similar al siguiente:
{ "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 habilite la conmutación por error regional del balanceo de carga por 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 EOFEl código de ejemplo anterior solo habilita el enrutamiento local para el servicio
frontend. También necesitas una configuración adicional que gestione el backend.Aplica el archivo
frontend-drYAML a 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 con balanceo de carga local 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
backend-drYAML a ambos clústeres:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/backend-dr.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/backend-dr.yamlSi se aplican ambos conjuntos de archivos YAML a los dos clústeres, las solicitudes seguirán siendo locales del clúster al que se dirijan.
DestinationRulePara probar la conmutación por error del servicio
frontend, reduce el número de réplicas de la puerta de enlace de entrada de tu clúster principal.Desde la perspectiva del balanceador de carga multirregional, esta acción simula un fallo del clúster. Esto provoca que el clúster no supere las comprobaciones de estado del balanceador de carga. En este ejemplo se usa el clúster de
CLUSTER_1_REGION. Solo deberías ver las respuestas del clúster enCLUSTER_2_REGION.Reduce a cero el número de réplicas de la puerta de enlace de entrada de tu clúster principal y llama al endpoint público para verificar que las solicitudes se han transferido al otro clúster:
.kubectl --context=${CLUSTER_1_NAME} -n asm-ingress scale --replicas=0 deployment/asm-ingressgatewayLa salida debería ser similar a la 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 habitual, restaura 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 un fallo del servicio
backendreduciendo a 0 el número de réplicas de la región principal:kubectl --context=${CLUSTER_1_NAME} -n backend scale --replicas=0 deployment/whereami-backendVerifica que las respuestas del servicio
frontendprocedan de la región principalus-central1a través del balanceador de carga y que las respuestas del serviciobackendprocedan de la región secundariaus-east4.El resultado también debe incluir una respuesta del servicio
frontendde la región principal (us-central1) y una respuesta del serviciobackendde la región secundaria (us-east4), tal como se espera.Restaura las réplicas del servicio de backend al valor original para reanudar el enrutamiento de tráfico habitual:
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, elimina los 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.yamlElimina los recursos de la pasarela de GKE:
kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/frontend-gateway.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/frontend-gateway.yamlElimina 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.yamlElimina las exportaciones de servicios:
kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/svc_export.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/svc_export.yamlElimina 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 --quietElimina 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 --quietElimina la entrada DNS de Endpoints:
gcloud --project=PROJECT_ID endpoints services delete "frontend.endpoints.PROJECT_ID.cloud.goog" --quietElimina la dirección IP estática:
gcloud --project=PROJECT_ID compute addresses delete mcg-ip --global --quietElimina los clústeres de Autopilot de GKE. 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- Consulta más funciones que ofrece GKE Gateway y que puedes usar con tu malla de servicios.
- Consulta los diferentes tipos de Cloud Load Balancing disponibles para GKE.
- Consulta las características y funciones que ofrece Cloud Service Mesh.
- Para ver más arquitecturas de referencia, diagramas y prácticas recomendadas, consulta el centro de arquitectura de Cloud.
- Alex Mattson | Ingeniero especialista en aplicaciones
- Mark Chilvers | Ingeniero especialista en aplicaciones
- Abdelfettah Sghiouar | Cloud Developer Advocate
- Greg Bray | Ingeniero de clientes
- Paul Revello | Arquitecto de soluciones en la nube
- Valavan Rajakumar | Arquitecto empresarial clave
Crear 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.
Instalar una malla de servicios
En esta sección, se configura Cloud Service Mesh gestionado con la API Fleet. Usar la API de flota para habilitar Cloud Service Mesh proporciona un enfoque declarativo para aprovisionar una malla de servicios.
Desplegar un balanceador de carga de aplicación externo y crear pasarelas de entrada
En esta sección, desplegarás un balanceador de carga de aplicaciones externo a través del controlador de GKE Gateway y crearás gateways de entrada para ambos clústeres. Los recursos gateway y gatewayClass automatizan el aprovisionamiento del balanceador de carga y la comprobación del estado del backend. Para proporcionar la terminación de TLS en el balanceador de carga, crea recursos de Gestor de certificados y adjúntalos al balanceador de carga. Además, puedes usar endpoints para aprovisionar automáticamente un nombre de DNS público para la aplicación.
Instalar una pasarela de entrada en ambos clústeres
Como medida de seguridad recomendada, te aconsejamos que implementes la puerta de enlace de entrada en un espacio de nombres diferente del plano de control de la malla.
Exponer pods de pasarela de entrada al balanceador de carga 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 ServiceExport
recurso personalizado. Debes exportar los pods de la pasarela de entrada
mediante un recurso personalizado ServiceExport por los siguientes motivos:
Crear recursos de dirección IP externa, registro DNS y certificado TLS
En esta sección, crearás recursos de red que admitan los recursos de balanceo de carga que crearás más adelante en este despliegue.
Crear políticas de servicio de backend y recursos de balanceador de carga
En esta sección, completarás las siguientes tareas:
Desplegar la aplicación de ejemplo whereami
En esta guía se usa whereami como aplicación de ejemplo para proporcionar comentarios directos sobre los clústeres que responden a las solicitudes. En la siguiente sección se configuran dos implementaciones independientes de whereami en ambos clústeres: una implementación de frontend y otra de backend.
La implementación de frontend es la primera carga de trabajo que recibe la solicitud. Después, llama a la backendimplementación.
Este modelo se usa para mostrar una arquitectura de aplicación multiservicio.
Los servicios frontend y backend se han desplegado en ambos clústeres.
Si ejecutas el comando curl varias veces, verás que las respuestas (tanto de frontend como de backend) proceden de diferentes regiones. En su respuesta, el balanceador de carga proporciona el enrutamiento geográfico. Esto significa que el balanceador de carga está enrutando las solicitudes del cliente al clúster activo más cercano, pero las solicitudes siguen llegando de forma aleatoria. Cuando las solicitudes pasan ocasionalmente de una región a otra, aumenta la latencia y el coste.
En la siguiente sección, implementarás el balanceo de carga de la localidad en la malla de servicios para que las solicitudes se mantengan locales.
Habilitar y probar el balanceo de carga según la ubicación de whereami
En esta sección, implementarás el balanceo de carga de la localidad en la malla de servicios para que las solicitudes se mantengan locales. También realizas algunas pruebas para ver cómo gestiona whereami varios casos de error.
Cuando haces una solicitud al servicio whereami frontend, el balanceador de carga 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 de la malla equilibran la carga de las solicitudes a los pods de whereami frontend en ambos clústeres. En esta sección se abordará ese problema habilitando el balanceo de carga según la ubicación en la malla.
Ahora tienes un balanceador de carga HTTP(S) global que actúa como frontend de tu aplicación multirregión alojada en una malla de servicios.
Limpieza
Para evitar que se apliquen cargos en tu cuenta de Google Cloud por los recursos utilizados en esta implementación, elimina el proyecto que contiene los recursos o conserva el proyecto y elimina los recursos.
Eliminar el proyecto
Eliminar los recursos concretos
Si quieres conservar el Google Cloud proyecto que has usado en esta implementación, elimina los recursos individuales:
Siguientes pasos
Colaboradores
Autores:
Otros colaboradores: