📘

Amazon RDS×Terraform

2022/10/29に公開約9,700字

Amazon RDSとは

Amazon RDS(Relational Database Service)とは、AWSにハードウェア・ネットワーク機器をマネジメントされたRDBSのこと。MySQL, Postgresに互換性を持ち、1AZ(Availabiliy Zone)内に2箇所、3AZにわたってデータ保存が可能です。

https://aws.amazon.com/jp/rds/features/
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_parameter_group

Amazon RDSの構成要素・依存関係

  • パラメータグループ
    データベースの文字設定を行います。

  • オプショングループ
    データベースのエンジン名やバージョンを設定します。

  • サブネットグループ
    関連付けたいプライベートサブネットを指定します。

RDSを構築

Terraformでリソースを作成していきます。
https://registry.terraform.io/modules/terraform-aws-modules/rds/aws/latest

完成イメージ

運用管理者 ⇒ [Public Subnet] EC2 踏み台サーバ ⇒ [Private Subnet] RDS

構築手順

STEP1: RDSインスタンスを作成

  1. RDS接続可能なネットワーク経路を作成
  2. パラメータグループを作成
  3. オプショングループを作成
  4. サブネットグループを作成
  5. RDSインスタンスを作成

1.1. RDS接続可能なネットワーク経路を作成

RDSのインバウンド設定を参考。
https://zenn.dev/mizuneko4345/articles/3356928428a5d1

1.2. パラメータグループを作成

resource "aws_db_parameter_group" "mysql_standalone_parametergroup" {
  name   = "${var.project}-${var.environment}-mysql-standalone-parametergroup"
  family = "mysql8.0"

  parameter {
    name  = "character_set_database"
    value = "utf8mb4"
  }

  parameter {
    name  = "character_set_server"
    value = "utf8mb4"
  }
}

反映が確認できました。

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_parameter_group#example-usage

1.3. オプショングループを作成

option {...は今回つけずシンプルな構成とします。

resource "aws_db_option_group" "mysql_standalone_optiongroup" {
  name                 = "${var.project}-${var.environment}-mysql-standalone-optiongroup"
  engine_name          = "mysql"
  major_engine_version = "8.0"
}

反映が確認できました。

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_option_group

1.4. サブネットグループを作成

  • 完成イメージ

秘密情報を保管する目的で、前回作成したVPC内のサブネットの内プライベートサブネットを利用します。

resource "aws_db_subnet_group" "mysql_standalone_subnetgroup" {
  name = "${var.project}-${var.environment}-mysql-standalone-subnetgroup"
  subnet_ids = [
    aws_subnet.private_subnet_1a.id, //秘密情報のためprivate
    aws_subnet.private_subnet_1c.id
  ]

  tags = {
    Name    = "${var.project}-${var.environment}-mysql-standalone-subnetgroup"
    Project = var.project
    Env     = var.environment
  }
}

反映が確認できました。

参照しているサブネットを確認します。以前作成した2AZのprivateサブネットに紐づいていることが確認できました。

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_subnet_group

1.5. RDSインスタンスを作成

resource "aws_db_instance" "mysql_standalone" {
  engine         = "mysql"
  engine_version = "8.0.23" //最新

  identifier = "${var.project}-${var.environment}-mysql-standalone"

  username = "admin" //DBのユーザ名
  password = random_string.db_password.result

  instance_class = "db.t2.micro"

  allocated_storage     = 20 # ストレージの大きさ
  max_allocated_storage = 50 # ストレージの自動拡張サイズ
  storage_type          = "gp2"
  storage_encrypted     = false # ストレージの暗号化無し

  multi_az               = false
  availability_zone      = "ap-northeast-1a"
  db_subnet_group_name   = aws_db_subnet_group.mysql_standalone_subnetgroup.name
  vpc_security_group_ids = [aws_security_group.db_sg.id]
  publicly_accessible    = false # もちろん
  port                   = 3306 # SGの設定でそうなってる

  db_name              = "zenn" //推奨の書き方を使う
  parameter_group_name = aws_db_parameter_group.mysql_standalone_parametergroup.name
  option_group_name    = aws_db_option_group.mysql_standalone_optiongroup.name

  backup_window              = "04:00-05:00"
  backup_retention_period    = 7 //バックアップ保存期間
  maintenance_window         = "Mon:05:00-Mon:08:00" //DB,OSのバージョン自動更新対応
  auto_minor_version_upgrade = false //常に最新

  deletion_protection = true //RDSインスタンス削除受付
  skip_final_snapshot = false //RDSインスタンス削除後の自動スナップショット

  apply_immediately = true //すぐ使う

  tags = {
    Name    = "${var.project}-${var.environment}-mysql-standalone"
    Project = var.project
    Env     = var.environment
  }
}

反映が確認できました。

https://rurukblog.com/post/terraform-mysql/
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_instance

STEP2: 踏み台サーバ作成

  1. キーペアを作成
  2. 踏み台サーバを作成
  3. 踏み台サーバ内にMySQLクライアントをインストール
  4. 踏み台サーバ⇒RDS接続確認

2.1. キーペアを作成

2.2. 踏み台サーバを作成


2.3. 踏み台サーバ内にMySQLクライアントをインストール

キーペアが保存された階層から下記コマンドを叩き、踏み台サーバに接続していきます。
@配下はEC2インスタンスのパブリックIPv4アドレスをコピペします。

\aws> ssh -i ./zenn.pem ec2-user@52.195.12.108
       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/

MySQLクライアントをインストールします。

~]$ 
sudo yum localinstall -y https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
sudo yum install -y mysql-community-client

