AWSのネットワークにおけるベストプラクティス(2)
VPCの制限
VPCは通常の「ネットワーク」を模したものであるため、特にある程度の規模のネットワークを設計・運用したことがある方々にとっては通常のネットワークと同様の性質をもったものとしてとらえがちです。しかしながら、通常のネットワークとの最も大きな違いは「あるネットワークを経由して別のネットワークと接続する」という性質が無いところになります。
「AWSのネットワークの論理的な側面」で解説した通り、VPC内の通信は通信先を検索し、その検索結果に向かって直接パケットを送信する、といったものになっています。つまり、通常のIPネットワークで発生するような「送信先がどこにあるか分からないけど、とりあえず送信先がどっちの方向(ネットワーク)にあるかは分かるから、とりあえずそっちへ送ってみる」というプロセスが発生しません。
その結果、VPCでは「XXX を経由して YYY へ接続」(XXXからYYYへ中継する)といった通信ができないことが多くなります。
たとえば、VPCにはVPCピアという機能があり、VPC同士を接続することができます。すると、普通のIPネットワークを知っている方ならば「じゃあ、VPCを3つ直列につなげて、それぞれ通信できるかな?」と思われると思います。しかし、上記のような背景により、実際にはVPCピアを使った場合、直接つながっているVPC同士しか通信はできません。
それ以外にも、オンプレミス環境からDirect ConnectやVPNを通して接続したVPCを経由しさらに別のVPCへ接続することもできません。これらの制限は「無効なVPCピア接続設定」に詳しいのでご覧ください。
また、VPCエンドポイントという機能にも制限があります。VPCエンドポイントという機能を使うと、VPCから直接S3へとアクセスできるようになるのです。そうすると自然な発想として「お! VPNやDirect Connectを通して、VPCエンドポイントを使えば、オンプレミス環境から直接S3へとアクセスできるかな!?」と思われるはずです。
しかし、ここでもVPCの「中継はしない」という性質により、オンプレミス環境からの通信はVPCエンドポイントを経由してS3へは到達できないのです。この制限については「エンドポイントの制限」というドキュメントに「エンドポイントの接続を、VPCから延長することはできません。VPC接続、VPCピア接続、AWS Direct Connect接続、またはVPCのClassicLink接続のもう一方の側のリソースは、エンドポイントを使用してエンドポイントサービスのリソースと通信することはできません」と書かれています。
他にも「NATゲートウェイ」という、パブリックIPアドレスやElastic IPを持たないEC2インスタンスがインターネットと通信する際に必要となるNAT機能を提供するサービスがありますが、こちらも「VPCエンドポイント、VPN接続、AWS Direct Connect、またはVPCピア接続を通じてトラフィックを送信でき」ず、逆に「VPCピア接続、VPN接続、またはAWS Direct Connectを経由してNATゲートウェイにトラフィックをルーティングすること」もできない、という制約がドキュメントに書かれています。
以上のように、IPネットワークと似て非なるVPCの性質には、オンプレミス環境との接続や複数のVPCの利用など、VPCを拡張していく過程でしばしば「ハマる」ことがありますのでお気をつけください。
そこで、このような仕様(制限)を回避するための一つのモデルケース(設定)を「Transit VPC」という名前でご提案しています。このモデルではTransit VPCと呼ばれる、各VPCをVPNで接続するためだけのVPCを一つ作っていただき、そのVPCから実際にサービスを展開する各VPCへVPNを張ることでVPC間の通信も実現しています。
より具体的な実装内容は「Overview - Transit Network VPC (Cisco CSR)」にて紹介しています。
ただしこのモデルでは、Transit VPC内において、ソフトウェアVPNルータをEC2インスタンスで実行していただく必要があるなど、お客さまに管理していただくリソースが必要となります。そのための追加コストに加え、データ転送料も必要となってきますので、利便性とコストを比較の上、ご検討いただけるとよいかと思います。
EC2インスタンスの監視
EC2インスタンスが正常に動作しているかどうかを別のEC2インスタンスからツールなどで常時監視し、監視が失敗したらエラーを通知する、といったようなことは非常に多く行われています。しかしながら、エラーが発生した際の原因を特定するにあたっては注意が必要となります。
たとえば通常のIPネットワークで、エラーが(しかも大量に)発生した場合、監視元と監視先の間の共通のインフラ(ネットワーク)で発生した問題が原因であった、ということはよくあると思います。具体的には、同一セグメント内の通信がすべて失敗した場合、通信先の問題よりもそのセグメントを構成しているL2スイッチの問題である可能性が高い、といったような話です。
しかし、EC2インスタンス間の通信では同一セグメント内の通信であったとしても、先述の通り全然別の物理的なネットワークを経由して通信することがよく発生するため、そもそも「共通のインフラ」を経由する可能性(区間)が通常のIPネットワークに比べて非常に限られてきます。つまり、上述の複数のインスタンスの監視が同時に失敗するような事象がVPCで発生した場合は、どちらかというと監視元となっているEC2インスタンスで問題が発生している可能性が高いと思っていただいた方がよいことが多いです。
また逆に、通常なら全然別の通信に見えるもの(例えば、同一セグメント内の通信と別セグメントとの通信)に同時に問題が発生した場合、それらの通信が、たまたま物理的に同じ箇所を通っており、そこで発生した問題の影響を受けている可能性もあります。この場合、EC2インスタンスからは当然その問題自体は観測できないため、イマイチ腑に落ちないエラーの結果が手元に残ることになります。
そこでそういったことがあり得るということを念頭に置きつつも、ここは基本に立ち返って仮想化されているかどうかとは関係無く、以下のような点を確認していただき、そこから事象の調査へと進んでいただけるとよいかと思います。
- 通信の送信元(監視元)、送信先(監視対象)
- 監視プロトコル(監視方法)
- 監視間隔
- エラーの発生日時
- エラーの継続時間
- エラー率
- エラーの発生している通信と発生していない通信の比較
複数ENIの利用
EC2インスタンスにて複数のElastic Network Interface(ENI)を利用する事例は割とよく見かけます。しかしながら、必ずしもいつもお勧めできる方法ではありません。
サーバーを複数のセグメントにつなぐ手法は通常のIPネットワークではパフォーマンス(スループット)を上げたり、NIC、スイッチ、ルーターといった物理的なコンポーネントの障害への耐障害性を高める方法として非常に一般的です。
しかしながらVPCにおいては、「AWSのネットワークの論理的な側面」での解説の通りどちらのENIからのパケットも同じようにソフトウェア的に処理されるだけなので、パフォーマンスや耐障害性といった観点からは特に違いはありません。
その一方、ENIを複数使うことで、EC2インスタンス内のルーティングテーブルとルートテーブルの整合性を保つ必要があったり、Reverse Path Filteringを考慮したり、「送信元/送信先チェック」を気にしたり、と色々と考慮ポイントが増えます。
そのため、利用しているソフトウェアの制約上どうしても必要とか、管理上ENIを分けた方が管理しやすいなどといった理由がなければ、複数ENIを使うより一つのENIに複数のIPアドレスを割り当てた方が色々と楽だと思います。
