Desplegar una aplicación de contenedor de alta disponibilidad

En esta página se describe la estrategia de implementación recomendada para crear una aplicación de contenedor de Kubernetes sólida y de alta disponibilidad (HA) en Google Distributed Cloud (GDC) aislado. Debes desplegar la aplicación de contenedor en varias zonas de GDC y configurar la replicación de almacenamiento asíncrona para que la aplicación y sus datos se puedan recuperar en caso de tiempo de inactividad inesperado o desastre local.

Esta página está dirigida a los desarrolladores del grupo de operadores de aplicaciones, que son responsables de crear cargas de trabajo de aplicaciones para su organización. Para obtener más información, consulta Audiencias de la documentación aislada de GDC.

Objetivos

  • Crea un clúster de Kubernetes en dos o más zonas de tu universo de GDC.
  • Configura el balanceo de carga global.
  • Despliega cargas de trabajo de contenedores en cada clúster de Kubernetes zonal.
  • Aprovisiona el almacenamiento y adjúntalo a tus pods.
  • Configura la replicación de almacenamiento asíncrona mediante almacenamiento en bloque o almacenamiento de objetos.

Antes de empezar

  • Comprueba que estás trabajando en un universo de GDC con varias zonas disponibles. Ejecuta gdcloud zones list para ver las zonas disponibles en tu universo. Para obtener más información, consulta Listar zonas de un universo.

  • Pide al administrador de gestión de identidades y accesos de tu organización que te conceda los siguientes roles:

    • El rol Administrador de espacio de nombres (namespace-admin) para crear y gestionar cargas de trabajo de contenedores.

    • Los roles Administrador de clúster de usuario (user-cluster-admin) y Desarrollador de clúster de usuario (user-cluster-developer) para crear y gestionar clústeres de Kubernetes y sus grupos de nodos.

    • Los roles Administrador de balanceadores de carga (load-balancer-admin) y Administrador de balanceadores de carga globales (global-load-balancer-admin). Debes tener este rol para crear y gestionar balanceadores de carga.

    • El rol Administrador global de replicación de volúmenes (app-volume-replication-admin-global). Debes tener este rol para administrar la replicación de volúmenes.

    • El rol de administrador global de PNP (global-project-networkpolicy-admin) para crear y gestionar políticas de red de proyectos en todas las zonas.

    • Los roles Administrador de instancias de Harbor (harbor-instance-admin), Lector de instancias de Harbor(harbor-instance-viewer) y Creador de proyectos de Harbor (harbor-project-creator). Estos roles son necesarios para crear y gestionar imágenes de contenedor en el registro de artefactos.

    • El rol de administrador global de replicación de volúmenes (app-volume-replication-admin-global) para administrar la relación de replicación de volúmenes de los recursos de almacenamiento en bloque.

    • Los roles Administrador de objetos del segmento de proyecto (project-bucket-object-admin) y Administrador del segmento de proyecto (project-bucket-admin) para crear y gestionar segmentos de almacenamiento.

    Para obtener más información, consulta las descripciones de los roles.

  • Instala y configura la CLI de gdcloud y configura los contextos zonales y globales. Consulta el artículo sobre cómo gestionar recursos en varias zonas para obtener más información.

  • Instala y configura la CLI kubectl con los archivos kubeconfig adecuados definidos para el servidor de la API global, el servidor de la API de gestión y el clúster de Kubernetes. Para obtener más información, consulta Generar manualmente el archivo kubeconfig.

Crear un clúster de Kubernetes en varias zonas

Un clúster de Kubernetes es un recurso zonal, por lo que debes crear un clúster por separado en cada zona.

Consola

  1. En el menú de navegación, selecciona Kubernetes Engine > Clústeres.

  2. Haz clic en Crear clúster.

  3. En el campo Nombre, especifica un nombre para el clúster.

  4. Selecciona la versión de Kubernetes del clúster.

  5. Selecciona la zona en la que quieras crear el clúster.

  6. Haz clic en Adjuntar proyecto y selecciona un proyecto para adjuntarlo a tu clúster. A continuación, haz clic en Guardar. Puedes adjuntar o separar proyectos después de crear el clúster desde la página Detalles del proyecto. Debes tener un proyecto asociado a tu clúster antes de implementar cargas de trabajo de contenedores en él.

  7. Haz clic en Siguiente.

  8. Configura los ajustes de red de tu clúster. No puedes cambiar estos ajustes de red después de crear el clúster. El protocolo de Internet predeterminado y único compatible con los clústeres de Kubernetes es el protocolo de Internet versión 4 (IPv4).

    1. Especifica el tamaño del grupo de direcciones IP del balanceador de carga, como 20.

    2. Selecciona el CIDR (enrutamiento de interdominios sin clases) del servicio que quieras usar. Tus servicios implementados, como los balanceadores de carga, tienen asignadas direcciones IP de este intervalo.

    3. Selecciona el CIDR de pod que quieras usar. El clúster asigna direcciones IP de este intervalo a tus pods y VMs.

    4. Haz clic en Siguiente.

  9. Revisa los detalles del grupo de nodos predeterminado generado automáticamente del clúster. Haz clic en Editar para modificar el grupo de nodos predeterminado.

  10. Para crear más grupos de nodos, selecciona Añadir grupo de nodos. Cuando editas el grupo de nodos predeterminado o añades uno nuevo, puedes personalizarlo con las siguientes opciones:

    1. Asigna un nombre al pool de nodos. No puedes modificar el nombre después de crear el grupo de nodos.
    2. Especifica el número de nodos de trabajador que se crearán en el grupo de nodos.
    3. Selecciona la clase de máquina que mejor se adapte a los requisitos de tu carga de trabajo. Consulta la lista de los siguientes ajustes:

      • Tipo de máquina
      • CPU
      • Memoria
    4. Haz clic en Guardar.

    5. Haz clic en Crear para que se genere el clúster.

  11. Repite estos pasos con cada zona de tu universo de GDC. Asegúrate de que haya un clúster de Kubernetes en cada zona que quieras incluir en tu estrategia de alta disponibilidad.

API

