AWSとGCPのマルチクラウドインフラにおけるVPN設計のポイント

みなさん、ごきげんよう。プレイドの@tik-sonと申します。

前回のエントリーでは、
弊社のKARTEで、インフラにはAWSGCPの2つのクラウドプラットフォームを組み合わせ、マルチクラウドインフラとして利用しているというお話をいたしました。
今回のエントリーではその中から、「AWSとGCPをVPNで接続した」内容についてフォーカスして

  • 各クラウドプラットフォームでのVPNの仕様
  • KARTEではどのようなVPN設計にしているのか

等をお話したいと思います。

目次

  • VPNを用いる理由
  • AWSとGCPのSubnetの違い
  • VPNを接続する
  • 可用性を考える
  • パフォーマンスを考える
  • VPN周りの設計について
  • 悩まされたこと
  • 最後に

VPNを用いる理由

前回のエントリーで、マルチクラウドインフラの要件として 「各クラウドプラットフォームのサーバが相互に通信できる」 と記載しましたが、私達はその実現方法としてVPNを選択しました。
VPNであればプライベートネットワークを拡張する形になるので
既存のAWSのネットワーク構成変更を少なく、GCPのサーバとセキュアに通信ができるようにすることができるからです。

もちろんサーバにグローバルIPアドレスを持たせて直接通信させる案も考えましたが、

  • 外部に対して通信できるように新たにポートを空けなければならない
  • 通信を暗号化しなければならない

など考慮しなければいけないポイントが多くでてきてしまい、実装まで時間がかかりそうだったため、今回は選択しませんでした。

AWSとGCPのSubnetの違い

はじめにVPNにて利用するSubnetにおけるAWSとGCPの違いについて軽くお話をします。

AWSのSubnet

AWSでプライベートなネットワークを作る時はVPCという機能を使います。1つのVPCの中に最大 /16 のネットマスクのプライベートネットワークを定義でき、そのプライベートネットワークの中で更にSubnetを切っていくことができます。

`https://cloud.google.com/compute/docs/networking#subnet_network`

GCPのSubnet

GCPではAWSのVPCのようなサービスとして定義はされていないのですが、以下の図のように1つのGCP Networkという単位の中に様々なSubnetを作成することができます。
例えば、10.240.0.0/24192.168.1.0/24 を1つのGCP Networkを共存させることができ、それぞれのSubnetは特に設定不要で相互通信が可能になります。
GCPの方がAWSより柔軟にSubnetを作れるようです。
ただし、Subnetは柔軟に作れますが、 GCP Network上で稼働させるインスタンスの台数制限はデフォルトだと7000台 だということ は注意しなければなりません。(なかなかその上限に引っかかることは無いと思いますが)

https://cloud.google.com/compute/docs/networking#subnet_network

VPNを接続する

VPNには色々な種類がありますが、今回使用するVPNはAWS、GCPが共にサポートしているIPsecVPNになります。

AWSとGCPをVPN接続する際の詳細な手順については
クラスメソッドさんの記事に記載されているので参考にさせていだきました。少し古い記事になりますが、流れとしてはほとんど変わっていないので、こちらとあわせて
AWSのドキュメント
GCPのドキュメント
を参考にしていただければ、特につまることなくVPN接続が出来るかと思います。
記事内でも紹介されていますが、VPN接続の設定順番が重要になってきます。
また、この記事の記載後にGCEのネットワークの機能が拡張されたことで、現在はVPN接続を定義したリージョン以外のインスタンスからもVPN接続を利用できるようになっています。

可用性を考える

本番環境で運用する上で可用性を考えないわけにはいきません。
VPNトンネルが1つしかない状態でそのVPNトンネルが切断されてしまうとどうなるでしょうか?
答えは簡単でAWS、GCP間で通信ができなくなるというクリティカルな問題が発生してしまいます。
したがってVPNを冗長化 することはとても大切です。

AWSでは1VPN設定に対して、2VPNトンネル、GCPでは1VPN設定に対して1VPNトンネルが提供されます。
GCP、AWS共に2VPN設定ずつ用意し、以下の図のように構成を組むことで、冗長構成を取ることができます。

http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/VPC_VPN.html#VPNConnections

尚、どちらのプラットフォームにおいても、それぞれのゲートウェイで同じルーティングを設定しておけば、片方のトンネルが落ちてしまった時に残りのトンネルを利用してくれるようになります。

GCP

