今回はAWSの話題です。
AWS初心者がインフラ構成する際、
躓くポイントであるNATゲートウェイを解説します。
主に以下を説明する記事を書いていきます。
- どこに配置するか?
- どうやって使うのか?
- 設計ミスった時に挽回する方法はないか?
【AWS】NATゲートウェイとEC2を同じサブネットに置くとどうなるか?
NATゲートウェイの標準的な配置方法
まずはAWS公式で解説されているNATゲートウェイのユースケースを紹介します。
【AWS公式】NATゲートウェイのユースケース
NATゲートウェイを使うと、EC2へ直接グローバルIPアドレス(Elastic IP)を付与しなくても
インターネット向けに通信できるようになります。
これによりEC2がインターネットに直接晒されることを回避しつつ、
インターネットへアクセスできるようになります。
特に、インターネットアクセスすることが前提となるソフト
(ウィルス対策ソフトのアップデートなど)
を利用する際非常に相性が良いです。
ちなみにこれ、一般的な家庭のホームネットワークと同じですね!
NATゲートウェイまわりのルーティング
ホームネットワークとは異なり、NATゲートウェイをただ配置するだけでは
利用されません。AWS内でルーティングの設定が必要となります。
以下例を挙げて解説します。
こんな風にいくつかのリソースを配置/設定する必要があります。
AWSに触り慣れてくるとこの辺りは特に構成図や設計を書いたりしなくとも
パパっと設定できたりするのですが、初学だと難しいと思いますので解説していきます。
VPC
クラウド上に自分専用の仮想ネットワークを作るサービス。
とりあえず一番最初に作るもの、と思っておけばOK。
これがないと始まらない。
ここで作成する仮想ネットワークにCIDR(IPアドレスの範囲)を設定します。
上記例では「10.10.10.0/24」としています。
サブネット
VPCで設定したCIDRを用途ごとに切り出すもの。
VPCを作ったら次に作成するもの、と思っておけばOK。
プライベートサブネットはインターネットと直接通信しないサブネットを示す概念。
パブリックサブネットはインターネットと直接通信するサブネットを示す概念。
概念なので、設定上どちらか選択するものではないことに気を付ける。
上記例では
プライベートサブネット用に「10.10.10.0/27」
パブリックサブネット用に「10.10.10.32/27」
をそれぞれ切り出しています。
ルートテーブル
各サブネットから出力される通信をどこに転送するかを定めるもの。
インターネットに向かいたいときはインターネットゲートウェイやNATゲートウェイ
に向かうルートを設定する。
VPC作成時に勝手に作成されるので、
初期状態でVPC CIDRだけ通信できるルートテーブルが用意される。
上記例では
プライベートサブネット用に「インターネット経路をNATゲートウェイへ向けて」
パブリックサブネット用に「インターネット経路をインターネットゲートウェイへ向けて」
それぞれ追加しています。
Elastic IP
AWSから借用できるグローバルIPアドレス。
AWSが保持しているものからランダムに払い出される。
NATゲートウェイを配置する際、割り当てされるようになっている。
既に用意していればそれを使うことも可能。
EC2
いわゆる仮想サーバのこと。数クリックでサクッと作成可能。
前提条件としてこのEC2を配置するためのサブネットを用意しておく必要あり。
※一応デフォルトVPCのサブネットが最初から用意されているけど、
デフォルトでインターネット公開されたりするためあまり使わないほうが良いと思う。
仕事で配置するときは、先にIAMロールやENI、セキュリティグループを作っておいたりする。
インターネットゲートウェイ
インターネットと接続するために配置する。
NATゲートウェイを配置する前提にもなっている。
EC2やNATゲートウェイをElastic IPと関連付けたとき、
このインターネットゲートウェイがプライベートIPアドレスをグローバルIPアドレスへ変換する。
NATゲートウェイ
ここにアクセスすることで、
EC2のプライベートIPアドレスをNATゲートウェイのグローバルIPアドレスへ変換できる。
EC2へ直接グローバルIPを付与せずにインターネット接続を実現するために配置する。
NATゲートウェイと同じサブネットにEC2を配置してOKなパターン
サンプル構成図
以下の構成図では、
EC2-AはNATゲートウェイを使ってインターネット接続のみ行う。
EC2-Bは直接インターネット接続をしてかつ、インターネットへサービス提供する前提とする。
実際に作ってみましょう
AWSのハンズオン的な内容を掲載します。
このぐらいサクッと作れるよ!という方は本項を飛ばしてください。
前提
東京リージョン(ap-northeast-1)
①VPCを作成
最初にVPCを作成します。
※説明では実行していませんがVPCを作成するついでにサブネットなどいろいろ作成できます
項目 | 設定値 | 備考 |
---|---|---|
名前タグ | addache-demo | |
IPv4 CIDR | 10.10.10.0/24 |
②サブネットを作成
次にサブネットを作成します。
サブネットは複数同時作成できるので、以下2個をまとめて作成します。
サブネット区分 | VPC ID | サブネット名 | アベイラビリティー ゾーン | IPv4 サブネット CIDRブロック |
---|---|---|---|---|
プライベート | addache-demo | addache-demo-PRI | ap-northeast-1a | 10.10.10.0/27 |
パブリック | addache-demo | addache-demo-PUB | ap-northeast-1a | 10.10.10.32/27 |
③インターネットゲートウェイを作成
次にインターネットゲートウェイを作成します。
めちゃくちゃ簡単です。
項目 | 設定値 | 備考 |
---|---|---|
名前タグ | addache-igw | |
使用可能なVPC | addache-demo | アタッチするVPC |
④NATゲートウェイ
項目 | 設定値 | 備考 |
---|---|---|
名前 | addache-nat | |
サブネット | addache-demo-PUB | NATゲートウェイの配置サブネット |
⑤ルートテーブルを作成
ルートテーブルの作成は複数同時にできないので1個ずつ作成していきます。
名前 | VPC | 追加ルートと ゲートウェイ | 関連付けサブネット |
---|---|---|---|
addache-rtb-pub | addache-demo | 0.0.0.0/0 インターネット ゲートウェイ | addache-demo-PUB |
addache-rtb-pri | addache-demo | 0.0.0.0/0 NATゲートウェイ | addache-demo-PRI |
ルートテーブル作成後は追加ルートを設定します。
追加ルート設定したらサブネットの関連付けを行います。
同じ要領でもうひとつのサブネットを作成していきます。
追加ルートの設定を行います。
サブネットとの関連付けを行います。
⑥セキュリティグループを作成
EC2用にセキュリティグループを作成していきます。
方向 | ポート | CIDR |
---|---|---|
インバウンド | すべてのトラフィック | 10.10.10.0/24 |
アウトバウンド | すべてのトラフィック | 0.0.0.0/0 |
⑦IAMロールを設定
EC2への接続はSSMフリートマネージャを利用するので、下準備として
SSMアクセス権限のついたIAMロールを作成します。
ユースケース | 許可ポリシー | IAMロール名 |
---|---|---|
EC2 | AmazonEC2RoleForSSM | addache-ec2-role |
⑧インスタンスの作成
EC2-AとEC2-Bを順番に作成していきます。
どちらもOSはAmazonLinux 2023を選択します。
※特に選択しないデフォルト状態
パラメータは名前、サブネットぐらいしか違わないです。
他にも、インスタンスタイプやボリュームサイズはデフォルト値とします。
ここに記載のないものは基本的にデフォルト値です。
項目 | EC2-A | EC2-B |
---|---|---|
AMI | AmazonLinux 2023 | AmazonLinux 2023 |
Nameタグ | addache-EC2-A | addache-EC2-B |
キーペア冥 | addache-tokyo | addache-tokyo |
VPC | addache-demo | addache-demo |
サブネット | addache-demo_PRI | addache-demo_PUB |
セキュリティグループ | addache-share-SEG | addache-share-SEG |
IAMインスタンスプロフィール | addache-ec2-role | addache-ec2-role |
CloudWatchモニタリングの詳細 | 無効 | 無効 |
クレジット仕様 | スタンダード | スタンダード |
キーペアは作っていなければここで作成します。
同じように、EC2-Bも作成します。
以下のようにローンチ(生成)したインスタンスが並びました。
⑨Elastic IPアドレスをEC2-Bへ関連付け
OKパターンの検証のため、EC2-Bへは一時的にグローバルIPアドレスを付与します。
⑪作成後の疎通確認
SSMのフリートマネージャーを開いて、EC2が2台並んでいる状態を確認します。
順番にログインして、Googleに向かってPing疎通を検証してみます。
以下のコマンドを打鍵します。
bash
sudo su -
ping -c 3 google.com
打鍵風景はこんな感じです。EC2-AとEC2-Bそれぞれにて成功すれば問題なしとします。
なんでOKなのか?
インターネット通信をするときは
NATゲートウェイ、EC2-Bともインターネットゲートウェイを目指していきます。
インターネットゲートウェイでそれぞれのグローバルIPアドレスへ変換されます。
実設計に取り込むのは避けたほうがいいかもしれませんが、
理屈上矛盾しませんので問題なし、です。
NATゲートウェイと同じサブネットにEC2を配置してNGなパターン
サンプル構成図
このパターンではEC2-BにグローバルIPアドレス(Elastic IP)を付与せず、
NATゲートウェイと同じサブネットへ配置しています。
EC2-Bをインターネットへ公開する予定のないときは、
グローバルIPアドレス(Elastic IP)を付与しないで使いたいときもあると思います。
そういう時は素直にEC2-Aと同じサブネットへ配置しましょう。
なんでNGなのか?
EC2-Bはインターネット接続するとき、グローバルIPアドレスの変換ルールを持たないのに
インターネットゲートウェイを目指してしまいます。
プライベートIPアドレスのまま、インターネットに出ていくことはできないのです。
これはホームネットワークでも同様です。
インターネット接続できないだけなので、それ以上の実害はありません。
元々インターネット接続するつもりが一切ないならこのままでも問題ありません。
NGパターンの裏技的な解決方法
ルーティングを見直す
実害はないと書きましたが、それで終わってしまうのも寂しいので
裏技的に解決する方法を書きます。
まあ、EC2-BへElasticIPを付与できるなら一発解決ですが。。。
本記事は制約あって、それが容易にできなくて困っている人向けの記事です。
ここから本編。
裏技はAWSのリソースを新たに増やすとかではなく、
OS上のルーティングを編集します。
実際どうやるのか?
先ほどハンズオン的に作成したEC2-BからElasticIPの関連づけを解除します。
これでインターネット接続できなくなりました。
インターネット接続不可になった弊害として、
EC2-Bへはフリートマネージャー経由でログインできなくなってます。
よって、EC2-Aを踏み台にして、次にEC2-Bへログインします。
ログインするまで下準備が必要なので、EC2-Aにてコマンドを打鍵していきます。
bash
vi ~.ssh/id_rsa
#----------------------------------------
[キーペアファイルの中身を丸ごと張り付けする]
#----------------------------------------
chmod 0600 .ssh/id_rsa
ssh -i .ssh/id_rsa ec2-user@[EC2-BのIPアドレス]
rootログイン後まずは現在のルーティングを確認します。
sudo su -
route
このルーティングはAWSのルートテーブルで設定するものとはまた異なっています。
AWSのルートテーブルはOS上のデフォルトゲートウェイへ到達してから適用されていきます。
defaultとは、0.0.0.0 のデフォルトゲートウェイのことを指しています。
_gatewayとは、このEC2が所属するサブネット上のデフォルトゲートウェイ(10.10.10.33)
のAlias(別名)です。
デフォルトゲートウェイに転送された後はルートテーブルの経路設定に従い転送されます。
ただこれだとインターネットゲートウェイに向かってしまうので、
NATゲートウェイを強引に使うように設定を変更していきます。
ちなみに一時設定です。常時設定する方法もありますがいったん後述します。
※順番大事です!上から順番に実行しましょう!
route add -net 10.10.10.0/24 gw 10.10.10.33
route add -net 0.0.0.0/1 gw 10.10.10.54
route add -net 128.0.0.0/1 gw 10.10.10.54
はい、経路が増えました。
疎通テスト
再び、googleに向かってPing疎通が成功するようになりました。
ついでにEC2-Aに対して疎通できていることを確認。
ちなみにインスタンスメタデータに試しにアクセスしてみると。。。
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/local-hostname
応答がない。。。
なんだか変だ・・・
原因:リンクローカルアドレス上にあるAWSサービスと接続できなくなっている
上記ルーティングの追加を行う際にリンクローカルアドレスのルーティング設定がされてなかったのが原因です。
サンプルのEC2はAmazonLinux 2023なのであまり問題になってない感じがしますが、
RHELやWindowsなどリンクローカルアドレス上のライセンスサーバへ接続できている前提があるOSを選択している場合は「ライセンス違反」の表示が出たり、「yumコマンドが失敗」したりします。
そういうわけで、ルーティングを追加してリトライしましょう。
route add -net 169.254.0.0/16 gw 10.10.10.33
うまく行きましたね!今度はちゃんとレスポンスが返ってきました!
永続的にルートを設定するには?
以下のようにコマンドを入力します。
何をしているかというと、スタティックルートの定義ファイルを作成している感じです。
AmazonLinux 2023ではコレというだけで、
ディストリビューションにより異なりますので、適宜変更してください。
# 元の設定をテンプレ風にコピー
cp -p /run/systemd/network/70-enX0.network /etc/systemd/network/70-enX0.network
vi /etc/systemd/network/70-enX0.network
# ---追記----------------------------
[Route]
Gateway=10.10.10.33
Destination=10.10.10.0/24
[Route]
Gateway=10.10.10.54
Destination=0.0.0.0/1
[Route]
Gateway=10.10.10.54
Destination=128.0.0.0/1
[Route]
Gateway=10.10.10.33
Destination=169.254.0.0/16
# -----------------------------------
systemctl restart systemd-networkd
routeコマンドを打鍵して再起動後に反映されているか確認しましょう。
まとめ
なるべくNATゲートウェイを配置したサブネットへEC2を置かないようにしましょう。
構成/設計の健全さを保つため原則裏技(OS上のルーティング設定)は避けましょう。
(余談)
AmazonLinux 2023の最新においてスタティックルート設定するときは
systemd-networkd なるサービスを使わなければならないらしい。
コメント