Para crear un clúster de Kubernetes directamente con la API, aplica un recurso personalizado a cada zona de GDC.

  1. Crea un Cluster recurso personalizado e impleméntalo en el servidor de la API Management de tu zona:

    kubectl --kubeconfig MANAGEMENT_API_SERVER apply -f - <<EOF \
    apiVersion: cluster.gdc.goog/v1
    kind: Cluster
    metadata:
      name: CLUSTER_NAME
      namespace: platform
    spec:
      clusterNetwork:
        podCIDRSize: POD_CIDR
        serviceCIDRSize: SERVICE_CIDR
      initialVersion:
        kubernetesVersion: KUBERNETES_VERSION
      loadBalancer:
        ingressServiceIPSize: LOAD_BALANCER_POOL_SIZE
      nodePools:
      - machineTypeName: MACHINE_TYPE
        name: NODE_POOL_NAME
        nodeCount: NUMBER_OF_WORKER_NODES
        taints: TAINTS
        labels: LABELS
        acceleratorOptions:
          gpuPartitionScheme: GPU_PARTITION_SCHEME
      releaseChannel:
        channel: UNSPECIFIED
    EOF
    

    Haz los cambios siguientes:

    • MANAGEMENT_API_SERVER: la ruta de kubeconfig del servidor de la API Management zonal. Para obtener más información, consulta Cambiar al contexto de zona.
    • CLUSTER_NAME: el nombre del clúster. El nombre del clúster no puede terminar con -system. El sufijo -system está reservado para los clústeres creados por GDC.
    • POD_CIDR: tamaño de los intervalos de red desde los que se asignan las direcciones IP virtuales (VIP) de los pods. Si no se define, se usa el valor predeterminado 21.
    • SERVICE_CIDR: tamaño de los intervalos de red desde los que se asignan las IPs virtuales de servicio. Si no se define, se usa el valor predeterminado 23.
    • KUBERNETES_VERSION: la versión de Kubernetes del clúster, como 1.26.5-gke.2100. Para ver la lista de versiones de Kubernetes disponibles que se pueden configurar, consulta Listar las versiones de Kubernetes disponibles de un clúster.
    • LOAD_BALANCER_POOL_SIZE: tamaño de los grupos de direcciones IP no superpuestos que usan los servicios de balanceador de carga. Si no se define, se usa el valor predeterminado 20.
    • MACHINE_TYPE: el tipo de máquina de los nodos de trabajador del grupo de nodos. Consulta los tipos de máquinas disponibles para ver qué se puede configurar.
    • NODE_POOL_NAME: el nombre del grupo de nodos.
    • NUMBER_OF_WORKER_NODES: el número de nodos de trabajo que se aprovisionarán en el grupo de nodos.
    • TAINTS: los taints que se aplicarán a los nodos de este grupo de nodos. Este campo es opcional.
    • LABELS: las etiquetas que se aplicarán a los nodos de este grupo de nodos. Contiene una lista de pares clave-valor. Este campo es opcional.
    • GPU_PARTITION_SCHEME: el esquema de partición de GPU, si ejecutas cargas de trabajo de GPU, como mixed-2. La GPU no se particiona si no se define este campo. Para ver los perfiles de GPU con varias instancias (MIG) disponibles, consulta Perfiles de MIG admitidos.
  2. Repita el paso anterior con cada zona en la que quiera alojar su aplicación de contenedor para su estrategia de alta disponibilidad.

Configurar balanceadores de carga

Para distribuir el tráfico entre tus pods en diferentes zonas, crea balanceadores de carga. Puedes crear balanceadores de carga externos (ELB) y balanceadores de carga internos (ILB), que se pueden configurar por zonas o de forma global. En este ejemplo, configure un balanceador de carga interno global y un balanceador de carga externo global para su aplicación de contenedor.

Crear un balanceador de carga interno global

Los balanceadores de carga internos (ILBs) exponen servicios dentro de la organización desde un grupo de direcciones IP internas asignado a la organización. Nunca se puede acceder a un servicio de ILB desde ningún punto final que no pertenezca a la organización.

Sigue estos pasos para crear un ILB global para tus cargas de trabajo de contenedores.

gdcloud

Crea un ILB que tenga como destino cargas de trabajo de pods mediante la CLI de gcloud.

Este ILB está dirigido a todas las cargas de trabajo del proyecto que coincidan con la etiqueta definida en el objeto Backend. El recurso personalizado Backend debe tener un ámbito de zona.

