Recibir eventos de Pub/Sub en un endpoint HTTP privado de un clúster de GKE privado

En este tutorial se muestra cómo crear un endpoint HTTP privado en un clúster privado de Google Kubernetes Engine (GKE) que recibe eventos de mensajes de Pub/Sub mediante Eventarc. Para obtener más información sobre este destino de eventos, consulta Dirigir eventos a un endpoint HTTP interno en una red de VPC.

Los clústeres de GKE privados son un tipo de clúster nativo de nube privada virtual (VPC) en el que los nodos solo tienen direcciones IP internas, lo que significa que los nodos y los pods están aislados de Internet de forma predeterminada. Puedes elegir si quieres que los clientes tengan acceso al plano de control, si quieres que tengan acceso limitado o si quieres que tengan acceso sin restricciones. No puedes convertir un clúster que ya existe y que no es privado en un clúster privado. Para obtener más información, consulta Acerca de los clústeres privados.

Puedes ejecutar los siguientes comandos con la CLI de Google Cloud en tu terminal o en Cloud Shell.

Crear una subred de solo proxy

A menos que crees una política de organización que lo prohíba, los proyectos nuevos empiezan con una red predeterminada (una red VPC de modo automático) que tiene una subred en cada región. Cada red de VPC consta de uno o varios intervalos de direcciones IP denominados subredes. Las subredes son recursos regionales y tienen intervalos de direcciones IP asociados.

  1. Usa el comando gcloud compute networks subnets create para crear una subred de solo proxy en la red predeterminada.

    gcloud compute networks subnets create proxy-only-subnet \
        --purpose=REGIONAL_MANAGED_PROXY \
        --role=ACTIVE \
        --region=us-central1 \
        --network=default \
        --range=10.10.10.0/24
    

    Ten en cuenta que una subred con purpose=REGIONAL_MANAGED_PROXY está reservada para los balanceadores de carga basados en Envoy y que range debe proporcionar al menos 64 direcciones IP.

  2. Crea una regla de cortafuegos que coincida con el intervalo de la subred de solo proxy y que permita el tráfico en el puerto TCP 8080.

    gcloud compute firewall-rules create allow-proxy-connection \
        --allow tcp:8080 \
        --source-ranges 10.10.10.0/24 \
        --network=default
    

Crear un clúster privado de GKE

Usa el comando gcloud container clusters create-auto para crear un clúster de GKE privado en modo Autopilot que tenga nodos privados y que no tenga acceso de cliente al endpoint público.

En el siguiente ejemplo se crea un clúster de GKE privado llamado private-cluster y una subred llamada my-subnet:

gcloud container clusters create-auto private-cluster \
    --create-subnetwork name=my-subnet \
    --enable-master-authorized-networks \
    --enable-private-nodes \
    --enable-private-endpoint \
    --region=us-central1

Ten en cuenta lo siguiente:

  • --enable-master-authorized-networks especifica que el acceso al endpoint público está restringido a los intervalos de direcciones IP que autorices.
  • --enable-private-nodes indica que los nodos del clúster no tienen direcciones IP externas.
  • --enable-private-endpoint indica que el clúster se gestiona mediante la dirección IP interna del endpoint de la API del plano de control.

La creación del clúster puede tardar varios minutos. Una vez creado el clúster, el resultado debería indicar que su estado es RUNNING.

Crear una instancia de VM en una subred específica

Una instancia de VM de Compute Engine es una máquina virtual alojada en la infraestructura de Google. Los términos instancia de Compute Engine, instancia de VM y VM son sinónimos y se usan indistintamente. Las instancias de VM incluyen clústeres de GKE, instancias del entorno flexible de App Engine y otros Google Cloud productos creados en VMs de Compute Engine.

Usa el comando gcloud compute instances create para crear una instancia de VM de Compute Engine en la subred que has creado anteriormente. Asigna una cuenta de servicio y define el ámbito de acceso de la máquina virtual como cloud-platform.

gcloud compute instances create my-vm \
    --service-account=PROJECT_NUMBER-compute@developer.gserviceaccount.com \
    --scopes=https://www.googleapis.com/auth/cloud-platform \
    --zone=us-central1-a \
    --subnet=my-subnet

