個人的備忘録：マイグレーション（migrateコンテナ）がRDSへの接続時にタイムアウトする原因と対策をまとめてみた

## はじめに
AWS 環境で **migrate コンテナが RDS への接続時にタイムアウトする問題** は、**ネットワーク設定やセキュリティグループの制約** など、複数の要因によって発生します。  

本記事では、**よくある原因とその解決策を整理し、スムーズなデータ移行を実現するための対策** を紹介します。  

## 書こうと思ったきっかけ
受講している **IT スクールのハッカソン** で、インフラ担当として **AWS の構成を設計** する中で、**migrate コンテナの RDS への接続トラブル** に直面しました。

**実際のAWS構成図**

![Screenshot 2025-02-21 at 7.29.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/14c68cef-7863-4742-97de-dc012a8dfd49.png)

この経験をもとに、**同様の問題を抱える方がスムーズに解決できるよう、本記事を執筆しました。**

**内容は個人の備忘録レベルのため、参考程度にご覧ください。**

## 可能な原因と解決策

### 1. セキュリティグループ (SG) 設定ミス

#### 問題点
- `aws_security_group_rule.rds_allow_ecs` は `ecs_sg` からの **3306 ポート** へのアクセスのみ許可しています。
- しかし、**`migrate` コンテナが `ecs_sg` の範囲内で動作していることを確認する必要があります**。

#### 解決策
##### ECSのSG (`ecs_sg`) に属しているか確認
```sh
aws ec2 describe-instances --filters Name=group-id,Values=<ecs_sgのID>
```
- **`migrate` のIPが出てこない場合**、ECSのセキュリティグループを適切に設定する必要があります。

##### 一時的に `rds_sg` の 3306 ポートをすべてのVPC内から許可

- 一時的に、以下のように設定を変更し、ECSタスクがRDSに接続できるか確認します。
```hcl
resource "aws_security_group_rule" "rds_allow_vpc" {
  type                     = "ingress"
  from_port                = 3306
  to_port                  = 3306
  protocol                 = "tcp"
  security_group_id        = aws_security_group.rds_sg.id
  cidr_blocks              = ["10.0.0.0/16"]  # VPC全体からのアクセスを許可
  description              = "Allow all VPC instances to access RDS"
}
```
接続確認後、不要なアクセスを制限すること。

### 2. RDS のプライベートサブネット (`private3`, `private4`) に NAT が設定されている

#### 問題点
- RDS (`private3`, `private4`) はプライベートサブネットに配置されており、NAT経由でインターネットアクセスできる設定になっています。
- **RDSは通常、外部にアクセスする必要はないため、NAT設定は不要です。**

#### 解決策
##### RDS にNAT経由のルート (`private3_nat_access`, `private4_nat_access`) を削除
```hcl
resource "aws_route" "private3_nat_access" {
  route_table_id         = aws_route_table.private3.id
  destination_cidr_block = "0.0.0.0/0"
  nat_gateway_id         = aws_nat_gateway.public1.id
}

resource "aws_route" "private4_nat_access" {
  route_table_id         = aws_route_table.private4.id
  destination_cidr_block = "0.0.0.0/0"
  nat_gateway_id         = aws_nat_gateway.public1.id
}
```
削除 or コメントアウトし、`terraform apply` する。

### 3. ECS `migrate` タスクのネットワーク設定 (`awsvpc`) が適切でない

#### 問題点
- **ECS タスクが `awsvpc` モードで動作しており、適切なサブネット (`private1`, `private2`) に配置されていない可能性がある。**

#### 解決策
##### `migrate` のECSログを確認
```sh
aws logs tail /ecs/datadog --follow
```
- **「network not reachable」エラーがあるか確認**
- **コンテナの `ifconfig` でIPアドレスが `10.0.128.0/20` または `10.0.144.0/20` になっているか確認**

##### ECSの `network_configuration` を明示的に設定
```hcl
network_configuration {
  subnets         = [aws_subnet.private1.id, aws_subnet.private2.id]
  security_groups = [aws_security_group.ecs_sg.id]
  assign_public_ip = false
}
```
`migrate` が適切なサブネットで動作していることを確認。

### 4. DNS解決ができていない

#### 問題点
- RDSのエンドポイント (`aws_db_instance.rds_instance.address`) が **ECSの`migrate`から解決できていない可能性がある**。

#### 解決策
##### ECS `migrate` コンテナの中でDNS解決を試す
```sh
nslookup terraform-2025022008565705500000000e.crq4wsi04dj7.ap-northeast-1.rds.amazonaws.com
```
- **解決できなければ、ECSタスクがVPC内のDNSに接続できていない**
- **VPCの `enable_dns_hostnames = true`, `enable_dns_support = true` を再確認**

##### MySQLのポートが開いているか確認
```sh
telnet terraform-2025022008565705500000000e.crq4wsi04dj7.ap-northeast-1.rds.amazonaws.com 3306
```
- **タイムアウトする場合、SGの問題でポートが開いていない可能性がある**

### 5. `migrate` コンテナの MySQL 接続リトライ処理

#### 問題点
- RDSがまだ起動していない状態で `migrate` を実行すると、**即座に失敗してしまう**。

#### 解決策
##### `migrate` のエントリポイントを修正し、MySQLが起動するまでリトライする
```hcl
entryPoint = ["/bin/sh", "-c", "
  until mysql -h '$MYSQL_HOST' -u '$MYSQL_USER' -p'$MYSQL_PW' -e 'SELECT 1'; do
    echo 'Waiting for MySQL to be ready...'
    sleep 5
  done;
  echo 'MySQL is ready, running migration...';
  ./migrate;
"]
```

この手順で `migrate` のタイムアウト問題を解決できるはずです...。

## まとめ

migrate コンテナが RDS に接続できない原因として、**セキュリティグループの設定ミスやネットワーク設定の誤り、DNS の解決不可** などが考えられます。  

:::note warn
**ECS のネットワーク設定 (**awsvpc モード**) や、RDS へのアクセス許可 (**3306 ポート開放**) を適切に確認することが重要です。**
:::

本記事は **個人の備忘録レベル** のため、参考程度にご覧ください...。