【AWS】VPC環境の作成ノウハウをまとめた社内向け資料を公開してみる
よく訓練されたアップル信者、都元です。今回のお題は久しぶりにVPCです。
この記事は、アップデート版が存在します。最新情報は【AWS】VPC環境構築ノウハウ社内資料 2014年4月版を参照してください。
VPCを利用する理由
弊社で構築するAWSのサーバ環境は、一部の例外を除いて全てVPCを利用しています。
突然ですが、筆者はあまり大規模なシステムに携わった経験がありません。大規模なプロジェクトだと「数百数千台のサーバがラッキングされ、それが論理的なネットワークで区切られていて」「複数のデータセンターが冗長化された専用線で結ばれて」等、正直ちょっと想像つかない世界があるんだと思います。よくわかんないですが。
(c)John McStravick. (CC BY 2.0 Licensed)
逆に、小さなシステムであれば、月々数万円でレンタルサーバを借りて「1台のマシンの中にWebサーバとDBサーバが同居する」といった世界で、あまりネットワークインフラについて考えない事が多いわけです。中小規模なプロジェクトでは「オンプレミスでネットワークを設計すると高く付く」という理由で、ネットワーク設計をしないのだと思います。そもそも私、データセンターって所に行ったことがありませんw
一方AWSは、あらゆる規模のプロジェクトに対応するインフラを提供しています。前述のサーバ数千台規模のプロジェクトしかり、1台構成しかり。大規模プロジェクトであれば当然、オンプレミスと同様にネットワークインフラについての設計を綿密に行う必要がありますが、では、中小規模のプロジェクトにおいてはネットワークの設計をする必要はないのでしょうか。
AWSでは、VPCという「ネットワーク環境」を構築するサービスを提供しています。しかもVPCの利用料金は(VPN接続を除いて)無料です。自ら設計したネットワークの上でEC2サーバを起動(これをEC2-VPCと呼びます)して、そのリソースを利用できるのです。もちろん「ネットワークの事は考えたくない」というニーズもあるでしょう。そういった場合は、VPCを使わずにEC2サーバを利用する(これをEC2-Classicと呼びます)ことも可能です。しかし、そのシステムを大きく育てていくつもりであれば、無料なんですから、最初からネットワークインフラについてもある程度考えておくと良いでしょう。EC2-Classic環境からEC2-VPCへの移行作業というのは、結構大掛かりになってしまいがちなので、尚更です。
無料だからVPC、今後成長した時困らないようにようVPCです。
設計コストの行方
ただし、ここで問題になるのは設計コストかもしれません。いくらネットワーク利用料が無料だからといって、ネットワーク設計をするコストは掛かってしまうでしょう。VPCに触れた事がなければ尚更です。
その点、弊社ではAWSを専門としたチームが毎日のようにVPCネットワークインフラの設計構築をしています。大規模プロジェクトであれば独自のネットワーク設計が必要かと思いますが、今回テーマにしている中小規模のネットワークはどれも似たり寄ったりです。結果、その設計コストは限りなくゼロに近づいています。
というわけで、弊社で利用している、VPC環境の基本構成をここでご紹介します。
基本方針
ここで設計の基本方針を列挙します。とりあえず方針だけで、理由は列挙しません。理由は後から説明したりしなかったり。説明が足りなければ下のコメントで指摘してください。
- サブネットのレイヤは3層とし、Frontend / Application / Datastore と呼ぶ。
- 2つのAZを利用したマルチAZ構成とする。
- NATサーバをt1.microでFrontendサブネットに構築する。セキュリティグループはVPC defaultのみ。
- Bastion *1サーバをt1.microでFrontendサブネットに構築する。セキュリティグループはVPC default及び、特定IP/CIDRからのSSH接続のみを許可するグループの計2つ。
- 各サブネットのルーティングは、Frontendはpublic、それ以外はprotectedとする。privateは利用しない。
- ネットワークの内部通信は制限しない。(VPCのdefaultセキュリティグループを、全インスタンスに付与する)
- NetworkACLは利用しない。(ALL OK)
- セキュリティグループのoutbound制御は行わない。(ALL OK)
- プライベートIPアドレスは制御(固定)しない。
- ドメイン名を1つ確保し、プライベートIPを名前解決できるようにDNSレコードを定義する。
- 以上の環境を、出来る限りCloudFormationで作る。
各項解説
3層レイヤ
中小規模のシステムは、大抵この3層レイヤがフィットします。各層に、以下のような指針でサーバを配置しましょう。
- Frontend: ELB, NAT, Bastion、(直アクセスの)Webサーバ等、internet-facingなサーバを配置する。
- Application: (ELB配下の)WebサーバやAPサーバ等、計算処理を主体とするサーバを配置する。
- Datastore: RDSやMongoDB、fluentd等、データリポジトリを主体とするサーバを配置する。
マルチAZ
本番システムは、何か不可能な理由がない限りマルチAZ構成を取ります。詳しくはAWSにおける可用性の考え方を参照してください。
VPCサブネットは1つのAZに紐付きますので、結果として、各レイヤには2つ、計6サブネットが作成されることになります。
ルーティング等、各種通信制御
まず、VPCのローカルネットワーク内同士の通信については、全ての通信を許可することを基本方針とします。必要に応じて制御を行いますが、基本は全通信OKとしておきます。
次に、メンテナンス経路として必ず踏み台サーバを置きます。メンテナンスをしない時はサーバをstopすることによりバックドアが閉じますし、インスタンスタイプもt1.microで充分です。(参考: )
グローバルIPを持たないサーバに外部通信を許可するために、NATを配置します。(この辺り、default-VPC以外のVPCにおいても、非EIPのグローバルIPを付与することができるようになったため、改訂の余地があるのではないかと認識しています。)
ルーティングテーブルの種類は、public / protected / private の3種類があります。
- public: グローバルIPを持てばIGWを介して外部ネットワークとinbound/outbound通信できる。
- protected: NATを介して外部ネットワークとoutbound通信のみが可能。
- private: 外部ネットワークと直接通信は一切できない。
ただし、基本的にprivateは利用しません。なぜかといいますと。EC2やRDS等のサーバは、NTPプロトコルを使って外部サーバと時刻の同期を行っています(参考: Amazon Linuxにおけるシステム時計とNTP)。privateは外部ネットワークと通信できませんので、NTPによる時刻同期ができない、ということになってしまいます。この点を解決する仕組みを構築しない限り、privateルーティングは実用的でないと判断しています。
これらのルーティング命名については2つの流派があり、少々の混乱を招いているのが現状です。AWSの公式ドキュメント上では、上に挙げたprotectedとprivateの区別をしておらず、両者をprivateと呼んでいます。それに対して、本エントリでは、NATを介して外部通信ができるかどうかを明確にしたいため、protectedという命名を採用しました。そして、privateはNAT通信ができるものを含まず、完全に外部と直接通信ができない性質のものを指す方針です。
NetworkACLはハマりどころが多いので、使いません。使わなくても充分セキュアだと認識しています。そしてセキュリティグループのアウトバウンド制御も、同様に使いません。まぁこれはあくまでも基本方針ですので、使いたければどうぞ。
サーバ間の宛先識別
ご存知の通り、TCP/IPプロトコルでは、IPアドレスを使ってノードの識別を行っています。VPCはプライベートIPアドレスを固定できることが一つのメリットであると思いますが、後に出て来るCloudFormationにおいては、IPアドレスを固定することにより、メンテナンス上の問題が発生します。
プライベートIPを固定できれば、サーバ同士がIPアドレスで宛先を認識して通信することができるのですが、この構成ではその代わりに、ドメイン名による通信を行うようにします。それを実現する為の仕組みとしてRoute53を使います。例えば、example.comというhostedZoneについて、以下のように利用します。
- 表向きはexample.com, foo.example.com, bar.example.com等を利用する。
- nat.local.example.com等、*.local.example.comというドメイン名を利用して、それに対するプライベートIPのAレコードを作成する。
- RDSを利用するときも同様、rds.local.example.comに対するCNAMEレコードで、RDSのエンドポイント名を指定する。
以前、AWSにおける静的コンテンツ配信パターンカタログ(アンチパターン含む)でも触れたのですが、「AWSから当てがわれるIPアドレス・ドメイン名をそのまま利用する」のはアンチパターンです。RDSのホスト名も対象です。従って、Route53を介して、必ずドメイン名でアクセスするようにしましょう。
一つ問題となるのが、AutoScalingを使ったサーバへのアクセスですが、これはIPアドレスが特定できず、また、動的にDNSレコードを作成するのも少々面倒なため、都度都度プライベートIPアドレスを確認しながら利用する、という運用にしています。
以上の構成図
どーん。
…という環境のCloudFormationテンプレートください。
ですよね。差し上げます。gistに貼っておきました。
https://gist.github.com/miyamoto-daisuke/7149842
動かす前に、事前にRoute53 HostedZoneを作成し、ネームサーバの設定は済ませておいてください。パラメータのHostedZoneにexample.comを指定した場合、スタックが完成すると、example.comでロードバランサ(Frontend)に繋がるようになっています。
配下のWebサーバ(Application)にはApacheをインストールしてindex.htmlを配置しただけです。一応、AutoScaling体制になっていますが、2台固定です。
また、RDS(Datastore)も構築されますが、Webサーバから繋ぐ処理は特に記述していません。MySQL clientをインストールしておきましたが、特に繋ぐ処理は書いていません。Bastion経由でWebサーバにSSHでログインし、下記コマンド等でRDSに接続を試みてみるのも良いでしょう。
$ mysql -h rds.local.example.com -u admin -p
まとめ
というわけで、中小規模のAWSネットワーク環境の雛形をご紹介しました。上記のテンプレートはそのまま使う事はできないと思いますが、さまざまな構成の起点に使うと便利です。ご活用下さい。
脚注
- 踏み台 ↩