TerraformでAWSを使う(Terraform学習備忘録 #3)

TerraformでAWSを使う(Terraform学習備忘録 #3)

Terraformを学習内容を備忘録として残します。versionはv1.6です。

VPC

resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  instance_tenancy     = "default"
  enable_dns_support   = "true"
  enable_dns_hostnames = "true"
  tags = {
    Name = "main"
  }
}

  • cidr_block – (オプション)VPCのIPv4 CIDRブロック。CIDRは明示的に設定するか、IPv4_netmask_lengthを使用してIPAMから導き出すことができます。
  • instance_tenancy – (オプション) VPCに起動されるインスタンスのテナンシーオプション。デフォルトはdefault。他の唯一のオプションはdedicatedです。
    • default – デフォルトの設定で、複数のAWSアカウントが同じ物理ハードウェアを共有します。これは、インスタンスがホスト上で共有されることを意味します。
    • dedicated – インスタンスはシングルテナントのハードウェアで実行されます。これは、単一のカスタマー専用のハードウェアのVirtual Private Cloud (VPC)で実行されるAmazon EC2インスタンスを意味します。リージョンごとの専用使用料が1時間あたり2ドル、さらにインスタンスごとの使用料が1時間あたり1ドルかかります。
  • enable_dns_support – (オプション) VPC が Amazon 提供の DNS サーバーを介した DNS 解決策をサポートするかどうかを決定します。デフォルトはtrueです。
    • (補足) VPCのDNS(Amazon Route 53 Resolver)は、VPC内のリソース(例えば、EC2インスタンスやRDSデータベースなど)間の名前解決を行うために使用されます。VPC内の異なるアベイラビリティゾーンにあるサーバ間の通信においても、VPCのDNSは役立ちます。例えば、あるEC2インスタンスが別のEC2インスタンスに接続するためには、そのインスタンスのIPアドレスまたはホスト名が必要です。VPCのDNSは、インスタンスのプライベートDNSホスト名を解決し、対応するプライベートIPアドレスを返すことで、この名前解決を行います。
  • enable_dns_hostnames – (オプション) VPC がパブリック IP アドレスを持つインスタンスへのパブリック DNS ホスト名の割り当てをサポートするかどうかを決定します。デフォルトはfalseです。
  • tags – (オプション)リソースに割り当てるタグのマップ。プロバイダの default_tags 設定ブロックが存在する状態で設定された場合、一致するキーを持つタグはプロバイダ・レベルで定義されたものを上書きします。

Subnet

resource "aws_subnet" "main-public-1" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.1.0/24"
  map_public_ip_on_launch = "true"
  availability_zone       = "ap-northeast-1a"

  tags = {
    Name = "main-public-1"
  }
}

  • vpc_id – (必須) VPC ID。
  • cidr_block – (オプション)サブネットのIPv4 CIDRブロック。
  • map_public_ip_on_launch – (オプション)サブネットに起動したインスタンスにパブリックIPアドレスを割り当てる必要がある場合は true を指定します。デフォルトは false です。
  • availability_zone – (オプション)サブネットの AZ。
  • tags – (オプション)リソースに割り当てるタグのマップ。プロバイダの default_tags 設定ブロックが存在する状態で設定された場合、一致するキーを持つタグはプロバイダ・レベルで定義されたものを上書きします。

Internet Gateway

resource "aws_internet_gateway" "main-gw" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "main"
  }
}

  • vpc_id – (オプション)作成する VPC ID。
  • tags – (オプション)リソースに割り当てるタグのマップ。プロバイダの default_tags 設定ブロックが存在する状態で設定された場合、一致するキーを持つタグはプロバイダ・レベルで定義されたものを上書きします。

Route Table

resource "aws_route_table" "main-public" {
  vpc_id = aws_vpc.main.id
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.main-gw.id
  }

  tags = {
    Name = "main-public-1"
  }
}

  • vpc_id – (必須) VPC ID。
  • route – (オプション)ルートテーブルに追加するルートオブジェクトのリストを指定するためのもの。各ルートオブジェクトは、特定の送信先(CIDRブロック)から特定のターゲット(例えば、インターネットゲートウェイやNATゲートウェイなど)への経路を定義します。routeattribute-as-blocks (属性としてのブロック)モードで処理されます。この route という引数を省略すると、すでに設定されているルートテーブルには何ら影響を与えません。管理されているすべてのルートを削除するには、空のリストを指定する必要があります。
  • tags – (オプション)リソースに割り当てるタグのマップ。プロバイダの default_tags 設定ブロックが存在する状態で設定された場合、一致するキーを持つタグはプロバイダ・レベルで定義されたものを上書きします。

