Terraformを使用してWordPressを構築するハンズオン

# はじめに
DMM WEBCAMP Advent Calendar 2021の12日目 :christmas_tree: を担当させていただきます。
前日の記事: @keijitsumori さんの<a href="https://qiita.com/keijitsumori/items/f17a56a583a3c24a88a3">[Rails] param is missing or the value is empty error と向き合う</a>



普段DMM WEBCAMPでメンターをしている@koseiinfratopです！
よろしくお願いします:santa_tone1:


# 背景
- 近年、さまざまなインターネットサービスがクラウド化しているので自分も主要なクラウドサービス(AWS, GCP, Azure, さくら)を使ってみたいと思いWordPressを構築してみました。各種サービスのサイトの<font color="blue">GUI</font>をぽちぽちしてインスタンス等を立ち上げて、立ち上がったインスタンスにSSHし各種設定。。。。

QiitaやZenn等の情報共有サイトを見てもインフラの構築系記事は大体がGUIをベースとした記事が多いと思います。

それでもいいのですが、、、最近ではインフラの構築をコードで宣言するサービスが人気を集めています。
その１サービスが<b>Terraform</b>です。
今回はTerraformを使用してWordPressを構築するハンズオンを紹介しようと思います。

# 事前準備と注意事項
- 本記事ではTerraformの使い方・記述方法については割愛しています。
Terraformの基本知識については<a href="https://www.lac.co.jp/lacwatch/service/20200903_002270.html" target="_blank" rel="noopener">5分で分かるTerraform（Infrastructure as Code)</a>を、<br>
Terraformの構文については<a href="https://dev.classmethod.jp/articles/terraform-getting-started-with-aws/" target="_blank" rel="noopener">AWSでTerraform入門</a>をご覧になってください。


- 本記事はAWS,さくらのクラウド, GCP等のクラウドサービスを使用したことがある人を対象としています。

# 0. 今回作成するインフラの構成図と使用するサービス、ファイル構成
## 構成図
![WardPress構成図-Page-2.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541740/704a532d-d668-a581-7ca0-691609099e9c.png)

## 使用するサービス
- Terraform
- AWS
- Terraformがインストールされている環境(今回は標準でTerraformがインストールされているAWSのCloud9を使用しています。)

## ファイル構成
- Terraformのアーキテクチャはまだベストプラクティスがないかつ、今回のゴールはコードを使用してインフラを構築することに焦点を当てているためこのようなファイル構成になっています。

```
ec2-user:~/environment $ ls -1
init.sh
main.tf
mariadb_config.sh
nginx_config.sh
nginx_default
prepareWordPress.sql
README.md
terraform.tfstate
terraform.tfstate.backup
terraform.tfvars
variable.tf
wordpress_config.sh

------------------------------------------------------

ec2-user:~/environment $ ls ~/.ssh -1
id_rsa.pub
id_rsa
```

# 1. 構築

## 1-0 SSH鍵を用意する
- 作成したEC２にSSHでログインできるようにするために
`ssh-keygen -b 4096`コマンドを実行してSSH鍵を作成する。

## 1-0.1 ワークスペースを初期化する
- 下記コマンドを実行してワークスペースを初期化する。
- terraformを使用する上で必須コマンドとなる。
`terrform init`

## 1-1 providerの宣言
- terraformではAWS,GCP,Azure等の様々なクラウドサービスにインフラを構築することができます。
まずはどのサービスを使用してインフラを構築するのかを宣言します。

```:main.tf
provider "aws" {　　　
  region     = "ap-northeast-1"
  access_key = var.access_key
  secret_key = var.secret_key
}
```
#### 解説
> - `provider "aws"`: 今回はAWSにインフラを構築するので`"aws"`と記述しています。
- `region     = "ap-northeast-1"`: 東京リージョンにインフラを構築するので`"ap-northeast-1"`と記述しています。
- `access_key, secret_key`: クレデンシャル情報値を記述します。<br>
＊　access_keyとsecret_keyの取得については<a href="https://qiita.com/miriwo/items/a513c91eac7186db59fe" target="_blank" rel="noopener">こちら</a>をご覧ください。

###### GUIだと。。。
a. AWSのサイトにログインしヘッダーのリージョンを"東京"に選択する。
![スクリーンショット 2021-12-10 5.06.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541740/a7f82f84-c606-b8b6-9df1-80a46f6b3060.png)![スクリーンショット 2021-12-10 5.07.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541740/014ca15f-cb04-00ba-8c7c-1e9ca56c53db.png)

