본문 바로가기!

Terraform

[Terraform] count, for_each 등 실습예제

728x90
반응형

Challenge1) 

data "aws_availability_zones" "az" {
  state = "available"
}

resource "aws_vpc" "vpc" {
  cidr_block           = var.vpc_cidr
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name = "${var.env}-vpc"
  }
}

resource "aws_subnet" "pub_subnet1" {
  vpc_id            = aws_vpc.vpc.id
  cidr_block        = "${var.pub_cidr[0]}"
  availability_zone = data.aws_availability_zones.az.names[0]
  tags = {
    Name = "${var.env}-pub-${data.aws_availability_zones.az.names[0]}"
  }
}

resource "aws_subnet" "pub_subnet2" {
  vpc_id            = aws_vpc.vpc.id
  cidr_block        = "${var.pub_cidr[1]}"
  availability_zone = data.aws_availability_zones.az.names[2]
  tags = {
    Name = "${var.env}-pub-${data.aws_availability_zones.az.names[2]}"
  }
}

 

 

Challenge2)

resource "리소스 종류" "리소스 이름" {
  ~!@#
}

 

 

Challenge3)

init_busybox.tpl 간단한 웹서버 배포 템플릿
instance.tf userdata에 템플릿 파일을 활용하여 my_name변수와 port_num변수를 입력변수에서 받아와 user_data를 적용하며 count를 통한 인스턴스를 var.instance_num의 리스트 수만큼 생성한다.
또한 root volume_size도 입력 변수로 받아온다.
vars.tf instance.tf 에서 사용할 입력변수들을 선언
outputs.tf 인스턴스 프로비저닝 후 public ip 및 port 정보 확인

 

  • init_busybox.tpl
#!/bin/bash
echo "Hello, ${my_name}" > index.html
nohup busybox httpd -f -p ${port_num} &

 

  • instance.tf
provider "aws" {
  region = "ap-northeast-2"
}

resource "aws_instance" "httpd" {
  count         = length(var.instance_num)
  ami           = data.aws_ami.latest_ubuntu_2204.id
  instance_type = var.instance_type

  user_data = base64encode(templatefile("${path.module}/init_busybox.tpl", merge({my_name = var.my_name[count.index]}, {port_num = var.port_num[count.index]})))

  root_block_device {
    volume_size           = var.instance_volume_size[count.index]
    volume_type           = "gp2"
    encrypted             = true
    delete_on_termination = true
  }

  lifecycle {
    ignore_changes = [ user_data ]
  }

  tags = {
    Name = "instance-${count.index+1}"
  }
}

 

  • vars.tf
data "aws_ami" "latest_ubuntu_2204" {
  most_recent = true #최신 ami가져옴
  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server*"]
  }
  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
  owners = ["099720109477"] # Canonical (우분투를 만든회사에 대해서만 ami가져옴)
}

variable "instance_num" {
  description = "number of busybox instance"
  type        = list(string)
  default     = ["1", "2", "3"]
}

variable "instance_volume_size" {
  description = "instance volume size"
  type        = list(string)
  default     = ["30", "40", "50"]
}

variable "instance_type" {
  default = "t2.micro"
}

variable "my_name" {
  type        = list(string)
  default     = ["junho1", "junho2", "junho3"]
}

variable "port_num" {
  type        = list(string)
  default     = ["7070", "8080", "9090"]
}

 

  • outputs.tf
output "instance1_public_ip" {
  value = "curl ${aws_instance.httpd[0].public_ip}:${var.port_num[0]}"
}
output "instance2_public_ip" {
  value = "curl ${aws_instance.httpd[1].public_ip}:${var.port_num[1]}"
}
output "instance3_public_ip" {
  value = "curl ${aws_instance.httpd[2].public_ip}:${var.port_num[2]}"
}

 

  • 결과 확인)
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.

Outputs:

instance1_public_ip = "curl 54.180.8.137:7070"
instance2_public_ip = "curl 3.39.22.156:8080"
instance3_public_ip = "curl 3.35.208.125:9090"

 

 

Challenge4)

init_busybox.tpl 간단한 웹서버 배포 템플릿
instance.tf userdata에 템플릿 파일을 활용하여 my_name변수와 port_num변수를 입력변수에서 받아와 user_data를 적용하며 count를 통한 인스턴스를 var.instance_num의 리스트 수만큼 생성한다.
또한 root volume_size도 입력 변수로 받아온다.
vars.tf instance.tf 에서 사용할 입력변수들을 선언
  • challenge3과 차이점은 vars.tf에 local을 활용해서 인스턴스 블록에서 사용하는 값들을 정형화하고 user_data에 사용할 템플릿 파일에 적용할 변수는 custom_data_args로 관리

 

  • init_busybox.tpl
#!/bin/bash
echo "Hello, ${my_name}" > index.html
nohup busybox httpd -f -p ${port_num} &

 

  • instance.tf
provider "aws" {
  region = "ap-northeast-2"
}

resource "aws_instance" "httpd" {
  ami           = local.ubuntu_22_04_ami
  instance_type = local.inst_type

  user_data = base64encode(templatefile("${path.module}/init_busybox.tpl", local.custom_data_args))

  root_block_device {
    volume_size           = local.inst_vol_size
    volume_type           = "gp2"
    encrypted             = true
    delete_on_termination = true
  }

  lifecycle {
    ignore_changes = [user_data]
  }

  tags = {
    Name = "${local.custom_data_args.my_name}-instance"
  }
}

output "public_ip" {
  value = "curl ${aws_instance.httpd.public_ip}:${local.custom_data_args.port_num}"
}

 

  • vars.tf