Route Table Association

ルートテーブルとサブネット、またはルートテーブルとインターネットゲートウェイやバーチャルプライベートゲートウェイとの関連付けを作成するためのリソースを提供します。

resource "aws_route_table_association" "main-public-1-a" {
  subnet_id      = aws_subnet.main-public-1.id
  route_table_id = aws_route_table.main-public.id
}

  • subnet_id – (オプション) 関連付けを作成するサブネットID。gateway_id と競合します。subnet_idgateway_id のどちらかは必ず必要です。
  • route_table_id – (必須)関連付けるルーティング・テーブルの ID。

Nat Gateway

resource "aws_eip" "nat" {
  domain = "vpc"
}

resource "aws_nat_gateway" "nat-gw" {
  allocation_id = aws_eip.nat.id
  subnet_id     = aws_subnet.main-public-1.id
  depends_on    = [aws_internet_gateway.main-gw]
}

aws_eip リソースは、AWSの Elastic IPアドレス(EIP) を確保するために使用されます。EIPは、AWSのパブリックIPv4アドレスで、AWSアカウントに関連付けられています。EIPは、AWSリソース(例えば、EC2インスタンスやNATゲートウェイなど)に関連付けることができます。

一方、aws_nat_gateway リソースは、AWSのNATゲートウェイを作成するために使用されます。NATゲートウェイは、プライベートサブネット内のインスタンスがインターネットや他のAWSサービスに接続できるようにするためのゲートウェイです。

NATゲートウェイを作成する際には、EIP( aws_eip リソースで確保したもの)を指定する必要があります。これは、NATゲートウェイはデフォルトでパブリックIPアドレスが付与されないため、インターネットに接続するためにパブリックIPアドレス(つまり、EIP)が必要になるためです。

  • domain – このEIPがVPC(vpc)で使用されるかどうかを示す。
  • allocation_id – (オプション) NATゲートウェイのElastic IPアドレスの割り当てID。connectivity_typepublic の場合は必須。
  • subnet_id – (必須) NAT ゲートウェイを配置するサブネットのサブネット ID。
  • depends_on – インターネット・ゲートウェイへの明示的な依存関係は、NATゲートウェイがインターネット・ゲートウェイの後に作成されることを保証し、リソース・プロビジョニングの正しい順序を維持します。

Security Group

ingress (インバウンドの制御) と egress (アウトバウンドの制御) のルールをインラインで定義したSecurity Group のリソースと、1つ以上の ingress または egress のルールを管理する Security Group Rule リソースが提供されています。これらのリソースはどちらもAWSがセキュリティグループルールの一意なIDを割り当てる前に追加されたもので、一意なIDに依存する description 属性や tags 属性を使ったすべてのシナリオでうまく動作しません。つまり、どちらも設定している場合、期待通りに動かない可能性があります。

aws_vpc_security_group_egress_ruleaws_vpc_security_group_ingress_rule リソースは、これらの制限に対処するために追加されたもので、すべての新しいセキュリティグループルールに使用する必要があります。 aws_vpc_security_group_egress_ruleaws_vpc_security_group_ingress_rule リソースは、インラインルールの aws_security_group リソースや、同じ Security Group に定義された aws_security_group_rule リソースと組み合わせて使用してはいけません。ルールの競合が発生し、ルールが上書きされる可能性があります。

resource "aws_security_group" "allow-ssh" {
  vpc_id      = aws_vpc.main.id
  name        = "allow-ssh"
  description = "security group that allows ssh and all egress traffic"
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  tags = {
    Name = "allow-ssh"
  }
}

  • vpc_id – (オプション、強制新規リソース) VPC ID。デフォルトはリージョンのデフォルト VPC です。
  • egress – (オプション、VPC のみ) egress ルールの構成ブロック。egress ルールごとに複数回指定できます。各 egress ブロックは、以下で説明するフィールドをサポートします。この引数は、attribute-as-blocks モードで処理されます。
  • ingress – (オプション) イングレス・ルールの構成ブロック。イングレス・ルールごとに複数回指定できる。各 ingress ブロックは、以下に文書化されたフィールドをサポートする。この引数は attribute-as-blocks モードで処理される。
  • tags – (オプション)リソースに割り当てるタグのマップ。プロバイダの default_tags 設定ブロックが存在する状態で設定された場合、一致するキーを持つタグはプロバイダレベルで定義されたものを上書きします。

EC2

