🐾

FargateとRDSを接続するために、VPCエンドポイントとセキュリティグループを設定する

に公開

社内の業務効率化システムを、踏み台サーバー構成からECS on Fargateに移行した話の続きになります。

事象

社内の業務効率化システムを、踏み台サーバー構成からECS on Fargateに移行する際に、FargateとRDS(データベース)を異なるVPC(=家の敷地みたいなもの)に置いてしまい、RDSへの接続エラーが出ていました。

同じVPC内に移せばいいってものじゃなかった

エラーを解消するため、FargateをRDSと同じVPC内に移す、つまりFargateとRDSを同じ家の敷地内に移せばいいのかと思ったのですが、そうは問屋が卸しませんでした。

なぜ接続できないのかを理解するには、VPCにおける「サブネット」について理解する必要があります。

VPCは家の敷地ないしはマンションのようなものなのですが、その中は「サブネット」という部屋で分かれています。サブネットにも3種類存在し、インターネットとの通信が発生するPublic Subnet、一部のアクセスのみが許可されるProtected Subnet、インターネットから直接アクセスできないPrivate Subnetがあります。

はじめにFargateをRDSと同じVPC内に移動する時、以下のように、FargateをPrivate Subnet、RDSをProtected Subnetに配置するアーキテクチャにしました。

( Internet / AWS Managed Area )

      ┌──────────▼──────────┐
      │     AWS ECR 📦      │
      │  (Image Registry)   │
      └─────────────────────┘

      ===========│===================================
       【 VPC 】  │ ❌ 接続できない

      ┌──────────▼──────────┐
      │   Private Subnet    │
      │                     │
      │   ┌─────────────┐   │
      │   │   Fargate   │   │
      │   └──────┬──────┘   │
      └──────────┼──────────┘

                 │ ❌ 接続できない

      ┌─────────────────────┐
      │  Protected Subnet   │
      │   ┌─────────────┐   │
      │   │     RDS     │   │
      │   │  (Database) │   │
      │   └─────────────┘   │
      └─────────────────────┘

でもこれだけでは接続できません。

Dockerイメージが保管してあるECRや、ログを保存するCloudWatch LogsはVPCの外にあるため、これらにアクセスするためにはインターネットを経由しなくてはいけません。

なので、FargateがECRという倉庫からイメージを取ってくる手段と、RDSにリクエストを送る手段を作ってあげる必要があります。

VPCエンドポイントの導入

まず、FargateがECRからイメージを取得できるようにするため、VPCエンドポイントを導入しました。

VPCエンドポイントはAWSサービスへの直通トンネルのようなもので、Private Subnetに置いてあるFargateがECRやCloudWatch Logsと接続することを可能にします。

今回導入したのは以下の4つのエンドポイントです。

エンドポイント 用途
ECR API ECRの認証やAPI操作用
ECR DKR Dockerイメージのダウンロード用
S3 イメージの実体(レイヤー)がS3にあるため必須
CloudWatch Logs CloudWatch Logsへのログ送信用

これで無事にコンテナが起動し、FargateがECRからイメージを取得・起動できるようになりました。
しかし、アプリケーションのログを見るとDB接続エラーが発生していました。

Connection timed out: could not connect to server: Connection refused
Is the server running on host "rds-endpoint" and accepting TCP/IP connections on port 5432?

同じVPCの中にいて、ネットワークも繋がっているはずなのに、RDSに拒否されてしまいます。

セキュリティグループを設定する

これについては、セキュリティグループを設定することで解決しました。

セキュリティグループというのは、VPCというマンションのインターフォンのようなものです。
セキュリティグループは、デフォルトで「すべての受信を拒否」となっており、いくら同じ敷地内(VPC)にいるFargateさんであっても、セキュリティグループという入館許可リストに名前がなければ、かなしいかな、門前払いです。

というわけで、セキュリティグループIDを使って許可設定を行いました。
(ちなみに、FargateのIPアドレスを許可することを最初考えたのですが、Fargateは再起動のたびにIPアドレスが変わるので断念しました)

設定手順としては、

  1. Fargate用のセキュリティグループを作成(例: hogehoge)
  2. RDSのセキュリティグループのインバウンドルールを編集
    • タイプ: PostgreSQL (5432)
    • ソース: hogehoge (IPアドレスではなく、SGのIDを選択)
# イメージ:AWS CLIで書くとこんな感じ
aws ec2 authorize-security-group-ingress \
  --group-id [RDS_SG_ID] \
  --protocol tcp \
  --port 5432 \
  --source-group [FARGATE_SG_ID]

これで、「このIDの名札(hogehoge)を付けている人なら、IPが何であろうと通してOK」 という柔軟な設定が可能になります。

同様に、Dify(EC2)からFargateへのアクセス(Port 8000)も、DifyのセキュリティグループIDをソースに指定して許可しました。

FargateとRDSを接続する構成

VPCエンドポイントという直通トンネルでVPCという屋敷の壁を抜け、セキュリティグループの設定でRDSの扉を開く通行手形を発行したことで、FargateとRDSがようやく接続できるようになりました。

最終的な構成は次のようになりました。

( Internet / AWS Managed Area )

      ┌──────────▼──────────┐
      │  AWS ECR / S3 📦    │
      │ (Image & Layers)    │
      └──────────▲──────────┘

      ===========│===================================
       【 VPC 】 │ ✅ トンネル開通 (VPC Endpoint)

      ┌──────────┴──────────┐
      │   Private Subnet    │
      │                     │
      │   ┌─────────────┐   │ 🏷️ hogehoge (通行手形)
      │   │   Fargate   │───┼──────────┐
      │   │  (Running!) │   │          │
      │   └──────┬──────┘   │          │
      │          │          │ 🚇 VPC Endpoint
      │          │          │    (Interface/Gateway)
      └──────────┼──────────┘

                 │ ✅ 許可 (Allow hogehoge)

      ┌─────────────────────┐
      │  Protected Subnet   │
      │   ┌─────────────┐   │
      │   │     RDS     │   │
      │   │  (Database) │◀──┘ "hogehoge" なら
      │   └─────────────┘      通してよし!
      └─────────────────────┘

学び

  • プライベートサブネットはデフォルトではインターネットに接続できない。ECRといったVPC外にあるAWSサービスを使うにはVPCエンドポイントを設定する必要がある
  • 同じVPC内であっても、セキュリティグループの設定がなければ接続することができない。接続元が変わるコンテナ環境では、IP指定ではなく、セキュリティグループIDで接続許可する方が🙆‍♀️
Atrae Tech

Discussion