Para obtener más información, consulta Crear e iniciar una instancia de VM.

Desplegar un receptor de eventos en la VM

Con una imagen prediseñada, us-docker.pkg.dev/cloudrun/container/hello, implementa un servicio en tu VM que escuche en el puerto 80 y que reciba y registre eventos.

  1. Establece una conexión SSH con tu instancia de VM ejecutando el siguiente comando:

    gcloud compute ssh my-vm --project=PROJECT_ID --zone=us-central1-a
    

    Una vez que se haya establecido una conexión con el servidor SSH, ejecuta los comandos restantes en tu instancia de VM.

  2. Si es necesario, instala kubectl y los complementos necesarios.

  3. En tu instancia de VM, usa el comando get-credentials para habilitar kubectl y que funcione con el clúster que has creado.

    gcloud container clusters get-credentials private-cluster \
        --region=us-central1 \
        --internal-ip
    
  4. Usa un comando de Kubernetes, kubectl create deployment, para desplegar una aplicación en el clúster.

    kubectl create deployment hello-app \
        --image=us-docker.pkg.dev/cloudrun/container/hello
    

    De esta forma, se crea un despliegue llamado hello-app. El pod de la implementación ejecuta la imagen de contenedor hello.

  5. Después de desplegar la aplicación, puedes exponerla al tráfico creando un servicio de Kubernetes. Ejecuta el siguiente comando:kubectl expose

    kubectl expose deployment hello-app \
        --type ClusterIP \
        --port 80 \
        --target-port 8080
    

    Deberías ver service/hello-app exposed en la salida.

    Puedes ignorar los mensajes similares al siguiente:

    E0418 14:15:33.970933    1129 memcache.go:287] couldn't get resource list for metrics.k8s.io/v1beta1: the server is currently unable to handle the request
    

Configurar el enrutamiento del tráfico de Kubernetes

Un recurso Gateway representa un plano de datos que enruta el tráfico en Kubernetes. Una puerta de enlace puede representar muchos tipos diferentes de balanceo de carga y de enrutamiento en función de la GatewayClass de la que derive. Para obtener más información, consulta el artículo sobre implementación de pasarelas. Se implementa un manifiesto HTTPRoute para crear rutas y enviar tráfico a los back-ends de las aplicaciones.

  1. Despliega una pasarela en tu clúster.

    kubectl apply -f - <<EOF
    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: internal-http
    spec:
      gatewayClassName: gke-l7-rilb
      listeners:
      - name: http
        protocol: HTTP
        port: 80
    EOF
    

    Ten en cuenta lo siguiente:

    • gatewayClassName: gke-l7-rilb especifica el GatewayClass del que deriva este Gateway. gke-l7-rilb corresponde al balanceador de carga de aplicación interno.
    • port: 80 especifica que la puerta de enlace solo expone el puerto 80 para escuchar el tráfico HTTP.
  2. Valida que la pasarela se haya implementado correctamente. Puede que tarde unos minutos en desplegar todos sus recursos.

    kubectl describe gateways.gateway.networking.k8s.io internal-http
    

    El resultado debería ser similar al siguiente:

    Name:         internal-http
    Namespace:    default
    ...
    API Version:  gateway.networking.k8s.io/v1beta1
    Kind:         Gateway
    ...
    Spec:
      Gateway Class Name:  gke-l7-rilb
      Listeners:
        Allowed Routes:
          Namespaces:
            From:  Same
        Name:      http
        Port:      80
        Protocol:  HTTP
    Status:
      Addresses:
        Type:   IPAddress
        Value:  10.36.172.5
    ...
    Events:
      Type    Reason  Age                From                   Message
      ----    ------  ----               ----                   -------
      Normal  ADD     80s                sc-gateway-controller  default/internal-http
      Normal  UPDATE  20s (x3 over 80s)  sc-gateway-controller  default/internal-http
      Normal  SYNC    20s                sc-gateway-controller  SYNC on default/internal-http was a success
    
  3. Despliega un manifiesto HTTPRoute para enrutar el tráfico HTTP al hello-app servicio en el puerto 80.

    kubectl apply -f - <<EOF
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: hello-app-route
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      rules:
      - backendRefs:
        - name: hello-app
          port: 80
    EOF
    