resource "aws_instance" "example" {
  ami           = var.AMIS[var.AWS_REGION]
  instance_type = "t2.micro"

  # the VPC subnet
  subnet_id = aws_subnet.main-public-1.id

  # the security group
  vpc_security_group_ids = [aws_security_group.allow-ssh.id]

  # the public SSH key
  key_name = aws_key_pair.mykeypair.key_name
}

  • ami -(オプション)インスタンスに使用するAMI。launch_template が指定され、Launch Template で AMI が指定されていない場合は必須。Launch TemplateでAMIが指定されている場合、ami を設定するとLaunch Templateで指定されているAMIが上書きされます。
  • instance_type – (オプション)インスタンスに使用するインスタンス・タイプ。launch_template が指定され、Launch Template がインスタンス・タイプを指定しない限り、必須です。Launch Templateでインスタンスタイプが指定されている場合、instance_type を設定するとLaunch Templateで指定されているインスタンスタイプが上書きされます。このフィールドを更新すると、EC2インスタンスの停止/起動がトリガーされる。
  • subnet_id – (オプション)起動するVPCサブネットID。
  • vpc_security_group_ids – (オプション、VPCのみ)関連付けるセキュリティ・グループIDのリスト。
  • key_name – (オプション)aws_key_pair のリソースを使用して管理できます。

Key Pair

キー・ペアは、EC2インスタンスへのログイン・アクセスを制御するために使用されます。ユーザーが提供する既存のキーペアが必要です。この鍵ペアの公開鍵がAWSに登録され、EC2インスタンスへのログインが可能になります。既存の鍵ペアをインポートする場合、公開鍵の素材はAWSがサポートするフォーマットであれば何でもよいです。

resource "aws_key_pair" "mykeypair" {
  key_name   = "mykeypair"
  public_key = file(var.PATH_TO_PUBLIC_KEY)
}

  • key_name – (オプション) キーペアの名前。key_namekey_name_prefix も指定しない場合、Terraformは接頭辞 terraform- を使って一意なキー名を作成します。
  • public_key – (必須) 公開鍵の素材。

EBS

resource "aws_ebs_volume" "ebs-volume-1" {
  availability_zone = "ap-northeast-1a"
  size              = 20
  type              = "gp2"
  tags = {
    Name = "extra volume data"
  }
}

  • availability_zone – (必須)EBSボリュームが存在するAZ。
  • size – (オプション)ドライブのサイズ(GiB単位)。
  • type – (オプション)EBSボリュームのタイプ。standard、gp2、gp3、io1、io2、sc1、またはst1を指定できます(デフォルト:gp2)。
  • tags – (オプション)リソースに割り当てるタグのマップ。プロバイダの default_tags 設定ブロックが存在する状態で設定された場合、一致するキーを持つタグはプロバイダ・レベルで定義されたものを上書きします。

Volume Attachment

resource "aws_volume_attachment" "ebs-volume-1-attachment" {
  device_name                    = "/dev/xvdh"
  volume_id                      = aws_ebs_volume.ebs-volume-1.id
  instance_id                    = aws_instance.example.id
  stop_instance_before_detaching = true
}

  • device_name – (必須)インスタンスに公開するデバイス名(例:/dev/sdh または xvdh)。
  • volume_id – (必須)アタッチするボリュームのID。
  • instance_id – (必須)アタッチするインスタンスの ID。
  • stop_instance_before_detaching – (オプション、ブール値) これを true に設定すると、ボリュームのデタッチを試みる前にターゲット・インスタンスが確実に停止します。インスタンスがまだ停止していない場合、インスタンスを停止します。

User Data, Cloud Init

resource "aws_instance" "example" {
  ami           = var.AMIS[var.AWS_REGION]
  instance_type = "t2.micro"

  # the VPC subnet
  subnet_id = aws_subnet.main-public-1.id

  # the security group
  vpc_security_group_ids = [aws_security_group.allow-ssh.id]

  # the public SSH key
  key_name = aws_key_pair.mykeypair.key_name

  # user data
  user_data = data.cloudinit_config.cloudinit-example.rendered
}

  • user_data(オプション)- インスタンスの起動時に提供するユーザーデータです。この引数を通じてgzip圧縮されたデータを渡すことはできません。その代わりに user_data_base64 を参照してください。このフィールドへの更新は、デフォルトではEC2インスタンスの停止/開始をトリガーします。user_data_replace_on_change が設定されている場合、このフィールドへの更新はインスタンスの破棄と再作成をトリガーします。

cloudinit_config は、クラウドコンピューティングインスタンスの起動時に実行する設定スクリプトを提供するために使用されます。インスタンスが起動すると同時に必要な設定やインストールが行われるため、手動での作業を省略できます。

