ネットワークしくじり先生

kaga氏:それでは、「ネットワーク設計アンチパターン」という話をさせていただきます……と思ったんですけれども、ちょっとタイトルが堅いので「ネットワークしくじり先生」に、ちょっとやさしい雰囲気に変えたので、肩の力を抜いて聞いていただければなと思います。よろしくお願いします。

(会場拍手)

自己紹介です。kagaといいます。もともとQAを5年やって、サーバサイドを3年やって、今はインフラを5年やっています。この5年間はほとんどがAWS環境で、オンプレについては全然詳しくないです。

この資料は既にアップしてあるので、Twitterのハッシュタグとかを追っていただければわかると思います。

私の趣味なんですけど、エンジニア向けのカンファレンスやイベントでカメラマンをやっています。主にiOSエンジニア向けのカンファレンスや、PHPエンジニア向けのカンファレンス等で撮影担当をやっています。

今日のアジェンダです。まずAWSのVPCについて話そうと思います。その次にVPCの設計のベストプラクティスって何だっけという話をして、みなさんが大好きな失敗談をやって、最後まとめたいと思います。

じゃあ、まずVPCについてお話しします。先にお聞きしたほうがよかったんですけど、オンプレミスメインで担当されている方ってどれぐらいいます? ちょっと手を挙げてもらってもいいですかね。

(会場挙手)

なるほど。ありがとうございます。AWS、パブリッククラウドをメインで見ている方ってどれぐらいいます?

(会場挙手)

半々。若干オンプレのほうが上でしょうか。ありがとうございます。

VPCについて

じゃあ、VPCについてお話しします。

これは公式のドキュメントから引っ張ってきたやつなんですけど、「VPCってそもそも何だ?」ということから始めます。AWSっていろいろなサービスが利用できるんですけど、その中で仮想ネットワーク、ほかのネットワークから論理的に切り離されていて干渉されない独自のネットワークを作ることができるのがVPCです。

それに付随してVPCの中でIPのレンジをこういうふうに定めるのがSubnetです。もしピンと来なかったら、あとで公式のドキュメントを見ていただけるとすごくわかりやすいかなと思います。

ここで3つの構成図をご紹介します。

1、VPCを開発環境などの単位で区切ったような、よく見る感じの構成図ですね。

2、VPCは1つですけど、Subnetを各環境ごとに切ってあるやつ。

3、最後にデフォルト構成。これはAWSアカウントを作って、一番最初にアクセスするとこういう環境になります。

「AWSのネットワークの設計って何が正しいのか。どうあるべきなんだろうか」ということは私自身すごく悩んでいまして、自分の中の答えの1つとしては、論理的な単位で分割するといいと考えています。

じゃあ「論理的な単位って何ぞや?」って話になるんですけれども、1つは、いわゆる開発環境とか提供しているサービスの単位ですね。例えば前者ですと、開発環境があり、staging環境があり、本番環境があります。さっき紹介したVPCで切った、その1という構成図、あとはSubnetで切ったその2の構成図が、この環境単位というところに当てはまります。

あとは、1社1サービスじゃなくて1社で複数サービスを提供している場合は、提供しているサービスの単位でネットワークを切ってあげるのもありですね。大きな組織になると、組織単位でネットワークを切る。と、ここまでいくとアカウントを分割しようって話になると思うんですけど、こういうのが論理的な単位に当てはまるのかなと考えています。

VPCのベストプラクティス

じゃあ、ここで「AWSはどういうふうに考えているのか」というベストプラクティスを紹介してみます。

ある程度は公式ドキュメントに書かれていますし、あとは「Black Beltオンラインセミナー」というオンラインセミナーがあって、そちらのスライドも参考にすることができます。

これは公式ドキュメントのスライドの1つなんですが、AWS環境をコード化することができるCloudFormationというサービスのサンプルの一環として、インターネットに露出するパブリックのSubnet、アプリケーションを置くプライベートのSubnet、あとはデータベースを置くSubnetみたいな構成をベストプラクティスのサンプルとして1つ挙げられています。

あとは、「Black Beltオンラインセミナー」で紹介されているように、VPCを分割するケースっていっぱい考えられるんですね。今回このスライドに紹介されているのは、アプリケーションの単位だったり、これは大規模なところになるとあり得るかもしれないんですけど、システム監査のスコープの単位だったり、リスクレベルによる単位というものあります。

一番最後に書かれているんですけれども、この分割パターンって結局正解がなくて、使う側のオペレーション次第で分割する必要があるというのが1つの結論ではあります。

実際にVPCを作成する際にはVPCウィザードを活用するのも手です。けっこう使いやすい機能なので、そういったものを活用していけばいいと思います。VPCウィザードを使用してVPCを作成するときに4パターンぐらいの構成を選ぶことができます。パブリックのSubnetと1つのVPC、あとはVPCにパブリックのSubnetとプライベートのSubnetみたいな感じで、あとはVPNのアクセスが考慮されているものなどを選択することができます。

インフラネットワークの失敗談

ここまでVPCの説明が続いてしまったので、そろそろ本編に入りたいと思います。ちょっと息を整えさせてください。はい、いきます。先にお断りしておきますが、私が今所属している会社のサービスがこういう構成であるということではないという点だけ最初にお伝えさせてください。

じゃあ見ていきます。ドーン。VPC1個にSubnetが2個あります。いわゆるデフォルト状態のVPCにEC2とかデータベースとかキャッシュがわーって載っているんですね。これは見た瞬間「オッ?」ってなりますね。

先ほど説明したデフォルトのVPCを作ると、1つのVPCと2つのSubnetが作成されます。今だとSubnetは3つなのかな。そして、ネットワークのアクセスを制限するSecurity Groupという機能があって、それが大量にあって、稼働している複数のサービスがこんな感じで同居しているわけです。

