Registrar endereços IP particulares para pools de workers usando o Cloud DNS

Este tutorial descreve como registrar o endereço IP particular de uma instância de pool de workers do Cloud Run em uma zona gerenciada do Cloud DNS. Neste tutorial, você usa um script de inicialização para detectar dinamicamente o IP da instância pelo servidor de metadados e criar um aplicativo Node.js para processar a entrada diretamente na rede VPC.

Objetivos

Custos

Neste documento, você vai usar os seguintes componentes faturáveis do Google Cloud:

Para gerar uma estimativa de custo baseada na projeção de uso, use a calculadora de preços.

Novos usuários do Google Cloud podem estar qualificados para um teste sem custo financeiro.

Antes de começar

  1. Faça login na sua Google Cloud conta do. Se você não conhece o Google Cloud, crie uma conta para avaliar o desempenho dos nossos produtos em cenários reais. Clientes novos também recebem US $300 em créditos para executar, testar e implantar cargas de trabalho.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  5. Verify that billing is enabled for your Google Cloud project.

  6. Ative as APIs Cloud DNS, Cloud Run, Compute Engine, Artifact Registry e Cloud Build.

    Funções necessárias para ativar APIs

    Para ativar as APIs, é necessário ter o papel do IAM de administrador de uso do serviço (roles/serviceusage.serviceUsageAdmin), que contém a permissão serviceusage.services.enable. Saiba como conceder papéis.

    Ativar as APIs

  7. Instale e inicialize a CLI gcloud.
  8. Atualize os componentes:
    gcloud components update
  9. Defina o ID do projeto executando o seguinte comando:
    gcloud config set project PROJECT_ID
    Substitua PROJECT_ID pelo ID do seu Google Cloud projeto.

Funções exigidas

Para receber as permissões necessárias para concluir o tutorial, peça ao administrador para conceder os seguintes papéis do IAM no seu projeto:

Para mais informações sobre a concessão de papéis, consulte Gerenciar o acesso a projetos, pastas e organizações.

Também é possível conseguir as permissões necessárias por meio de papéis personalizados ou de outros papéis predefinidos.

Criar uma conta de serviço personalizada

Crie uma conta de serviço personalizada com as permissões mínimas necessárias para registrar registros DNS. Para configurar a conta de serviço, faça o seguinte:

  1. Execute o seguinte comando para criar uma conta de serviço:

    gcloud iam service-accounts create SERVICE_ACCOUNT_NAME \
      --display-name="DNS Worker Pool Service Account"

    Substitua SERVICE_ACCOUNT_NAME por um nome para sua conta de serviço personalizada, por exemplo, dns-worker-sa.

  2. Conceda o papel de administrador do Cloud DNS à conta de serviço:

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member="serviceAccount:SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com" \
      --role="roles/dns.admin"

Criar uma zona de DNS do Cloud DNS

Crie uma zona gerenciada privada do Cloud DNS chamada test-wp para registrar o IP da instância do pool de workers.

gcloud dns managed-zones create test-wp --description="new DNS zone for worker pools"  --dns-name="workerpools.example.com."  --visibility="private" --networks=default

Criar um aplicativo Node.js