## cloudinit.tf
# note: previous templatefile datasources have been replaced by the template_file() function

data "cloudinit_config" "cloudinit-example" {
  gzip          = false
  base64_encode = false

  part {
    filename     = "init.cfg"
    content_type = "text/cloud-config"
    content      = templatefile("scripts/init.cfg", {
      REGION = var.AWS_REGION
    })
  }

  part {
    content_type = "text/x-shellscript"
    content      = templatefile("scripts/volumes.sh", {
      DEVICE = var.INSTANCE_DEVICE_NAME
    })
  }
}

  • part (ブロックリスト)- (必須)生成 さ れ る cloud-init 設定に フ ァ イ ルを追加する入れ子ブロック 型。複数のパートブロックを使って複数のファイルを指定し、最終的な MIME ドキュメントに宣言順に含まれるようにします。
  • content (文字列)- (必須)part の本文。
  • content_type (文字列)- (オプション) その部分のヘッダで報告したい MIME 形式のコンテントタイプ。デフォルトは text/plain
  • filename (文字列)- (オプション)部分のヘッダで報告したいファイル名。

## init.cfg
#cloud-config

repo_update: true
repo_upgrade: all

packages:
  - lvm2

output:
  all: '| tee -a /var/log/cloud-init-output.log'

## volumes.sh
#!/bin/bash

set -ex 

vgchange -ay

DEVICE_FS=`blkid -o value -s TYPE ${DEVICE} || echo ""`
if [ "`echo -n $DEVICE_FS`" == "" ] ; then 
  # wait for the device to be attached
  DEVICENAME=`echo "${DEVICE}" | awk -F '/' '{print $3}'`
  DEVICEEXISTS=''
  while [[ -z $DEVICEEXISTS ]]; do
    echo "checking $DEVICENAME"
    DEVICEEXISTS=`lsblk |grep "$DEVICENAME" |wc -l`
    if [[ $DEVICEEXISTS != "1" ]]; then
      sleep 15
    fi
  done
  # make sure the device file in /dev/ exists
  count=0
  until [[ -e ${DEVICE} || "$count" == "60" ]]; do
   sleep 5
   count=$(expr $count + 1)
  done
  pvcreate ${DEVICE}
  vgcreate data ${DEVICE}
  lvcreate --name volume1 -l 100%FREE data
  mkfs.ext4 /dev/data/volume1
fi
mkdir -p /data
echo '/dev/data/volume1 /data ext4 defaults 0 0' >> /etc/fstab
mount /data

# install docker
curl https://get.docker.com | bash

Elastic IP, Route53

## route53.tf
resource "aws_route53_zone" "newtech-academy" {
  name = "newtech.academy"
}

resource "aws_route53_record" "server1-record" {
  zone_id = aws_route53_zone.newtech-academy.zone_id
  name    = "server1.newtech.academy"
  type    = "A"
  ttl     = "300"
  records = ["104.236.247.8"]
}

resource "aws_route53_record" "www-record" {
  zone_id = aws_route53_zone.newtech-academy.zone_id
  name    = "www.newtech.academy"
  type    = "A"
  ttl     = "300"
  records = ["104.236.247.8"]
}

resource "aws_route53_record" "mail1-record" {
  zone_id = aws_route53_zone.newtech-academy.zone_id
  name    = "newtech.academy"
  type    = "MX"
  ttl     = "300"
  records = [
    "1 aspmx.l.google.com.",
    "5 alt1.aspmx.l.google.com.",
    "5 alt2.aspmx.l.google.com.",
    "10 aspmx2.googlemail.com.",
    "10 aspmx3.googlemail.com.",
  ]
}

output "ns-servers" {
  value = aws_route53_zone.newtech-academy.name_servers
}

aws_route53_zone

Route53 Hosted Zoneを管理します。

  • name – (必須) ホストされているゾーンの名前です。

aws_route53_record

Route53 レコードリソースを提供します。

  • zone_id – (必須) このレコードを含むホストされているゾーンの ID。
  • name – (必須)レコードの名前。
  • type – (必須) レコードタイプ。有効な値は、A、AAAA、CAA、CNAME、DS、MX、NAPTR、NS、PTR、SOA、SPF、SRV、TXTです。
  • ttl – (非エイリアスレコードでは必須)レコードのTTL。
  • records – (非エイリアスレコードの場合は必須) レコードの文字列リスト。DKIM用のTXTレコードなど、255文字より長いレコード値を1つだけ指定する場合は、Terraformの設定文字列の中に \"\" を追加します(例:"first255characters\"\"morecharacters" )。