Para crear un ILB con la CLI de gdcloud, sigue estos pasos:

  1. Crea un recurso Backend zonal en cada zona en la que se ejecuten tus pods para definir el endpoint del ILB:

    gdcloud compute backends create BACKEND_NAME \
        --labels=LABELS \
        --project=PROJECT \
        --cluster=CLUSTER_NAME \
        --zone=ZONE
    

    Haz los cambios siguientes:

    • BACKEND_NAME: el nombre elegido para el recurso de backend, como my-backend.
    • LABELS: el selector que define qué endpoints entre pods se van a usar para este recurso de backend, como app=web.
    • PROJECT: el nombre de tu proyecto.
    • CLUSTER_NAME: el clúster de Kubernetes al que se limita el ámbito de los selectores definidos. Si no se especifica este campo, se seleccionarán todos los endpoints con la etiqueta indicada. Este campo es opcional.
    • ZONE: la zona que se va a usar en esta invocación. Para predefinir la marca de zona en todos los comandos que la requieran, ejecuta gdcloud config set core/zone ZONE. La marca de zona solo está disponible en entornos multizona. Este campo es opcional.

    Repite este paso con cada zona de tu universo de GDC.

  2. Crea un recurso BackendService global:

    gdcloud compute backend-services create BACKEND_SERVICE_NAME \
        --project=PROJECT \
        --target-ports=TARGET_PORTS \
        --global
    

    Haz los cambios siguientes:

    • BACKEND_SERVICE_NAME: el nombre del servicio de backend.
    • PROJECT: el nombre de tu proyecto.
    • TARGET_PORTS: lista separada por comas de puertos de destino que traduce este servicio de backend. Cada puerto de destino especifica el protocolo, el puerto de la regla de reenvío y el puerto de la instancia de backend. Puede especificar varios puertos de destino. Este campo debe tener el formato protocol:port:targetport, como TCP:80:8080. Este campo es opcional.
  3. Añade el recurso BackendService al recurso Backend que has creado anteriormente en cada zona:

    gdcloud compute backend-services add-backend BACKEND_SERVICE_NAME \
        --backend-zone=ZONE \
        --backend=BACKEND_NAME \
        --project=PROJECT \
        --global
    

    Haz los cambios siguientes:

    • BACKEND_SERVICE_NAME: el nombre del servicio de backend global.
    • ZONE: la zona del backend.
    • BACKEND_NAME: el nombre del backend zonal.
    • PROJECT: el nombre de tu proyecto.

    Complete este paso para cada backend zonal que haya creado anteriormente.

  4. Crea un recurso ForwardingRule interno que defina la dirección IP virtual (VIP) en la que está disponible el servicio:

    gdcloud compute forwarding-rules create FORWARDING_RULE_INTERNAL_NAME \
        --backend-service=BACKEND_SERVICE_NAME \
        --cidr=CIDR \
        --ip-protocol-port=PROTOCOL_PORT \
        --load-balancing-scheme=INTERNAL \
        --project=PROJECT \
        --global
    

    Haz los cambios siguientes:

    • FORWARDING_RULE_INTERNAL_NAME: el nombre de la regla de reenvío.
    • CIDR: el CIDR que se va a usar en la regla de reenvío. Este campo es opcional. Si no se especifica ninguna, se reserva automáticamente un CIDR IPv4/32 del grupo de direcciones IP global. Especifica el nombre de un recurso Subnet en el mismo espacio de nombres que esta regla de reenvío. Un recurso Subnet representa la información de solicitud y asignación de una subred global. Para obtener más información sobre los recursos de Subnet, consulta Gestionar subredes.
    • PROTOCOL_PORT: el protocolo y el puerto que se expondrán en la regla de reenvío. Este campo debe tener el formato ip-protocol=TCP:80. El puerto expuesto debe ser el mismo que el que expone la aplicación real dentro del contenedor.
  5. Para validar el ILB configurado, confirma la condición Ready en cada uno de los objetos creados. Verifica el tráfico con una solicitud curl a la VIP:

    1. Para obtener la VIP asignada, describe la regla de reenvío:

      gdcloud compute forwarding-rules describe FORWARDING_RULE_INTERNAL_NAME --global
      
    2. Verifica el tráfico con una solicitud curl a la dirección IP virtual en el puerto especificado en el campo de la regla de reenvío:

      curl http://FORWARDING_RULE_VIP:PORT
      

    Haz los cambios siguientes:

    • FORWARDING_RULE_VIP: el VIP de la regla de reenvío.
    • PORT: número de puerto de la regla de reenvío.

API

Crea un ILB que tenga como destino cargas de trabajo de contenedores mediante la API de KRM. Este ILB se dirige a todas las cargas de trabajo del proyecto que coincidan con la etiqueta definida en el objeto Backend. Para crear un ILB global con la API KRM, sigue estos pasos:

  1. Crea un recurso Backend para definir los endpoints del ILB. Crea recursos Backend para cada zona en la que se coloquen las cargas de trabajo de los contenedores:

    kubectl --kubeconfig MANAGEMENT_API_SERVER apply -f - <<EOF
    apiVersion: networking.gdc.goog/v1
    kind: Backend
    metadata:
      namespace: PROJECT
      name: BACKEND_NAME
    spec:
      clusterName: CLUSTER_NAME
      endpointsLabels:
        matchLabels:
          app: APP_NAME
    EOF
    

    Haz los cambios siguientes:

    • MANAGEMENT_API_SERVER: la ruta de kubeconfig del servidor de la API Management zonal. Para obtener más información, consulta Cambiar a un contexto zonal.
    • PROJECT: el nombre de tu proyecto.
    • BACKEND_NAME: el nombre del Backend recurso.
    • CLUSTER_NAME: el clúster de Kubernetes al que se limita el ámbito de los selectores definidos. Si no se especifica este campo, se seleccionarán todos los endpoints con la etiqueta indicada. Este campo es opcional.
    • APP_NAME: el nombre de tu aplicación de contenedor.

    Puede usar el mismo recurso Backend para cada zona o crear recursos Backend con conjuntos de etiquetas diferentes para cada zona.

  2. Crea un objeto BackendService usando el recurso Backend que has creado anteriormente. Incluye el recurso HealthCheck:

    kubectl --kubeconfig GLOBAL_API_SERVER apply -f - <<EOF
    apiVersion: networking.global.gdc.goog/v1
    kind: BackendService
    metadata:
      namespace: PROJECT
      name: BACKEND_SERVICE_NAME
    spec:
      backendRefs:
      - name: BACKEND_NAME
        zone: ZONE
      healthCheckName: HEALTH_CHECK_NAME
      targetPorts:
      - port: PORT
        protocol: PROTOCOL
        targetPort: TARGET_PORT
    EOF
    

    Haz los cambios siguientes:

    • GLOBAL_API_SERVER: la ruta de kubeconfig del servidor de la API global.
    • PROJECT: el nombre de tu proyecto.
    • BACKEND_SERVICE_NAME: el nombre que elijas para tu recurso BackendService.
    • HEALTH_CHECK_NAME: el nombre del recurso HealthCheck que has creado anteriormente.
    • BACKEND_NAME: nombre del recurso de zona Backend
    • ZONE: la zona en la que se encuentra el recurso Backend. Puedes especificar varios back-ends en el campo backendRefs. Por ejemplo:

      - name: my-backend-1
        zone: us-east1-a
      - name: my-backend-2
        zone: us-east1-b
      

      El campo targetPorts es opcional. En este recurso se enumeran los puertos que traduce este recurso BackendService. Si usas este objeto, proporciona valores para lo siguiente:

    • PORT: el puerto expuesto por el servicio.

    • PROTOCOL: el protocolo de capa 4 con el que debe coincidir el tráfico. Solo se admiten TCP y UDP.

    • TARGET_PORT: el puerto al que se traduce el valor, como 8080. El valor no se puede repetir en un objeto determinado.

      Un ejemplo de targetPorts podría ser el siguiente:

      targetPorts:
        - port: 80
          protocol: TCP
          targetPort: 8080
      
  3. Crea un recurso ForwardingRule interno que defina la dirección IP virtual (VIP) en la que está disponible el servicio.

    kubectl --kubeconfig GLOBAL_API_SERVER apply -f - <<EOF
    apiVersion: networking.global.gdc.goog/v1
    kind: ForwardingRuleInternal
    metadata:
      namespace: PROJECT
      name: FORWARDING_RULE_INTERNAL_NAME
    spec:
      cidrRef: CIDR
      ports:
      - port: PORT
        protocol: PROTOCOL
      backendServiceRef:
        name: BACKEND_SERVICE_NAME
    EOF
    

    Haz los cambios siguientes:

    • GLOBAL_API_SERVER: la ruta de kubeconfig del servidor de la API global.
    • PROJECT: el nombre de tu proyecto.
    • FORWARDING_RULE_INTERNAL_NAME: el nombre que elijas para tu recurso ForwardingRuleInternal.
    • CIDR: el CIDR que se va a usar en la regla de reenvío. Este campo es opcional. Si no se especifica ninguna, se reserva automáticamente un CIDR IPv4/32 del grupo de direcciones IP global. Especifica el nombre de un recurso Subnet en el mismo espacio de nombres que esta regla de reenvío. Un recurso Subnet representa la información de solicitud y asignación de una subred global. Para obtener más información sobre los recursos de Subnet, consulta Gestionar subredes.
    • PORT: el puerto que se va a exponer en la regla de reenvío. Utilice el campo ports para especificar una matriz de puertos L4 para los que se reenvían paquetes a los back-ends configurados con esta regla de reenvío. Se debe especificar al menos un puerto. Usa el campo port para especificar un número de puerto. El puerto expuesto debe ser el mismo que el que expone la aplicación real dentro del contenedor.
    • PROTOCOL: el protocolo que se va a usar en la regla de reenvío, como TCP. Una entrada de la matriz ports debe tener el siguiente formato:

      ports:
      - port: 80
        protocol: TCP
      
  4. Para validar el ILB configurado, confirma la condición Ready en cada uno de los objetos creados. Verifica el tráfico con una solicitud curl a la VIP:

    1. Recuperar el VIP:

      kubectl get forwardingruleinternal -n PROJECT
      

      La salida tiene este aspecto:

      NAME           BACKENDSERVICE                  CIDR              READY
      ilb-name       BACKEND_SERVICE_NAME            192.0.2.0/32      True
      
    2. Prueba el tráfico con una solicitud curl a la IP virtual en el puerto especificado en el campo de la regla de reenvío:

      curl http://FORWARDING_RULE_VIP:PORT
      

      Haz los cambios siguientes:

      • FORWARDING_RULE_VIP: el VIP de la regla de reenvío.
      • PORT: número de puerto del campo de la regla de reenvío.

