【Terraform】Terraform ~ AWS EC2 ~

■ はじめに

休み明けに、Terraform で EC2 を立ち上げそうなので
予習をしておく

目次

【1】公式ドキュメント
 1)AMI
【2】サンプル
 例1:Systems Manager(Session Manager)経由でアクセス
 例2:SSH経由でアクセス
【3】EC2あれこれ
 1)シェルを実行するには
 2)環境変数を設定するには

【1】公式ドキュメント

Resource: aws_instance

* EC2 を作成する

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

1)AMI

https://aws.amazon.com/jp/amazon-linux-ami/

【2】サンプル

例1:Systems Manager(Session Manager)経由でアクセス

シェル作成

mkdir userdata
cat <<EOF > /userdata/demo.sh
#!/bin/bash
yum update -y

## Apache Setup
yum install -y httpd
chown -R apache:apache /var/www/html
systemctl start httpd
systemctl enable httpd
EOF

main.tf

# [1] IAM

# Step1: 信頼ポリシーを作成
data "aws_iam_policy_document" "assume_role" {
  statement {
    effect = "Allow"

    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com"]
    }

    actions = ["sts:AssumeRole"]
  }
}

# Step2: IAM role
resource "aws_iam_role" "demo_aws_iam_role_for_ec2" {
  name = "demo-aws-iam-role-for-ec2"
  assume_role_policy = data.aws_iam_policy_document.assume_role.json
}

# Step3: IAM Policy for Systems Manager
data "aws_iam_policy" "systems_manager" {
  name = "AmazonSSMManagedInstanceCore"
}

# Step4: Systems Manager用のIAM PolicyをRoleに紐づける 
resource "aws_iam_role_policy_attachment" "default" {
  role       = aws_iam_role.demo_aws_iam_role_for_ec2.name
  policy_arn = data.aws_iam_policy.systems_manager.arn
}

# Step5: インスタンスプロファイルを作成する
# => インスタンスプロファイル は、
#   IAM Role と EC2 を紐づけるコネクタのようなもの
resource "aws_iam_instance_profile" "demo_aws_iam_instance_profile" {
  name = "demo-aws-iam-instance-profile"
  role = aws_iam_role.role.name
}

resource "aws_iam_role_policy" "demo_ec2_role_policy" {
  name = "demo-ec2-role-policy"
  role       = aws_iam_role.demo_aws_iam_role_for_ec2.id
  policy = jsonencode({
    Version = "",
    Statement = [
       {
         Sid = "ForDemo"
         Effect = "Allow"
         Action = [
           "s3:GetObject",
           "s3:PutObject",
           "s3:GetBucketLocation",
           "s3:ListAllMyBuckets",
           "s3:ListBucket"
         ],
         Resource = [
           "arn:aws:s3:::awsexamplebucket1/*",
           "arn:aws:s3:::awsexamplebucket1"
         ]
      }
    ]
  })
}


# [2] Security group
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
resource "aws_security_group" "allow_http" {
  name        = "allow_http"
  description = "Allow HTTP inbound traffic"

  ingress {
    description      = "TLS from VPC"
    from_port        = 80
    to_port          = 80
    protocol         = "tcp"
    cidr_blocks      = [aws_vpc.main.cidr_block]
    ipv6_cidr_blocks = [aws_vpc.main.ipv6_cidr_block]
  }

  egress {
    from_port        = 0
    to_port          = 0
    protocol         = "-1"
    cidr_blocks      = ["0.0.0.0/0"]
    ipv6_cidr_blocks = ["::/0"]
  }

  tags = {
    Name = "allow_http"
  }
}

# ★Main★
resource "aws_instance" "demo_ec2" {
  ami = "ami-04e914639d0cca79a"
  instance_type = "t2.small"

  # [1] IAM Role
  iam_instance_profile = aws_iam_instance_profile.demo_aws_iam_instance_profile.name

  # [2] Security Group
  vpc_security_group_ids = [aws_security_group.allow_http.id]

  user_data = file("./userdata/demo.sh")

  tags = {
    Name = "demo-ec2"
  }
}

例2:SSH経由でアクセス

# See https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
resource "aws_security_group" "allow_ssh" {
  name        = "allow-ssh"
  description = "Allow SSH inbound traffic"
  vpc_id      = aws_vpc.main.id

  ingress {
    description      = "SSH from VPC"
    from_port        = 22
    to_port          = 22
    protocol         = "tcp"
    cidr_blocks      = ["0.0.0.0/0"]
    ipv6_cidr_blocks = ["::/0"]
  }

  egress {
    description      = "SSH from VPC"
    from_port        = 0
    to_port          = 0
    protocol         = "-1"
    cidr_blocks      = ["0.0.0.0/0"]
    ipv6_cidr_blocks = ["::/0"]
  }

  tags = {
    Name = "allow-ssh"
  }
}