RDS

resource "aws_db_subnet_group" "mariadb-subnet" {
  name        = "mariadb-subnet"
  description = "RDS subnet group"
  subnet_ids  = [aws_subnet.main-private-1.id, aws_subnet.main-private-2.id]
}

resource "aws_db_parameter_group" "mariadb-parameters" {
  name        = "mariadb-parameters"
  family      = "mariadb10.4"
  description = "MariaDB parameter group"

  parameter {
    name  = "max_allowed_packet"
    value = "16777216"
  }
}

resource "aws_db_instance" "mariadb" {
  allocated_storage       = 100 # 100 GB of storage, gives us more IOPS than a lower number
  engine                  = "mariadb"
  engine_version          = "10.4"
  instance_class          = "db.t2.small" # use micro if you want to use the free tier
  identifier              = "mariadb"
  db_name                 = "mariadb"
  username                = "root"           # username
  password                = var.RDS_PASSWORD # password
  db_subnet_group_name    = aws_db_subnet_group.mariadb-subnet.name
  parameter_group_name    = aws_db_parameter_group.mariadb-parameters.name
  multi_az                = "false" # set to true to have high availability: 2 instances synchronized with each other
  vpc_security_group_ids  = [aws_security_group.allow-mariadb.id]
  storage_type            = "gp2"
  backup_retention_period = 30                                          # how long you’re going to keep your backups
  availability_zone       = aws_subnet.main-private-1.availability_zone # prefered AZ
  skip_final_snapshot     = true                                        # skip final snapshot when doing terraform destroy
  tags = {
    Name = "mariadb-instance"
  }
}

aws_db_subnet_group

  • name – (オプション、強制新規リソース) DBサブネットグループの名前。省略した場合、Terraform はランダムでユニークな名前を割り当てます。
  • description – (オプション) DB サブネットグループの説明。デフォルトは “Managed by Terraform”。
  • subnet_ids – (必須) VPCサブネットIDのリスト。

aws_db_parameter_group

  • name – (オプション、強制新規リソース) DBパラメータグループの名前。省略した場合、Terraformはランダムでユニークな名前を割り当てます。
  • family – (必須、強制新規リソース) DB パラメータグループのファミリ。
  • description – (オプション、強制新規リソース) DB パラメータグループの説明。デフォルトは “Managed by Terraform” です。

aws_db_instance

  • allocated_storage -(snapshot_identifier または replicate_source_db が指定さ れていない場合は必須)割り当て済みストレージ。max_allocated_storage が設定されている場合、この引数は最初のストレージ割り当てを表し、Storage Autoscaling が発生すると設定との違いは自動的に無視されます。replicate_source_db が設定されている場合、この値はインスタンスの作成時には無視されます。
  • engine – (snapshot_identifier または replicate_source_db が指定されていない場合は必須) 使用するデータベース・エンジン。Amazon Auroraインスタンスの場合、エンジンはDBクラスタのエンジンと一致しなければならないことに注意してください。
  • engine_version – (オプション) 使用するエン ジ ンのバージ ョ ン。auto_minor_version_upgrade が有効になっている場合は、5.7 ( 5.7.10 の場合) のようにバージョンのプレフィックスを指定することができます。実際に使用す る エン ジ ンバージ ョ ンは属性 engine_version_actual で返されます。Amazon Auroraインスタンスの場合、エンジンバージョンはDBクラスタのエンジンバージョンと一致しなければならないことに注意してください。
  • instance_class – (必須) RDSインスタンスのインスタンスタイプ。
  • identifier – (オプション) RDSインスタンスの名前。省略した場合、Terraformはランダムな一意の識別子を割り当てます。restore_to_point_in_time が指定されている場合は必須。
  • db_name – (オプション) DB インスタンスの作成時に作成するデータベースの名前。このパラメータを指定しない場合、DB インスタンスにデータベースは作成されません。Oracle や SQL Server エンジンには適用されないことに注意してください。Oracle DB 名を指定する場合は、すべて大文字にする必要があります。レプリカには指定できません。
  • username – ( snapshot_identifier または replicate_source_db が指定されていない場合は必須) マスターDBユーザのユーザ名。レプリカには指定できません。
  • password – ( manage_master_user_passwordtrue に設定されている場合、または snapshot_identifier または replicate_source_db が指定されている場合、または manage_master_user_password が設定されている場合を除き、必須)マスターDBユーザのパスワード。これはログに表示される可能性があり、状態ファイルに保存されることに注意してください。manage_master_user_passwordtrue に設定されている場合は設定できません。
  • db_subnet_group_name – (オプション) DB サブネットグループの名前。DBインスタンスはDBサブネットグループに関連付けられたVPCに作成される。未指定の場合、デフォルトのVPC、またはEC2クラシック(利用可能な場合)に作成される。リードレプリカを使用する場合は、ソースデータベースが別のAWSリージョンにあるインスタンスを指定している場合のみ指定する。
  • parameter_group_name – (オプション) 関連付ける DB パラメータ・グループの名前。
  • multi_az – (オプション) RDSインスタンスがマルチAZであるかどうかを指定します。
  • vpc_security_group_ids – (オプション)関連付けるVPCセキュリティグループのリスト。
  • storage_type – (オプション) “standard”(磁気)、”gp2″(汎用SSD)、”gp3″(iopsが独立して必要な汎用SSD)、”io1″(プロビジョニングされたIOPS SSD)のいずれか。デフォルトは、iops が指定されている場合は “io1″、指定されていない場合は “gp2″です。
  • backup_retention_period – (オプション)バックアップを保持する日数。0 から 35 の間で設定する必要があります。デフォルトは 0 です。データベースが Read Replica のソースとして使用される場合、低ダウンタイム更新を使用する場合、または RDS Blue/Green デプロイメントを使用する場合は、0より大きくする必要があります。
  • availability_zone – (オプション)RDSインスタンスのAZ。
  • skip_final_snapshot – (オプション) DB インスタンスが削除される前に DB の最終スナップショットを作成するかどうかを決定します。true を指定すると、DBSnapshot は作成されません。false を指定すると、DB インスタンスが削除される前に、final_snapshot_identifier の値を使用して DB スナップショットが作成されます。デフォルトは false です。
  • tags – (オプション)リソースに割り当てるタグのマップ。プロバイダの default_tags 設定ブロックが存在する状態で設定された場合、一致するキーを持つタグはプロバイダ・レベルで定義されたものを上書きします。

