パブリックサブネットをインターネットに接続する

AWSBeginner
オンラインで実践に進む

はじめに

配送アプリケーションは VPC 内で準備されていますが、公開サービスはまだ外部リクエストを受信できません。不足している経路を構築します。VPC にインターネットゲートウェイをアタッチし、アプリケーションのサブネットのルートテーブルにデフォルトルートを追加し、アプリケーションのネットワークインターフェイスにパブリックアドレスを関連付けます。

先に「アプリケーション用サブネットを持つ VPC を作成する」を完了してください。この新しい環境には独自の VPC、サブネット、アプリケーション、アクセスルールが用意されており、以前の VM は再利用しません。CLI は設定済みです。無関係な参照ネットワークと、提供されているすべてのアプリケーションリソースを保持してください。

認定試験との関連

この実験では、次の試験項目を実践します。

インターネットゲートウェイをアタッチする

このステップでは、提供されたアプリケーションネットワークを調べ、その VPC にインターネットゲートウェイをアタッチします。

コマンドには Terminal を使い、隣の AWS View をクリックしてください。このビューは CLI と同じリソース状態を読み取ります。application-network VPC には public-subnet と private-subnet があり、アプリケーションは public-subnet 内のプライベートアドレス 10.20.1.10 を使います。

cd /home/labex/project

Name タグでアプリケーションの VPC を選びます。--filters はサーバーの結果を絞り込み、--query は ID を選択します。$(...) はその ID をシェル変数に取り込み、以降のステップで利用できるようにします。

VPC_ID=$(aws ec2 describe-vpcs \
  --filters Name=tag:Name,Values=application-network \
  --query 'Vpcs[0].VpcId' \
  --output text)

選択したネットワークのサブネットを確認します。

aws ec2 describe-subnets \
  --filters "Name=vpc-id,Values=$VPC_ID" \
  --query 'Subnets[].{CIDR:CidrBlock,ID:SubnetId}' \
  --output table

範囲は 10.20.1.0/24 と 10.20.2.0/24 です。別の参照ネットワーク 10.99.0.0/16 はこの作業と無関係なので保持してください。

HTTP は、このアプリケーションのエンドポイントが使うリクエストとレスポンスのプロトコルです。ポートは受信サービスを識別します。このアプリケーションは TCP ポート 80 で待ち受けます。AWS View で Request application · client A をクリックしてください。用意されたクライアント 198.51.100.10 から外部リクエストを送信します。結果は Connection failed と No public address です。アプリケーションは存在しますが、公開経路は未完成です。

インターネットゲートウェイ(IGW)は、VPC の公開ルーティング経路をインターネットに接続します。作成とアタッチは別の操作です。練習用リソースを識別できるよう、新しいゲートウェイにタグを付けます。引用符で囲まれたタグ指定は一つの引数です。

IGW_ID=$(aws ec2 create-internet-gateway \
  --tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value=parcel-internet},{Key=Project,Value=parcel}]' \
  --query 'InternetGateway.InternetGatewayId' \
  --output text)

このゲートウェイだけを、選択したアプリケーションの VPC にアタッチします。

aws ec2 attach-internet-gateway --internet-gateway-id "$IGW_ID" --vpc-id "$VPC_ID"

アタッチに成功してもコマンドの出力はありません。代わりに関連を問い合わせます。

aws ec2 describe-internet-gateways \
  --internet-gateway-ids "$IGW_ID" \
  --query 'InternetGateways[].{ID:InternetGatewayId,Attachments:Attachments}' \
  --output json

アタッチ情報は自分の VPC を示し、状態は available です。AWS View では VPC の下にこのゲートウェイが表示されます。アタッチだけではサブネットのルートやアプリケーションのパブリックアドレスは提供されません。保存した ID を保持するため、この Terminal を開いたままにしてください。

パブリックサブネットのデフォルトルートを追加する

このステップでは、パブリックサブネットのインターネット通信を、アタッチしたゲートウェイへ送ります。

ルートテーブルは宛先の範囲と転送先を対応付けます。各サブネットは関連付けられたテーブルを使用し、明示的な関連付けがなければ VPC のメインテーブルを使用します。この環境には、個別に関連付けられた public-routes と private-routes が用意されています。アプリケーションの VPC 内の public-routes を選択します。