b. <a href="https://console.aws.amazon.com/iamv2/home#/home" taget="_blank" rel="noopener">IAMダッシュボード</a>にアクセスし、access_keyとsecret_keyを取得するためにユーザの作成

## 1-2 VPCの宣言
- 仮想ネットワークの作成

 `main.tf`に追記

```
# document: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc
resource "aws_vpc" "main" {
  cidr_block       = "10.1.0.0/16"
  instance_tenancy = "default"

  enable_dns_hostnames = "false"
  enable_dns_support   = "true"
  tags = {
    Name = "WordPress_vpc"
  }
}
```
####　解説
> - `instance_tenancy`: デフォルトでは`"default"`値なので`"default"`と記述する。
- `enable_dns_hostnames`: VPC がパブリック IP アドレスを持つインスタンスへのパブリック DNS ホスト名の割り当てをサポートするかどうかを決定している。今回は不必要なので`"false"`と記述する。
- `enable_dns_support`: デフォルトでは`"true"`値なので`"true"`と記述する。

###### GUIだと。。。
- <a href = "https://ap-northeast-1.console.aws.amazon.com/vpc/home?region=ap-northeast-1#wizardFullpagePublicAndPrivate:" target="_blank">こちら</a>からVPCを作成する
![スクリーンショット 2021-12-10 15.53.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541740/56e2c23d-13fb-6d33-75ed-4a7722b85f8d.png)



## 1-3 サブネットの宣言
- サブネットを３つ作成する
- `main.tf`に追記

```:main.tf
# document: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet#map_public_ip_on_launch
resource "aws_subnet" "public-a" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.1.1.0/24"
  availability_zone       = "ap-northeast-1a"
  map_public_ip_on_launch = "true"

  tags = {
    Name = "WP-PublicSubnet-1a"
  }
}

resource "aws_subnet" "private-a" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.1.2.0/24"
  availability_zone = "ap-northeast-1a"

  tags = {
    Name = "WP-PrivateSubnet-1a"
  }
}

resource "aws_subnet" "private-d" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.1.10.0/24"
  availability_zone = "ap-northeast-1d"

  tags = {
    Name = "WP-PrivateSubnet-1d"
  }
}
```
####　解説
> - `vpc_id`: "1-2 VPCの作成"で作成したVPCと紐付ける

###### GUIだと。。。
- <a href="https://ap-northeast-1.console.aws.amazon.com/vpc/home?region=ap-northeast-1#CreateSubnet:" target="_blank">こちら</a>からサブネットを作成する。
![スクリーンショット 2021-12-11 2.35.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541740/327e66e6-5b0d-3c42-49f1-f8f4e410c038.png)


## 1-4 ゲートウェイの宣言
- インターネットに出るためのゲートウェイの作成
- `main.tf`に追記

```:main.tf
#document: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/internet_gateway
resource "aws_internet_gateway" "gw" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "WP-InternetGateway"
  }
}
```
####　解説
> `vpc_id`: "1-2 VPCの作成"で作成したVPCと紐付ける。

###### GUIだと。。。
- 特に設定する必要はない。

## 1-5　VPCルーティングテーブルを作成する
- ラスト リゾート ゲートウェイを作成する。
- - `main.tf`に追記

```:main.tf
# document: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table
resource "aws_route_table" "public-table" {
  vpc_id = aws_vpc.main.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.gw.id
  }

  tags = {
    Name = "vpc-public-table"
  }
}
```
####　解説
> - `vpc_id`: "1-2 VPCの作成"で作成したVPCと紐付ける。
- `route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.gw.id
  }
`: 全てのトラフィックは"aws_internet_gateway.gw.id"のインターネットゲートウェイに送信するようにする。

###### GUIだと。。。
- 特に設定する必要はない。

## 1-6 "VPCルーティングテーブルを作成する" で作成したルーティングテーブルをメインルーティングテーブルに関連付ける。

```
#document:  https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table_association
resource "aws_main_route_table_association" "public-a" {
  vpc_id         = aws_vpc.main.id
  route_table_id = aws_route_table.public-table.id
}
```
####　解説
> - `vpc_id`: "1-2 VPCの作成"で作成したVPCと紐付ける。
- `route_table_id`: "1-5 スタティックルートの作成" で作成したルーティングをルーティングテーブルに追加するために`aws_route_table.public-table.id`と記述する。


###### GUIだと。。
- 特に設定する必要はない。

<details><summary>実際のルーティングテーブル</summary>
![スクリーンショット 2021-12-10 6.21.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541740/b2c54ac8-08ad-b24a-dd95-64224fc4ee59.png)
下記画像のレコードは"1-2 VPCの作成"で作成したVPCと紐付けているためデフォルトで追加されている。
![スクリーンショット 2021-12-10 6.22.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541740/dfe215c0-6fc9-8b47-b352-4b76f5b9166d.png)
</details>