IAM

# group definition
resource "aws_iam_group" "administrators" {
  name = "administrators"
}

resource "aws_iam_policy_attachment" "administrators-attach" {
  name       = "administrators-attach"
  groups     = [aws_iam_group.administrators.name]
  policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}

# user
resource "aws_iam_user" "admin1" {
  name = "admin1"
}

resource "aws_iam_user" "admin2" {
  name = "admin2"
}

resource "aws_iam_group_membership" "administrators-users" {
  name = "administrators-users"
  users = [
    aws_iam_user.admin1.name,
    aws_iam_user.admin2.name,
  ]
  group = aws_iam_group.administrators.name
}

  • (注意)すでにユーザにpolicyをアタッチしている場合、aws_iam_policy_attachment を使用すると影響が出る可能性があります。代わりに、aws_iam_role_policy_attachment , aws_iam_user_policy_attachment , aws_iam_group_policy_attachment を使用することが推奨されます。

IAM Role

resource "aws_iam_role" "s3-mybucket-role" {
  name               = "s3-mybucket-role"
  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF

}

resource "aws_iam_instance_profile" "s3-mybucket-role-instanceprofile" {
  name = "s3-mybucket-role"
  role = aws_iam_role.s3-mybucket-role.name
}

resource "aws_iam_role_policy" "s3-mybucket-role-policy" {
  name = "s3-mybucket-role-policy"
  role = aws_iam_role.s3-mybucket-role.id
  policy = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
              "s3:*"
            ],
            "Resource": [
              "arn:aws:s3:::mybucket-c29df1",
              "arn:aws:s3:::mybucket-c29df1/*"
            ]
        }
    ]
}
EOF

}

aws_iam_role

IAMロールの設定。ヒアドキュメント(EOF (end of fileの略))ではなく、 jsonencode を使っても良い。

aws_iam_instance_profile

IAMインスタンスプロファイルの設定。EC2インスタンスにIAMロールをアタッチする。

aws_iam_role_policy

IAMポリシー。IAMロールに紐づけるポリシー(権限)を設定する。

Auto Scaling

## autoscaling.tf

# resource "aws_launch_configuration" "example-launchconfig" {
#   name_prefix     = "example-launchconfig"
#   image_id        = var.AMIS[var.AWS_REGION]
#   instance_type   = "t2.micro"
#   key_name        = aws_key_pair.mykeypair.key_name
#   security_groups = [aws_security_group.allow-ssh.id]
# }