Crear un balanceador de carga externo global

Los balanceadores de carga externos (ELB) exponen los servicios para que se pueda acceder a ellos desde fuera de la organización a partir de las direcciones IP de un pool asignadas a la organización desde el pool de direcciones IP externas de instancias más grande.

Sigue estos pasos para crear un ELB global para tus cargas de trabajo de contenedores.

gdcloud

Usa la CLI gdcloud para crear un ELB global que tenga como destino todas las cargas de trabajo del proyecto que coincidan con la etiqueta definida en el objeto Backend. El recurso personalizado Backend debe tener un ámbito de zona.

  1. Para que los servicios de ELB funcionen, debes configurar y aplicar tu propia transferencia de datos de ProjectNetworkPolicy personalizada en la política para permitir el tráfico a las cargas de trabajo de este servicio de ELB. Las políticas de red controlan el acceso a tus cargas de trabajo, no al propio balanceador de carga. Los ELBs exponen las cargas de trabajo a la red de tus clientes, lo que requiere políticas de red explícitas para permitir el tráfico externo al puerto de la carga de trabajo, como 8080.

    Especifica la dirección CIDR externa para permitir el tráfico a las cargas de trabajo de este ELB:

    kubectl --kubeconfig GLOBAL_API_SERVER apply -f - <<EOF
    apiVersion: networking.global.gdc.goog/v1
    kind: ProjectNetworkPolicy
    metadata:
      namespace: PROJECT
      name: allow-inbound-traffic-from-external
    spec:
      policyType: Ingress
      subject:
        subjectType: UserWorkload
      ingress:
      - from:
        - ipBlock:
            cidr: CIDR
        ports:
        - protocol: TCP
          port: PORT
    EOF
    

    Haz los cambios siguientes:

    • GLOBAL_API_SERVER: la ruta de kubeconfig del servidor de la API global. Si aún no has generado un archivo kubeconfig para el servidor de la API global, consulta Generar manualmente un archivo kubeconfig para obtener más información.
    • PROJECT: el nombre de tu proyecto.
    • CIDR: el CIDR externo desde el que se debe acceder al ELB. Esta política es obligatoria, ya que el balanceador de carga externo usa la devolución directa del servidor (DSR), que conserva la dirección IP externa de origen y omite el balanceador de carga en la ruta de retorno. Para obtener más información, consulta Crear una regla de firewall de entrada global para el tráfico entre organizaciones.
    • PORT: el puerto de backend de los pods que hay detrás del balanceador de carga. Este valor se encuentra en el campo .spec.ports[].targetPortfield del manifiesto del recurso Service. Este campo es opcional.

    Esta configuración proporciona a todos los recursos de los proyectos acceso al intervalo CIDR especificado.

  2. Cree un recurso Backend en cada zona para definir el endpoint del balanceador de carga elástico:

    gdcloud compute backends create BACKEND_NAME \
      --labels=LABELS \
      --project=PROJECT \
      --cluster=CLUSTER_NAME \
      --zone=ZONE
    

    Haz los cambios siguientes:

    • BACKEND_NAME: el nombre del recurso de backend, como my-backend.
    • LABELS: selector que define qué endpoints entre pods se van a usar para este recurso de backend, como app=web.
    • PROJECT: el nombre de tu proyecto.
    • CLUSTER_NAME: el clúster de Kubernetes al que se limita el ámbito de los selectores definidos. Si no se especifica este campo, se seleccionarán todos los endpoints con la etiqueta indicada. Este campo es opcional.
    • ZONE: la zona que se va a usar en esta invocación. Para predefinir la marca de zona en todos los comandos que la requieran, ejecuta gdcloud config set core/zone ZONE. La marca de zona solo está disponible en entornos multizona. Este campo es opcional.

    Puede usar el mismo recurso Backend para cada zona o crear recursos Backend con conjuntos de etiquetas diferentes para cada zona.

  3. Crea un recurso BackendService global:

    gdcloud compute backend-services create BACKEND_SERVICE_NAME \
      --project=PROJECT \
      --target-ports=TARGET_PORTS \
      --health-check=HEALTH_CHECK_NAME \
      --global
    

    Haz los cambios siguientes:

    • BACKEND_SERVICE_NAME: el nombre elegido para este servicio de backend.
    • PROJECT: el nombre de tu proyecto.
    • TARGET_PORTS: lista de puertos de destino separados por comas que traduce este servicio de backend. Cada puerto de destino especifica el protocolo, el puerto de la regla de reenvío y el puerto de la instancia de backend. Puede especificar varios puertos de destino. Este campo debe tener el formato protocol:port:targetport, como TCP:80:8080. Este campo es opcional.
    • HEALTH_CHECK_NAME: el nombre del recurso de comprobación de estado. Este campo es opcional.
  4. Añade el recurso global BackendService al recurso de zona Backend que has creado anteriormente:

    gdcloud compute backend-services add-backend BACKEND_SERVICE_NAME \
      --backend=BACKEND_NAME \
      --backend-zone=ZONE \
      --project=PROJECT \
      --global
    

    Complete este paso para cada backend zonal que haya creado anteriormente.

  5. Crea un recurso ForwardingRule externo que defina la IP virtual en la que está disponible el servicio:

    gdcloud compute forwarding-rules create FORWARDING_RULE_EXTERNAL_NAME \
      --backend-service=BACKEND_SERVICE_NAME \
      --cidr=CIDR \
      --ip-protocol-port=PROTOCOL_PORT \
      --load-balancing-scheme=EXTERNAL \
      --project=PROJECT \
      --global
    

    Haz los cambios siguientes:

    • FORWARDING_RULE_EXTERNAL_NAME: el nombre de la regla de reenvío.
    • CIDR: el CIDR que se va a usar en la regla de reenvío. Este campo es opcional. Si no se especifica ninguna, se reserva automáticamente un CIDR IPv4/32 del grupo de direcciones IP global. Especifica el nombre de un recurso Subnet en el mismo espacio de nombres que esta regla de reenvío. Un recurso Subnet representa la información de solicitud y asignación de una subred global. Para obtener más información sobre los recursos de Subnet, consulta Gestionar subredes.
    • PROTOCOL_PORT: el protocolo y el puerto que se expondrán en la regla de reenvío. Este campo debe tener el formato ip-protocol=TCP:80. El puerto expuesto debe ser el mismo que el que expone la aplicación real dentro del contenedor.
    • PROJECT: el nombre de tu proyecto.
  6. Para validar el ELB configurado, confirma la condición Ready en cada uno de los objetos creados. Verifica el tráfico con una solicitud curl a la VIP:

    1. Para obtener la VIP asignada, describe la regla de reenvío:

      gdcloud compute forwarding-rules describe FORWARDING_RULE_EXTERNAL_NAME
      
    2. Verifica el tráfico con una solicitud curl a la IP virtual en el puerto especificado en el campo PROTOCOL_PORT de la regla de reenvío:

      curl http://FORWARDING_RULE_VIP:PORT
      

      Haz los cambios siguientes:

      • FORWARDING_RULE_VIP: la IP virtual de la regla de reenvío.
      • PORT: número de puerto del campo PROTOCOL_PORT de la regla de reenvío.

