AWSにRails + Nginxな環境をTerraformで構築してみようと思います。
はじめに
本連載で一つずつインフラを構築していきます。
ドメインのhttps化したり、ECS Fargateを使用したコンテナオーケストレーションを用いてアプリケーションをデプロイします。
この記事ではRDSの構築をします。
環境は以下です。
OS | Cataline 10.15.6 |
Terraform | 0.14.4 |
基本構文などこちらにまとめてますので、よかったらみてください!
AWS Terraform 基本コード まとめ
連載一覧
- terraform AWS環境構築 事前準備
- 【ネットワーク環境構築】terraform AWS環境構築 第1回
- 【ドメインhttps化・ACM(SSL)証明書発行】terraform AWS環境構築 第2回
- 【ロードバランサー構築】terraform AWS環境構築 第3回
- 【ECS Fargate(nginx)実行】terraform AWS環境構築 第4回
- 【RDS構築】terraform AWS環境構築 第5回 ←ここ
- 【Docker/ECR作成】terraform AWS環境構築 第6回
- 【ECS Fargate(rails + nginx)実行】terraform AWS環境構築 第7回
- 【CircleCIによるCI/CD】terraform AWS環境構築 番外
やること
以下の定義と作成をします。
RDSの構築
DBの環境構築を定義しておきます。
./terrafrom.tfvars に以下を追記します。
db_name = "rails-hello" db_username = "root" db_password = "password"
./variable.tf に以下を追記します。
variable "db_name" {} variable "db_username" {} variable "db_password" {}
rdsモジュールの作成
RDSを作成するモジュールを作成します。
terraformフォルダ内にrdsフォルダを作成しましょう。main.tfも作成しておきます。
rdsモジュールを使用できるよう./main.tfに以下を追記します。
./main.tf
module "rds" { source = "./rds" app_name = var.app_name # DB環境変数 db_name = var.db_name db_username = var.db_username db_password = var.db_password }
rdsモジュール内でapp_nameを受け取れるように、variable.tfを用意します。
./rds/variable.tf
variable "app_name" {} variable "db_name" {} variable "db_username" {} variable "db_password" {}
ディレクトリ構成は以下のようにしています。
[terraform] $ tree . ├── rds │ ├── main.tf │ └── variable.tf ├── ecs_cluster │ ├── main.tf │ └── output.tf ├── ecs_nginx │ ├── container_definitions.json │ ├── data.tf │ ├── main.tf │ └── variable.tf ├── iam_role │ ├── data.tf │ ├── main.tf │ ├── output.tf │ └── variable.tf ├── elb │ ├── data.tf │ ├── main.tf │ ├── output.tf │ └── variable.tf ├── acm │ ├── data.tf │ ├── main.tf │ ├── output.tf │ └── variable.tf ├── network │ ├── main.tf │ ├── output.tf │ └── variable.tf ├── env │ └── backend.config ├── main.tf ├── output.tf ├── backend.tf ├── provider.tf ├── terraform.tfvars └── variable.tf
用意できたら、terraformの初期化を行いましょう。
[terraform] $ terraform init -backend-config=env/backend.config -upgrade
セキュリティーグループの作成
MySQL用のセキュリティーグループを作成します。
./rds/main.tf に以下を追記します。
resource "aws_security_group" "db_sg" { name = "${var.app_name}-mysql" description = "security group on db of ${var.app_name}" vpc_id = var.vpc_id egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } tags = { Name = "${var.app_name}-sg of mysql" } } resource "aws_security_group_rule" "mysql-rule" { security_group_id = aws_security_group.db_sg.id type = "ingress" from_port = 3306 to_port = 3306 protocol = "tcp" source_security_group_id = var.alb_security_group }
- source_security_group_id:アクセスを許可するセキュリティーグループ
vpc_id, alb_security_group が必要になるので、rdsモジュールに追記します。
module "rds" { source = "./rds" app_name = var.app_name db_name = var.db_name db_username = var.db_username db_password = var.db_password # 追記 vpc_id = module.network.vpc_id alb_security_group = module.elb.alb_security_group }
受け取れるように、variable.tfにも追記しておきます。
./rds/variable.tf
variable "vpc_id" {} variable "alb_security_group" {}
terraform plan, apply して作成されるか見てみましょう。
セキュリティーグループが追加で作成さたのが確認できましたね。
DBサブネットグループの作成
RDSインスタンスが配置されうるサブネットのグループを作成します。
./rds/main.tf に以下を追記します。
resource "aws_db_subnet_group" "db_subnet_group" { name = var.db_name description = "db subent group of ${var.db_name}" subnet_ids = var.private_subnet_ids }
- name:DBサブネットグループ名
- description:説明
- subnet_ids:グループ化するサブネット
private_subnet_ids が必要なので、rdsモジュールに追記します。
module "rds" { source = "./rds" app_name = var.app_name db_name = var.db_name db_username = var.db_username db_password = var.db_password vpc_id = module.network.vpc_id alb_security_group = module.elb.alb_security_group # 追記 private_subnet_ids = module.network.private_subnet_ids }
受け取れるように、variable.tfにも追記しておきます。
./rds/variable.tf
variable "private_subnet_ids" {}
terraform plan, apply して作成されるか見てみましょう。
サブネットグループが作成されたのが確認できましたね。
RDSの定義
データベースであるRDSの作成します。
./rds/main.tf に以下を追記します。
resource "aws_db_instance" "db" { allocated_storage = 10 storage_type = "gp2" engine = var.engine engine_version = var.engine_version instance_class = var.db_instance identifier = var.db_name username = var.db_username password = var.db_password skip_final_snapshot = true vpc_security_group_ids = [aws_security_group.db_sg.id] db_subnet_group_name = aws_db_subnet_group.db_subnet_group.name }
- allocated_storage:割当ストレージ
- storage_type:ストレージタイプ
- engine:DBデータベースエンジン
- egine_version:DBエンジンバージョン
- instance_class:DBインスタンスサイズ
- identifier:RDSonly lowercase alphanumeric characters and hyphens allowed inインスタンス名
- username:マスターユーザー名
- password:マスターパスワード
- skip_final_snapshot:DB削除時にスナップショット作成するかどうか
- vpc_security_group_ids:セキュリティーグループ
- db_subnet_group_name:DBサブネットグループ
./rds/variable.tf
variable "engine" { type = string default = "mysql" } variable "engine_version" { type = string default = "8.0.20" } variable "db_instance" { type = string default = "db.t2.micro" }
terraform plan, apply して作成されるか見てみましょう。
データベースが作成されたのが確認できましたね。
まとめ
DBインスタンスのエンドポイントは、Railsサーバーで使用するのでアウトプット変数を定義しておきましょう。
./rds/output.tf
output "db_address" { value = aws_db_instance.db.address }
※ aws_db_instance.db.endpoint だと :3306が最後についてしまうんで、これだとrailsから繋がらないので注意が必要です。
今回、作成したコードとディレクトリ構成は以下になります。
[terraform] $ tree . ├── rds │ ├── main.tf │ ├── output.tf │ └── variable.tf ├── ecs_cluster │ ├── main.tf │ └── output.tf ├── ecs_nginx │ ├── container_definitions.json │ ├── data.tf │ ├── main.tf │ └── variable.tf ├── iam_role │ ├── data.tf │ ├── main.tf │ ├── output.tf │ └── variable.tf ├── elb │ ├── data.tf │ ├── main.tf │ ├── output.tf │ └── variable.tf ├── acm │ ├── data.tf │ ├── main.tf │ ├── output.tf │ └── variable.tf ├── network │ ├── main.tf │ ├── output.tf │ └── variable.tf ├── env │ └── backend.config ├── main.tf ├── output.tf ├── backend.tf ├── provider.tf ├── terraform.tfvars └── variable.tf
./rds/main.tf
resource "aws_security_group" "db_sg" { name = "${var.app_name}-mysql" description = "security group on db of ${var.app_name}" vpc_id = var.vpc_id egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } tags = { Name = "${var.app_name}-sg of mysql" } } resource "aws_security_group_rule" "mysql-rule" { security_group_id = aws_security_group.db_sg.id type = "ingress" from_port = 3306 to_port = 3306 protocol = "tcp" source_security_group_id = var.alb_security_group } resource "aws_db_subnet_group" "db_subnet_group" { name = var.db_name description = "db subent group of ${var.db_name}" subnet_ids = var.private_subnet_ids } resource "aws_db_instance" "db" { allocated_storage = 10 storage_type = "gp2" engine = var.engine engine_version = var.engine_version instance_class = var.db_instance identifier = var.db_name username = var.db_username password = var.db_password skip_final_snapshot = true enabled_cloudwatch_logs_exports = [ "error", "general", "slowquery" ] vpc_security_group_ids = [aws_security_group.db_sg.id] db_subnet_group_name = aws_db_subnet_group.db_subnet_group.name }
./rds/variable.tf
variable "app_name" {} variable "vpc_id" {} variable "alb_security_group" {} variable "engine" { type = string default = "mysql" } variable "engine_version" { type = string default = "8.0.20" } variable "db_instance" { type = string default = "db.t2.micro" } variable "private_subnet_ids" {} variable "db_name" {} variable "db_username" {} variable "db_password" {}
おわり
これで、RDSの構築が完了しました。お疲れさまでした!
何か疑問に思うことがあれば、何でもコメントしてください!
次回は、Rails+NginxのDockerイメージを作成してECRへpushをします。
コメント