terraform cloudで初めるAWS その5: RDS編

Share on:

これはシリーズ化する予定なので続きは←リンクからどうぞ。

ちなみに最低限AWSでEC2を起動してSSHした事程度は事ある人向けの記事です

前回まで

  • とりあえずwebサーバが構築できた

今回最初にやる事はsubnetの二重化

今までsubnetは一本しか作ってきませんでした。

1resource "aws_subnet" "pub" {
2  vpc_id            = aws_vpc.vpc.id
3  cidr_block        = "192.168.1.0/24"
4  availability_zone = "ap-northeast-1d"
5
6  tags = {
7    Name = local.workspace
8  }
9}

非常にシンプルな構成ならこれでもいいんですが、RDSが絡んでくるとゾーンを2つ求められるので、これだとダメって事になります。

これはロードバランサーを使う時も結局そうなので今のうちに改良した方がよさそうな点です。

とりあえず3つもいらないにせよ2つは入れたい所です。

ここでterraformは1つのエントリで2つ作る的な、なかなか強引な書式を持っています。

1resource "aws_subnet" "pub" {
2  vpc_id            = aws_vpc.vpc.id
3  count             = length(local.az)
4  cidr_block        = cidrsubnet("192.168.0.0/16", 8, 0 + count.index)
5  availability_zone = local.az[count.index]
6}

ここでlocal.azというのをリストで定義します。これはsettings.tfとかに書いてありましたっけ。

1locals {
2  # If your backend is not Terraform Cloud, the value is ${terraform.workspace}
3  # otherwise the value retrieved is that of the TFC_WORKSPACE_NAME with trimprefix
4  workspace = var.TFC_WORKSPACE_NAME != "" ? trimprefix(var.TFC_WORKSPACE_NAME, "ecs-") :
5terraform.workspace
6
7  az = ["ap-northeast-1a", "ap-northeast-1d"]
8}

こうしたいんですが、「a」とか「d」とかっていう文字列を名前に使いたいなあとなった時にこれだと面倒なので、こうしといたらよさそうです。

1  region    = "ap-northeast-1"
2  az_suffix = ["a", "d"]
3  az        = formatlist("%s%s", local.region, local.az_suffix)

cidrsubnetに関して

これはterraform consoleで確認してみてください。詳しくは述べないけど、こういう感じです。

1% terraform console                                                        20-10-13 19:20
2> cidrsubnet("192.168.0.0/16", 8, 0 + 0)
3192.168.0.0/24
4> cidrsubnet("192.168.0.0/16", 8, 0 + 1)
5192.168.1.0/24

countが0, 1と上がっていくと

  • 192.168.0.0/24
  • 192.168.1.0/24

とか定義されていきます。もちろん/24じゃない範囲を使いたい場合は引数を変更するわけだけどまあ255もあれば足りるでしょう!?!(足りない運用って1人でできるもんなんだろうか…)

修正していく

さて、これに基いてnetwork.tfを直します。

 1resource "aws_subnet" "pub" {
 2  vpc_id            = aws_vpc.vpc.id
 3  count             = length(local.az)
 4  cidr_block        = cidrsubnet("192.168.0.0/16", 8, 0 + count.index)
 5  availability_zone = local.az[count.index]
 6
 7  tags = {
 8    Name = local.workspace
 9  }
10}
1resource "aws_route_table_association" "pub" {
2  count          = length(local.az)
3  subnet_id      = aws_subnet.pub.*.id[count.index]
4  route_table_id = aws_route_table.pub.id
5}

subnetにのっかっているweb.tfも修正。ここはsubnetが2つあるんですがボリュームがdに置いてある都合上今までの奴を動作させる場合はdに決め打ちせにゃなりませんね

 1resource "aws_instance" "web" {
 2  instance_type = "t2.micro"
 3  ami           = "ami-0662319323823ba88" # jessie
 4  subnet_id     = aws_subnet.pub.1.id     # [d] FIXED
 5  key_name      = "xxxxxx"
 6  user_data     = data.template_cloudinit_config.web.rendered
 7
 8  vpc_security_group_ids = [
 9    aws_security_group.web.id,
10    aws_vpc.vpc.default_security_group_id
11  ]
12
13  tags = {
14    Name = local.workspace
15  }
16}

