Terraform入門

1. Homebrew（ホームブルー）をインストール

Homebrewは

ソフトウェアのインストール、アンインストール
バージョン管理
を非常に簡単に行うことができる「パッケージ管理ソフト」です。
```
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
$ brew -v
```
2. tfenvをインストール

tfenv は Terraform のバージョン管理ツールです。

```
$ brew install tfenv
$ tfenv -v
```
3. terraformをインストール

```
$ tfenv install 1.0.6
$ tfenv use 1.0.6
$ terraform -v
```
4. aws-cliインストール
```
$ brew install awscli
$ aws --version
```

ステップ1（IAMユーザの作成）
「すべてのサービス」から「セキュリティ、ID、およびコンプライアンス」の「IAM」をクリック。
「IAM リソース」から「ユーザー」をクリック。
「ユーザーを追加」をクリック。
ユーザー名のフォームに任意のユーザー名を入力。今回は「terraform-user」とする。
アクセスの種類は「プログラムによるアクセス」を選択。
アクセス許可の設定は「既存のポリシーを直接アタッチ」を選択。
ポリシー名「AdministratorAccess」を選択。
今回、タグの追加は行わない。
「ユーザーの作成」をクリック。
「アクセスキー ID」と「シークレットアクセスキー」を控えておく。（取り扱い注意）
今回はユーザに「AdministratorAccess」というポリシーを直接アタッチさせます。（本来であれば細かくポリシーを設定させる必要がありますが、本講座の趣旨ではないので割愛します。）AdministratorAccess は「Provides full access to AWS services and resources.」とありますので、取り扱いには十分注意してください。

ステップ2（IAMユーザの認証キーの登録）
```
$ aws configure --profile terraform-user
```
対話型の設定画面が現れる。

AWS Accrss Key ID [None]: ステップ1で取得したアクセスキー ID
AWS Secret Access Key [None]: ステップ1で取得したシークレットアクセスキー
Default region name [None]: ap-northeast-1
Default output format [None]: json
ステップ3（sshキーの作成）
作業ディレクトリの作成
```
$ mkdir terraform_tutorial && cd terraform_tutorial
```
「id_rsa_terraform」という名前でsshキーを作成
```
$ ssh-keygen -t rsa -f id_rsa_terraform
```
キーのファイル権限を変更
```
$ sudo chmod 600 id_rsa_terraform.pub
$ ls -l
```
を実行して、id_rsa_terraform.pub の権限が

-rw-------
と表示されていればOKです。

