
Google Cloudで複数のネットワークインターフェースを使う際に押さえておきたいポイント
1つのグローバルIPと多数のバックエンドサービス(VM、Kubernetes pod、Cloud Functionsインスタンスなど)を組み合わせたGoogle CloudのLoad Balancerは、今日アプリケーションをインターネットに公開する代表的な手段です。特に必要なのが昔ながらのHTTP(S)だけであれば、すべてを束ねる1つのIPアドレスがあれば事足ります。
とはいえ、特殊な、あるいは_従来型_とでも呼ぶべき構成で、1台のVMに複数のIPでトラフィックを受けさせたいケースもときには出てきます。多くはTCPプロトコル経由になりますが、典型例としてすぐ思い浮かぶのは、IPベースのHTTPバーチャルホスティングでしょう。
つまるところ「GCPのVMに複数のIPを持たせるにはどうすればいいか?」という問いに行き着きます。Webで検索すれば、たいていは「複数のネットワークインターフェースを持つGCP VM」という方向にたどり着くはずです。この方法は公式ドキュメントのとおりに動作します — VMの各ネットワークインターフェースカード(NIC)に外部IPを1つずつ割り当てる、というやり方です。ただし、いくつかの制約に注意が必要です:
- NICごとに別々のVPCネットワークが必要。これ自体は問題ではありませんが、相応のDevOps作業が伴います。VPCを作成してIPレンジが重ならないように設計するだけでなく、VPCごとにファイアウォールルールも設定しなければなりません。
- 1台のVMにつきNICは最大8個まで。 用途次第で十分なこともあれば、足りないこともあります。
- VM作成後にNICの数は変更不可。 5個のIPで運用を始め、後から1個追加したくなった場合は、VMを_作り直す_必要があります。
- vCPU数はNIC数以上でなければならない。ここがコスト面で一気に重くのしかかってきます。実際のトラフィック処理にはvCPU 1〜2個で十分でも、IPを8個使いたいなら8 vCPUのマシン代を払い続けることになります。
ちょっとした裏技を紹介しておきます — まず8 NIC構成の8 vCPU VMを作成し、いったん停止してマシンタイプをダウンサイズしてから起動し直す、という方法です。GCPがいつこの抜け穴を塞ぐかわからないので、利用は自己責任で。
Forwarding rules
より安く、より素直な選択肢が転送ルール(forwarding rules)です。GCPのネットワークはすべてソフトウェア定義であり、VMが勝手にIPを取得してARP応答で広告するようなことはできません — そもそもARPはほとんど使われていません。localhost宛て以外は、すべてデフォルトゲートウェイ経由になります。同じVPC内の「お隣」VMへのトラフィックですら、デフォルトゲートウェイを通ります。
me@my-vm:~$ ip route showdefault via 10.128.0.1 dev ens410.128.0.1 dev ens4 scope linkそこで「もっと多くのIPでトラフィックを受け取りたい」とGCPに「伝える」必要があり、その「伝達手段」が転送ルールです。
GCPの転送ルールは非常に柔軟で、IP・ポート・プロトコル・HTTPホスト&パスを任意に組み合わせて待ち受けし、マッチしたトラフィックをVM、VMプール、Cloud Storageバケット、Cloud Function、Kubernetesサービスなどのターゲットに転送できます。
転送ルールには費用がかかります。詳しくは後述します。
今回必要なのは最もシンプルな形 — tcp:address:portで待ち受けし、すべてのトラフィックを単一のターゲットインスタンスに転送するだけです。
最もシンプルな形の転送ルール
GCPのドキュメントには、設定方法を解説した良質かつ非常に長い記事があります。GCPではこの方式をProtocol Forwardingと呼んでおり、UIコンソールからの操作はほぼサポートされていません。デフォルト以外のリージョンで構築する場合は、各コマンドで指定するリージョンとゾーンを取り違えないよう、細心の注意が必要です(詳しい手順を読みたい方はコメントでお知らせください)。
幸い、UIから手軽に設定する方法もあります。
まずはIPをいくつか確保しましょう:

注意: IPはリージョナルで取得し、ターゲットVMと同じリージョンに置いてください。
UIには、未使用の静的外部IPは使用中のものより料金が高くなる旨の警告が出ますが、これはすぐに解消されます。
次にVMを作成します — australia-southeast1リージョンに「au-vm」という名前で立ててみましょう。「HTTPトラフィックを許可する」にチェックを入れるか、対象ポートのTCPを通すファイアウォールルールを設定するのを忘れないでください。
続いて転送ルールの設定に進みます。Network ServicesメニューからLoad Balancingを選び、新規TCPロードバランサーの設定を開始します。「インターネットからVMへ」「単一リージョンのみ」「ターゲットプールまたはターゲットインスタンス」というデフォルト値が、ちょうど今回の用途にぴったりです。
ロードバランサーに名前を付けたら、Backend configurationセクションで既存のau-vmインスタンスを選択します。

ターゲット側の設定はこれで完了です。次に「Frontend configuration」をクリックして「待ち受け」側を設定し、確保しておいたIPをすべて追加します。
先ほど確保したIPを、すべてポート80で待ち受けるよう追加したところ
「作成」をクリックすれば完了です。オンラインになるまで数分待てば、これでVMは上記3つのIPすべてからトラフィックを受け取れるようになります。うまく動かない場合は、必要なポートを通すファイアウォールルールが設定されているか確認してください。
ロードバランサーは後からいつでも編集して、IPを追加・削除できます。
VM上のプロセスは、Linuxのネットワークインターフェース上に明示的に設定されていないように見えるアドレスでも(ip address showでは確認できません)、目的のIPアドレスにバインドできます。例えば次のコマンドが問題なく動作します:
nc -s 34.87.204.138 -l -p 80このカラクリの正体は、マシン上で動作するGCPのデーモンです。対象の宛先アドレス向けのパケットを受け取れるよう、Linuxのルーティングを次のように構成してくれています:
me@au-vm:~$ ip route show table all...local 34.87.204.138 dev ens4 table local proto 66 scope hostlocal 34.87.228.28 dev ens4 table local proto 66 scope hostlocal 34.116.108.163 dev ens4 table local proto 66 scope host...気になるお金の話
転送ルールは申し分なく動作し、この課題に対する素直な解にも思えます。ただし、無料ではありません。
Googleは最初の5ルールについて、一律$0.025/時間を課金します — つまりルールが1個でも5個でも、合計$0.025/時間という同額になります。6個目以降の転送ルールは1個あたり$0.01/時間。したがって、1台のVMに10個のIPを1か月間用意するだけで、転送ルールだけで$55/月かかる計算です。
残念ながら、話はこれで終わりません。少し前からGCPは、使用中の外部IPにも課金するようになりました(IPの利用先がVMか転送ルールかは問いません)。1IPあたり$0.004/時というと一見些細ですが、$0.004*730時間=$2.92/月となり、今回のように10個のIPを掛け合わせると、VMに10個のIPをルーティングするための合計コストは:
$55 + $29.2 ≒ $85/月 — VM代を払う前に、IPだけでこの金額になります
これが高いか安いかは、皆さまのご判断にお任せします :-)
お読みいただきありがとうございました! 最新情報は DoiT Engineering Blog 、 DoiT Linkedin Channel 、 DoiT Twitter Channel でフォローしてください。採用情報は https://careers.doit.com をご覧ください。