API

Crea un ELB que tenga como destino cargas de trabajo de pods mediante la API de KRM. Este ELB se dirige a todas las cargas de trabajo del proyecto que coincidan con la etiqueta definida en el objeto Backend. Para crear un ELB zonal con la API KRM, sigue estos pasos:

  1. Para que los servicios de ELB funcionen, debes configurar y aplicar tu propia transferencia de datos de ProjectNetworkPolicy personalizada en la política para permitir el tráfico a las cargas de trabajo de este servicio de ELB. Las políticas de red controlan el acceso a tus cargas de trabajo, no al propio balanceador de carga. Los ELBs exponen las cargas de trabajo a la red de tus clientes, lo que requiere políticas de red explícitas para permitir el tráfico externo al puerto de la carga de trabajo, como 8080.

    Especifica la dirección CIDR externa para permitir el tráfico a las cargas de trabajo de este ELB:

    kubectl --kubeconfig GLOBAL_API_SERVER apply -f - <<EOF
    apiVersion: networking.global.gdc.goog/v1
    kind: ProjectNetworkPolicy
    metadata:
      namespace: PROJECT
      name: allow-inbound-traffic-from-external
    spec:
      policyType: Ingress
      subject:
        subjectType: UserWorkload
      ingress:
      - from:
        - ipBlock:
            cidr: CIDR
        ports:
        - protocol: TCP
          port: PORT
    EOF
    

    Haz los cambios siguientes:

    • GLOBAL_API_SERVER: la ruta de kubeconfig del servidor de la API global. Si aún no has generado un archivo kubeconfig para el servidor de la API global, consulta Generar manualmente un archivo kubeconfig para obtener más información.
    • PROJECT: el nombre de tu proyecto.
    • CIDR: el CIDR externo desde el que se debe acceder al ELB. Esta política es obligatoria, ya que el balanceador de carga externo usa la devolución directa del servidor (DSR), que conserva la dirección IP externa de origen y omite el balanceador de carga en la ruta de retorno. Para obtener más información, consulta Crear una regla de firewall de entrada global para el tráfico entre organizaciones.
    • PORT: el puerto de backend de los pods que hay detrás del balanceador de carga. Este valor se encuentra en el campo .spec.ports[].targetPortfield del manifiesto del recurso Service. Este campo es opcional.
  2. Crea un recurso Backend para definir los endpoints del ELB. Crea recursos Backend para cada zona en la que se coloquen las cargas de trabajo:

    kubectl --kubeconfig MANAGEMENT_API_SERVER apply -f - <<EOF
    apiVersion: networking.gdc.goog/v1
    kind: Backend
    metadata:
      namespace: PROJECT
      name: BACKEND_NAME
    spec:
      clusterName: CLUSTER_NAME
      endpointsLabels:
        matchLabels:
          app: APP_NAME
    EOF
    

    Haz los cambios siguientes:

    • MANAGEMENT_API_SERVER: la ruta de kubeconfig del servidor de la API Management zonal. Si aún no has generado un archivo kubeconfig para el servidor de la API en tu zona de destino, consulta Generar manualmente un archivo kubeconfig para obtener más información.
    • PROJECT: el nombre de tu proyecto.
    • BACKEND_NAME: el nombre del recurso Backend.
    • CLUSTER_NAME: el clúster de Kubernetes al que se limita el ámbito de los selectores definidos. Si no se especifica este campo, se seleccionarán todos los endpoints con la etiqueta indicada. Este campo es opcional.
    • APP_NAME: el nombre de tu aplicación de contenedor.

    Puede usar el mismo recurso Backend para cada zona o crear recursos Backend con conjuntos de etiquetas diferentes para cada zona.

  3. Crea un objeto BackendService usando el recurso Backend que has creado anteriormente:

    kubectl --kubeconfig GLOBAL_API_SERVER apply -f - <<EOF
    apiVersion: networking.global.gdc.goog/v1
    kind: BackendService
    metadata:
      namespace: PROJECT
      name: BACKEND_SERVICE_NAME
    spec:
      backendRefs:
      - name: BACKEND_NAME
        zone: ZONE
      healthCheckName: HEALTH_CHECK_NAME
    EOF
    

    Haz los cambios siguientes:

    • BACKEND_SERVICE_NAME: el nombre que elijas para tu recurso BackendService.
    • HEALTH_CHECK_NAME: el nombre del recurso HealthCheck que has creado anteriormente. No incluyas este campo si vas a configurar un ELB para cargas de trabajo de pods.
    • ZONE: la zona en la que se encuentra el recurso Backend. Puedes especificar varios back-ends en el campo backendRefs. Por ejemplo:
    - name: my-backend-1
      zone: us-east1-a
    - name: my-backend-2
      zone: us-east1-b
    

  4. Crea un recurso ForwardingRule externo que defina la IP virtual en la que está disponible el servicio.

    kubectl --kubeconfig GLOBAL_API_SERVER apply -f - <<EOF
    apiVersion: networking.global.gdc.goog/v1
    kind: ForwardingRuleExternal
    metadata:
      namespace: PROJECT
      name: FORWARDING_RULE_EXTERNAL_NAME
    spec:
      cidrRef: CIDR
      ports:
      - port: PORT
        protocol: PROTOCOL
      backendServiceRef:
        name: BACKEND_SERVICE_NAME
    EOF
    

    Haz los cambios siguientes:

    • FORWARDING_RULE_EXTERNAL_NAME: el nombre elegido para tu recurso ForwardingRuleExternal.
    • CIDR: el CIDR que se va a usar en la regla de reenvío. Este campo es opcional. Si no se especifica ninguna, se reserva automáticamente un CIDR IPv4/32 del grupo de direcciones IP global. Especifica el nombre de un recurso Subnet en el mismo espacio de nombres que esta regla de reenvío. Un recurso Subnet representa la información de solicitud y asignación de una subred global. Para obtener más información sobre los recursos de Subnet, consulta Gestionar subredes.
    • PORT: el puerto que se va a exponer en la regla de reenvío. Utilice el campo ports para especificar una matriz de puertos de nivel 4 para los que se reenvían paquetes a los backends configurados con esta regla de reenvío. Se debe especificar al menos un puerto. Utilice el campo port para especificar un número de puerto. El puerto expuesto debe ser el mismo que el que expone la aplicación real dentro del contenedor.
    • PROTOCOL: el protocolo que se va a usar en la regla de reenvío, como TCP. Una entrada del array ports debe tener el siguiente formato:
    ports:
    - port: 80
      protocol: TCP
    
  5. Para validar el ELB configurado, confirma la condición Ready en cada uno de los objetos creados. Prueba el tráfico con una solicitud curl a la VIP.

    1. Obtén la VIP del proyecto:

      kubectl get forwardingruleexternal -n PROJECT
      

      La salida tiene este aspecto:

      NAME           BACKENDSERVICE                  CIDR              READY
      elb-name       BACKEND_SERVICE_NAME            192.0.2.0/32      True
      
    2. Verifica el tráfico con una solicitud curl a la IP virtual en el puerto especificado en el campo PORT de la regla de reenvío:

      curl http://FORWARDING_RULE_VIP:PORT
      

      Sustituye FORWARDING_RULE_VIP:PORT por la IP virtual y el puerto de la regla de reenvío, como 192.0.2.0:80.