PUBLIC_ROUTE_TABLE_ID=$(aws ec2 describe-route-tables \
  --filters "Name=vpc-id,Values=$VPC_ID" Name=tag:Name,Values=public-routes \
  --query 'RouteTables[0].RouteTableId' \
  --output text)

ルートと関連付けの両方を読み取ります。

aws ec2 describe-route-tables \
  --route-table-ids "$PUBLIC_ROUTE_TABLE_ID" \
  --query 'RouteTables[].{ID:RouteTableId,Routes:Routes,Associations:Associations}' \
  --output json

関連付けは public-subnet を示します。既存の 10.20.0.0/16 ルートの転送先は local で、VPC の通信を VPC 内に保ちます。このローカルルートを削除したり、private-routes を変更したりしないでください。

デフォルトルート 0.0.0.0/0 は、より具体的なルートに一致しない IPv4 宛先を対象とします。--gateway-id でインターネットゲートウェイを転送先に設定します。

aws ec2 create-route \
  --route-table-id "$PUBLIC_ROUTE_TABLE_ID" \
  --destination-cidr-block 0.0.0.0/0 \
  --gateway-id "$IGW_ID"

レスポンスには Return: true が含まれます。テーブルを再度問い合わせます。

aws ec2 describe-route-tables \
  --route-table-ids "$PUBLIC_ROUTE_TABLE_ID" \
  --query 'RouteTables[].Routes[].{Destination:DestinationCidrBlock,Target:GatewayId,State:State}' \
  --output table

デフォルトルートは自分の igw-... を指し、状態は active です。ローカルルートは残っています。AWS View の public-routes の下にも、同じゲートウェイを指す 0.0.0.0/0 が表示されます。Request application · client A をもう一度クリックしてください。まだ No public address で失敗します。サブネットに公開ルートはできましたが、アプリケーションには自身のパブリック IPv4 アドレスが必要です。

パブリックアドレスを関連付けて HTTP をテストする

このステップでは、アプリケーションに Elastic IP を関連付け、外部リクエストを成功させます。

Elastic IP はアカウントに割り当てられるパブリック IPv4 アドレスで、対応リソースに関連付けられます。割り当て ID は予約されたアドレスを識別し、関連付け ID はリソースとの接続を識別します。クリーンアップでは関連付けと割り当ての両方を削除します。

ネットワークインターフェイス(ENI)は、アプリケーションのネットワーク接続とプライベート IP を提供します。この実験ではアプリケーションのインターフェイスが用意されているため、インスタンスの作成や OS の設定は不要です。VPC と名前で選択します。

ENI_ID=$(aws ec2 describe-network-interfaces \
  --filters "Name=vpc-id,Values=$VPC_ID" Name=tag:Name,Values=application-interface \
  --query 'NetworkInterfaces[0].NetworkInterfaceId' \
  --output text)

VPC 用のアドレスを割り当て、割り当て ID を保存します。

ALLOCATION_ID=$(aws ec2 allocate-address \
  --domain vpc \
  --query 'AllocationId' \
  --output text)

アプリケーションのインターフェイスに関連付け、関連付け ID を保存します。

ASSOCIATION_ID=$(aws ec2 associate-address \
  --allocation-id "$ALLOCATION_ID" \
  --network-interface-id "$ENI_ID" \
  --query 'AssociationId' \
  --output text)

変更後のインターフェイスの状態を確認します。

aws ec2 describe-network-interfaces \
  --network-interface-ids "$ENI_ID" \
  --query 'NetworkInterfaces[].{ID:NetworkInterfaceId,PrivateIP:PrivateIpAddress,PublicIP:Association.PublicIp}' \
  --output table

プライベートアドレスは 10.20.1.10 のままで、公開アドレスのフィールドにアドレスが入ります。AWS View のアプリケーションカードには、パブリックアドレスとゲートウェイルートが表示されます。Request application · client A をクリックしてください。

結果は Success、送信元アドレス 198.51.100.10、宛先ポート 80、本文 Application online です。これは用意されたアプリケーションからの HTTP レスポンスです。設定済みリソースの一覧だけではリクエストの成功を証明できません。

アプリケーションにパブリックアドレスとインターネットゲートウェイルートがあり、クライアント A が HTTP レスポンスを受信する

結果の例:パブリックサブネットにはゲートウェイルートとアプリケーションのアドレスが表示され、リクエストは Application online を返します。ID や割り当てアドレスは異なる場合があります。