これで準備はokっぽいです。

適用したい、が、

ここまで大規模に変化させており、また、運用前の場合は一度destroyしてから組み直す事をおすすめします。じゃないとなんかsubnetが干渉してるぞとか言われる事があるような気がします。

作成されたsubnetを見てみる

VPCから確認できます。

(001.png)

これでsubnetが2つになったようです。2つになったので、今後はそれをある程度意識して管理してあげてください。

DBに戻る

まずセキュリティグループを作ります。

 1resource "aws_security_group" "mysql" {
 2  name        = "mysql-${local.workspace}"
 3  description = "MySQL Database hosts"
 4  vpc_id      = aws_vpc.vpc.id
 5
 6  ingress {
 7    from_port   = 3306
 8    to_port     = 3306
 9    protocol    = "tcp"
10    cidr_blocks = ["0.0.0.0/0"]
11  }
12
13  lifecycle {
14    create_before_destroy = true
15  }

ingressが0.0.0.0/0なのは正直微妙なので後で考えますか?

DBのサブネットです

1resource "aws_db_subnet_group" "main" {
2  name       = "main"
3  subnet_ids = aws_subnet.pub.*.id
4
5  tags = {
6    Name = "Main DB subnets"
7  }
8}

もっと言うと、この構成も若干微妙で、データベースサーバをパブリックネットワークに出すべきじゃないのかもしれませんね(グローバルIPを当てていないとはいえ)。まあ今回はこれでいいでしょう。マルチAZだとここで指定したsubnet2つのうち1つがアクティブで1つがスタンバイになるはずです。今回はマルチAZ使いませんが、料金はもちろん倍になります。

DBの本体です

 1resource "aws_db_instance" "db" {
 2  identifier                = local.workspace
 3  allocated_storage         = 20
 4  storage_type              = "gp2"
 5  engine                    = "mysql"
 6  engine_version            = "5.7"
 7  instance_class            = "db.t2.micro"
 8  name                      = "testdb"
 9  username                  = "root"
10  password                  = "testtesttest"
11  db_subnet_group_name      = aws_db_subnet_group.main.id
12  skip_final_snapshot       = false
13  final_snapshot_identifier = "${local.workspace}-finalsnapshot"
14
15  vpc_security_group_ids = [
16    aws_security_group.mysql.id,
17    aws_vpc.vpc.default_security_group_id
18  ]
19}

正直適当感が凄いです。慣れたらチューニングして欲しいんですが、少なくとも変えるべき所はいろいろあるでしょう。

これをApplyして正常に構成できるか確認します。

起動した後

とにかく破壊します。繰り返しになりますが、破壊とか含めてディープな設定ができるのは運用に入る前だけなので、十分にテストしといてください。

DBインスタンスも問題なく消えますがファイナルスナップショットが残っている事を確認します。削除の保護はありません。

接続してみる

EC2からmysql-clientとかを入れて接続したらいいと思われます。

 1admin@ip-192-168-1-232:~$ mysql -uroot -ptesttesttest -hvm2-replace.czxd3vjyribx.ap-north
 2east-1.rds.amazonaws.com testdb
 3Welcome to the MySQL monitor.  Commands end with ; or \g.
 4Your MySQL connection id is 7
 5Server version: 5.7.26 Source distribution
 6
 7Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
 8
 9Oracle is a registered trademark of Oracle Corporation and/or its
10affiliates. Other names may be trademarks of their respective
11owners.
12
13Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
14
15mysql> show databases;
16+--------------------+
17| Database           |
18+--------------------+
19| information_schema |
20| innodb             |
21| mysql              |
22| performance_schema |
23...

ここまで

RDSの起動をterraformからやりました。auroraに関してはまたちょっと設定が変わってくるので注意してください。

エンドポイントとかがweb consoleにアクセスしないとわからんとかあって非常に面倒くさいので次回はDNSを何とかします。その次にALBやって多分このチュートリアルは終わりです。あと2回くらいですね。それでは