Crie um aplicativo Node.js que recupere o endereço IP da instância do pool de workers usando o servidor de metadados e, em seguida, registre-o no Cloud DNS.

  1. Crie uma pasta chamada worker e mude o diretório para ela:

    mkdir worker
    cd worker
    
  2. Crie um arquivo chamado setup_dns.sh e adicione o seguinte script que é executado quando a instância do pool de workers é iniciada. Esse script usa o nome do host da instância para gerar o nome do registro DNS. Se houver mais de uma instância, várias instâncias poderão usar o mesmo nome do host, levando à criação de registros DNS sobrepostos.

    #!/bin/bash
    
    # --- Variables ---
    # The name of your Cloud DNS managed zone.
    ZONE_NAME="test-wp"
    # The base domain suffix for the DNS entry. Use the part *after* the hostname.
    # For example, for "testinstance.workerpools.example.com.", the suffix is ".workerpools.example.com."
    DNS_SUFFIX=".workerpools.example.com."
    # The Time-To-Live (TTL) in seconds.
    TTL="300"
    # The record type (A for IPv4).
    RECORD_TYPE="A"
    # -----------------
    
    # 1. Dynamically generate DNS_NAME
    # Get the simple hostname (e.g., "testinstance") and append the defined suffix.
    # We use 'hostname -s' to get the short hostname.
    SHORT_HOSTNAME=$(hostname -s)
    DNS_NAME="${SHORT_HOSTNAME}${DNS_SUFFIX}"
    
    # 2. Dynamically assign NEW_IP
    # Get the IP address from metadata server using predefined key.
    NEW_IP=$(curl "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip" -H "Metadata-Flavor: Google")
    
    # --- Input Validation ---
    if [ -z "$NEW_IP" ]; then
        echo "❌ ERROR: Could not obtain a valid IP address from metadata server. Aborting."
        exit 1
    fi
    
    echo "Starting DNS record update for ${DNS_NAME} in zone ${ZONE_NAME}..."
    echo "New IP detected on this instance: ${NEW_IP}"
    
    # 3. Get the current existing IP address (if any)
    # This is required to know what to put in the --rrdatas for the delete command.
    EXISTING_IP=$(gcloud dns record-sets list \
        --zone="${ZONE_NAME}" \
        --name="${DNS_NAME}" \
        --type="${RECORD_TYPE}" \
        --format="value(rrdatas[0])" 2>/dev/null)
    
    # --- Conditional Deletion/Skip Check ---
    if [ -n "$EXISTING_IP" ] && [ "$EXISTING_IP" != "$NEW_IP" ]; then
        echo "Found existing IP: ${EXISTING_IP}. It is different from the new IP."
    
        # Delete the existing record
        echo "Deleting old record..."
        gcloud dns record-sets delete "${DNS_NAME}" \
            --zone="${ZONE_NAME}" \
            --type="${RECORD_TYPE}" \
            --quiet
    
        if [ $? -ne 0 ]; then
            echo "❌ ERROR: Failed to delete existing record. Aborting."
            exit 1
        fi
    elif [ -n "$EXISTING_IP" ] && [ "$EXISTING_IP" == "$NEW_IP" ]; then
        echo "Existing IP (${EXISTING_IP}) matches the new IP. Skipping update."
        exit 0
    else
        echo "No existing record found for ${DNS_NAME}. Proceeding with creation."
    fi
    # ----------------------------------------
    
    # 4. Add the new record
    echo "Creating new record with IP: ${NEW_IP}..."
    gcloud dns record-sets create "${DNS_NAME}" \
      --zone="${ZONE_NAME}" \
      --type="${RECORD_TYPE}" \
      --ttl="${TTL}" \
      --rrdatas="${NEW_IP}"
    
    # Final status check
    if [ $? -eq 0 ]; then
        echo "✅ Successfully created/updated DNS record for ${DNS_NAME} to ${NEW_IP}."
    else
        echo "❌ ERROR: Failed to create the new DNS record."
        exit 1
    fi
    
  3. Crie um arquivo server.js com o seguinte código para processar a entrada de endereço IP particular:

    // server.js
    
    // 1. Import the built-in 'http' module
    console.log("hello from worker pool")
    const http = require('http');
    
    // Define the port the server will listen on
    const PORT = 3000;
    
    // 2. Create the server instance
    const server = http.createServer((req, res) => {
      // Set the response HTTP header with status and type of content
      res.writeHead(200, {'Content-Type': 'text/plain'});
      // Write the response body
      res.end('Hello World!\n');
    });
    
    // 3. Start the server and listen on the specified port
    server.listen(PORT, () => {
      console.log(`Server running at http://localhost:${PORT}/`);
    });
    
  4. Crie um script start.sh com o seguinte código para executar a configuração de DNS primeiro, antes de executar o aplicativo Node.js:

    #!/bin/bash
    set -e
    
    # 1. Execute the setup script
    echo "Running setup_dns.sh..."
    /app/setup_dns.sh
    
    # 2. Run the main application
    echo "Starting server.js..."
    exec node /app/server.js
    
  5. Crie o Dockerfile a seguir para empacotar o aplicativo em uma imagem:

    # Choose a base image. This image includes gcloud, kubectl, etc.
    FROM google/cloud-sdk:latest
    
    # Install Node.js on top of the Cloud SDK image.
    RUN apt-get update && \
        apt-get install -y curl && \
        curl -sL https://deb.nodesource.com/setup_lts.x | bash - && \
        apt-get install -y nodejs && \
        # Clean up to reduce image size
        apt-get clean && \
        rm -rf /var/lib/apt/lists/*
    
    # Set the working directory inside the container.
    WORKDIR /app
    
    # Copy the application and scripts into the container.
    COPY setup_dns.sh .
    COPY server.js .
    COPY start.sh .
    
    # Make both scripts executable.
    RUN chmod +x setup_dns.sh start.sh
    
    # Define the entrypoint and default command.
    ENTRYPOINT ["/app/start.sh"]
    CMD []
    

Implantar um pool de workers com entrada direta de VPC

Implante um pool de workers chamado test-cli-dns e anexe-o a uma rede VPC.

gcloud beta run worker-pools deploy test-cli-dns \
  --network default \
  --subnet default \
  --region us-central1 \
  --source . \
  --service-account SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com \
  --project PROJECT_ID

Substitua PROJECT_ID pelo ID do seu Google Cloud projeto e SERVICE_ACCOUNT_NAME pelo nome da conta de serviço que você criou.

Teste o aplicativo

Os pools de workers do Cloud Run com entrada direta de VPC são projetados para tráfego apenas interno. Eles não têm um IP público. Para verificar a funcionalidade de entrada, siga estas etapas para executar uma solicitação usando curl de uma VM do Compute Engine hospedada na mesma rede VPC e sub-rede:

  1. Crie uma VM de teste na mesma rede e região do pool de workers:

     gcloud compute instances create wp-test-vm \
         --zone=us-central1-a \
         --network=default \
         --subnet=default
    
  2. Conecte-se à VM de teste por SSH executando o seguinte comando:

     gcloud compute ssh wp-test-vm --zone=us-central1-a
    
  3. No terminal da VM, invoque o serviço no endereço IP particular da instância do pool de workers registrada no Cloud DNS:

    curl http://localhost.workerpools.example.com:3000

    Você verá a saída:

    Hello World!

Pronto. Você configurou o pool de workers do Cloud Run com entrada direta de VPC usando um endereço IP particular e o Cloud DNS.

Liberar espaço

Para evitar cobranças extras na sua Google Cloud conta, exclua todos os recursos implantados com este tutorial.

Excluir o projeto

Se você criou um novo projeto para este tutorial, exclua-o. Se você usou um projeto atual e precisa mantê-lo sem as alterações incluídas neste tutorial, exclua os recursos criados para o tutorial.

O jeito mais fácil de evitar cobranças é excluindo o projeto que você criou para o tutorial.

Para excluir o projeto:

  1. No Google Cloud console, acesse a página Gerenciar recursos.

    Acessar "Gerenciar recursos"

  2. Na lista de projetos, selecione o projeto que você quer excluir e clique em Excluir.
  3. Na caixa de diálogo, digite o ID do projeto e clique em Desligar para excluir o projeto.

Excluir recursos do tutorial

  1. Exclua o serviço do Cloud Run que você implantou neste tutorial. Os serviços do Cloud Run não geram custos até receberem solicitações.

    Para excluir o serviço do Cloud Run, execute o seguinte comando:

    gcloud run services delete SERVICE-NAME

    Substitua SERVICE-NAME pelo nome do serviço.

    Também é possível excluir os serviços do Cloud Run no Google Cloud console.

  2. Remova a configuração de região padrão gcloud que você adicionou durante a configuração do tutorial:

     gcloud config unset run/region
    
  3. Remova a configuração do projeto:

     gcloud config unset project
    
  4. Exclua outros Google Cloud recursos criados neste tutorial:

A seguir