## 1-7 セキュリティグループの宣言
- webserverとdbserver用のセキュリティグループを作成する。
- `main.tf`に追記

```
# document: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
resource "aws_security_group" "app" {
  name        = "WP-Web-DMZ"
  description = "WordPress Web App Security Group"
  vpc_id      = aws_vpc.main.id

  tags = {
    Name = "WP-Web-DMZ"
  }
}

resource "aws_security_group" "db" {
  name        = "WP-DB"
  description = "WordPress Mysql Security Group"
  vpc_id      = aws_vpc.main.id
}

```
####　解説
> - `vpc_id`: "1-2 VPCの作成"で作成したVPCと紐付ける。

###### GUIだと。。。
- <a href="https://ap-northeast-1.console.aws.amazon.com/vpc/home?region=ap-northeast-1#CreateSecurityGroup:" target="_blank" rel="noopener">こちら</a>からセキュリティグループを作成する

![スクリーンショット 2021-12-10 6.52.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541740/ded1e7c1-2d58-58c9-fd79-3c41f568c8da.png)


## 1-8 セキュリティルールを宣言する
- インバウンドルール・アウトバウンドルールを適宜宣言し、必要なセキュリティグループに紐付ける。
- `main.tf`に追記

```:main.tf
document: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule

resource "aws_security_group_rule" "ssh" {
  type        = "ingress"
  from_port   = 22
  to_port     = 22
  protocol    = "tcp"
  cidr_blocks = ["0.0.0.0/0"]

  security_group_id = aws_security_group.app.id
}

resource "aws_security_group_rule" "http" {
  type        = "ingress"
  from_port   = 80
  to_port     = 80
  protocol    = "tcp"
  cidr_blocks = ["0.0.0.0/0"]

  security_group_id = aws_security_group.app.id
}


resource "aws_security_group_rule" "mysql" {
  type      = "ingress"
  from_port = 3306
  to_port   = 3306
  protocol  = "tcp"

  source_security_group_id = aws_security_group.app.id

  security_group_id = aws_security_group.db.id
}

resource "aws_security_group_rule" "all" {
  type              = "egress"
  from_port         = 0
  to_port           = 0
  protocol          = "-1"
  cidr_blocks       = ["0.0.0.0/0"]
  security_group_id = aws_security_group.app.id
}
```

####　解説
> `security_group_id`: "1-7 セキュリティグループの作成"で作成したセキュリティグループ内で紐付けたいセキュリティグループに紐づける。
- `source_security_group_id`: type(今回なら"ingress")に応じてアクセスを許可するセキュリティグループID。（今回ならセキュリティグループ"app"が適用されているインスタンスからの通信であれば許可する。）
- `from_port         = 0
  　　　to_port           = 0　　　　　　
  　　　protocol          = "-1"`: 全てのトラフィックへの通信を許可する。

###### GUIだと。。。
下記画像のようにインバウンド・アウトバウンドルールに適宜追加していく。
![スクリーンショット 2021-12-10 6.52.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541740/ded1e7c1-2d58-58c9-fd79-3c41f568c8da.png)

<details><summary>実際に作成されたセキュリティグループの１例</summary>![スクリーンショット 2021-12-10 7.08.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541740/b9b1cc6f-6e53-6a62-2789-3d2b09c24981.png)
</details>

## 1-9 DBのサブネットグループを宣言する
- DB用のサブネットを定義する。
- `main.tf`に追記

```:main.tf
# document: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_subnet_group
resource "aws_db_subnet_group" "main" {
  name        = "wp-dbsubnet"
  description = "WordPress DB_Mysql_ Subnet"
  subnet_ids  = [aws_subnet.private-a.id, aws_subnet.private-d.id]

  tags = {
    Name = "WordPressDB"
  }
}
```
####　解説
> - `subnet_ids`: "1-3 サブネットの作成"で作成したサブネットの中からDB用のサブネットを記述する。

###### GUIだと。。。
- <a href="https://ap-northeast-1.console.aws.amazon.com/rds/home?region=ap-northeast-1#create-db-subnet-group:" target="_blank" rel="noopener">こちら</a>からDBサブネットグループを作成する。

![スクリーンショット 2021-12-10 11.36.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541740/c6b84bbf-40b1-0f30-1856-479244cdc958.png)

<details><summary>実際に作成されたDBサブネットグループ</summary>
![スクリーンショット 2021-12-11 3.08.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541740/a2f3ce15-3ad0-6369-5f4e-7a8296f58c4f.png)
スクリーンショット 2021-12-11 3.08.47
</details>

