Elastic Beanstalk で NAT ゲートウェイを使用しない場合に必要な VPC エンドポイントを調べてみた
Elastic Beanstalk にプライベートなアプリケーションを構築する場合、NAT ゲートウェイを使用することがあると思います。
Amazon VPC で Elastic Beanstalk を使用する - AWS Elastic Beanstalk
プライベートサブネット – インスタンスは NAT デバイスを使用してインターネットにアクセスします。
しかし、セキュリティ要件で直接インターネットへ接続することができない場合に、NAT ゲートウェイを使用できない場合もあると思います。
その際、アプリケーションを正常に起動するために最低限必要な VPC エンドポイントが AWS 公式ドキュメントには記載されていなかったので調べてみました。
結論
以下の 4 つの VPC エンドポイントが必要でした。
・com.amazonaws.ap-northeast-1.s3
・com.amazonaws.ap-northeast-1.sqs
・com.amazonaws.ap-northeast-1.cloudformation
・com.amazonaws.ap-northeast-1.logs
なお、最低限必要な VPC エンドポイントではありませんが、Elastic Beanstalk コンソールで環境のヘルスを表示するためには、以下の VPC エンドポイントが必要でした。
・com.amazonaws.ap-northeast-1.elasticbeanstalk-health
検証環境
- パブリックサブネット × 2 (図では 1 つに省略)
- プライベートサブネット × 1
- ルートテーブル
- VPC のローカル (
10.0.0.0/16
) - S3 の VPC エンドポイント
- VPC のローカル (
- ルートテーブル
- VPC エンドポイント
- com.amazonaws.ap-northeast-1.s3 (ゲートウェイ型)
- com.amazonaws.ap-northeast-1.sqs (インターフェイス型)
- com.amazonaws.ap-northeast-1.cloudformation (インターフェイス型)
- com.amazonaws.ap-northeast-1.logs (インターフェイス型)
- VPC エンドポイントのセキュリティグループ
- インバウンドは VPC 内からのすべてのトラフィックを許可
- アウトバウンドはデフォルトですべてのトラフィックを許可
- パブリック ALB
- Elastic Beanstalk により自動作成
- プライベートサブネットで起動した Elastic Beanstalk 環境
Elastic Beanstalk 起動時の設定
- ウェブサーバー環境
- プラットフォーム
- Node.js 16 running on 64bit Amazon Linux 2
- 5.6.0 (Recommended)
- サンプルアプリケーション
- プリセット
- カスタム設定
- ソフトウェア
- CloudWatch Logs へのインスタンスログのストリーミング: 有効
- ライフサイクル: 終了時にログを削除する
- ネットワーク
- ロードバランサーのサブネット
- パブリックサブネット × 2
- インスタンスサブネット
- プライベートサブネット × 1
- ロードバランサーのサブネット
上記以外はデフォルト設定です。
環境起動確認
上記の設定で Elastic Beanstalk 環境を起動すると、数分でサンプルアプリケーションに接続できました。
ALB のヘルスチェックにも合格しています。
CloudWatch Logs にもログが出力されています。
環境が起動できない場合には、VPC エンドポイントを設置するサブネットや、VPC エンドポイントのセキュリティグループの設定を見直してください。
elasticbeanstalk-health がない場合
拡張ヘルスのための VPC エンドポイントである「elasticbeanstalk-health.region.amazonaws.com」がない場合、Elastic Beanstalk コンソールでは以下のように表示されます。
また、以下のイベントも記録されていました。
Environment health has transitioned from Ok to Unknown. None of the instances are sending data.
上記の表示になる理由については、以下の AWS 公式ドキュメントに関連する情報が記載されています。
VPC エンドポイントでの Elastic Beanstalk の使用 - AWS Elastic Beanstalk
環境の 拡張ヘルスレポート を有効にすると、拡張ヘルス情報を AWS PrivateLink 経由で送信するように設定することもできます。拡張ヘルス情報は、環境インスタンスの Elastic Beanstalk コンポーネントである healthd デーモンによって、別の Elastic Beanstalk 拡張ヘルスサービスに送信されます。VPC でこのサービスのインターフェイス VPC エンドポイントを作成するには、「インターフェイスエンドポイントの作成」の手順に従います。[サービス名] で、com.amazonaws.region.elasticbeanstalk-healthを選択します。
拡張ヘルスのための VPC エンドポイントは Elastic Beanstalk 環境の起動には必須ではありませんでしたが、環境のヘルスチェックに関する情報が必要な場合には設定すると良いと思います。
拡張ヘルスのための VPC エンドポイントを設定後の Elastic Beanstalk コンソールではヘルスが OK になりました。
VPC エンドポイントが不足している場合
先述の 4 つの VPC エンドポイントのうち、1 つでも不足している場合には、アプリケーションが正常にインストールされないようで、ALB によるヘルスチェックが失敗します。
試しに S3 のエンドポイントをルートテーブルから削除して、既存 Elastic Beanstalk 環境の EC2 をスケールアウトで新規起動するよう、最小容量を増やします。
新規に起動した EC2 インスタンスですが、ALB のヘルスチェックに失敗しています。
また、CloudWatch Logs にもログが出力されていません。
EC2 の中身までは確認していませんが、ユーザーデータには以下の設定が記載されています。
Content-Type: multipart/mixed; boundary="===============5189065377222898407=="
MIME-Version: 1.0
--===============5189065377222898407==
Content-Type: text/cloud-config; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="cloud-config.txt"
#cloud-config
repo_upgrade: none
repo_releasever: 2.0
cloud_final_modules:
- [scripts-user, always]
--===============5189065377222898407==
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="user-data.txt"
#!/bin/bash
exec > >(tee -a /var/log/eb-cfn-init.log|logger -t [eb-cfn-init] -s 2>/dev/console) 2>&1
echo [`date -u +"%Y-%m-%dT%H:%M:%SZ"`] Started EB User Data
set -x
function sleep_delay
{
if (( $SLEEP_TIME < $SLEEP_TIME_MAX )); then
echo Sleeping $SLEEP_TIME
sleep $SLEEP_TIME
SLEEP_TIME=$(($SLEEP_TIME * 2))
else
echo Sleeping $SLEEP_TIME_MAX
sleep $SLEEP_TIME_MAX
fi
}
# Executing bootstrap script
SLEEP_TIME=2
SLEEP_TIME_MAX=3600
while true; do
curl https://elasticbeanstalk-platform-assets-ap-northeast-1.s3.ap-northeast-1.amazonaws.com/stalks/eb_nodejs16_amazon_linux_2_1.0.1696.0_20220929200609/lib/UserDataScript.sh > /tmp/ebbootstrap.sh
RESULT=$?
if [[ "$RESULT" -ne 0 ]]; then
sleep_delay
else
/bin/bash /tmp/ebbootstrap.sh 'https://cloudformation-waitcondition-ap-northeast-1.s3-ap-northeast-1.amazonaws.com/arn%3Aaws%3Acloudformation%3Aap-northeast-1%3A470745586162%3Astack/awseb-e-38amvtnyvm-stack/5df91d70-477b-11ed-ae80-0aa73405eab9/AWSEBInstanceLaunchWaitHandle?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20221009T023755Z&X-Amz-SignedHeaders=host&X-Amz-Expires=86399&X-Amz-Credential=AKIASU3QWAIZOQBBO25R%2F20221009%2Fap-northeast-1%2Fs3%2Faws4_request&X-Amz-Signature=d1fa0c3c2aef9c8e7ab0f1bbc4bc8dd69d0f40a52e4360d096c52a285e0dff2f' 'arn:aws:cloudformation:ap-northeast-1:470745586162:stack/awseb-e-38amvtnyvm-stack/5df91d70-477b-11ed-ae80-0aa73405eab9' 'a4cbe856-ff20-4927-9d2e-c69e9361562b' 'https://elasticbeanstalk-health.ap-northeast-1.amazonaws.com' '' 'https://elasticbeanstalk-platform-assets-ap-northeast-1.s3.ap-northeast-1.amazonaws.com/stalks/eb_nodejs16_amazon_linux_2_1.0.1696.0_20220929200609' 'ap-northeast-1'
RESULT=$?
if [[ "$RESULT" -ne 0 ]]; then
sleep_delay
else
exit 0
fi
fi
done
--===============5189065377222898407==--
ユーザーデータの中で、S3 や CloudFormation のエンドポイントらしき URL が記載されているので、このあたりが必要な VPC エンドポイントと関連がありそうです。
S3 のエンドポイントを再度ルートテーブルに設定すると、正常にアプリケーションがインストールされ、CloudWatch Logs にもログが出力されます。
SQS の VPC エンドポイントの必要性
ワーカー環境であれば SQS の VPC エンドポイントの必要性が分かりやすいのですが、ウェブサーバー環境で SQS の VPC エンドポイントが必要な理由については、以下の外部サイトで記載されていました。
amazon web services - Elastic Beanstalk App in Private VPC without NAT - Stack Overflow
On the following deployment I now noticed a new sqs connection error which was solved by adding the sqs endpoint.
どうやらウェブサーバー環境でも裏側で SQS との通信が行われているようです。
そのため、SQS の VPC エンドポイントが必要であることがわかりました。
EC2 のセキュリティグループで必要なアウトバウンドルール
セキュリティ要件が厳しい場合には、Elastic Beanstalk 環境内の EC2 インスタンスのセキュリティグループルールで、特定のアウトバウンドルールのみ許可するという場合もあると思います。
そこで、必要なアウトバウンドルールについても調査してみたところ、以下のようなアウトバウンドルールであればアプリケーションが正常にインストールされることが確認できました。
・すべてのトラフィック: VPC のローカル (10.0.0.0/16
)
・HTTPS: S3 の VPC エンドポイントのプレフィックスリスト
HTTPS のルールがない場合、おそらくユーザーデータに記載されている S3 のエンドポイントに接続できなくなるため、アプリケーションのインストールができないものと思われます。
そのため、HTTPS で S3 へのアクセスも許可することが必要であると思われます。
まとめ
今回は Elastic Beanstalk で NAT ゲートウェイを使用しない場合に必要な VPC エンドポイントを調べてみました。
NAT ゲートウェイを使用できない要件の場合に参考になれば幸いです。
参考資料
- Amazon VPC で Elastic Beanstalk を使用する - AWS Elastic Beanstalk
- VPC エンドポイントでの Elastic Beanstalk の使用 - AWS Elastic Beanstalk
- amazon web services - Elastic Beanstalk App in Private VPC without NAT - Stack Overflow
- AWS cfn-signal not working in private subnets – Linux n DevOPS
- Elastic beanstalk instances can't be placed in private subnets (without NAT gateway) ? : aws
Discussion