data "aws_ami" "latest_ubuntu_2204" {
  most_recent = true #최신 ami가져옴
  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server*"]
  }
  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
  owners = ["099720109477"] # Canonical (우분투를 만든회사에 대해서만 ami가져옴)
}

variable "instance_num" {
  description = "number of busybox instance"
  type        = list(string)
  default     = ["1", "2", "3"]
}

variable "instance_volume_size" {
  default = "30"
}

variable "instance_type" {
  default = "t2.micro"
}

variable "my_name" {
  default = "junho"
}

variable "port_num" {
  default = "8080"
}

locals {
  inst_num         = var.instance_num
  inst_vol_size    = var.instance_volume_size
  inst_type        = var.instance_type
  ubuntu_22_04_ami = data.aws_ami.latest_ubuntu_2204.id

  custom_data_args = {
    my_name  = var.my_name
    port_num = var.port_num
  }
}

 

 

Challenge5)

  • count, for_each 반복문, for문, dynamic문을 활용해서 리소스(어떤 리소스든지 상관없음)을 배포해보고, 해당 코드를 정리

 

data "aws_availability_zones" "az" {
  state = "available"
}

variable "env" {
  description = "environment"
  default = "test"
}

variable "vpc_cidr" {
  description = "VPC CIDR BLOCK : x.x.x.x/x"
  default     = "192.168.0.0/16"
}

variable "pub_cidr" {
  description = "pub CIDR BLOCK : x.x.x.x/x"
  type        = list(string)
  default     = ["192.168.1.0/24", "192.168.2.0/24"]
}

resource "aws_vpc" "vpc" {
  cidr_block           = var.vpc_cidr
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name = "${var.env}-vpc"
  }
}

resource "aws_subnet" "pub_subnet" {
  count             = length(var.pub_cidr)
  vpc_id            = aws_vpc.vpc.id
  cidr_block        = element(var.pub_cidr, count.index)
  availability_zone = ((count.index) % 2) == 0 ? data.aws_availability_zones.az.names[0] : data.aws_availability_zones.az.names[2]

  tags = {
    Name = "${var.env}-pub-${((count.index) % 2) == 0 ? "a" : "c"}"
  }
}

 

data "aws_availability_zones" "az" {
  state = "available"
}

data "aws_ami" "latest_ubuntu_2204" {
  most_recent = true #최신 ami가져옴
  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server*"]
  }
  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
  owners = ["099720109477"] # Canonical (우분투를 만든회사에 대해서만 ami가져옴)
}

variable "env" {
  description = "environment"
  default = "test"
}

variable "vpc_cidr" {
  description = "VPC CIDR BLOCK : x.x.x.x/x"
  default     = "192.168.0.0/16"
}

variable "pub_cidr" {
  description = "pub CIDR BLOCK : x.x.x.x/x"
  type        = list(string)
  default     = ["192.168.1.0/24", "192.168.2.0/24"]
}

variable "project" {
  description = "Map of project names to configuration."
  type        = map(any)

  default = {
    client-webapp = {
      instance_type           = "t2.micro",
      environment             = "dev"
      volume_size             = "30"
      aws_availability_zones  = "0"
      public_subnet      = "0"
    },
    internal-webapp = {
      instance_type           = "t2.nano",
      environment             = "test"
      volume_size             = "50"
      aws_availability_zones  = "2"
      public_subnet      = "1"
    }
  }
}
resource "aws_vpc" "vpc" {
  cidr_block           = var.vpc_cidr
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name = "${var.env}-vpc"
  }
}

resource "aws_subnet" "pub_subnet" {
  count             = length(var.pub_cidr)
  vpc_id            = aws_vpc.vpc.id
  cidr_block        = element(var.pub_cidr, count.index)
  availability_zone = ((count.index) % 2) == 0 ? data.aws_availability_zones.az.names[0] : data.aws_availability_zones.az.names[2]

  tags = {
    Name = "${var.env}-pub-${((count.index) % 2) == 0 ? "a" : "c"}"
  }
}

resource "aws_instance" "httpd" {
  for_each      = var.project
  ami           = data.aws_ami.latest_ubuntu_2204.id
  instance_type = each.value.instance_type
  subnet_id     = aws_subnet.pub_subnet[each.value.public_subnet].id

  root_block_device {
    volume_size           = each.value.volume_size
    volume_type           = "gp2"
    encrypted             = true
    delete_on_termination = true
  }

  tags = {
    Name = "${each.value.environment}-${each.key}"
  }
}

 

output "public_ip_test1" {
  value = [for t in aws_instance.ec2.*.public_ip : "${t}"]
}

output "public_ip_test2" {
  value = [for t in aws_instance.ec2 : "${t.tags.Name} public_ip = ${t.public_ip}"]
}
  • 결과 확인)
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.

Outputs:

public_ip_test1 = [
  "43.200.178.21",
  "43.201.27.160",
  "3.35.24.246",
]
public_ip_test2 = [
  "instance-1 public_ip = 43.200.178.21",
  "instance-2 public_ip = 43.201.27.160",
  "instance-3 public_ip = 3.35.24.246",
]

 

resource "aws_security_group" "bastion_sg" {
  name        = "allow_tls"
  description = "Bastion Allow inbound traffic"
  dynamic "ingress" {
    for_each = [80,443,22]
    iterator = port
    content {
      description = "bastion_allow_inbound"
      from_port   = port.value
      to_port     = port.value
      protocol    = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
    }
  }
  egress {
    from_port        = 0
    to_port          = 0
    protocol         = "-1"
    cidr_blocks      = ["0.0.0.0/0"]
    ipv6_cidr_blocks = ["::/0"]
  }
}
  • 결과확인)

728x90
반응형