ここで設定変更の依頼が来るんですね。AWSにS3 Endpointというのがあるので、それを追加したいということで依頼が来ました。

S3 Endpointって何ですかという話ですが、先ほど紹介した論理的なネットワークであるVPCから、AWSのS3というオブジェクトストレージに内部通信でアクセスするためのエンドポイント、それがこのS3 Endpointというものです。

こいつをどこに設定するのかというと、VPCのSubnet。だから、ネットワークのところに設定することになります。

設定する前には設定変更内容の確認や、動作テストをするじゃないですか。この環境にはデフォルトのVPCしかなく、テストできる環境がなかったんですね。そのVPC環境しかありませんでした。なので、別Subnetを作って擬似的な環境を作り、そこでテストをしようかと考えました。とはいえ、既にたくさんのサービス動いているため「いやー、完全な環境は作れないですね……」って妥協してしまったわけです。「設定をチェックすればなんとかなるやろ」と。

S3、オブジェクトストレージの設定を確認

まず最初に確認したのが、S3、オブジェクトストレージの設定です。どのIPからのアクセスを受け入れるとかどの権限を受け入れるみたいな設定をチェックして、「うん、大丈夫。ヨシ!」ってなりました。

次、各サーバのネットワークアクセスを設定するSecurity Groupがあって、こいつもチェックしたら「ヨシ!」となりました。

最後に一応念のため、動いているサービスのソースコードをgrepして、そういう変なIP設定とか制限がないかを確認しました。なかったので「ヨシ!」ってなりました。

ということでS3 Endpointを追加しました。動かなくなりました。残念でした。

(会場笑)

「管理画面から画像がアップロードできません」というお問い合わせが来て、秒速で戻しました。その節は本当にすみませんでした...…。

AWSっていくつかリージョンがあって、東京とかUSとかいろいろあるんですけど、リージョンを指定してあげないとルーティングができなくて通信ができない場合があるってドキュメントに書いてあったのを見逃してしまいました。原因はこいつだった。やっちゃいましたね。

ここまできて反省です。まず、そもそもどういう動きをするのか、ちゃんとドキュメントを読めよという話ですよね。CLIとかSDKを扱うときに設定が必要なはずなので、こういうのをちゃんと読んで調べておけよという当たり前の反省がまず1つ。

2つ目。こちらが今回の本題なのですが、妥協せずテスト用の環境を作って試すべきだった。これは本当に反省していて、「テスト環境ができるまでどれぐらいかかるかな」「この設定変更だけで1週間か……うーん、うーん」となって諦めてしまいました。

テスト環境ですが、実際に作るのはWebサーバ、DBサーバ、キャッシュ、S3、全部ゼロから作れと言われると、やっぱりめげちゃうわけですね。こういう時のためにちゃんとコード化しなさいと言われると「そうだな」しか言えなくて、本当すみませんでしたって感じです。ちゃんとコード化しましょう。

このネットワークの何がダメだったのか

最後にまとめです。

このネットワークの何がダメだったか。まずデフォルトのVPCとデフォルトtのSubnetを使用する場合、開発環境・staging環境・本番環境が同じネットワークに乗ってしまうわけですね。その時点でセキュリティ的にも設定変更に対する影響度的にも良くないわけです。

別の視点から見てみると、ロードバランサーとWebサーバとデータベースが同じレイヤーにいるんですよ。これもアクセス保護やデータ保護の観点から良くないです。

今回私がやらかしてしまったように、この各環境が同一のネットワークでは、例えば開発環境で設定変更をしましたと言ってて、実は本番環境にも影響していたという事が起こり得ます。開発環境だけ、staging環境だけといったテストがしづらい。とくにネットワーク部分の設定変更が難しいですね。

例えば開発環境がハッキング、乗っ取られてしまったら、他の環境にも入られてしまう可能性があります。よろしくない。最悪、全部死です。

ロードバランサーとWebサーバとデータベースが同じレイヤー。この何が悪いかというと、基本的にデフォルトSubnetってインターネットで外部と通信できてしまう設定になっており、設定の不備で外に露出すべきではないサーバまで見えてしまう可能性があります。本来であればインターネットに見せる接点は、ロードバランサーとかだけでいいはずなんです。あるべき形としてインターネットからの接点を絞ろうというところで、これはよくないです。

最後、Security Group頼みのコントロール。これは本当につらくて、似たような名前のSecurity Groupが量産されていって、「あれ、なんか複雑に絡み合っててリファクタリングが厳しいです」みたいな感じに陥ってしまうので、Security Groupだけに頼らずちゃんとネットワークを分けてやりましょう。

じゃあ逆に、本当に一応とだけ言っておくんですけど、このネットワークの何がよかったのかを考えました。

とりあえずデフォルトVPCの状態でも動くんですよ。だから、ネットワークに詳しい人がいないのに「とりあえずAWS環境で何かサービス作ってよ」と言われた時に、デフォルトでもある程度は動かせちゃうんですよね。

なので、例えば「どうしてもこのタイミングにこのサービスをリリースしないと競合他社に出し抜かれる!」みたいな感じで、今すぐリリースしないといけないみたいなサービス、ユーザに価値を提供するものに注力したいのであれば、できなくはないよって話です。ただし、こういうのって絶対負債になるし、ネットワークを考えたくないんだったらHerokuとか他のPaaSを検討したほうがいいかと思います。

結論としては、「動くからええやん?」じゃなくて、ネットワークもサボらずちゃんと設計しましょうという話でした。終わりです。

以上です。ありがとうございました。

(会場拍手)