以下の内容はhttps://kakakakakku.hatenablog.com/entry/2025/07/09/211955より取得しました。


Moto: AWS アカウントなしで Terraform のチュートリアル「Manage similar resources with count」を実施する

Moto を使えば AWS アカウントなしで Terraform のチュートリアル「Use configuration to move resources」を実施できるよ〜という紹介記事を前に書いた📝

kakakakakku.hatenablog.com

今度は Terraform のチュートリアル「Manage similar resources with count」を試してみた.Terraform の count を使って複数台の Amazon EC2 インスタンスを適切なサブネットにデプロイするというリファクタリングを体験できる.最終的に AWS アカウントなしで実施できた❗️

developer.hashicorp.com

セットアップ

Moto (Server Mode) を起動すれば OK👌

$ docker run --rm -p 5000:5000 --name moto motoserver/moto

また Amazon EC2 インスタンスが依存する AMI (Amazon Machine Image)amzn2-ami-hvm-*-x86_64-gp2 というフィルタ条件を使っている.Moto にもともと登録されている AMI 情報でフィルタ条件を満たせるため,Moto に独自の AMI を登録する仕組みは使わなくて大丈夫だった.

$ aws ec2 describe-images --endpoint-url http://localhost:5000 --region us-east-2 \
  --filters "Name=name,Values=amzn2-ami-hvm-*-x86_64-gp2" | jq -r '.Images[].Name'
amzn2-ami-hvm-2.0.20180810-x86_64-gp2
amzn2-ami-hvm-2.0.20250321.0-x86_64-gp2

👾 main.tf

次に GitHub リポジトリ hashicorp-education/learn-terraform-count を clone する.

github.com

そして main.tfprovider 部分を以下のように書き換えると Amazon EC2 API と Elastic Load Balancing API に対する操作は Moto を参照するようになる.

provider "aws" {
  region = var.aws_region

  skip_credentials_validation = true
  skip_requesting_account_id  = true

  endpoints {
    ec2 = "http://localhost:5000"
    elb = "http://localhost:5000"
  }
}

チュートリアルを実施する

あとは Moto を意識することなくチュートリアル「Manage similar resources with count」を実施できる👌

main.tf を読むと Terraform AWS modules を活用する例としても参考になる.Classic Load Balancer はなつかしすぎるけど😇

そして,最初に apply するときに「40 リソースも」追加される.AWS x Terraform 初学者だと不安に感じてここで挫折してしまう人もいると思う.Moto なら AWS アカウントなしで問題なく apply できる❗️

$ terraform apply

(中略)

Apply complete! Resources: 40 added, 0 changed, 0 destroyed.

Outputs:

instance_ids = [
  "i-fe2512068483faa46",
  "i-943c5191a02d3b2c0",
]
public_dns_name = "lb-Kh0g-client-webapp-dev.us-east-1.elb.amazonaws.com"
vpc_arn = "arn:aws:ec2:us-east-2:123456789012:vpc/vpc-0353f604b991548bb"

あとは countlength 関数を使って aws_instance リソースを複数デプロイできるようにリファクタリングする.サブネット指定も % を使って Multi-AZ 配置できるように自動計算している👌

developer.hashicorp.com

developer.hashicorp.com

resource "aws_instance" "app" {
  depends_on = [module.vpc]

  count = var.instances_per_subnet * length(module.vpc.private_subnets)

  ami           = data.aws_ami.amazon_linux.id
  instance_type = var.instance_type


  subnet_id              = module.vpc.private_subnets[count.index % length(module.vpc.private_subnets)]
  vpc_security_group_ids = [module.app_security_group.security_group_id]

  user_data = <<-EOF
    #!/bin/bash
    sudo yum update -y
    sudo yum install httpd -y
    sudo systemctl enable httpd
    sudo systemctl start httpd
    echo "<html><body><div>Hello, world!</div></body></html>" > /var/www/html/index.html
    EOF

  tags = {
    Terraform   = "true"
    Project     = var.project_name
    Environment = var.environment
  }
}

さらにスプラット演算子を使って ELB に紐付ける Amazon EC2 インスタンスを指定するようにリファクタリングする.ちなみに aws_instance.app.*.id は非推奨だから,今なら aws_instance.app[*].id って書くと良いと思う💡

developer.hashicorp.com

module "elb_http" {
  source  = "terraform-aws-modules/elb/aws"
  version = "3.0.1"

  # Comply with ELB name restrictions
  # https://docs.aws.amazon.com/elasticloadbalancing/2012-06-01/APIReference/API_CreateLoadBalancer.html
  name     = trimsuffix(substr(replace(join("-", ["lb", random_string.lb_id.result, var.project_name, var.environment]), "/[^a-zA-Z0-9-]/", ""), 0, 32), "-")
  internal = false

  security_groups = [module.lb_security_group.security_group_id]
  subnets         = module.vpc.public_subnets

  number_of_instances = length(aws_instance.app)
  instances           = aws_instance.app.*.id

  listener = [{
    instance_port     = "80"
    instance_protocol = "HTTP"
    lb_port           = "80"
    lb_protocol       = "HTTP"
  }]

  health_check = {
    target              = "HTTP:80/index.html"
    interval            = 10
    healthy_threshold   = 3
    unhealthy_threshold = 10
    timeout             = 5
  }
}

リファクタリング後の apply も OK👌

$ terraform apply

(中略)

Apply complete! Resources: 8 added, 0 changed, 4 destroyed.

Outputs:

instance_ids = [
  "i-902dbb50c04807a0f",
  "i-3ec3f6a467d833c0e",
  "i-fd30ccdad5fd027de",
  "i-f11c775ec22650c6d",
]
public_dns_name = "lb-Kh0g-client-webapp-dev.us-east-1.elb.amazonaws.com"
vpc_arn = "arn:aws:ec2:us-east-2:123456789012:vpc/vpc-0353f604b991548bb"

destroy を実行できた❗️(もはや destroy を実行せず Moto (Server Mode) を停止してしまっても OK💡)

$ terraform destroy

(中略)

Destroy complete! Resources: 44 destroyed.

まとめ

Moto を使って AWS アカウントなしで Terraform のチュートリアルを実行できた👏




以上の内容はhttps://kakakakakku.hatenablog.com/entry/2025/07/09/211955より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14