resource "aws_launch_template" "example-launchtemplate" {
  name_prefix       = "example-launchtemplate"
  image_id          = var.AMIS[var.AWS_REGION]
  instance_type     = "t2.micro"
  key_name        = aws_key_pair.mykeypair.key_name
  
  network_interfaces {
    security_groups = [ aws_security_group.allow-ssh.id ]
  }
}

resource "aws_autoscaling_group" "example-autoscaling" {
  name                      = "example-autoscaling"
  vpc_zone_identifier       = [aws_subnet.main-public-1.id, aws_subnet.main-public-2.id]
  # launch_configuration      = aws_launch_configuration.example-launchconfig.name
  min_size                  = 1
  max_size                  = 2
  health_check_grace_period = 300
  health_check_type         = "EC2"
  force_delete              = true

  launch_template {
    id                      = aws_launch_template.example-launchtemplate.id
    version                 = "$Latest"
  }

  tag {
    key                 = "Name"
    value               = "ec2 instance"
    propagate_at_launch = true
  }
}

aws_launch_configuration

(非推奨)autoscaling時の起動設定。使用は推奨されず、起動テンプレートの使用が推奨されます。aws_launch_configurationaws_autoscaling_group と一緒に使う場合、name (Optional) 属性の代わりに name_prefix (Optional) 属性を使うことを推奨します。こうすることで、Terraformのライフサイクルが起動設定の変更を検知し、オートスケーリンググループを正しく更新できるようになります。

aws_autoscaling_group

オートスケーリンググループリソースを提供します。launch_configurationlaunch_templatemixed_instances_policy のいずれかを指定する必要があります。

aws_launch_template

EC2の起動テンプレートリソースを提供する。インスタンスやオートスケーリンググループの作成に使用できる。

(注意) AWSはEC2 Auto Scalingの一部である Launch Configurations について、2022年12月31日以降にリリースされる新しいEC2機能や新しいEC2インスタンスタイプをサポートしないと発表しています。新しいEC2インスタンスタイプをAuto Scaling groupで使用するためには、Launch Templates を使用する必要があります。

## autoscalingpolicy.tf

# scale up alarm
resource "aws_autoscaling_policy" "example-cpu-policy" {
  name                   = "example-cpu-policy"
  autoscaling_group_name = aws_autoscaling_group.example-autoscaling.name
  adjustment_type        = "ChangeInCapacity"
  scaling_adjustment     = "1"
  cooldown               = "300"
  policy_type            = "SimpleScaling"
}

resource "aws_cloudwatch_metric_alarm" "example-cpu-alarm" {
  alarm_name          = "example-cpu-alarm"
  alarm_description   = "example-cpu-alarm"
  comparison_operator = "GreaterThanOrEqualToThreshold"
  evaluation_periods  = "2"
  metric_name         = "CPUUtilization"
  namespace           = "AWS/EC2"
  period              = "120"
  statistic           = "Average"
  threshold           = "30"

  dimensions = {
    "AutoScalingGroupName" = aws_autoscaling_group.example-autoscaling.name
  }

  actions_enabled = true
  alarm_actions   = [aws_autoscaling_policy.example-cpu-policy.arn]
}

# scale down alarm
resource "aws_autoscaling_policy" "example-cpu-policy-scaledown" {
  name                   = "example-cpu-policy-scaledown"
  autoscaling_group_name = aws_autoscaling_group.example-autoscaling.name
  adjustment_type        = "ChangeInCapacity"
  scaling_adjustment     = "-1"
  cooldown               = "300"
  policy_type            = "SimpleScaling"
}

resource "aws_cloudwatch_metric_alarm" "example-cpu-alarm-scaledown" {
  alarm_name          = "example-cpu-alarm-scaledown"
  alarm_description   = "example-cpu-alarm-scaledown"
  comparison_operator = "LessThanOrEqualToThreshold"
  evaluation_periods  = "2"
  metric_name         = "CPUUtilization"
  namespace           = "AWS/EC2"
  period              = "120"
  statistic           = "Average"
  threshold           = "5"

  dimensions = {
    "AutoScalingGroupName" = aws_autoscaling_group.example-autoscaling.name
  }

  actions_enabled = true
  alarm_actions   = [aws_autoscaling_policy.example-cpu-policy-scaledown.arn]
}

aws_autoscaling_policy

AutoScaling Scaling Policy リソースを提供します。オートスケーリングポリシーを使用する場合、アタッチされた aws_autoscaling_group から desired_capacity 属性を省略することができます。手動または動的(ポリシーベース)スケーリングを選択するのが良い習慣です。

aws_cloudwatch_metric_alarm

CloudWatch Metric Alarmリソースを提供します。

ELB