## 1-10 DBのインスタンスを宣言する
- `main.tf`に追記

```:main.tf
resource "aws_db_instance" "db" {
  identifier        = "wp-mysql-db" #lowcase
  allocated_storage = 5
  engine            = "mysql"
  engine_version    = "8.0.23"
  instance_class    = "db.t2.micro"

  storage_type            = "gp2"
  username                = var.username
  password                = var.password
  backup_retention_period = 0
  skip_final_snapshot     = true
  apply_immediately       = true
  vpc_security_group_ids  = [aws_security_group.db.id]
  db_subnet_group_name    = aws_db_subnet_group.main.name

  lifecycle {
    ignore_changes = [password]
  }
}
```

####　解説
> - `identifier`: DBの一意な識別子を割り当てる。＊全て小文字でなければいけない。<br>
(省略した場合はAWS側で一意な識別子が割り当てられる。)
- `apply_immediately `: RDSへの設定変更を即時反映するかどうかの設定。即時反映したいので`true`
を記述する。
- `skip_final_snapshot`: インスタンス削除時にスナップショットの取得をスキップするかどうかの設定。コスト節約のため`true`を記述する。
- `lifecycle {
    ignore_changes = [password]
  }`: ライフサイクルの設定。Terraformで管理しない項目を記述する。passwordの変更はTerraformとして無視する。セキュリティの観点からインスタンス構築後、手動でパスワードを変更するため。

###### GUIだと。。。
- <a href="https://ap-northeast-1.console.aws.amazon.com/rds/home?region=ap-northeast-1#launch-dbinstance:gdb=false" target="_blank" rel="noopener">こちら</a>からDBを作成する。

![スクリーンショット 2021-12-10 11.51.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541740/5810115f-94c9-b237-29ff-a4a9546eab12.png)

## 1-11 SSH接続するための公開鍵を宣言する。
- "1-0 SSH鍵を用意する"で作成したキーペアの公開鍵を指定する。
- `main.tf`に追記

```:main.tf
document: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/key_pair
resource "aws_key_pair" "deployer" {
  key_name   = "test-key"
  public_key = file("~/.ssh/id_rsa.pub")
}
```

####　解説
> - `key_name`: キーペア名を記述する。
- `public_key`: Terraformの'file'メソッドを使用して"1-0 SSH鍵を用意する"で事前に用意したキーペアの公開鍵ファイルパスを記述する。
 
###### GUIだと。。。
- EC2を起動するときに画像ようなモーダルが出てくるところで設定する。

![スクリーンショット 2021-12-10 12.31.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541740/3a3bb112-c284-a091-8c35-1ed97a37e8f9.png)

## 1-12 EC2を宣言する
- ubuntuを使用してEC２を作成する。
- `main.tf`に追記

```:main.tf
# document: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "app" {
  ami                         = var.ami
  instance_type               = "t2.micro"
  subnet_id                   = aws_subnet.public-a.id
  associate_public_ip_address = true
  vpc_security_group_ids      = [aws_security_group.app.id]

  private_ip = "10.1.1.100"

  key_name = aws_key_pair.deployer.id

  provisioner "file" {
    connection {
      type = "ssh"
      user = "ubuntu"
      private_key = file("~/.ssh/id_rsa")
      host = self.public_ip
    }
    source = "prepareWordPress.sql"
    destination = "/home/ubuntu/prepareWordPress.sql"
  }

  
  
  provisioner "remote-exec" {
    connection {
      type = "ssh"
      user = "ubuntu"
      private_key = file("~/.ssh/id_rsa")
      host = self.public_ip
    }
    scripts =[
      "init.sh",
      "nginx_config.sh",
    ]
  }
  
  provisioner "remote-exec" {
    connection {
      type = "ssh"
      user = "ubuntu"
      private_key = file("~/.ssh/id_rsa")
      host = self.public_ip
    }
    inline = [
    "sudo apt update -y",
    "sudo apt install default-mysql-client -y",
    "sudo mysql -u ${var.username} -p${var.password} -h ${aws_db_instance.db.address} < /home/ubuntu/prepareWordPress.sql"
    ]
  }
  
  provisioner "file" {
    connection {
      type = "ssh"
      user = "ubuntu"
      private_key = file("~/.ssh/id_rsa")
      host = self.public_ip
    }
    source = "nginx_default"
    destination = "/home/ubuntu/default"
  }
  
  provisioner "remote-exec" {
    connection {
      type = "ssh"
      user = "ubuntu"
      private_key = file("~/.ssh/id_rsa")
      host = self.public_ip
    }
    script = "wordpress_config.sh"
    
  }
  
  

  tags = {
    Name = "WordPressServer"
  }
}
```