Cloud VPN ゲートウェイは、ピア VPN ゲートウェイが停止して一方の VPN トンネルが使用できなくなっても、もう一方の VPN トンネルを使用し続けます。停止した VPN トンネルが復帰すると、また自動的に両方のトンネルを使用しますhttps://cloud.google.com/compute/docs/vpn/advanced#redundancy_and_failover

AWS

AWS はときどき、仮想プライベートゲートウェイに対して定期的にメンテナンスを実行します。このメンテナンスによって VPN の 2 つのトンネルのうち 1 つが短時間無効になることがあります。このメンテナンスの実行中、VPN 接続は自動的に 2 番目のトンネルにフェイルオーバーします。サービスが中断されないようにするために、両方のトンネルを設定することが重要です。
http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/NetworkAdminGuide/Introduction.html#CustomerGateway

カスタマーゲートウェイが使用できなくなった場合に接続が失われるのを防ぐために、2 番目のカスタマーゲートウェイを使用して、VPC および仮想プライベートゲートウェイへの 2 番目の VPN 接続を設定できます。冗長な VPN 接続とカスタマーゲートウェイを使用すれば、1 つのカスタマーゲートウェイでメンテナンスを実行しながら、2 番目のカスタマーゲートウェイの VPN 接続を通してトラフィックの送信を継続することができます。
http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/VPC_VPN.html#VPNConnections

ちなみにGCPはVPNのSLAが定義されていますが、AWSにはSLAの記述がないようです。
また、GCPにもSLAはありますがGoogleのコントロール外の部分(インターネット等)による問題については保証されていない点については意識しておかなくてはいけません。

パフォーマンスを考える

もちろん本番環境で運用する上では可用性だけではなくパフォーマンスも考えないわけにはいきませんよね。ということで話をします。

VPNのスループット

各プラットフォームは以下の通りスループットについて説明があり、まとめると以下の通りです。

  • AWSでは仕様上、スループットの制限は特にない
  • GCPは仕様上、VPN ゲートウェイごとに1.5 Gbpsまでのスループットのサポートはしている
  • スループットは利用環境によって変わるので実質、保証はされない

AWS

Q: VPN 接続のスループット制限はありますか?
VPN のスループットについて、Amazon はいかなる制限も実施していません。ただし、その他の要因、例えばカスタマーゲートウェイの暗号化能力や、お客様側のインターネット接続速度、平均パケットサイズ、使用されているプロトコル(TCP か UDP か)、カスタマーゲートウェイと仮想プライベートゲートウェイの間のネットワークレイテンシーなどが、スループットに影響を与える可能性があります。
https://aws.amazon.com/jp/vpc/faqs/

GCP

各 Cloud VPN ゲートウェイでは、すべてのトンネルで最大 1.5 Gbps のスループットがサポートされています。スループットを最大にするには、トンネルごとに Cloud VPN ゲートウェイを作成します。 実際のパフォーマンスは次の要因によって変動します。

  • 2 つの VPN ピア間のネットワーク容量。
  • ピアデバイスの機能。詳しくは、デバイスのドキュメントをご覧ください。
  • パケットサイズ。パケット単位で処理が発生するため、小さなパケットの割合が高いと全体的なスループットが低下します。
  • RTT やパケット損失率の値が高いと、TCP のスループットが大幅に低下します。
    https://cloud.google.com/compute/docs/vpn/advanced#vpn_throughput

VPNトンネルへのトラフィックをコントロール

スループットについてお話しましたが、仕様上においても1VPNトンネルだけだとスループットに限界があるため、複数のVPNトンネルを組み合わせることが大切だということが分かると思います。
AWS、GCP共に、トラフィックを流すVPNトンネルをコントロールすることができるので、その仕様について紹介します。両クラウドプラットフォームともにトラフィックをコントロールすることはできるものの出来ることが少し異なっています。

GCP

  • 各VPNトンネルへのルーティング、Priorityを同じにすると、トラフィックをそれぞれのトンネルにバランシングしてくれます。
  • 各VPNトンネルへのルーティングを同じにし、Priorityに差をつけると、Priorityが高いVPNトンネルがプライマリーのVPNトンネルとして利用されるようになります。
    https://cloud.google.com/compute/docs/vpn/advanced#redundancy_and_failover