Crear un archivo adjunto de red

Una vinculación de red es un recurso que permite que una red de VPC de un productor inicie conexiones con una red de VPC de un consumidor a través de una interfaz de Private Service Connect.

Para publicar eventos, Eventarc usa el archivo adjunto de red para establecer una conexión con el endpoint HTTP interno alojado en una red VPC.

Puedes crear una vinculación de red que acepte automáticamente las conexiones de cualquier interfaz de Private Service Connect que haga referencia a la vinculación de red. Crea el adjunto de red en la misma red y región que contenga el servicio de destino HTTP.

gcloud compute network-attachments create my-network-attachment \
    --region=us-central1 \
    --subnets=my-subnet\
    --connection-preference=ACCEPT_AUTOMATIC

Para obtener más información, consulta Acerca de los archivos adjuntos de red.

Crear un activador de Eventarc

Crea un activador de Eventarc que cree un tema de Pub/Sub y enrute los eventos al receptor de eventos desplegado en la VM cuando se publique un mensaje en el tema de Pub/Sub.

  1. Obtén la dirección de la pasarela.

    GATEWAY_ADDRESS=$(kubectl get gateways.gateway.networking.k8s.io internal-http -o=jsonpath="{.status.addresses[0].value}")
    
  2. Crea un activador.

    gcloud eventarc triggers create my-trigger \
        --location=us-central1 \
        --destination-http-endpoint-uri="http://$GATEWAY_ADDRESS:80/" \
        --network-attachment="projects/PROJECT_ID/regions/us-central1/networkAttachments/my-network-attachment" \
        --event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" \
        --service-account=PROJECT_NUMBER-compute@developer.gserviceaccount.com
    

    Sustituye PROJECT_NUMBER por el número de tu proyecto. Google Cloud Puedes encontrar el número de tu proyecto en la página Bienvenido de la consola Google Cloud o ejecutando el siguiente comando:

    gcloud projects describe PROJECT_ID --format='value(projectNumber)'
    

Para obtener más información sobre cómo configurar el activador, consulta Dirigir eventos a un endpoint HTTP interno en una red de VPC.

Generar y ver un evento de tema de Pub/Sub

Puedes generar un evento publicando un mensaje en un tema de Pub/Sub.

  1. Busca y define el tema de Pub/Sub como variable de entorno.

    export MY_TOPIC=$(gcloud eventarc triggers describe my-trigger \
        --location=us-central1 \
        --format='value(transport.pubsub.topic)')
    
  2. Publica un mensaje en el tema de Pub/Sub para generar un evento.

    gcloud pubsub topics publish $MY_TOPIC --message "Hello World"
    

    El activador de Eventarc dirige el evento al endpoint HTTP interno del clúster privado de GKE.

  3. Consulta los registros de pods de la aplicación y verifica la entrega de eventos.

    POD_NAME=$(kubectl get pod --selector app=hello-app --output=name)
    kubectl logs $POD_NAME
    

    El cuerpo del evento debe ser similar al siguiente:

    2024/04/18 20:31:43 Hello from Cloud Run! The container started successfully and is listening for HTTP requests on $PORT
    {"severity":"INFO","eventType":"google.cloud.pubsub.topic.v1.messagePublished","message":"Received event of type google.cloud.pubsub.topic.v1.messagePublished.
    Event data: Hello World","event":{"specversion":"1.0","id":"10935738681111260","source":"//pubsub.googleapis.com/projects/my-project/topics/eventarc-us-central1-my-trigger-224","type":"google.cloud.pubsub.topic.v1.messagePublished","datacontenttype":"application/json","time":"2024-04-18T20:40:03Z","data":
    {"message":{"data":"SGVsbG8gV29ybGQ=","messageId":"10935738681111260","publishTime":"2024-04-18T20:40:03Z"}}}}
    

Has desplegado correctamente un servicio de receptor de eventos en un endpoint HTTP interno de un clúster privado de GKE, has creado un activador de Eventarc, has generado un evento desde Pub/Sub y has confirmado que el activador ha dirigido el evento al endpoint de destino según lo previsto.