####　解説
```
associate_public_ip_address = true
```
> - VPC内のインスタンスにパブリックIPアドレスを関連付けるために`true`を記述する。

```
 private_ip = "10.1.1.100"
```
> - このEC２で使用するプライベートIPを明示的に指定するために固定IPを記述している。

```
key_name = aws_key_pair.deployer.id
```
> - "1-11 SSH接続するための公開鍵を宣言する。"で宣言した公開鍵をEC2に登録するために記述している。

```
provisioner "file" {
    connection {
      type        = "ssh"
      user        = "ubuntu"
      private_key = file("~/.ssh/id_rsa")
      host        = self.public_ip
    }
    source      = "prepareWordPress.sql"
    destination = "/home/ubuntu/prepareWordPress.sql"
  }
```
> - EC２にファイルを転送している。
> 内部ではscpコマンドを使用してファイル転送をしている。

> ```:scpコマンドで表した場合
scp -i ~/.ssh/id_rsa prepareWordPress.sql ubuntu@self.public_ip:/home/ubuntu/prepareWordPress.sql
```
```
host        = self.public_ip
```
>> - 宛先のアドレス(`host`)にEC２のパブリックIP(`self.public_ip`)を指定している。

```
provisioner "remote-exec" {
    connection {
      type        = "ssh"
      user        = "ubuntu"
      private_key = file("~/.ssh/id_rsa")
      host        = self.public_ip
    }
    scripts = [
      "init.sh",
      "nginx_config.sh",
    ]
  }
```
> - EC2で実行したいシェルスクリプトを記述している。
> 内部ではSSH接続をして、`scripts`に記述しているスクリプトファイルを実行している。

###### GUIだと。。。
- <a href="https://ap-northeast-1.console.aws.amazon.com/ec2/v2/home?region=ap-northeast-1#LaunchInstanceWizard:" target="_blank" rel="noopener">こちら</a>からEC2を作成する。

## 1-13 EC２のグローバルIPを確認する
- main.tfに追記

```:main.tf
output "WordPressServer_EC2__PublicIP" {
  value = aws_instance.app.public_ip
}
```

#### 解説
- 後の動作確認のためにEC２に割り振られたグローバルIPをターミナルに出力するために記述する。

~補足~　後の項目"1-17 定義したファイルを実行しWordPressを構築する"で`terraform apply`コマンドを実行し正常に終了したらターミナルにグローバルIPが出力される。

## 1-14 スクリプトファイル、ダンプファイル、Terraformで使用している変数系のファイルを作成する
- こちらに関しての説明は割愛させていただきます。
- 詳しい変数値などは<a href="https://github.com/kodmm/WordPress_terraform" target="_blank" rel="noopener">こちら</a>をご覧ください。

## 1-15 作成したファイルのコードフォーマット
- 下記コマンドを実行してコード整形を行う。

`terraform fmt`

## 1-16 記述した設定ファイルの変更内容を確認する
- 下記コマンドを実行して定義内容が意図した通りに反映されるかを確認する。

`terraform plan`

## 1-17 定義したファイルを実行しWordPressを構築する
- 下記コマンドを実行してWordPressを構築する。

`terraform apply`

# 動作確認
- ターミナルに出力されたグローバルIPを使用して`http://グローバルIP/wordpress`にアクセスする。
- 下記の画像のような画面が表示される。
![スクリーンショット 2021-12-10 14.11.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541740/b0497e2d-cce8-bb88-0fe2-a929556fbe11.png)
![スクリーンショット 2021-12-10 14.13.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541740/e5e48fc9-a8c4-b2b4-fac6-793ff9bdb1fd.png)
- 言語を設定し、DBの設定等を行うとwordpressのサイトを表示できるようになる。


## 最後に
- このようにGUIを一切使用せずにインフラ構築を行うことができます。
- 今回はメンテナンス等は全く気にせずコードを書きましたが、メンテナンスを意識したコードに随時書き換えていこうと思います。
- 皆さんもぜひ、プログラミングでインフラを構築してみてください！！！

<font color="red">インフラがおもしろくない可能性これ、、、一切なーい！！！</font>


### 参考資料
https://reboooot.net/post/what-is-terraform/
https://kazuhira-r.hatenablog.com/entry/2020/06/20/172541
https://registry.terraform.io/
https://qiita.com/toshihirock/items/6a46fcba165a0b34a1f4
https://www.lac.co.jp/lacwatch/service/20200903_002270.html
https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-dns.html