mysqlコマンドのPATHを通します。
https://zenn.dev/link/comments/ec78849c913d63

2.4. 踏み台サーバ⇒RDS接続確認

下記コマンドを叩き、踏み台サーバからRDSインスタンスへ接続していきます。

mysql -h"${MYSQL_HOST}" -P"${MYSQL_PORT}" -u"${MYSQL_USERNAME}" -p"${MYSQL_PASSWORD}"

コマンド変数に関してはtfstateからaws_db_instanceを検索し、

  • MYSQL_HOST
    addressから取得
  • MYSQL_PORT
    portから取得
  • MYSQL_USERNAME
    usernameから取得
  • MYSQL_PASSWORD
    passwordから取得

OK

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| zenn               |👈あった
+--------------------+
5 rows in set (0.01 sec)

STEP3: RDSインスタンスへデータ投入

  1. local⇒踏み台サーバへリソースをSCP転送
  2. 踏み台サーバ⇒RDSへシェルを実行
  3. RDS内でDB反映を確認
  4. 踏み台サーバを削除

3.1. local⇒踏み台サーバへリソースをSCP転送

RDSへデータを挿入するリソースdata.tar.gzをEC2の階層/home/ec2-userに送信します。

\aws> scp -i ./zenn.pem ./data.tar.gz ec2-user@52.195.12.108:/home/ec2-user

再度踏み台サーバへログインし受信したリソースを解凍します。

$ tar -zxvf ./data.tar.gz

3.2. 踏み台サーバ⇒RDSへシェルを実行

dbconfigファイルを設定しEC2インスタンス内でRDS向けにシェルを実行できるようにします。

[client]
user     = terraform.tfstate.aws_db_instance.username
password = terraform.tfstate.aws_db_instance.password
host     = terraform.tfstate.aws_db_instance.address
port     = terraform.tfstate.aws_db_instance.port

下記シェルを実行します。

  • RDSユーザ作成
  • ddlでDB設計を反映
  • 反映したDBにデータをインサート

詳細はこちら、別日に実行したので変数等が少し異なります。ご了承ください(´・ω・`)
https://zenn.dev/link/comments/76e2714e8c4c84
https://zenn.dev/link/comments/ee9750651b091f

3.3. RDS内でDB反映を確認

踏み台サーバ⇒RDS接続し下記コマンドを叩き、DB反映を確認できればOKです。

mysql> show databases;
mysql> use zenn
mysql> select * from user limit 1;

3.4. 踏み台サーバを削除

おまけ

パラメータストアを設定

RDSを作成しましたのでパラメータストア(環境変数)の設定を追加でやってみます!

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_parameter

機密情報なのでハードコードはせず下記コマンドから得られるRDSインスタンス情報を参照先として指定するようにします。

$ terraform state show aws_db_instance.mysql_standalone
# aws_db_instance.mysql_standalone:
resource "aws_db_instance" "mysql_standalone" {
    address                               = "zenn-stg-mysql-standalone.ci4aamttyfr0.ap-northeast-1.rds.amazonaws.com"
    allocated_storage                     = 20
    apply_immediately                     = true

リソース

resource "aws_ssm_parameter" "password" {
  name  = "/${var.project}/${var.environment}/app/MYSQL_PASSWORD"
  type  = "SecureString"
  value = random_string.db_password.result
}

ログ

  # aws_ssm_parameter.password will be created
  + resource "aws_ssm_parameter" "password" {
      + arn            = (known after apply)
      + data_type      = (known after apply)
      + id             = (known after apply)
      + insecure_value = (known after apply)
      + key_id         = (known after apply)
      + name           = "/zenn/stg/app/MYSQL_PASSWORD"
      + tags_all       = (known after apply)
      + tier           = (known after apply)
      + type           = "SecureString"
      + value          = (sensitive value)
      + version        = (known after apply)
    }

AWS Systems Managerで確認します。

db名の指定は推奨された書き方を使うべき

RDS名の定義がname=だと警告が出るので推奨されたdb_name=を利用します。
https://zenn.dev/jun2021/articles/e752f436a6d9bb

エンジンバージョンが見当たらない

Error: creating RDS DB Instance (zenn-stg-mysql-standalone): InvalidParameterCombination: Cannot find version 8.0.20 for mysql
        status code: 400, request id: 1a7c52e4-840d-4846-a751-d0df5337aba5 

  on rds.tf line 55, in resource "aws_db_instance" "mysql_standalone":     
  55: resource "aws_db_instance" "mysql_standalone" {

中々ハマってしまいました。
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_instance#engine_version
https://tetlv11.hateblo.jp/entry/2020/04/24/051359

下記で解決しました。

古いエンジンバージョンは使いたくなかったので最新と思い込んでいた数値を指定しましたが、
公式を見るとどうやら非対応の数値を指定していたため、AutoUpgrade=trueとなるエンジンバージョンを指定することで解決しました。

RDSインスタンス作成完了まで結構時間かかる

まとめ

今回はAmazon RDSの基礎および構築手順を学びました。

次回はこれまでの設定を踏まえAmazon EC2, ELBを用いてAPサーバを構築しロードバランサー等の負荷分散設定を行います。

最後までお読みいただきありがとうございました。

GitHubで編集を提案

Discussion

ログインするとコメントできます