Desplegar cargas de trabajo de contenedores en cada clúster zonal

Las cargas de trabajo de los contenedores no son un recurso global, lo que significa que debes desplegar cada una de tus aplicaciones de contenedor por separado en los clústeres de Kubernetes zonales.

  1. Inicia sesión en la zona que aloja tu clúster de Kubernetes:

    gdcloud config set core/zone ZONE
    
  2. Verifica que tu imagen de contenedor esté disponible en el registro de Harbor gestionado. Para obtener más información, consulta el tutorial Implementar una aplicación de contenedor.

  3. Crea un archivo de manifiesto para tu carga de trabajo de contenedor y despliégalo en tu clúster de Kubernetes zonal:

    kubectl --kubeconfig KUBERNETES_CLUSTER -n PROJECT \
        apply -f - <<EOF
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: DEPLOYMENT_NAME
    spec:
      replicas: NUMBER_OF_REPLICAS
      selector:
        matchLabels:
          run: APP_NAME
      template:
        metadata:
          labels:
            run: APP_NAME
        spec:
          containers:
          - name: CONTAINER_NAME
            image: HARBOR_INSTANCE_URL/HARBOR_PROJECT_NAME/IMAGE:TAG
    EOF
    

    Haz los cambios siguientes:

    • KUBERNETES_CLUSTER: el archivo kubeconfig del clúster de Kubernetes zonal en el que vas a implementar cargas de trabajo de contenedores. Si aún no has generado un archivo kubeconfig para tu clúster de Kubernetes zonal, consulta Generar manualmente un archivo kubeconfig para obtener más información.
    • PROJECT: el espacio de nombres del proyecto en el que se van a desplegar las cargas de trabajo del contenedor.
    • DEPLOYMENT_NAME: el nombre de la implementación del contenedor.
    • NUMBER_OF_REPLICAS: número de objetos Pod replicados que gestiona la implementación.
    • APP_NAME: el nombre de la aplicación que se va a ejecutar en la implementación.
    • CONTAINER_NAME: el nombre del contenedor.
    • HARBOR_INSTANCE_URL: la URL de la instancia de Harbor, como harbor-1.org-1.zone1.google.gdc.test.. Para obtener la URL de la instancia de Harbor, consulta Ver instancias del registro de Harbor.
    • HARBOR_PROJECT_NAME: el nombre del proyecto de Harbor, como my-project.
    • IMAGE: el nombre de la imagen, como nginx.
    • TAG: la etiqueta de la versión de la imagen que quieras extraer, como 1.0.
  4. Repite los pasos anteriores con cada zona de tu universo de GDC. Asegúrate de que tu aplicación de contenedor se encuentre en todas las zonas que quieras para tu estrategia de alta disponibilidad.