resource "aws_instance" "demo_ec2_for_ssh" {
  ami = "ami-04e914639d0cca79a"
  instance_type = "t2.small"
  subnet_id = aws_subnet.example.id
  vpc_security_group_ids = [aws_security_group.allow_ssh.id]
  associate_public_ip_address = true
  key_name = "for_test"
  iam_instance_profile = "zzz"

  cpu_options {
    core_count = 2
    threads_per_core = 2
  }

  tags = {
    Name = "demo-ec2-for-ssh"
  }
}

【3】EC2あれこれ

1)シェルを実行するには
2)環境変数を設定するには

1)シェルを実行するには

* user_data に実行したいシェルを設定する

関連プロパティ

* user_data
 => インスタンス起動時に実行するファイルを設定する

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance#user_data

 => デフォルトでは、EC2 インスタンスの停止・開始をする (回避は以下)

https://atsum.in/terraform/ignore-changes-of-user-data/

* user_data_base64
 => user_data版のBase64エンコードのバイナリデータを直接設定する

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance#user_data_base64

* user_data_replace_on_change(true/false(default))
 => user_data / user_data_base64 が契機で破壊と再構築をするかどうか

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance#user_data_replace_on_change

* user_data のデバッグについては、以下を参照。

https://stackoverflow.com/questions/63921500/how-to-get-user-data-logs-in-terraform

参考文献 https://qiita.com/yomon8/items/1ffbfca9ba04c546d243
https://atsum.in/terraform/ignore-changes-of-user-data/

2)環境変数を設定するには

* user_data + シェルで環境変数を設定する
~~~~
  user_data = file("./sample.sh")
~~~~

sample.sh

#!/bin/bash

# Installing Kafka for MSK
wget https://dlcdn.apache.org/kafka/3.4.0/kafka_2.13-3.4.0.tgz
tar -xzf kafka_2.13-3.4.0.tgz
wget https://github.com/aws/aws-msk-iam-auth/releases/download/v1.1.6/aws-msk-iam-auth-1.1.6-all.jar
mv ./aws-msk-iam-auth-1.1.6-all.jar ./kafka_2.13-3.4.0/libs/.

# Create a setting file for Kafka
cat > "~/client.properties" <<EOF
# Sets up TLS for encryption and SASL for authN.
security.protocol=SASL_SSL
# Identifies the SASL mechanism to use.
sasl.mechanism=AWS_MSK_IAM
# Binds SASL client implementation.
sasl.jaas.config=software.amazon.msk.auth.iam.IAMLoginModule required;
# Encapsulates constructing a SigV4 signature based on extracted credentials.
# The SASL client bound by "sasl.jaas.config" invokes this class.
sasl.client.callback.handler.class=software.amazon.msk.auth.iam.IAMClientCallbackHandler
EOF

# ★ここに注目★
# Set environment valiables
cat > "/etc/environment" <<EOF
KAFKA_HOME=~/kafka_2.13-3.4.0/
PATH=${KAFKA_HOME}/bin:$PATH
CONFIG_PATH=~/client.properties

# Set bootstrap server URL
BOOTSTRAP_SERVER=b-1xxxxx.kafka.us-west-2.amazonaws.com:9094
TARGET_TOPIC=connect-test
EOF

参考文献

https://cross-black777.hatenablog.com/entry/2015/12/04/233206
https://qiita.com/charon/items/58c3ad20232c74a6dc01
https://kacfg.com/terraform-vpc-ec2/

関連記事

Terraform ~ 環境構築編 ~
https://dk521123.hatenablog.com/entry/2023/04/05/000224
Terraform ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2019/12/09/222057
Terraform ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2023/05/03/000000
Terraform ~ 基本編 / Module ~
https://dk521123.hatenablog.com/entry/2023/05/19/113544
Terraform ~ Terraformあれこれ ~
https://dk521123.hatenablog.com/entry/2023/05/15/205352
Terraform ~ AWS IAM ~
https://dk521123.hatenablog.com/entry/2023/04/12/214311
Terraform ~ AWS S3 ~
https://dk521123.hatenablog.com/entry/2023/04/09/104204
Terraform ~ AWS MSK ~
https://dk521123.hatenablog.com/entry/2023/05/14/122215
Terraform ~ 機密情報の扱いを考える ~
https://dk521123.hatenablog.com/entry/2023/05/18/005103
Amazon S3AWS CLIで操作 ~
https://dk521123.hatenablog.com/entry/2017/04/01/235355
ssh コマンド / scp コマンド
https://dk521123.hatenablog.com/entry/2017/12/09/231200