## elb.tf

resource "aws_elb" "my-elb" {
  name            = "my-elb"
  subnets         = [aws_subnet.main-public-1.id, aws_subnet.main-public-2.id]
  security_groups = [aws_security_group.elb-securitygroup.id]
  listener {
    instance_port     = 80
    instance_protocol = "http"
    lb_port           = 80
    lb_protocol       = "http"
  }
  health_check {
    healthy_threshold   = 2
    unhealthy_threshold = 2
    timeout             = 3
    target              = "HTTP:80/"
    interval            = 30
  }

  cross_zone_load_balancing   = true
  connection_draining         = true
  connection_draining_timeout = 400
  tags = {
    Name = "my-elb"
  }
}

Classic Load Balancerの設定。

Elastic Beanstalk

resource "aws_elastic_beanstalk_application" "app" {
  name        = "app"
  description = "app"
}

# this automatically retrieves the latest solution stack
data "aws_elastic_beanstalk_solution_stack" "php-latest" {
  most_recent = true
  name_regex = "^64bit Amazon Linux (.*) running PHP 8.(.*)$"
}

resource "aws_elastic_beanstalk_environment" "app-prod" {
  name                = "app-prod"
  application         = aws_elastic_beanstalk_application.app.name
  solution_stack_name = data.aws_elastic_beanstalk_solution_stack.php-latest.name
  setting {
    namespace = "aws:ec2:vpc"
    name      = "VPCId"
    value     = aws_vpc.main.id
  }
  setting {
    namespace = "aws:ec2:vpc"
    name      = "Subnets"
    value     = "${aws_subnet.main-private-1.id},${aws_subnet.main-private-2.id}"
  }
  setting {
    namespace = "aws:ec2:vpc"
    name      = "AssociatePublicIpAddress"
    value     = "false"
  }
  setting {
    namespace = "aws:autoscaling:launchconfiguration"
    name      = "IamInstanceProfile"
    value     = aws_iam_instance_profile.app-ec2-role.name
  }
  setting {
    namespace = "aws:autoscaling:launchconfiguration"
    name      = "SecurityGroups"
    value     = aws_security_group.app-prod.id
  }
  setting {
    namespace = "aws:autoscaling:launchconfiguration"
    name      = "EC2KeyName"
    value     = aws_key_pair.mykeypair.id
  }
  setting {
    namespace = "aws:autoscaling:launchconfiguration"
    name      = "InstanceType"
    value     = "t2.micro"
  }
  setting {
    namespace = "aws:elasticbeanstalk:environment"
    name      = "ServiceRole"
    value     = aws_iam_role.elasticbeanstalk-service-role.name
  }
  setting {
    namespace = "aws:ec2:vpc"
    name      = "ELBScheme"
    value     = "public"
  }
  setting {
    namespace = "aws:ec2:vpc"
    name      = "ELBSubnets"
    value     = "${aws_subnet.main-public-1.id},${aws_subnet.main-public-2.id}"
  }
  setting {
    namespace = "aws:elb:loadbalancer"
    name      = "CrossZone"
    value     = "true"
  }
  setting {
    namespace = "aws:elasticbeanstalk:command"
    name      = "BatchSize"
    value     = "30"
  }
  setting {
    namespace = "aws:elasticbeanstalk:command"
    name      = "BatchSizeType"
    value     = "Percentage"
  }
  setting {
    namespace = "aws:autoscaling:asg"
    name      = "Availability Zones"
    value     = "Any 2"
  }
  setting {
    namespace = "aws:autoscaling:asg"
    name      = "MinSize"
    value     = "1"
  }
  setting {
    namespace = "aws:autoscaling:updatepolicy:rollingupdate"
    name      = "RollingUpdateType"
    value     = "Health"
  }
  setting {
    namespace = "aws:elasticbeanstalk:application:environment"
    name      = "RDS_USERNAME"
    value     = aws_db_instance.mariadb.username
  }
  setting {
    namespace = "aws:elasticbeanstalk:application:environment"
    name      = "RDS_PASSWORD"
    value     = aws_db_instance.mariadb.password
  }
  setting {
    namespace = "aws:elasticbeanstalk:application:environment"
    name      = "RDS_DATABASE"
    value     = aws_db_instance.mariadb.db_name
  }
  setting {
    namespace = "aws:elasticbeanstalk:application:environment"
    name      = "RDS_HOSTNAME"
    value     = aws_db_instance.mariadb.endpoint
  }
}

Elastic BeanstalkはAWSへのデプロイやスケーリングを自動化してくれるツールです。

以上です。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です