Exponer una aplicación en contenedores con Kubernetes

Debes exponer tu aplicación de contenedor para permitir el acceso a ella desde otros recursos de tu universo de GDC.

  1. Crea un recurso Service de type: LoadBalancer. Este recurso expone los pods de tu aplicación a través de una red.

    kubectl --kubeconfig KUBERNETES_CLUSTER -n PROJECT \
    apiVersion: v1
    kind: Service
    metadata:
      name: SERVICE_NAME
    spec:
      selector:
        app: APP_NAME
      ports:
        - port: 80
          protocol: TCP
      type: LoadBalancer
    EOF
    

    Haz los cambios siguientes:

    • KUBERNETES_CLUSTER: el archivo kubeconfig del clúster de Kubernetes zonal en el que vas a implementar cargas de trabajo de contenedores.
    • PROJECT: el espacio de nombres del proyecto en el que residen las cargas de trabajo de tu contenedor.
    • SERVICE_NAME: el nombre del servicio del balanceador de carga.
    • APP_NAME: la etiqueta que has aplicado a tu aplicación de contenedor.
  2. Crea un NetworkPolicy recurso personalizado para permitir todo el tráfico de red al espacio de nombres predeterminado:

    kubectl --kubeconfig KUBERNETES_CLUSTER -n PROJECT \
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      annotations:
      name: allow-all
    spec:
      ingress:
      - from:
        - ipBlock:
            cidr: 0.0.0.0/0
      podSelector: {}
      policyTypes:
      - Ingress
    EOF
    

Aprovisionar almacenamiento persistente para tus pods

Debes crear un recurso PersistentVolumeClaim (PVC) para proporcionar almacenamiento persistente a los pods de la aplicación.

En las siguientes instrucciones se muestra cómo crear un volumen con la GDC standard-rwo StorageClass.

  1. Crea un PersistentVolumeClaim recurso. Por ejemplo, configúralo con un modo de acceso ReadWriteOnce y una clase de almacenamiento standard-rwo:

    kubectl --kubeconfig KUBERNETES_CLUSTER \
        --namespace PROJECT apply -f - <<EOF
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: PVC_NAME
    spec:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 10Gi
      storageClassName: standard-rwo
    EOF
    

    Haz los cambios siguientes:

    • KUBERNETES_CLUSTER: el archivo kubeconfig del clúster de Kubernetes.
    • PROJECT: el espacio de nombres del proyecto en el que se va a crear el PVC.
    • PVC_NAME: el nombre del objeto PersistentVolumeClaim.
  2. Los objetos PersistentVolume (PV) se aprovisionan de forma dinámica. Comprueba el estado de los nuevos PVs en tu clúster de Kubernetes:

    kubectl get pv --kubeconfig KUBERNETES_CLUSTER
    

    El resultado debería ser similar al siguiente:

    NAME       CAPACITY   ACCESS MODES   STATUS      CLAIM     STORAGECLASS   AGE
    pvc-uuidd  10Gi       RWO            Bound       pvc-name  standard-rwo   60s
    
  3. Configura tus cargas de trabajo de contenedor para que usen el PVC. A continuación, se muestra un ejemplo de manifiesto de pod que usa un PVC standard-rwo:

    kubectl --kubeconfig KUBERNETES_CLUSTER \
        --namespace PROJECT apply -f - <<EOF
    apiVersion: apps/v1
    kind: Pod
    metadata:
      name: web-server-deployment
      labels:
        app: APP_LABEL
    spec:
      containers:
      - name: CONTAINER_NAME
        image: HARBOR_INSTANCE_URL/HARBOR_PROJECT_NAME/IMAGE:TAG
        volumeMounts:
        - mountPath: MOUNT_PATH
          name: data
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: PVC_NAME
    EOF
    

    Haz los cambios siguientes:

    • KUBERNETES_CLUSTER: el archivo kubeconfig del clúster de Kubernetes en el que vas a implementar cargas de trabajo de contenedores.
    • PROJECT: el espacio de nombres del proyecto en el que reside el PVC.
    • APP_LABEL: la etiqueta que has aplicado a tu aplicación de contenedor.
    • CONTAINER_NAME: el nombre del contenedor.
    • HARBOR_INSTANCE_URL: la URL de la instancia de Harbor, como harbor-1.org-1.zone1.google.gdc.test.. Para obtener la URL de la instancia de Harbor, consulta Ver instancias del registro de Harbor.
    • HARBOR_PROJECT_NAME: el nombre del proyecto de Harbor, como my-project.
    • IMAGE: el nombre de la imagen, como nginx.
    • TAG: la etiqueta de la versión de la imagen que quieras extraer, como 1.0.
    • MOUNT_PATH: la ruta dentro del pod para montar el volumen.
    • PVC_NAME: el PVC que has creado.

Configurar la replicación de almacenamiento asíncrona

