En este documento, se muestra cómo realizar 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
- Integrar balanceadores de cargas a una malla de servicios implementada en varias regiones de Google Cloud.
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). En particular, usa una puerta de enlace de varios clústeres para configurar el balanceo de cargas multirregión frente a varios clústeres de Autopilot que son distribuidos en dos regiones.
En el diagrama anterior, se muestra cómo fluyen los datos a través de la entrada de la nube y las situaciones de 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
- Implementar 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 finalices las tareas que se describen en este documento, puedes borrar los recursos que creaste para evitar que continúe la facturación. Para obtener más información, consulta Cómo realizar una limpieza.
Antes de comenzar
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
In the Google Cloud console, activate Cloud Shell.
Ejecuta todos los comandos de terminal de esta implementación desde Cloud Shell.
Configura un proyecto predeterminado de Google Cloud:
export PROJECT=YOUR_PROJECT export PROJECT_NUMBER=$(gcloud projects describe PROJECT_ID --format="value(projectNumber)") gcloud config set project PROJECT_ID
Reemplaza
PROJECT_ID
por 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`
Crea clústeres de GKE
En esta sección, crearás clústeres de GKE para alojar las aplicaciones y la infraestructura de respaldo, que crearás más adelante en esta guía de implementación.
En Cloud Shell, crea un archivo
kubeconfig
nuevo. Con este paso te aseguras de no causar un conflicto con el archivokubeconfig
(predeterminado) existente.touch edge2mesh_mr_kubeconfig export KUBECONFIG=${WORKDIR}/edge2mesh_mr_kubeconfig
Define las variables de entorno que se usan cuando se crean los clústeres de GKE y los recursos dentro de ellos. Modifica las opciones de región predeterminadas para adaptarlas a tus fines.
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
Habilita 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.com
Crea un clúster de GKE Autopilot con nodos privados en
CLUSTER_1_REGION
. Usa la marca--async
para 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-fleet
Crea 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-fleet
Asegú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 list
El 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_NAME
de 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ámbiales el nombre 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}
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.
En Cloud Shell, habilita Cloud Service Mesh en la flota:
gcloud container fleet mesh enable
Habilita el plano de control y la administración automáticos 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 describe
El 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'
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.
En Cloud Shell, crea un espacio de nombres
asm-ingress
dedicado en cada clúster:kubectl --context=${CLUSTER_1_NAME} create namespace asm-ingress kubectl --context=${CLUSTER_2_NAME} create namespace asm-ingress
Agrega 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=enabled
El resultado es similar a este:
namespace/asm-ingress labeled
Si etiquetas los espacios de nombres
asm-ingress
conistio-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 uso futuro:
openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 \ -subj "/CN=frontend.endpoints.PROJECT_ID.cloud.goog/O=Edge2Mesh Inc" \ -keyout ${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.key \ -out ${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.crt
El 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 una dirección IP externa, un registro DNS y recursos de 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 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.crt
Para 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 EOF
Aplica 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
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, debes exportar 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:
- Permite que el balanceador de cargas aborde 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 enable
Otorga a MCS los permisos de IAM necesarios al 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 EOF
Aplica el archivo YAML
ServiceExport
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.yaml
Si recibes el siguiente mensaje de error, espera unos minutos para que se instalen las definiciones de recursos personalizados (CRD) de MCS. Luego, vuelve a ejecutar los comandos para aplicar el archivo YAML
ServiceExport
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 first
Crea direcciones IP externas, registros DNS y recursos de certificados TLS
En esta sección, crearás recursos de herramientas de redes que admiten los recursos de balanceo de cargas que crearás más adelante en esta implementación.
En Cloud Shell, reserva una dirección IP externa estática:
gcloud compute addresses create mcg-ip --global
El recurso de puerta de enlace de GKE usa una dirección IP estática. Permite que la dirección IP permanezca igual, 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}" EOF
El archivo
dns-spec.yaml
define el registro DNS público en el formatofrontend.endpoints.PROJECT_ID.cloud.goog
, en el quePROJECT_ID
es tu identificador de proyecto único.Implementa el archivo
dns-spec.yaml
para crear la entrada de DNS. Este proceso tarda unos minutos.gcloud endpoints services deploy ${WORKDIR}/dns-spec.yaml
Crea 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 de clientes entrantes en el balanceador de cargas.
Crea un mapa de certificados:
gcloud certificate-manager maps create mcg-cert-map
El balanceador de cargas hace referencia al certificado a través de la entrada de mapa de certificados que creas en el siguiente paso.
Crea una entrada de mapa de certificado para el certificado que creaste antes 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 políticas de servicio de backend y recursos de balanceadores de cargas
En esta sección, realizarás las siguientes tareas:
- Crea una política de seguridad de Google 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
ServiceExport
que creaste antes. - Usa la API de puerta de enlace de GKE para crear un recurso de balanceador de cargas.
- Usa el recurso personalizado
GatewayClass
para establecer el tipo de balanceador de cargas específico. - 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 de la flota.
En Cloud Shell, crea una política de seguridad de Google 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
ServiceExport
a través de un archivo YAMLServiceImport
correspondiente: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
Aplica la política de Google 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.yaml
Crea un archivo YAML personalizado que permita que el balanceador de cargas realice verificaciones de estado en el extremo de estado de Envoy (puerto
15021
en la ruta/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 EOF
Aplica 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.yaml
Habilita el balanceo de cargas de varios clústeres para la flota y designa
CLUSTER_1_NAME
como 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 la 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-mc
gatewayClass
y a la dirección IP estática que creaste antes:cat <<EOF > ${WORKDIR}/frontend-gateway.yaml kind: Gateway apiVersion: gateway.networking.k8s.io/v1beta1 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
Aplica el archivo YAML
frontend-gateway
a ambos clústeres. SoloCLUSTER_1_NAME
es autorizado, a menos que designes un clúster de configuración diferente como autorizado:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-gateway.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-gateway.yaml
Crea un archivo YAML
HTTPRoute
llamadodefault-httproute.yaml
que le indique al recurso de puerta de enlace que envíe solicitudes a las puertas de enlace de entrada:cat << EOF > ${WORKDIR}/default-httproute.yaml apiVersion: gateway.networking.k8s.io/v1beta1 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
Aplica el archivo YAML
HTTPRoute
que 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.yaml
Para realizar redireccionamientos HTTP a HTTP(S), crea un archivo YAML
HTTPRoute
adicional llamadodefault-httproute-redirect.yaml
:cat << EOF > ${WORKDIR}/default-httproute-redirect.yaml kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1beta1 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
Aplica el archivo YAML de redireccionamiento
HTTPRoute
a 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.yaml
Inspecciona 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-ingress
El resultado muestra la información que ingresaste en esta sección.
Implementa la aplicación de muestra 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 independientes de ambas en ambos clústeres: una implementación frontend
y una implementación backend
.
La implementación frontend
es la primera carga de trabajo que recibe la solicitud. Luego, llama a la implementación backend
.
Este modelo se usa para demostrar una arquitectura de aplicaciones de varios servicios.
Los servicios frontend
y backend
se implementan en ambos clústeres.
En Cloud Shell, crea los espacios de nombres para un
frontend
y unbackend
de 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=enabled
Crea 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 EOF
Aplica la variante
backend
de 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/variant
Crea 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 EOF
Aplica la variante
frontend
de 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/variant
Crea un archivo YAML
VirtualService
para enrutar las solicitudes al lugar en el quefrontend
: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
Aplica el archivo YAML
frontend-vs
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.yaml
Ahora que implementaste
frontend-vs.yaml
en ambos clústeres, intenta llamar al extremo público para tus clústeres:curl -s https://frontend.endpoints.PROJECT_ID.cloud.goog | jq
El 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" }
Si ejecutas el comando curl
varias veces, verás que las respuestas (tanto de frontend
como backend
) provienen de diferentes regiones. En su respuesta, el balanceador de cargas proporciona enrutamiento geográfico. Esto significa que el balanceador de cargas enruta las solicitudes del cliente al clúster activo más cercano, pero las solicitudes siguen llegando de forma aleatoria. Cuando las solicitudes van de una región a otra en ocasiones, 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 de 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
, 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 las solicitudes de balanceo de cargas de la malla a los Pods frontend
en ambos clústeres. En esta sección, se abordará ese problema mediante la habilitación del balanceo de cargas de localidad dentro de la malla.
En Cloud Shell, crea un archivo YAML
DestinationRule
que 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 EOF
En la muestra de código anterior, solo se habilita el enrutamiento local para el servicio
frontend
. También necesitas una configuración adicional que controla el backend.Aplica el archivo YAML
frontend-dr
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.yaml
Crea un archivo YAML
DestinationRule
que 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: n ame: backend namespace: backend spec: host: whereami-backend.backend.svc.cluster.local trafficPolicy: connectionPool: http: maxRequestsPerConnection: 0 loadBalancer: simple: LEAST_REQUEST localityLbSetting: enabled: true outlierDetection: consecutive5xxErrors: 1 interval: 1s baseEjectionTime: 1m EOF
Aplica el archivo YAML
backend-dr
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.yaml
Con ambos conjuntos de archivos YAML
DestinationRule
aplicados a ambos clústeres, las solicitudes permanecen locales en el clúster al que se enruta la solicitud.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. Hace que el clúster falle en las verificaciones de estado del balanceador de cargas. 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 la cantidad de réplicas para la puerta de enlace de entrada en tu 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-ingressgateway
El 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-ingressgateway
Simula una falla del servicio
backend
mediante la reducción de la cantidad de réplicas en la región principal a 0:kubectl --context=${CLUSTER_1_NAME} -n backend scale --replicas=0 deployment/whereami-backend
Verifica que las respuestas del servicio
frontend
provengan de la región principalus-central1
a través del balanceador de cargas y que las respuestas del serviciobackend
provengan de la región secundariaus-east4
.El resultado también debe incluir una respuesta para el servicio
frontend
de la región principal (us-central1
) y una respuesta para el serviciobackend
de 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
Ahora tienes un balanceador de cargas 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 cuenta de Google Cloud 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
- 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.
Borra los recursos individuales
Si deseas conservar el proyecto de Google Cloud que usaste en esta implementación, borra los recursos individuales:
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.yaml
Borra los recursos de 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.yaml
Borra 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.yaml
Borra 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.yaml
Borra los recursos de Google Cloud Armor:
gcloud --project=PROJECT_ID compute security-policies rules delete 1000 --security-policy edge-fw-policy --quiet gcloud --project=PROJECT_ID compute security-policies delete edge-fw-policy --quiet
Borra los recursos del Administrador de certificados:
gcloud --project=PROJECT_ID certificate-manager maps entries delete mcg-cert-map-entry --map="mcg-cert-map" --quiet gcloud --project=PROJECT_ID certificate-manager maps delete mcg-cert-map --quiet gcloud --project=PROJECT_ID certificate-manager certificates delete mcg-cert --quiet
Borra la entrada de DNS de Endpoints:
gcloud --project=PROJECT_ID endpoints services delete "frontend.endpoints.PROJECT_ID.cloud.goog" --quiet
Borra la dirección IP estática:
gcloud --project=PROJECT_ID compute addresses delete mcg-ip --global --quiet
Borra 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
¿Qué sigue?
- 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.
Colaboradores
Autores:
- Alex Mattson | Ingeniero especialista en aplicaciones
- Mark Chilvers | Ingeniero especialista en aplicaciones
Otros colaboradores:
- Abdelfettah Sghiouar | Cloud Developer Advocate
- Greg Bray | Ingeniero de Atención al cliente
- Paul Revello | Arquitecto de soluciones de nube
- Valavan Rajakumar | Arquitecto empresarial clave