ダイレクト VPC 下り(外向き)を使用して内部の Cloud Run サービスにアクセスするように Cloud Run サービスを構成する方法

1. はじめに

概要

多くの組織では、サービスやアプリケーションのネットワーク トラフィックを保護するために、境界制御が可能な Google Cloud で Virtual Private Cloud(VPC)ネットワークを使用して、データの引き出しを防止しています。VPC ネットワークは、Google の本番環境ネットワーク内に仮想的に実装された物理ネットワークです。VPC ネットワークは、Compute Engine 仮想マシン(VM)インスタンスの接続を提供し、内部パススルー ネットワーク ロードバランサと内部アプリケーション ロードバランサのプロキシ システムをネイティブに提供します。また、Cloud VPN トンネルと Cloud Interconnect の VLAN アタッチメントを使用してオンプレミス ネットワークに接続し、Google Cloud の外部ロードバランサからバックエンドにトラフィックを分散します。

VM とは異なり、Cloud Run サービスはデフォルトでは特定の VPC ネットワークに関連付けられていません。この Codelab では、VPC からのトラフィックのみが Cloud Run サービス(バックエンド サービスなど)にアクセスできるように上り(内向き)(インバウンド接続)の設定を変更する方法について説明します。また、この Codelab では、2 つ目のサービス(フロントエンド サービスなど)が VPC を介してバックエンド Cloud Run サービスにアクセスする方法についても説明します。

この例では、バックエンドの Cloud Run サービスが hello world を返します。フロントエンドの Cloud Run サービスは、URL を収集するための入力フィールドを UI に提供します。次に、フロントエンド サービスがその URL(バックエンド サービスなど)に GET リクエストを送信します。これにより、ブラウザからサービスへのリクエストではなく、サービスからサービスへのリクエストになります。フロントエンド サービスがバックエンドに正常に到達すると、ブラウザに「hello world」というメッセージが表示されます。

学習内容

  • VPC から Cloud Run サービスへのトラフィックのみを許可する方法
  • 内部 Ingress 専用の Cloud Run サービスと通信するように Cloud Run サービスで下り(外向き)を構成する方法

2. 設定と要件

前提条件

Cloud Shell をアクティブにする

  1. Cloud Console で、[Cloud Shell をアクティブにする] d1264ca30785e435.png をクリックします。

cb81e7c8e34bc8d.png

Cloud Shell を初めて起動する場合は、その内容を説明する中間画面が表示されます。中間画面が表示された場合は、[続行] をクリックします。

d95252b003979716.png

すぐにプロビジョニングが実行され、Cloud Shell に接続されます。

7833d5e1c5d18f54.png

この仮想マシンには、必要な開発ツールがすべて用意されています。仮想マシンは Google Cloud で稼働し、永続的なホーム ディレクトリが 5 GB 用意されているため、ネットワークのパフォーマンスと認証が大幅に向上しています。この Codelab で行う作業のほとんどはブラウザから実行できます。

Cloud Shell に接続すると、認証が完了しており、プロジェクトに各自のプロジェクト ID が設定されていることがわかります。

  1. Cloud Shell で次のコマンドを実行して、認証されたことを確認します。
gcloud auth list

コマンド出力

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Cloud Shell で次のコマンドを実行して、gcloud コマンドがプロジェクトを認識していることを確認します。
gcloud config list project

コマンド出力

[core]
project = <PROJECT_ID>

上記のようになっていない場合は、次のコマンドで設定できます。

gcloud config set project <PROJECT_ID>

コマンド出力

Updated property [core/project].

3. Cloud Run サービスを作成する

環境変数を設定する

この Codelab 全体で使用する環境変数を設定できます。

REGION=<YOUR_REGION, e.g. us-central1>
FRONTEND=frontend
BACKEND=backend

バックエンドの Cloud Run サービスを作成する

まず、ソースコードのディレクトリを作成し、そのディレクトリに移動します。

mkdir -p internal-codelab/frontend internal-codelab/backend && cd internal-codelab/backend

次に、次の内容の package.json ファイルを作成します。

{
    "name": "backend-service",
    "version": "1.0.0",
    "description": "",
    "scripts": {
        "start": "node index.js"
    },
    "dependencies": {
        "express": "^4.18.1"
    }
}

次に、次の内容を含む index.js ソースファイルを作成します。このファイルには、サービスのエントリ ポイントとアプリのメインロジックが含まれています。

const express = require('express');

const app = express();

app.use(express.urlencoded({ extended: true }));

app.get('/', function (req, res) {
    res.send("hello world");
});

const port = parseInt(process.env.PORT) || 8080;
app.listen(port, () => {
    console.log(`helloworld: listening on port ${port}`);
});

最後に、次のコマンドを実行して Cloud Run サービスをデプロイします。

gcloud run deploy $BACKEND --source . --allow-unauthenticated --region $REGION

フロントエンドの Cloud Run サービスを作成する

フロントエンド ディレクトリに移動します。

cd ../frontend

次に、次の内容の package.json ファイルを作成します。

{
  "name": "frontend",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "start": "node index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "axios": "^1.6.6",
    "express": "^4.18.2"
  }
}

次に、次の内容を含む index.js ソースファイルを作成します。このファイルには、サービスのエントリ ポイントとアプリのメインロジックが含まれています。

const express = require("express");
const app = express();
const port = 8080;
const path = require('path');
const axios = require('axios');

// serve static content (index.html) using
// built-in middleware function in Express 
app.use(express.static('public'));
app.use(express.urlencoded({ extended: true }));

