Cloud DNS を使用してワーカープールのプライベート IP アドレスを登録する

このチュートリアルでは、Cloud DNS マネージド ゾーン内に Cloud Run ワーカー プール インスタンスのプライベート IP アドレスを登録する方法について説明します。このチュートリアルでは、起動スクリプトを使用してメタデータ サーバーを介してインスタンス IP を動的に検出し、VPC ネットワーク内で上り(内向き)を直接処理する Node.js アプリケーションを作成します。

目標

費用

このドキュメントでは、課金対象である次の Google Cloudコンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。

新規の Google Cloud ユーザーは無料トライアルをご利用いただける場合があります。

始める前に

  1. Google Cloud アカウントにログインします。 Google Cloudを初めて使用する場合は、 アカウントを作成して、実際のシナリオでの Google プロダクトのパフォーマンスを評価してください。新規のお客様には、ワークロードの実行、テスト、デプロイができる無料クレジット $300 分を差し上げます。
  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. Cloud DNS、Cloud Run、Compute Engine、Artifact Registry、Cloud Build の各 API を有効にします。

    API を有効にするために必要なロール

    API を有効にするには、serviceusage.services.enable 権限を含む Service Usage 管理者 IAM ロール(roles/serviceusage.serviceUsageAdmin)が必要です。詳しくは、ロールを付与する方法をご覧ください。

    API を有効にする

  7. gcloud CLI をインストールして初期化します
  8. コンポーネントを更新します。
    gcloud components update
  9. 次のコマンドを実行して、プロジェクト ID を設定します。
    gcloud config set project PROJECT_ID
    PROJECT_ID は、 Google Cloud プロジェクトの ID に置き換えます。

必要なロール

チュートリアルを完了するために必要な権限を取得するには、プロジェクトに対する次の IAM ロールを付与するよう管理者に依頼してください。

ロールの付与については、プロジェクト、フォルダ、組織に対するアクセス権の管理をご覧ください。

必要な権限は、カスタムロールや他の事前定義ロールから取得することもできます。

カスタム サービス アカウントを作成する

DNS レコードを登録するために必要な最小限の権限を持つカスタム サービス アカウントを作成します。サービス アカウントを設定するには、次の操作を行います。

  1. 次のコマンドを実行してサービス アカウントを作成します。

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

    SERVICE_ACCOUNT_NAME は、カスタム サービス アカウントの名前に置き換えます(dns-worker-sa など)。

  2. サービス アカウントに Cloud DNS 管理者ロールを付与します。

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

Cloud DNS ゾーンの作成

test-wp という名前の限定公開 Cloud DNS マネージド ゾーンを作成して、ワーカープールのインスタンス IP を登録します。

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

Node.js アプリケーションを作成する

メタデータ サーバーを使用してワーカープール インスタンスの IP アドレスを取得し、Cloud DNS に登録する Node.js アプリケーションを作成します。

  1. worker という名前のフォルダを作成し、そのディレクトリに移動します。

    mkdir worker
    cd worker
    
  2. setup_dns.sh という名前のファイルを作成し、ワーカープール インスタンスの起動時に実行される次のスクリプトを追加します。このスクリプトは、インスタンスのホスト名を使用して DNS レコード名を生成します。インスタンスが複数ある場合、複数のインスタンスが同じホスト名を使用すると、重複する DNS レコードが作成されます。

    #!/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. 次のコードを含む server.js ファイルを作成して、プライベート IP アドレスの内向きトラフィックを処理します。

    // 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. 次のコードを含む start.sh スクリプトを作成して、Node.js アプリケーションを実行する前に DNS 設定を行います。

    #!/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. 次の Dockerfile を作成して、アプリケーションをイメージにパッケージ化します。

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

ダイレクト VPC 上り(内向き)を使用してワーカープールをデプロイする

test-cli-dns という名前のワーカープールをデプロイし、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

PROJECT_ID は実際の Google Cloud プロジェクト ID に、SERVICE_ACCOUNT_NAME は作成したサービス アカウントの名前に置き換えます。

アプリケーションをテストする

ダイレクト VPC 上り(内向き)を使用する Cloud Run ワーカープールは、内部専用トラフィック用に設計されています。パブリック IP はありません。上り(内向き)機能を確認するには、次の手順に沿って、同じ VPC ネットワークとサブネットでホストされている Compute Engine VM から curl を使用してリクエストを実行します。

  1. ワーカープールと同じネットワークとリージョンにテスト VM を作成します。

     gcloud compute instances create wp-test-vm \
         --zone=us-central1-a \
         --network=default \
         --subnet=default
    
  2. 次のコマンドを実行して、SSH 経由でテスト VM に接続します。

     gcloud compute ssh wp-test-vm --zone=us-central1-a
    
  3. VM ターミナルから、Cloud DNS に登録されているワーカー プール インスタンスのプライベート IP アドレスでサービスを呼び出します。

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

    次のような出力が表示されます。

    Hello World!

完了しました。プライベート IP アドレスと Cloud DNS を使用して、Direct VPC 上り(内向き)で Cloud Run ワーカープールを構成しました。

クリーンアップ

Google Cloud アカウントで追加料金が発生しないようにするには、このチュートリアルでデプロイしたすべてのリソースを削除します。

プロジェクトを削除する

このチュートリアル用に新規プロジェクトを作成した場合は、そのプロジェクトを削除します。既存のプロジェクトを使用し、このチュートリアルで行った変更を加えずに残す場合は、チュートリアル用に作成したリソースを削除します。

課金をなくす最も簡単な方法は、チュートリアル用に作成したプロジェクトを削除することです。

プロジェクトを削除するには:

  1. Google Cloud コンソールで [リソースの管理] ページに移動します。

    [リソースの管理] に移動

  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。

チュートリアル リソースの削除

  1. このチュートリアルでデプロイした Cloud Run サービスを削除します。Cloud Run サービスの費用は、リクエストを受け取るまでは発生しません。

    Cloud Run サービスを削除するには、次のコマンドを実行します。

    gcloud run services delete SERVICE-NAME

    SERVICE-NAME は、サービスの名前に置き換えます。

    Cloud Run サービスは Google Cloud コンソールで削除することもできます。

  2. チュートリアルの設定時に追加した gcloud のデフォルトのリージョン構成を削除します。

     gcloud config unset run/region
    
  3. プロジェクト構成を削除します。

     gcloud config unset project
    
  4. このチュートリアルで作成した他の Google Cloud リソースを削除します。

次のステップ