Registra indirizzi IP privati per i pool di worker utilizzando Cloud DNS

Questo tutorial descrive come registrare l'indirizzo IP privato di un'istanza del pool di worker Cloud Run all'interno di una zona gestita di Cloud DNS. In questo tutorial, utilizzerai uno script di avvio per rilevare dinamicamente l'IP dell'istanza tramite il server di metadati e creare un'applicazione Node.js per gestire l'ingresso direttamente all'interno della rete VPC.

Obiettivi

Costi

In questo documento vengono utilizzati i seguenti componenti fatturabili di Google Cloud:

Per generare una stima dei costi in base all'utilizzo previsto, utilizza il calcolatore prezzi.

I nuovi Google Cloud utenti potrebbero avere diritto a una prova senza costi.

Prima di iniziare

  1. Accedi al tuo Google Cloud account. Se non conosci Google Cloud, crea un account per valutare le prestazioni dei nostri prodotti in scenari reali. I nuovi clienti ricevono anche 300 $di crediti senza costi per l'esecuzione, il test e il deployment dei workload.
  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. Abilita le API Cloud DNS, Cloud Run, Compute Engine, Artifact Registry e Cloud Build.

    Ruoli richiesti per abilitare le API

    Per abilitare le API, devi disporre del ruolo IAM Amministratore Service Usage (roles/serviceusage.serviceUsageAdmin), che contiene l'autorizzazione serviceusage.services.enable. Scopri come concedere i ruoli.

    Abilita le API

  7. Installa e inizializza gcloud CLI.
  8. Aggiorna i componenti:
    gcloud components update
  9. Imposta l'ID progetto eseguendo questo comando:
    gcloud config set project PROJECT_ID
    Sostituisci PROJECT_ID con l'ID del tuo Google Cloud progetto.

Ruoli obbligatori

Per ottenere le autorizzazioni necessarie per completare il tutorial, chiedi all'amministratore di concederti i seguenti ruoli IAM nel tuo progetto:

Per saperne di più sulla concessione dei ruoli, consulta Gestisci l'accesso a progetti, cartelle e organizzazioni.

Potresti anche riuscire a ottenere le autorizzazioni richieste tramite i ruoli personalizzati o altri ruoli predefiniti.

Crea un account di servizio personalizzato

Crea un account di servizio personalizzato con le autorizzazioni minime richieste per registrare i record DNS. Per configurare il account di servizio, procedi nel seguente modo:

  1. Crea un account di servizio eseguendo questo comando:

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

    Sostituisci SERVICE_ACCOUNT_NAME con un nome per il tuo account di servizio personalizzato, ad esempio dns-worker-sa.

  2. Concedi il ruolo Amministratore Cloud DNS all'account di servizio:

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

Crea una zona Cloud DNS

Crea una zona gestita di Cloud DNS privata denominata test-wp per registrare l'IP dell'istanza del pool di worker.

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

Crea un'applicazione Node.js

Crea un'applicazione Node.js che recupera l'indirizzo IP dell'istanza del pool di worker utilizzando il server di metadati e poi lo registra con Cloud DNS.

  1. Crea una cartella denominata worker e cambia la directory in questa cartella:

    mkdir worker
    cd worker
    
  2. Crea un file denominato setup_dns.sh e aggiungi il seguente script che viene eseguito all'avvio dell'istanza del pool di worker. Questo script utilizza il nome host dell'istanza per generare il nome del record DNS. Se sono presenti più istanze, più istanze possono utilizzare lo stesso nome host, il che comporta la creazione di record DNS sovrapposti.

    #!/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. Crea un file server.js con il seguente codice per gestire l'ingresso dell'indirizzo IP privato:

    // 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. Crea uno script start.sh con il seguente codice per eseguire prima la configurazione DNS, prima di eseguire l'applicazione 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. Crea il seguente Dockerfile per creare il pacchetto dell'applicazione in un'immagine:

    # 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 []
    

Esegui il deployment di un pool di worker con l'ingresso VPC diretto

Esegui il deployment di un pool di worker denominato test-cli-dns e collegalo a una rete 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

Sostituisci PROJECT_ID con l'ID del tuo Google Cloud progetto e SERVICE_ACCOUNT_NAME con il nome del account di servizio che hai creato.

Testa l'applicazione

I pool di worker Cloud Run con l'ingresso VPC diretto sono progettati per il traffico solo interno. Non hanno un IP pubblico. Per verificare la funzionalità di ingresso, segui questi passaggi per eseguire una richiesta utilizzando curl da una VM Compute Engine ospitata sulla stessa rete VPC e subnet:

  1. Crea una VM di test nella stessa rete e regione del pool di worker:

     gcloud compute instances create wp-test-vm \
         --zone=us-central1-a \
         --network=default \
         --subnet=default
    
  2. Connettiti alla VM di test tramite SSH eseguendo il seguente comando:

     gcloud compute ssh wp-test-vm --zone=us-central1-a
    
  3. Dal terminale della VM, richiama il servizio all'indirizzo IP privato dell'istanza del pool di worker registrata con Cloud DNS:

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

    Dovresti visualizzare l'output:

    Hello World!

Operazione riuscita. Hai configurato correttamente il pool di worker Cloud Run con l'ingresso VPC diretto utilizzando un indirizzo IP privato e Cloud DNS.

Libera spazio

Per evitare addebiti aggiuntivi al tuo Google Cloud account, elimina tutte le risorse di cui hai eseguito il deployment con questo tutorial.

Elimina il progetto

Se hai creato un nuovo progetto per questo tutorial, eliminalo. Se hai utilizzato un progetto esistente e devi conservarlo senza le modifiche aggiunte in questo tutorial, elimina le risorse create per il tutorial.

Il modo più semplice per eliminare la fatturazione è eliminare il progetto che hai creato per il tutorial.

Per eliminare il progetto:

  1. Nella Google Cloud console, vai alla pagina Gestisci risorse.

    Vai a Gestisci risorse

  2. Nell'elenco dei progetti, seleziona il progetto che vuoi eliminare, quindi fai clic su Elimina.
  3. Nella finestra di dialogo, digita l'ID progetto e fai clic su Chiudi per eliminare il progetto.

Elimina le risorse del tutorial

  1. Elimina il servizio Cloud Run di cui hai eseguito il deployment in questo tutorial. I servizi Cloud Run non comportano costi finché non ricevono richieste.

    Per eliminare il servizio Cloud Run, esegui questo comando:

    gcloud run services delete SERVICE-NAME

    Sostituisci SERVICE-NAME con il nome del tuo servizio.

    Puoi eliminare i servizi Cloud Run anche dalla Google Cloud console.

  2. Rimuovi la configurazione della regione predefinita di gcloud che hai aggiunto durante la configurazione del tutorial:

     gcloud config unset run/region
    
  3. Rimuovi la configurazione del progetto:

     gcloud config unset project
    
  4. Elimina le altre Google Cloud risorse create in questo tutorial:

Passaggi successivi