🕌
Terraform × AWS で開発基盤を構築してみた(VPC / EC2 / RDS / SecretsManager)
Terraform を用いて、AWS 上に開発環境の基盤を構築した実録ブログです。
構成は最小限ながらも実用的で、VPC → EC2(Bastion/App)→ RDS(MySQL)→ SecretsManager連携までカバー。
また、途中で起きたトラブルの原因と対処法もふまえて、構造的かつ実践的に解説しています。
📘 Part 1: AWS基盤のTerraform構築編
✅ 構成概要
VPC(10.0.0.0/24)
├── Public Subnet(10.0.1.0/28)
│ ├── NAT Gateway
│ └── EC2(Bastion、SSH踏み台)
└── Private Subnet(10.0.2.0/28)
├── App EC2(アプリ用)
└── RDS(MySQL)
- リージョン:
ap-northeast-1
- OS:Ubuntu 20.04(AMI:
ubuntu-focal-20.04
) - 認証:SSH Key / SecretsManager(後述)
✅ Terraformファイル構成
main.tf → VPC, Subnet などのネットワーク系
ec2.tf → EC2(Bastion / App)
rds.tf → RDSインスタンスおよびDBサブネットグループ
secrets.tf → Secrets Managerおよびrandom_password
variables.tf → 各種変数定義
outputs.tf → 作成したリソースの確認用出力(terraform output 用)
outputs.tf の活用ポイント
- 疎通確認時に EC2のIP や RDSエンドポイント、生成されたパスワードなどを即確認できて便利
- 例:
output "bastion_public_ip" {
value = aws_instance.bastion.public_ip
}
output "rds_endpoint" {
value = aws_db_instance.mysql.endpoint
}
✅ SSHキー作成とBastionへの接続
aws ec2 create-key-pair \
--key-name sample-dev-ssh-key \
--query 'KeyMaterial' \
--output text > sample-dev-ssh-key.pem
chmod 400 sample-dev-ssh-key.pem
ssh -i sample-dev-ssh-key.pem ubuntu@<bastion_public_ip>
✅ App EC2へのSSH(Bastion内から)
scp -i sample-dev-ssh-key.pem sample-dev-ssh-key.pem ubuntu@<bastion_ip>:/home/ubuntu/
chmod 400 sample-dev-ssh-key.pem
ssh -i sample-dev-ssh-key.pem ubuntu@<app_private_ip>
📘 Part 2: RDS + SecretsManager接続トラブル解決編
✅ 構成の意図
Terraformで以下を自動作成:
- ランダムなパスワード(random_password)
- Secrets Manager に保存
- RDS にそのSecretsの
username
/password
を使って接続設定
❌ 発生したエラー(よくある)
ERROR 1045 (28000): Access denied for user 'sample_admin'@'10.0.2.X'
🔍 原因分析
Terraformのリソースは基本的に並列に実行されるため、
random_password → secretsmanager → rds
の流れに 明示的な依存関係(depends_on) がないと、
- RDS作成時に SecretsManager の値が まだ確定していない
- 結果として、 空パスワード or 初期値 で作成されてしまう
- → 実際のSecretsManagerとは不一致になり、接続エラー になる
random_password
を直接 RDS に渡す
✅ 解決策:resource "aws_db_instance" "mysql" {
...
username = "sample_admin"
password = random_password.rds_password.result
}
SecretsManagerとの連携は一旦切って、確実に接続できる形に修正。
🔁 RDSの再作成
terraform taint aws_db_instance.mysql
terraform apply
🔐 パスワード確認用のOutputを追加
output "rds_password" {
value = random_password.rds_password.result
sensitive = true
}
出力確認:
terraform output rds_password
✅ MySQL接続確認
mysql -h <rds_endpoint> -P 3306 -u sample_admin -p
📘 Part 3: 実践Tips集(学びポイント)
💡 terraform apply が途中で止まったときの注意点
- 削除しきれてないリソースが残り、再
apply
で失敗することがある - 例:VPCを削除しようとしたが、IGWがまだアタッチされていて削除失敗
DependencyViolation: The vpc 'vpc-xxxx' has dependencies and cannot be deleted.
→ terraform destroy
や taint
を使って順番に削除・再作成
🛢️ RDSは2つ以上のAZにサブネットをまたがる必要あり
DBSubnetGroupDoesNotCoverEnoughAZs:
The DB subnet group doesn't meet Availability Zone (AZ) coverage requirement.
- RDSは高可用性を前提としているため、最低2つの異なるAZにサブネットが必要
- ルートテーブルは共有でOK
🔐 SecretsManagerが削除スケジュール中エラー
InvalidRequestException:
You can't create this secret because a secret with this name is already scheduled for deletion.
- SecretsManagerの削除は猶予期間付き(30日)
- 再作成できないので、
-v2
など別名でSecretsを作るか、削除キャンセルする
👤 AMIによってSSHユーザー名が違う
AMIの種類 | SSHユーザー名 |
---|---|
Amazon Linux 2 | ec2-user |
Ubuntu | ubuntu |
Debian | admin |
RHEL / CentOS |
ec2-user / centos
|
🏁 まとめ
Terraform × AWSで構築するインフラ環境では、構成を自動化できる一方で、
- SecretsManager → RDSの順序依存
- 破棄されないリソースの依存関係
- AMIとユーザー名のマッピング
など細かな罠も多くあります。
それでも、一つずつ原因を突き止めて改善していくことで、信頼性の高い構成を安定して再現できるようになります。
🎯 次にやるなら…
- ECS × ALB × Fargate でのコンテナ化
- SSM Parameter Storeを用いた環境変数管理
- CI/CD(GitHub Actions + Terraform Cloud)導入
- CloudWatch によるモニタリング構成
以上、Terraform × AWS構築記録でした!
Discussion