Los universos multizona de GDC ofrecen el uso de recursos de almacenamiento replicados, como volúmenes y contenedores, en modo asíncrono para situaciones de recuperación tras desastres. Estas opciones de recursos de almacenamiento proporcionan replicación de datos asíncrona entre dos zonas de la misma región. La replicación asíncrona se produce en segundo plano, lo que proporciona un objetivo de punto de recuperación (RPO) bajo, pero no nulo, en caso de desastre. Todos los datos replicados están online y se puede acceder a ellos inmediatamente, pero puede que se necesite un procedimiento de conmutación por error manual para habilitar la escritura en la zona secundaria.

Puede elegir uno de los siguientes tipos de replicación de almacenamiento asíncrona para su aplicación de contenedor:

Crear un segmento de doble zona para el almacenamiento de objetos

Los datos de almacenamiento de objetos se escriben en un solo segmento cuyos datos se almacenan en ambas zonas. Como los datos se copian de forma asíncrona entre zonas, es posible que las zonas no contengan las mismas versiones de los objetos en un momento dado, pero, con el tiempo, se convertirán en equivalentes si no se realizan cambios adicionales. A diferencia de la replicación de volúmenes, los contenedores replicados se pueden escribir durante las particiones de zona. Cada escritura en un objeto genera una versión diferente, y la versión más reciente de cualquiera de las zonas será el estado final una vez que se haya restaurado la conectividad.

  1. Verifica que tu operador de infraestructura (IO) haya creado el recurso personalizado BucketLocationConfig, que es necesario para la replicación asíncrona entre zonas del almacenamiento de objetos. Este recurso debe implementarse en el servidor de la API global raíz.

  2. Crea el recurso personalizado de doble zona Bucket:

    kubectl --kubeconfig GLOBAL_API_SERVER apply -f - <<EOF
    apiVersion: object.global.gdc.goog/v1
    kind: Bucket
    metadata:
      name: BUCKET_NAME
      namespace: PROJECT
    spec:
      location: LOCATION_NAME
      description: Sample DZ Bucket
      storageClass: Standard
    EOF
    

    Haz los cambios siguientes:

    • GLOBAL_API_SERVER: el archivo kubeconfig del servidor de la API global.
    • BUCKET_NAME: el nombre del segmento de almacenamiento.
    • PROJECT: el nombre del proyecto en el que se encuentra el cubo.
    • LOCATION_NAME: el lugar físico donde se encuentran los datos de los objetos del segmento. Debe corresponderse con el nombre de un recurso BucketLocation. Para consultar el servidor de la API global de tu organización y obtener una lista de recursos BucketLocation disponibles, ejecuta kubectl --kubeconfig GLOBAL_API_SERVER bucketlocations. Si no hay recursos BucketLocation, ponte en contacto con tu IO para verificar que ha habilitado la replicación asíncrona.

Configurar la replicación de almacenamiento en bloque asíncrona entre zonas

El almacenamiento en bloques replicado proporciona volúmenes (PVs) replicados de forma asíncrona, que mantienen la equivalencia de bloques entre los volúmenes primario y secundario. Debido a la naturaleza asíncrona, el volumen secundario refleja el estado de la zona principal en algún momento del pasado (RPO distinto de cero). El volumen secundario no se puede montar mientras siga siendo el destino de la replicación, por lo que se requiere una intervención manual para finalizar la relación y permitir que se produzcan escrituras.

Debes configurar una relación de replicación de almacenamiento entre zonas para crear datos replicados que estén disponibles para la conmutación por error si los datos de la zona de origen dejan de estar disponibles. Esto es importante si usas almacenamiento en bloque para tu aplicación de contenedor.

Antes de empezar, comprueba que tu operador de infraestructura (IO) haya creado y configurado los recursos personalizados StorageClusterPeering y StorageVirtualMachinePeering para permitir la replicación del almacenamiento en bloque entre zonas. Este recurso debe implementarse en el servidor de la API global raíz.

  1. Crea un archivo YAML de recurso personalizado VolumeReplicationRelationship y despliega en el servidor de la API global:

    kubectl --kubeconfig GLOBAL_API_SERVER apply -f - <<EOF
    apiVersion: storage.global.gdc.goog/v1
    kind: VolumeReplicationRelationship
    metadata:
      name: PVC_REPL_NAME
      namespace: PROJECT
    spec:
      source:
        pvc:
          clusterRef: SOURCE_PVC_CLUSTER
          pvcRef: SOURCE_PVC
        zoneRef: SOURCE_ZONE
    destination:
        pvc:
          clusterRef: DEST_PVC_CLUSTER
        zoneRef: DEST_ZONE
    EOF
    

    Haz los cambios siguientes:

    • GLOBAL_API_SERVER: archivo kubeconfig del servidor de la API global.
    • PVC_REPL_NAME: el nombre de la relación de replicación de volúmenes.
    • PROJECT: el proyecto en el que reside la infraestructura de almacenamiento.
    • SOURCE_PVC_CLUSTER: el clúster de Kubernetes en el que se aloja el PVC.
    • SOURCE_PVC: el PVC de la zona de origen que se va a replicar.
    • SOURCE_ZONE: la zona de origen en la que se aloja el PVC.
    • DEST_PVC_CLUSTER: el clúster de Kubernetes de destino en el que se replicará el PVC.
    • DEST_ZONE: la zona de destino en la que se replicará el PVC.
  2. Crea un recurso personalizado VolumeFailover en la zona de destino, que detendrá la replicación en la zona de destino si la zona de origen no está disponible por cualquier motivo:

    kubectl --kubeconfig MANAGEMENT_API_SERVER apply -f - <<EOF
    apiVersion: storage.gdc.goog/v1
    kind: VolumeFailover
    metadata:
      name: PVC_FAILOVER_NAME
      namespace: PROJECT
    spec:
      volumeReplicationRelationshipRef: PVC_REPL_NAME
    EOF
    

    Haz los cambios siguientes:

    • MANAGEMENT_API_SERVER: archivo kubeconfig del servidor de la API Management zonal.
    • PVC_FAILOVER_NAME: el nombre del failover de PVC.
    • PROJECT: el proyecto en el que reside la infraestructura de almacenamiento.
    • PVC_REPL_NAME: el nombre de la relación de replicación de volúmenes.

Siguientes pasos