はじめに
こちらは バイセルテクノロジーズ Advent Calendar 2023 の6日目の記事です。 昨日は馬場さんによるCloud Run ジョブのオーバーライドで実現した単発処理群管理のための快適な環境でした。
こんにちは。開発2部の小松山です。
2023/08/14にCloud RunからVPCネットワークに直接トラフィックを送信できる機能 (以後Direct VPC Egressと表記) がプレビュー版でリリースされました。
私の所属するプロジェクトではAPIサーバを構築するのにCloud Runを大いに活用しており、VPC接続が必要な通信経路も存在していました。この機能を使えば、VPCへの接続のためにサーバレスVPCアクセスコネクタを経由していた部分を置換できるのではないかと考え、費用削減を目的に使ってみることにしました。しかし、結果的に置換することの目的を果たすことができず見送った、という話を書きます。
Direct VPC Egress について
機能の概要と導入メリット
前述の通り、Direct VPC EgressとはCloud Runからの外向きの通信をダイレクトにVPCネットワークを経由するようにしてくれる機能です。Cloud RunからVPCを経由してアクセスする従来の方法は、VPCネットワークへ接続をプロキシするための「サーバレスVPCアクセスコネクタ」を使うことでした (以後VPCコネクタと表記)。
VPCコネクタは内部的にはGCEインスタンスが数台動いているため、メトリクスの監視が必要な点、常時課金の対象となってしまう点、スループットがマシンスペックに依存してしまう点、スケールインを手動で行う必要がある点などのデメリットがありました。
上記Google公式のブログではDirect VPC Egressを使うことのメリットが下記のように紹介されています。
ネットワーク パス内のホップが減少し、レイテンシが低減されます。
新たなダイレクト ネットワーク パスが使われるため、スループットが向上します。
従量課金制 - ネットワーク料金のみ(常時有効化されるコネクタ インスタンスが不要)。
この中で私達にとって魅力的だったのは料金の部分です。常時課金対象となっていたVPCコネクタをDirect VPC Egressに置換し、コスト削減を試みました。低レイテンシ・高スループットとなる点もメリットとしては大きいですが、この機能がプレビュー版ということもあり検証環境のみでの利用を考えていたため、こちらはあまり気にしていませんでした。
制約事項
Direct VPC Egressは以下のような制約事項があります。
- サポートされるCloud Runサービスのインスタンスは最大100個
- サポートされるリージョンが限られている
- 東京リージョン (asia-northeast1) はサポート対象内です!
- トラフィックを流すサブネットのレンジにある程度余裕がないといけない
- NATが使えない
- VPC内部からインターネットとの通信ができない
これらの制約事項はプレビュー版時点での情報ですので、今後緩和される可能性があります。適宜公式ドキュメントをご確認ください。
プロジェクトのシステム構成
私のプロジェクトの簡易的なシステム構成は下記のとおりです。本記事に関係がありそうな部分のみを抜粋しています。
私のプロジェクトでは Hasura というオープンソースのGraphQLサーバを使っています。また、HasuraのRemote Schemasとして gqlgen を使ったGoのGraphQLサーバがあります。「そもそもHasuraとは?」という方は紹介記事がたくさん上がっていますのでそちらをご覧ください。テックブログにも関連記事が上がっています。(Hasuraについて詳しく知らなくとも本記事の趣旨は理解可能かと思います。)
HasuraとRemote SchemasはCloud Run上でホスティングされており、VPC経由で疎通をしています。Cloud Run同士の疎通をVPC経由にしているのは、Remote Schemasのインスタンスを公開したくなかったためです。Hasuraは公式が提供するイメージをそのまま動かしているので、自分でコードを書くことができません。そのためサービスアカウント認証情報を含めたリクエストができず、IAM認証によるアクセス制限をやっていません。
上記構成の中のHasuraとRemote Schemasの間のVPCコネクタをDirect VPC Egressに置換することを目標にしました。
Direct VPC Egress を使ってみる
素直に Direct VPC Egress を有効にしただけではうまくいかなかった
まずは素直にDirect VPC Egressを有効にしてみます。Cloud Runのリビジョンの編集画面の「ネットワーキング」のタブから外向きのトラフィックオプションを変更します。従来のようにVPCコネクタを使うかDirect VPC Egressを使うかを選択できます。Direct VPC Egressを使用することを選択すると、トラフィックを流す対象のサブネットの選択が可能になります。
構成図にある通り、HasuraはVPC外部のWebhook URLを叩けるようにする必要があります。そのため「トラフィック ルーティング」のオプションを「プライベートIPへのリクエストのみをVPCにルーティングする」を選択しました。
期待するのは以下のように、VPC内のリソースとCloud RunへのアクセスをVPCを経由してくれることでした。
しかし、実際は下記のような挙動となってしまいました。HasuraからRemote Schemasへアクセスすると、内向きのトラフィックの制限に弾かれRemote Schemasへアクセスできなくなってしまいました。
こうなってしまうのはCloud Runの発行するドメイン (https://*-an.a.run.app
) がグローバルIPに紐づいておりVPCを経由してくれていないためです。これは内向きトラフィックの制限をかけている場合、いない場合にかかわらず同じです。
Cloud Run 同士が内部 IP で疎通できるようにする
素直にVPCコネクタをそのままDirect VPC Egressに置き換えることはできませんでした。ルーティングオプションを「すべてのトラフィックをVPCにルーティング」にしてしまうと、Remote Schemasへの疎通はできるようになりますが、インターネットとの通信ができなくなります (構成図中のWebhookの部分です)。制約事項
の章でもお伝えしたとおり、現状Direct VPC Egressを使った場合ではNATが利用できないため、プライベートネットワークから外に出るためのグローバルIPの付与ができないためです。
以上を踏まえると、ルーティングオプションは「プライベートIPへのリクエストのみをVPCにルーティング」一択でした。この場合はHasuraからRemote Schemasの疎通をプライベートIP使ってできるようにする必要があります。そこで、Remote Schemasの前段に内部アプリケーションロードバランサ (以後内部LBと表記) を立てることにしました。
上記ドキュメントに従ってバックエンドサービスにRemote Schemasを持つ内部LBを構成します。
これでプライベートIPを使ってHasuraからRemote Schemasへの疎通が可能になりました。
Direct VPC Egress 使用前後の料金の比較
VPCコネクタからDirect Egressへの乗り換えは、CloudRun同士の接続部に内部LBを使うことで実現できました。内部LBの利用によって課金は発生するため、VPCコネクタを継続利用する場合との比較をしてみます。
VPC コネクタを継続利用した場合の料金
VPCコネクタの利用料金は、VPCコネクタに用いられるGCEインスタンスの料金と、VPC内部への下りトラフィック量の合算値です。
今回切り替えを行った環境は検証環境であり、開発者も大量にいるわけではないため、発生するトラフィック量は無視できる値でした。そのためGCEインスタンスの稼働による料金のみを考えます。インスタンスのスペックは最小構成で十分なので、f1-micro
を選択しています。
f1-micro
1 台あたりの料金は 0.0092 $/時間 です。VPCコネクタの最小インスタンス数は2台なので、最小構成での料金は以下のように算出できます。
0.0092 * 24時間 * 30日 * 2台 ≒ 13.25 $/月
こちらに Compute Engine の継続利用割引を加えると約10 $/月ほどとなります。
また、VPCからインターネットに出ていくためのCloud NATの料金も考慮します。NATの料金はNATゲートウェイの稼働時間とNATで処理されるデータ量によって決まります。
こちらも同様にネットワーク料金は無視して計算します。稼働時間あたりの料金は接続されるVMインスタンス1台につき0.0014 $/時間かかります。VPCコネクタ最小構成の場合、以下のように算出ができます。
0.0014 * 24時間 * 30日 * 2台 ≒ 2 $/月
VPC コネクタの利用料金と合算すると 約12 $/月 ほどとなります。
Direct VPC Egress と内部 LB を利用した場合の料金試算
Direct VPC Egressを利用する場合にかかるのは通常のCloud Runの料金に加えて、VPC内部への下りネットワーク量 (VPCコネクタ利用と同じ) のみです。お得ですね。
内部LBの料金は少々複雑なため要点を絞って紹介します。詳細は公式ドキュメントをご確認ください。
こちらのドキュメントには下記のような記載がありました。
ロードバランサは、トラフィックのニーズに基づき、トラフィックを処理するために必要なプロキシの数を自動的にスケーリングします。プロキシ インスタンスの料金は、トラフィックのニーズを満たすために必要なプロキシ インスタンスの数に基づきます。プロキシが追加されるごとに、上記の表に記載された 1 時間あたりの料金に従い、追加で課金されます。
LBを作成する際に明示的にインスタンス作成等は行っていませんが、内部的には「プロキシ インスタンス」なるものが立ち上がっているようです。立ち上がったプロキシインスタンス1台につき1時間単位での課金がされます。また、最低インスタンス数について下記のように記載がありました。
最適なパフォーマンスと信頼性を確保するため、各ロードバランサには、ロードバランサがデプロイされる Google Cloud リージョン内の少なくとも 3 つのプロキシ インスタンスが割り当てられます。これらのプロキシ インスタンスは、ロードバランサがトラフィックを処理しない場合でも割り振られます。 ... ロードバランサには 3 つのプロキシ インスタンスが最低で割り振られ、これにより 1 時間あたりのプロキシ インスタンスの最低料金が決まります。たとえば、us-central1 Google Cloud リージョンの場合、最低料金は次のように計算されます。
3 proxy instances * $0.025 per proxy per hour = $0.075 per hour
なんとプロキシインスタンスは常時3台以上稼働する仕様となっているようです。ドキュメントの例ではus-central1の計算式が書かれていますが、asia-northeast1 (東京リージョン) の場合でも単価は同じ0.025 $/時間となっています。そのため内部LBのプロキシインスタンスに対する最小料金は以下のように算出できます。
0.025 * 24時間 * 30日 * 3台 = 54 $/月
私のプロジェクトの場合、VPCコネクタの利用料金は約12 $/月ほどだったので、内部LBを使うほうが約40 $/月ほど安いです。実はVPCコネクタを継続利用するほうが料金は低く抑えられる、という結論になってしまいました。
ちなみにVPCコネクタのスペックはf1-micro
、e2-micro
、e2-standard-4
から選択可能ですが、GCEの料金だけで内部LBの料金より高くなるのはe2-standard-4
からでした。e2-micro
の想定スループットが200~1,000Mbps程度とのことなので、これを超えるトラフィックを伴う場合はDirect VPC Egressの利用検討を行うことができそうです。
まとめ
Direct VPC Egressを早速使ってみましたが、Cloud Run同士を疎通させたい かつ 一方が自分でコードを書けないコンテナであったことが要因で、結局採用を見送ってしまいました。NATを使えるようになれば、私のプロジェクトのようなケースでもVPCコネクタを置き換えることができるかもしれません。
今回は採用に至りませんでしたが、Direct VPC Egressはとても便利な機能です。NATが必要ない場合、VPCコネクタがボトルネックになっている場合などは前向きに利用を検討してみてはいかがでしょうか。記事執筆時点ではDirect VPC Egressはプレビュー版ですが、今後のGA等のアップデートでより強力な機能となることを期待します。
最後にBuySell Technologiesではエンジニアを募集しています。興味がある方はぜひご応募ください!
明日は那仁さんによる運用プロダクトのDataflowをBigQueryサブスクリプションに移行した話です。お楽しみに。