G-gen の佐々木です。当記事では、Cloud Run からインターネットアクセスを行う際に使用されるパブリック IP アドレスを固定する方法を解説します。
Cloud Run から Cloud NAT を使用してインターネット接続を行う
はじめに
当記事の内容は Cloud Run service、Cloud Run jobs の両方を対象としているため、それぞれを区別せずに「Cloud Run」と記載しています。
なお、当記事で解説する手順では Cloud Run services を使用しています。
サーバーレス VPC アクセスを使用する方法
Cloud Run では、コンテナインスタンスを起動する際にパブリック IP アドレスが動的に割り当てられ、インターネットにアクセスする場合はこの動的 IP アドレスが使用されるようになっています。
Cloud Run でインターネットアクセスに使用するパブリック IP アドレスを固定したい場合、静的 IP アドレスを紐付けた Cloud NAT を経由してインターネットアクセスを行うように設定する必要があります。
従来の方法では、Cloud NAT が存在する VPC にサーバーレス VPC アクセスを構成し、サーバーレス VPC アクセスコネクタを使用して Cloud Run から VPC に接続する必要がありました。
サーバーレス VPC アクセスを使用する方法については、以下の記事で詳細な手順を解説しています。
Direct VPC Egress を使用する方法(当記事で解説)
2024年3月に Direct VPC Egress で Cloud NAT が使用できるようになったことで、サーバーレス VPC アクセスを構成することなく、Cloud Run が使用するパブリック IP アドレスを固定できるようになりました。
Direct VPC Egress では、サーバーレス VPC アクセスとは異なり、常時起動のコネクタインスタンスを経由する必要がないため、より安価かつ高速に VPC に接続することができます。
Direct VPC Egress の解説、およびサーバーレス VPC アクセスとの詳細な比較については、以下の記事をご一読ください。
手順
シェル変数の設定
当記事では gcloud コマンドを使用して各種リソースを作成していきます。
コマンド内で何度か使用する値は、以下のようにシェル変数として設定しておきます。
PROJECT
変数の値にはリソースを作成するプロジェクトを、LOCATION
変数の値にはリージョンを設定してください。残りの変数は各種リソースの名前を指定する際に使用します。
PROJECT=myproject LOCATION=asia-northeast1 NETWORK=vpc-direct-vpc-egress SUBNET=subnet-direct-vpc-egress ROUTER=router-direct-vpc-egress ADDRESS=address-direct-vpc-egress NAT=nat-direct-vpc-egress
VPC とサブネットの作成
Cloud Run から接続する Cloud NAT を配置するための VPC を作成します。
# VPC の作成 $ gcloud compute networks create ${NETWORK} \ --project=${PROJECT} \ --subnet-mode=custom
作成した VPC にサブネットを作成します。Cloud Run から Direct VPC Egress を使用して VPC に接続する際、このサブネットに設定された IP アドレス範囲の IP アドレスが使用されます。
# サブネットの作成 $ gcloud compute networks subnets create ${SUBNET} \ --project=${PROJECT} \ --network=${NETWORK} \ --range=192.168.101.0/24 \ --region=${LOCATION}
サブネットのアドレス範囲は、最低でも /28
の CIDR 範囲で指定する必要があります。
Cloud Run がスケールアウトすると、ここで指定したアドレス範囲の IP アドレスが消費されます。使用できる IP アドレスが枯渇していると Cloud Run のスケールアウトが阻害されてしまうため、サブネットには十分なアドレス数を確保するようにアドレス範囲を設定する必要があります。
アドレス数の目安は、Cloud Run に設定された最大コンテナインスタンス数の4倍となっています。また、Cloud Run jobs を使用する場合は少なくとも1,024個の IP アドレスを確保しておく必要があります。
Cloud NAT の作成
作成した VPC に Cloud NAT を作成していきます。Cloud NAT は VPC 内の Cloud Router に関連付ける必要があるため、Cloud Router を先に作成しています。
# Cloud Router の作成 $ gcloud compute routers create ${ROUTER} \ --project=${PROJECT} \ --network=${NETWORK} \ --region=${LOCATION} # Cloud NAT 用のパブリック IP アドレスを予約 $ gcloud compute addresses create ${ADDRESS} \ --region=${LOCATION} # Cloud NAT の作成 $ gcloud compute routers nats create ${NAT} \ --router=${ROUTER} \ --region=${LOCATION} \ --nat-all-subnet-ip-ranges \ --nat-external-ip-pool=${ADDRESS}
Cloud Run サービスのデプロイ
使用するコード
当記事では Cloud Run のクイックスタートのサンプルコードをベースに、Cloud Run のコンテナインスタンスがインターネットアクセスに使用している IP アドレスをブラウザ上に表示するだけの Web アプリケーションを実装します。
インターネットアクセスに使用している IP アドレスは「https://inet-ip.info/ip」から取得します。
// main.go package main import ( "fmt" "log" "net/http" "os" ) func main() { log.Print("starting server...") http.HandleFunc("/", ipCheck) // Determine port for HTTP service. port := os.Getenv("PORT") if port == "" { port = "8080" } // Start HTTP server. log.Printf("listening on port %s", port) if err := http.ListenAndServe(":"+port, nil); err != nil { log.Fatal(err) } } // インターネットアクセスに使用される IP アドレスを確認する func ipCheck(w http.ResponseWriter, r *http.Request) { // https://inet-ip.info/ip にアクセスし、自身の IP アドレスを取得する resp, err := http.Get("https://inet-ip.info/ip") if err != nil { log.Fatal(err) } defer resp.Body.Close() // レスポンスボディを読み込む buf := make([]byte, 32) n, err := resp.Body.Read(buf) if err != nil { log.Fatal(err) } // ブラウザに IP アドレスを表示する fmt.Fprintf(w, string(buf[:n])) }
ソースコードから Cloud Run をデプロイする
main.go
と go.mod
ファイルがあるディレクトリで以下のコマンドを実行し、Cloud Run サービスをデプロイします。
# Cloud Run サービスのデプロイ $ gcloud run deploy ipcheck \ --source . \ --project=${PROJECT} \ --region=${LOCATION} \ --network=${NETWORK} \ --subnet=${SUBNET} \ --vpc-egress=all-traffic \ --allow-unauthenticated
このデプロイコマンドでは、Cloud Run で Direct VPC Egress を使用するために、以下のフラグを使用しています。
フラグ | 設定する値 | 説明 |
---|---|---|
--region | VPCの名前 | Direct VPC Egress で接続する VPC の名前を指定する。 |
--subnet | サブネットの名前 | Direct VPC Egress で接続する VPC のサブネットの名前を指定する。 |
--vpc-egress | all-trafic |
すべての Egress トラフィックを VPC で送信する場合 all-trafic を指定する。プライベート IP アドレスへの通信のみ VPC 経由にしたい場合は private-ranges-only を指定する。(参考) |
Cloud Run からのインターネットへのアクセスを Cloud NAT 経由にする場合、--vpc-egress
フラグの値は必ず all-trafic
を指定します。
ここでprivate-ranges-only
を指定した場合、インターネットへのアクセスには Cloud Run インスタンスの動的なパブリック IP アドレスが使用されてしまいます。
なお、コンソールから Direct VPC Egress を設定する場合は、以下のスクリーンショットのように設定します。
動作確認
gcloud コマンドによる Cloud Run サービスのデプロイが完了すると、標準出力のService URL:
の行にサービスの URL が表示されています。
Building using Buildpacks and deploying container to Cloud Run service [ipcheck] in project [myproject] region [asia-northeast1] ✓ Building and deploying new service... Done. ✓ Uploading sources... ✓ Building Container... Logs are available at [https://console.cloud.google.com/cloud-build/builds/2aa331ab-11aa-46bd-976b-xxxxxxxxxxxx?project=xxxxxxxxxxxx]. ✓ Creating Revision... ✓ Routing traffic... ✓ Setting IAM Policy... Done. Service [ipcheck] revision [ipcheck-00001-k2j] has been deployed and is serving 100 percent of traffic. Service URL: https://ipcheck-ai4xxxxxxx-an.a.run.app
ブラウザでサービスの URL にアクセスすると、Cloud Run のコンテナインスタンスが起動し、コンテナインスタンスがインターネットアクセスに使用した IP アドレスが表示されます。
ブラウザに表示された IP アドレスが、Cloud NAT に設定された静的パブリック IP アドレスと一致するかを確認します。
以下のコマンドを使用するか、コンソール上で Cloud NAT の IP アドレスを確認します。
# Cloud NAT に紐づけた静的パブリック IP アドレスを確認 $ gcloud compute addresses describe ${ADDRESS} | head -n 1
佐々木 駿太 (記事一覧)
G-gen最北端、北海道在住のクラウドソリューション部エンジニア
2022年6月にG-genにジョイン。Google Cloud Partner Top Engineer 2024に選出。好きなGoogle CloudプロダクトはCloud Run。
趣味はコーヒー、小説(SF、ミステリ)、カラオケなど。
Follow @sasashun0805