// this endpoint receives a URL in the post body
// and then makes a get request to that URL
// results are sent back to the caller
app.post('/callService', async (req, res) => {

    const url = req.body.url;
    let message = "";

    try {
        console.log("url: ", url);
        const response = await axios.get(url);
        message = response.data;

    } catch (error) {
        message = error.message;
        console.error(error.message);
    }

    res.send(`
        ${message}
        <p>
        </p>
    `);
});

app.listen(port, () => {
    console.log(`Example app listening on port ${port}`);
});

index.html ファイルの公開ディレクトリを作成する

mkdir public
touch public/index.html

また、index.html を更新して、次の内容を含めます。

<html>
  <script
    src="https://unpkg.com/htmx.org@1.9.10"
    integrity="sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC"
    crossorigin="anonymous"
  ></script>
  <body>
    <div style="margin-top: 100px; margin-left: 100px">
      <h1>I'm the Frontend service on the Internet</h1>
      <form hx-trigger="submit" hx-post="/callService" hx-target="#message">
        <label for="url"> URL:</label>
        <input
          style="width: 308px"
          type="text"
          id="url"
          name="url"
          placeholder="The backend service URL"
          required
        />
        <button hx-indicator="#loading" type="submit">Submit</button>
        <p></p>
        <span class="htmx-indicator" id="loading"> Loading... </span>
        <div id="message" style="white-space: pre-wrap"></div>
        <p></p>
      </form>
    </div>
  </body>
</html>

最後に、次のコマンドを実行して Cloud Run サービスをデプロイします。

gcloud run deploy $FRONTEND --source . --allow-unauthenticated --region $REGION

バックエンド サービスを呼び出す

2 つの Cloud Run サービスが正常にデプロイされたことを確認します。

ウェブブラウザでフロントエンド サービスの URL を開きます。

テキスト ボックスに、バックエンド サービスの URL を入力します。このリクエストは、ブラウザからではなく、フロントエンドの Cloud Run インスタンスからバックエンドの Cloud Run サービスにルーティングされます。

「hello world」と表示されます。

4. 内部上り(内向き)専用のバックエンド サービスを設定する

次の gcloud コマンドを実行して、VPC ネットワーク内からのトラフィックのみがバックエンド サービスにアクセスできるようにします。

gcloud run services update $BACKEND --ingress internal --region $REGION

バックエンド サービスが VPC からのトラフィックのみを受信できることを確認するには、フロントエンド サービスからバックエンド サービスの呼び出しをもう一度試します。

今回は「Request failed with status code 404」と表示されます。

このエラーは、フロントエンドの Cloud Run サービスのアウトバウンド リクエスト(下り(外向き))が最初にインターネットに送信されるため、Google Cloud がリクエストの送信元を認識できないことが原因で発生します。

次のセクションでは、VPC にアクセスするようにフロントエンド サービスを構成します。これにより、Google Cloud はリクエストが VPC から送信されたことを認識し、内部ソースとして認識します。

5. VPC にアクセスするようにフロントエンド サービスを構成する

このセクションでは、VPC を介してバックエンド サービスと通信するようにフロントエンド Cloud Run サービスを構成します。

これを行うには、フロントエンドの Cloud Run インスタンスにダイレクト VPC 下り(外向き)を追加して、VPC 内で使用する内部 IP をサービスに付与する必要があります。次に、フロントエンド サービスからのすべてのアウトバウンド接続が VPC に送信されるように下り(外向き)を構成します。

まず、次のコマンドを実行してダイレクト VPC 下り(外向き)を有効にします。

gcloud beta run services update $FRONTEND \
--network=default \
--subnet=default \
--vpc-egress=all-traffic \
--region=$REGION

これで、フロントエンド サービスが VPC にアクセスできることを確認できます。

gcloud beta run services describe $FRONTEND \
--region=$REGION

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

VPC access:
    Network:         default
    Subnet:          default
    Egress:          all-traffic

フロントエンド サービスからバックエンド サービスを再度呼び出してみます。

今回は「hello world」と表示されます。

注: すべての下り(外向き)が VPC に転送されているため、フロントエンド サービスはインターネットにアクセスできません。たとえば、フロントエンド サービスが https://curlmyip.org/ にアクセスしようとすると、タイムアウトします。

6. 完了

以上で、この Codelab は完了です。

Cloud Run のドキュメントと、Cloud Run サービスのプライベート ネットワーキングを構成する方法を確認することをおすすめします。

学習した内容

  • VPC から Cloud Run サービスへのトラフィックのみを許可する方法
  • 内部 Ingress 専用の Cloud Run サービスと通信するように Cloud Run サービスで下り(外向き)を構成する方法

7. クリーンアップ

誤って課金されないようにするには(たとえば、Cloud Run サービスが誤って 無料枠の Cloud Run 呼び出しの月間割り当てよりも多く呼び出された場合など)、Cloud Run を削除するか、ステップ 2 で作成したプロジェクトを削除します。

Cloud Run サービスを削除するには、https://console.cloud.google.com/run で Cloud Run Cloud Console に移動し、$FRONTEND サービスと $BACKEND サービスを削除します。

プロジェクト全体を削除する場合は、https://console.cloud.google.com/cloud-resource-manager に移動し、ステップ 2 で作成したプロジェクトを選択して、[削除] を選択します。プロジェクトを削除した場合は、Cloud SDK でプロジェクトを変更する必要があります。gcloud projects list を実行すると、使用可能なすべてのプロジェクトのリストを表示できます。