はじめに
プライベートECSクラスターを構築する機会があったので、作業中つまったところをまとめておきます。
本記事で扱う内容
- ECSクラスターをプライベートに構築した際のハマりどころと、その対処方法
- API Gateway → NLB、ECR、S3、DynamoDB、OpenSearch Serverlessなどの各AWSサービスとの統合・通信周りの話
今回構築した構成
今回構築した構成は以下の通りです。
API Gateway から Network Load Balancer (NLB) を通し、Private Subnet 内の ECS クラスターへアクセスするアーキテクチャになっています。外部アクセスを最小化しつつ、各種AWSサービス(DynamoDB、S3、ECR、OpenSearch Serverless など)と連携するようにしています。
構築にはCloudFormationを使用しました。
課題①: API Gateway と NLB の通信設定
状況
- API Gateway と NLB の間で通信できず、API Gatewayのテストで
500 Internal Server Error
が返ってくる -
- API Gatewayで
500
を返す設定にデフォルトでなっているのは以下の場合: - API 設定エラー
- オーソライザー設定エラー
- オーソライザーエラー
- API Gatewayで
- 認証自体はうまくいっているが通信が確立しないので、APIGW-NLBの通信に関する設定が間違っていそう。
原因
- API GatewayのエンドポイントURLを http で指定していたが、NLB側のリスナーが 8000 ポートを待ち受ける設定になっていた。(8000ポート はアプリで使用)
解決策
- NLBのリスナーをポート80でリッスン するように変更する。
- NLBのセキュリティ設定で「PrivateLink トラフィックにインバウンドルールを適用する」オプションを無効化する。(←これは念の為に)
課題②: プライベートECSクラスターへのアプリデプロイがうまくいかない
状況
- ECSクラスタのタスクを作成してもアプリが起動しない。
- 作成したサービスのログがまったく出力されていない。
原因
- ECSクラスターはCloudWatch Logsの使用が必要だった
- タスク実行ロールで
CreateLogGroup
が足りていなかった。(AWS管理のAmazonECSTaskExecutionRolePolicy
ポリシーをタスク実行ロールに関連付けていたがこの権限はなかった) - ECSクラスタは CloudWatch Logs へのアクセスを必要としているが、通信経路が存在しなかった。
以下はプライベートECSクラスターに最低限必要な通信経路
com.amazonaws.region.ecr.api, com.amazonaws.region.ecr.dkr
com.amazonaws.region.s3 (ゲートウェイ型)
com.amazonaws.region.ecr.api (Linux 1.4.0およびWindows 1.0.0から必要)
解決策
- CloudWatch Logs用のVPCエンドポイント を作成。
- タスク実行ロールに **
logs:CreateLogGroup
**の権限を付与。 - CloudWatch Logsのロググループを事前に作成、またはタスク作成時に自動作成されるよう設定
課題③: DynamoDBのVPCエンドポイント選択(Gateway型 or Interface型)
状況
- ECSクラスタ上のアプリから DynamoDB に通信できない
- Interface型エンドポイント を作成済み
- ECSクラスタから他のサービスエンドポイントはOKだが、DynamoDB用エンドポイントのモニタリングでアクティブ接続が確認できない
原因
- Interface型エンドポイント ではプライベートDNS名の有効化ができず、アプリ側でエンドポイントURLを指定する必要がある
- Gateway型エンドポイント ならルートテーブルだけの設定で済み、DNS周りの追加手順が不要
解決策
アプリ側での変更を必要としないよう、DynamoDBのVPCエンドポイントを Interface型 から Gateway型 に切り替えた。
課題④: OpenSearch Serverlessのエンドポイント作成方法
状況
- OpenSearch ServerlessのVPCエンドポイントを、他のサービス同様「VPC → エンドポイント」から作ろうとしたところ、該当サービスが見つからず困った
- CloudFormationを使っても
AWS::EC2::VPCEndpoint
では作成できない
解決策
- OpenSearch Serverlessのコンソール からVPCエンドポイントを作成。
- CloudFormationを使う場合は
Type: AWS::OpenSearchServerless::VpcEndpoint
を指定する。 - 他のエンドポイントのように
AWS::EC2::VPCEndpoint
でServerless用エンドポイントは作成できないので注意。