はじめに
パブリックサブネットのECSでコンテナが動いたので、次はセキュリティを考えてプライベートサブネットに配置してみよう。そう思って設定を変更したら、タスクが起動しなくなった...という話です。この記事では、その時の問題と解決方法を共有します。
やりたかったこと
AWSでWebサイトを公開する方法として、最初はS3の静的ホスティングを検討していました。しかし、せっかくなのでコンテナ技術を学びたいと思い、nginxコンテナを使うことにしました。
コンテナを選んだ理由:
- コンテナ技術の学習: DockerやECSといったコンテナ技術を実際に触って学びたかった
- 設定の自由度: nginxの設定ファイルを自分で書くことで、Webサーバーの動作を細かく制御できる
- 今後の応用: 最初は静的コンテンツだけでも、将来的にバックエンドAPIを追加したり、認証機能を組み込んだりと拡張しやすい
なぜプライベートサブネットに配置したかったのか
最初はパブリックサブネットでコンテナを動かしていましたが、AWSのベストプラクティスやセキュリティの記事を読むうちに「アプリケーションはプライベートサブネットに置くべき」ということを知りました。
プライベートサブネットに置く理由:
- コンテナに直接アクセスされるリスクを減らせる
- ALB(ロードバランサー)経由でのみアクセスできるようにする
「よし、サブネットを変更するだけだから簡単だろう」と思っていたのですが...ここで問題が発生しました。
遭遇した問題
ECS タスクが起動しない
プライベートサブネットにECSタスクを配置してデプロイしたところ、さっきまで動いていたコンテナが突然起動しなくなりました。タスクは一瞬起動するものの、すぐに停止してしまいます。
サブネットを変えただけなのに、何が起きたのか...?
原因の特定プロセス
最初は何が問題なのか全く分かりませんでした。というのも、CloudWatch Logsにログが表示されない状態だったからです。
タスク定義ではログドライバーをawslogsに設定していたのに、CloudWatch Logsのコンソールを見ても何も表示されません。ログが確認できないので、エラーの詳細も分からず、原因の特定に時間がかかりました。
後で分かったのですが、これもプライベートサブネットからCloudWatch Logsにアクセスできないことが原因でした。
なんとかECSコンソールのstoppedタスクの詳細を確認したところ、以下のようなエラーメッセージが表示されていました:
CannotPullContainerError: pull image manifest has been retried 5 time(s):
failed to resolve ref: failed to do request:
Head "https://*****.dkr.ecr.ap-northeast-1.amazonaws.com/v2/my-nginx/manifests/latest":
dial tcp *.*.*.*:443: i/o timeout
エラーメッセージを読み解いてみます:
-
CannotPullContainerError→ コンテナイメージを取得できない -
pull image manifest has been retried 5 time(s)→ 5回リトライしても失敗 -
dial tcp *.*.*.*:443: i/o timeout→ 443番ポート(HTTPS)への接続がタイムアウト
つまり、ECRからコンテナイメージをダウンロードしようとしているが、接続できないということです。
ここで気づいたのが、「プライベートサブネットにはインターネットへの経路がない」という基本的な事実でした。
パブリックサブネットにいた時は、インターネット経由でECR(コンテナイメージの保管場所)にアクセスできていました。しかしプライベートサブネットには外への道がないので、ECRに接続できなくなってしまったのです。
同様に、CloudWatch Logsにもアクセスできないため、ログも送信できなかったというわけです。
解決方法
プライベートサブネットからECRにアクセスするには、VPCエンドポイントを使用する必要があります。
1. VPC エンドポイントの設定
ECSタスクがプライベートサブネットからECRのイメージをpullするには、以下の4つのVPCエンドポイントが必要です:
① ECR API用エンドポイント (com.amazonaws.ap-northeast-1.ecr.api)
- ECRのAPIリクエストに使用
- 認証や認可の処理を担当
- タイプ: Interface型
② ECR Docker用エンドポイント (com.amazonaws.ap-northeast-1.ecr.dkr)
- Dockerクライアントがイメージレイヤーをpullする際に使用
- タイプ: Interface型
③ S3用ゲートウェイエンドポイント (com.amazonaws.ap-northeast-1.s3)
- ECRはイメージレイヤーの実体をS3に保存しているため、S3へのアクセスも必要
- タイプ: Gateway型(コスト: 無料)
④ CloudWatch Logs用エンドポイント (com.amazonaws.ap-northeast-1.logs)
- ECSタスクのログをCloudWatch Logsに送信するために必要
- これがないとログが見れず、デバッグが困難になる
- タイプ: Interface型
設定手順:
- VPCコンソールで「エンドポイント」を選択
- 「エンドポイントの作成」をクリック
- 上記4つのサービス名をそれぞれ選択して作成
- ECR用とCloudWatch Logs用の3つはプライベートサブネットを選択
- S3用はルートテーブルを選択
2. セキュリティグループの設定
VPCエンドポイント(Interface型)には、適切なセキュリティグループの設定が必要です。
VPCエンドポイント用セキュリティグループ
インバウンドルール:
Type: HTTPS
Protocol: TCP
Port: 443
Source: ECSタスクのセキュリティグループ
ECSタスク用セキュリティグループ
アウトバウンドルール:
Type: HTTPS
Protocol: TCP
Port: 443
Destination: VPCエンドポイントのセキュリティグループ
この設定により、ECSタスクからVPCエンドポイント経由でECRへ安全に通信できるようになります。
3. 最終構成図
Internet
|
v
[ALB] (パブリックサブネット)
|
v
[ECS Task - nginx] (プライベートサブネット)
|
+---> [VPC Endpoint: ECR API]
+---> [VPC Endpoint: ECR Docker]
+---> [VPC Endpoint: S3 Gateway]
+---> [VPC Endpoint: CloudWatch Logs]
|
v
[ECR / CloudWatch Logs] (AWSサービス)
ユーザーからのリクエストはALB経由でnginxコンテナに到達し、コンテナのイメージpullはVPCエンドポイント経由でECRから行われます。また、コンテナのログはCloudWatch Logsに送信されます。
ハマったポイント
VPCエンドポイントの種類
最初、ECR用のエンドポイントを2つ作成する必要があることを知らず、ecr.apiだけを作成してしまい、同じエラーが継続しました。ECRではAPIとDockerの両方のエンドポイントが必須なので注意が必要です。
S3エンドポイントの見落とし
ECRがS3にイメージレイヤーを保存していることを最初は知らず、S3のゲートウェイエンドポイントを設定し忘れていました。ECR用の2つのエンドポイントだけでは不十分で、S3も必要になります。
CloudWatch Logsエンドポイントの見落とし
ECRからのpullは成功したのに、なぜかタスク定義のログ設定で指定したログが見れない...ということがありました。これもCloudWatch Logs用のVPCエンドポイントが必要でした。ログが見れないとデバッグが大変なので、最初から設定しておくことをおすすめします。
セキュリティグループの設定漏れ
VPCエンドポイントを作成しただけでは通信できず、適切なセキュリティグループの設定が必要でした。特に、ECSタスクからVPCエンドポイントへのHTTPS(443)通信を許可する設定を忘れがちです。
まとめ
学んだこと
- プライベートサブネットからAWSサービスにアクセスするには、VPCエンドポイントが必要
- ECRからイメージをpullするには、ECR API、ECR Docker、S3の3つのエンドポイントが必要
- ログを確認するには、CloudWatch Logs用のVPCエンドポイントも必要(デバッグに必須!)
- VPCエンドポイントにも適切なセキュリティグループの設定が必要
- ネットワーク構成を理解することで、セキュアなアーキテクチャを構築できる
コスト面の考慮点
- Interface型VPCエンドポイント: 約0.01 USD/時間 × 3 = 約22 USD/月
- ECR API、ECR Docker、CloudWatch Logs
- Gateway型VPCエンドポイント(S3): 無料
- データ転送料: 0.01 USD/GB
頻繁にデプロイを行わない場合、VPCエンドポイントのコストは比較的低く抑えられます。一方で、セキュリティ向上のメリットは大きいため、本番環境では導入を推奨します。
おわりに
プライベートサブネット構成は最初は複雑に感じるかもしれませんが、一度理解すればセキュアで拡張性の高いインフラを構築できます。同じ問題で困っている方の助けになれば幸いです。
質問やフィードバックがあれば、コメント欄でお気軽にどうぞ!