ステップ4
provider.tf
```
provider "aws" {
  profile = "terraform-user"
  region  = "ap-northeast-1"
}
```
key.tf
```
resource "aws_key_pair" "my-kp" {
  key_name   = "ec2_and_rds_demo_rsa"
  public_key = file("ec2_and_rds_demo_rsa.pub")
}
```
vpc.tf
```
resource "aws_vpc" "my-vpc" {
  cidr_block           = "10.0.0.0/16"
  instance_tenancy     = "default"
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name = "my-vpc"
  }
}
```
igw.tf
```
resource "aws_internet_gateway" "my-igw" {
  vpc_id = aws_vpc.my-vpc.id

  tags = {
    Name = "my-igw"
  }
}
```
subnet.tf
```
resource "aws_subnet" "public-subnet-1a" {
  vpc_id                  = aws_vpc.my-vpc.id
  cidr_block              = "10.0.0.0/24"
  availability_zone       = "ap-northeast-1a"
  map_public_ip_on_launch = true

  tags = {
    Name = "public-subnet-1a"
  }
}

resource "aws_subnet" "public-subnet-1c" {
  vpc_id                  = aws_vpc.my-vpc.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = "ap-northeast-1c"
  map_public_ip_on_launch = true

  tags = {
    Name = "public-subnet-1c"
  }
}

resource "aws_subnet" "private-subnet-1a" {
  vpc_id                  = aws_vpc.my-vpc.id
  cidr_block              = "10.0.2.0/24"
  availability_zone       = "ap-northeast-1a"
  map_public_ip_on_launch = true

  tags = {
    Name = "private-subnet-1a"
  }
}

resource "aws_subnet" "private-subnet-1c" {
  vpc_id                  = aws_vpc.my-vpc.id
  cidr_block              = "10.0.3.0/24"
  availability_zone       = "ap-northeast-1c"
  map_public_ip_on_launch = true

  tags = {
    Name = "private-subnet-1c"
  }
}


resource "aws_db_subnet_group" "db-sg" {
  name       = "db-sg"
  subnet_ids = [aws_subnet.private-subnet-1a.id, aws_subnet.private-subnet-1c.id]
}
```
route_table.tf
```
resource "aws_route_table" "my-rt" {
  vpc_id = aws_vpc.my-vpc.id
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.my-igw.id
  }
}

resource "aws_route_table_association" "puclic-1a" {
  subnet_id      = aws_subnet.public-subnet-1a.id
  route_table_id = aws_route_table.my-rt.id
}

resource "aws_route_table_association" "puclic-1c" {
  subnet_id      = aws_subnet.public-subnet-1c.id
  route_table_id = aws_route_table.my-rt.id
}
```
security_group_rule.tf
```
resource "aws_security_group_rule" "ec2-sg-rule1" {
  type              = "ingress"
  from_port         = 22
  to_port           = 22
  protocol          = "tcp"
  cidr_blocks       = ["0.0.0.0/0"]
  security_group_id = aws_security_group.ec2-sg.id
}

resource "aws_security_group_rule" "ec2-sg-rule2" {
  type              = "ingress"
  from_port         = 80
  to_port           = 80
  protocol          = "tcp"
  cidr_blocks       = ["0.0.0.0/0"]
  security_group_id = aws_security_group.ec2-sg.id
}

resource "aws_security_group_rule" "ec2-sg-rule3" {
  type              = "egress"
  from_port         = 0
  to_port           = 0
  protocol          = "-1"
  cidr_blocks       = ["0.0.0.0/0"]
  security_group_id = aws_security_group.ec2-sg.id
}

resource "aws_security_group_rule" "rds-sg-rule" {
  type                     = "ingress"
  from_port                = 3306
  to_port                  = 3306
  protocol                 = "tcp"
  source_security_group_id = aws_security_group.ec2-sg.id
  security_group_id        = aws_security_group.rds-sg.id
}
security_group.tf

resource "aws_security_group" "ec2-sg" {
  name   = "ec2-sg"
  vpc_id = aws_vpc.my-vpc.id
}

# SecurityGroup for RDS
resource "aws_security_group" "rds-sg" {
  name   = "rds-sg"
  vpc_id = aws_vpc.my-vpc.id
}
```
ec2.tf
```
resource "aws_instance" "my-instance" {
  ami                    = "ami-09d28faae2e9e7138"
  instance_type          = "t2.micro"
  vpc_security_group_ids = [aws_security_group.ec2-sg.id]
  subnet_id              = aws_subnet.public-subnet-1a.id
  key_name               = aws_key_pair.my-kp.key_name
  root_block_device {
    volume_type = "gp2"
    volume_size = "20"
  }
  ebs_block_device {
    device_name = "/dev/sdf"
    volume_type = "gp2"
    volume_size = "100"
  }
  tags = {
    Name = "my-instance"
  }
}
```
eip.tf
```
resource "aws_eip" "my-eip" {
  vpc = true
}

resource "aws_eip_association" "eip_assoc" {
  instance_id   = aws_instance.my-instance.id
  allocation_id = aws_eip.my-eip.id
}
```
rds.tf
```
resource "aws_db_instance" "my-db" {
  engine                  = "MySQL"
  engine_version          = "5.7.30"
  identifier              = "sample-db"
  name                    = "sample_db"
  username                = "root"
  password                = "password"
  instance_class          = "db.t2.micro"
  storage_type            = "gp2"
  allocated_storage       = 20
  max_allocated_storage   = 1000
  port                    = 3306
  backup_retention_period = 7
  copy_tags_to_snapshot   = true
  skip_final_snapshot     = true
  vpc_security_group_ids  = [aws_security_group.rds-sg.id]
  parameter_group_name    = aws_db_parameter_group.db-pg.name
  db_subnet_group_name    = aws_db_subnet_group.db-sg.name
  availability_zone       = "ap-northeast-1a"
}
```
db_parameter_group.tf
```
resource "aws_db_parameter_group" "db-pg" {
  name   = "db-pg"
  family = "mysql5.7"

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

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

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

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

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

  parameter {
    name         = "skip-character-set-client-handshake"
    value        = "1"
    apply_method = "pending-reboot"
    # DBを再起動しないと適用できないパラメータの場合は、すぐ適用できないため失敗する。
  }
}
```

ステップ5（terraform init & ドライラン）
```
$ terraform init
$ terraform plan
```
ステップ5（terraform apply）
```
$ terraform apply
```
ステップ6（ssh接続 & nginxのインストール）
```
$ aws ec2 describe-instances --output table \
--query 'Reservations[*].Instances[].{
  ID: InstanceId,
  Name: Tags[?Key==`Name`] | [0].Value,
  State: State.Name
  }' --profile terraform-user
$ ssh -i id_rsa_terraform ec2-user@xx.xx.x.xxx
$ sudo yum -y update
$ sudo amazon-linux-extras enable nginx1
$ sudo yum -y install nginx
$ sudo systemctl enable nginx
$ sudo systemctl start nginx.service
```