AWS

  • VPCのVPNでは Multi Path でのルーティングには未対応なので、バランシングはしてくれません。AWS側で定められたロジックによって、必ずVPNトンネルのどれかを利用することになります。
    http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/NetworkAdminGuide/Introduction.html#MultipleVPNConnections

  • 静的ルーティングの場合は最も具体的な IP プレフィックスが優先されます。
    例を示します。(参考: ルーティングの優先度について)

    IP プレフィックスについて少しややこしいと思うので以下の静的ルーティングが設定されたVPN1、VPN2という2つのVPN接続を例に説明してみます。

    VPN1 VPN2
    設定された静的ルーティング 10.1.0.0/18, 10.1.64.0/18, 10.1.128.0/17 10.1.0.0/17, 10.1.128.0/18, 10.1.192.0/18
    この場合 - 全VPNが正常な場合はそれぞれ `/18` を設定したVPNが優先になります。 - 片方のVPN切断時には `/18` で設定されたルーティングを包括する `/17` のルーティングが別のVPNに設定されているのでそちらの経路が使って迂回されることになります。

VPN周りの設計について

可用性やパフォーマンスについて記載してきましたが、それらを踏まえてVPN周りは以下のように設計にしています。

  • VPNトンネルは複数作成する。
  • 特定のVPNトンネルにトラフィックが偏らないように、
    • GCP側のサーバは複数のSubnetにサーバを分散させて配置する。
    • AWS側のルーティングは特定のSubnetへの通信が特定のVPNトンネルを利用するよう設定する。
    • GCP側のルーティングは全VPNトンネルでバランシングされるように同じプライオリティで同じ内容を設定する。
  • VPNトンネルが切断された時に別トンネルで迂回できるよう、
    • AWS側のルーティングでは全VPNトンネルに対して別VPNトンネルのルーティングを包括するルーティングを記載しておく。
    • GCP側のルーティングでは全VPNトンネルに対して、同じルーティングを設定しておく。

イメージとしては以下の図のようになります

ちなみにKARTEではシンプルなネットワーク構成にしているので、静的ルーティングを利用し
ています。

悩まされたこと

VPNのDropパケットの増加問題

AWSとGCPをVPNで接続して運用していたある日、GCPのサーバのパフォーマンスが悪化することがありました。
GCPはStackDriverでVPNの様々なメトリックををモニタリングできるので確認してみたところ、特定のVPNトンネルでDropパケットの増加が見受けられました。
VPNトンネルが切断されてしまえば別のVPNトンネルを利用するようにしていたのですが、そのVPNトンネルは劣化した状態で生き続けていました。
対応としては、特定のVPNトンネルの問題として判断し、劣化したVPNトンネルを切断し正常なVPNトンネルのみを利用するようにしたところ現象が改善しました。

後々、GCP、AWS両方のサポートなどに問い合わせて原因を突き詰めていったところ、AWSにおけるネットワークの劣化が原因で、VPNトンネルは落ちないがパケットがDropされているという状況でした。
ネットワーク周りの問題は切り分けが難しいですが、モニタリングツールが存在することで切り分け、対応が迅速に行うことが出来ました。
この件以降、VPNトンネルに対し、DropパケットなどのMetricでアラートを仕掛けるようにしています。

VPNのスループット問題

元々単一クラウドプラットフォーム内のプライベートネットワーク内で通信していたものをVPN越しで通信させようとすると、想定した以上にアプリケーションの性能が出ませんでした。
その主な理由としては、DBとの通信の多くがVPN経由になっていたことでした。

VPNトンネルを増やしていけば暫定的には解決できる話になりますが、そもそも元々のアーキテクチャがマルチクラウドインフラに最適なアーキテクチャになっているとは言えなかったので、その部分について考え直しました。このあたりの話はまた別エントリーでお話しようと思うので乞うご期待を。

今後について

AWSとGCPの周りにはまだまだ改善の余地はあるので、今後以下を考えていきたいと思っています。

  • 特定の条件でVPNトンネル切断→接続する等のVPN運用周りでの自動化の仕組み
  • VPNトンネルのAutoscalingの仕組み
  • VPN経由ではないサーバ間通信の仕組み

最後に

ウェブ接客プラットフォーム「KARTE」を運営するプレイドでは、マルチクラウドインフラを成長させたい、KARTEを使ってこんなアプリケーションが作りたい! KARTE自体の開発に興味がある!というエンジニア(インターンも!)を募集しています。
詳しくは弊社採用ページ、またはWantedlyをご覧ください。 もしくはお気軽に、下記の「話を聞きに行きたい」ボタンを押してください!