準備されたアクセスルールは、このクライアントとポートを許可します。次の実験でルールの制御を学びます。ここでは変更しないでください。

ルートの障害を観察して復旧する

このステップでは、一つのルートを削除してリクエストの失敗を観察し、動作する経路を復旧します。

パブリックアドレスはルーティングの代わりにはなりません。自分で作成したデフォルトルートだけを削除し、用意されたローカルルートは保持します。

aws ec2 delete-route \
  --route-table-id "$PUBLIC_ROUTE_TABLE_ID" \
  --destination-cidr-block 0.0.0.0/0

パブリックアドレスがまだ関連付けられていることを確認します。

aws ec2 describe-addresses \
  --allocation-ids "$ALLOCATION_ID" \
  --query 'Addresses[].{PublicIP:PublicIp,Interface:NetworkInterfaceId}' \
  --output table

AWS View の public-routes にはローカルルートだけが残ります。古いレスポンスには Previous request と表示される場合があります。それは変更後の設定を示していません。Request application · client A をクリックして新しいリクエストを送ってください。パブリックアドレスが残っていても、結果は Connection failed になります。

パブリックアドレスは残るが、デフォルトルートの欠落により新しいリクエストが失敗する

診断の例:アプリケーションにはパブリックアドレスが残り、public-routes にはローカルルートしかなく、新しいリクエストは失敗します。

同じアタッチ済みゲートウェイを指すルートを復旧します。

aws ec2 create-route \
  --route-table-id "$PUBLIC_ROUTE_TABLE_ID" \
  --destination-cidr-block 0.0.0.0/0 \
  --gateway-id "$IGW_ID"

レスポンスには Return: true が含まれます。AWS View にルートが再表示されたら、Request application · client A をもう一度クリックします。Success と Application online が戻ります。複数の設定を同時に変えず、ルーティングだけを変更条件として切り分けました。

自分の公開経路を削除する

このステップでは、自分で作成したアドレス、ルート、ゲートウェイだけを削除し、用意されたアプリケーションネットワークと参照ネットワークを保持します。

リソースには依存関係があります。まず、アドレスとインターフェイスの関連付けを解除します。

aws ec2 disassociate-address --association-id "$ASSOCIATION_ID"

次に割り当てを解放します。関連付けの解除だけでは割り当て済みのリソースが残ります。

aws ec2 release-address --allocation-id "$ALLOCATION_ID"

ゲートウェイをデタッチする前に、自分のデフォルトルートを削除します。

aws ec2 delete-route \
  --route-table-id "$PUBLIC_ROUTE_TABLE_ID" \
  --destination-cidr-block 0.0.0.0/0
aws ec2 detach-internet-gateway --internet-gateway-id "$IGW_ID" --vpc-id "$VPC_ID"

最後に、デタッチしたゲートウェイを削除します。

aws ec2 delete-internet-gateway --internet-gateway-id "$IGW_ID"

これらの削除コマンドは成功時に何も出力しません。タグに頼らず、完全な一覧を問い合わせてリソースの不在を確認します。

aws ec2 describe-addresses --query 'Addresses' --output json
aws ec2 describe-internet-gateways --query 'InternetGateways' --output json

この新しい環境では、両方が [] を返します。用意されたサブネットのルートを再確認します。

aws ec2 describe-route-tables \
  --route-table-ids "$PUBLIC_ROUTE_TABLE_ID" \
  --query 'RouteTables[].Routes[].{Destination:DestinationCidrBlock,Target:GatewayId}' \
  --output table

ローカルルートだけが残ります。用意された VPC、サブネット、アプリケーションのインターフェイスは存在しています。AWS View には自分のゲートウェイとパブリックアドレスが表示されなくなります。Request application · client A をもう一度クリックしてください。削除された公開経路はリクエストを処理できません。一覧の取得失敗は、リソースの削除完了を証明しません。

このステップの完了チェックを実行してください。

まとめ

インターネットゲートウェイをアタッチし、アプリケーションのサブネットに関連付けられたテーブルへデフォルトルートを追加し、Elastic IP を関連付けました。実際の HTTP アクセスをテストし、パブリックアドレスがあってもルートの削除でリクエストが失敗することを示し、復旧した後、自分の練習リソースだけを削除しました。

「セキュリティグループでアプリケーションへのアクセスを制御する」に進み、アプリケーションに到達できる外部リクエストを制限しましょう。