본문 바로가기

DevOps/Terraform

[T102 2주차] (7) 도전과제

cloudNet@ 팀의 가시다 님이 진행하는 테라폼 102 스터디 2주차 정리입니다.
2주차 내용: 

도전과제 5가지

  • data_block 활용
  • 배포되는 리소스 이름과 참조에 대한 이해
  • 입력 변수를 활용한 리소스 배포 
  • local를 활용해서 리소스를 배포
  • count, for_each 반복문, for문, dynamic문 을 활용

1번,2번 도전과제 :

해당 링크는 aws_availability_zones의 데이터 소스 링크 페이지이다. 이를 참조하여, 현재 가용영역중 사용가능한 리스트를 뽑아 subnet 리소스에 적용시켜라.

 

data "aws_availability_zones" "available" {
  state = "available"
}
  • terraform apply 
mzc01-kook@MZC01-KOOK 3.1 % terraform state show data.aws_availability_zones.available

# data.aws_availability_zones.available:
data "aws_availability_zones" "available" {
    group_names = [
        "ap-northeast-2",
    ]
    id          = "ap-northeast-2"
    names       = [
        "ap-northeast-2a",
        "ap-northeast-2b",
        "ap-northeast-2c",
        "ap-northeast-2d",
    ]
    state       = "available"
    zone_ids    = [
        "apne2-az1",
        "apne2-az2",
        "apne2-az3",
        "apne2-az4",
    ]
}
  • VPC / subnet 생성 
data "aws_availability_zones" "available" {
  state = "available"
}

provider "aws" {
  region  = "ap-northeast-2"
}

resource "aws_vpc" "koovpc" {
  cidr_block       = "10.10.0.0/16"

  tags = {
    Name = "t101-study"
  }
}

resource "aws_subnet" "koosubnet1" {
  vpc_id     = aws_vpc.koovpc.id
  cidr_block = "10.10.1.0/24"

  availability_zone = data.aws_availability_zones.available.names[0]

  tags = {
    Name = "subnet1"
  }
}

resource "aws_subnet" "koosubnet2" {
  vpc_id     = aws_vpc.koovpc.id
  cidr_block = "10.10.2.0/24"

  availability_zone = data.aws_availability_zones.available.names[1]

  tags = {
    Name = "subnet2"
  }
}


3번 도전과제 :

입력변수를 활용해서 리소스를 배포

  • 입력 변수를 사용하려면 variable로 시작하는 tf 파일을 작성합니다.
# 먼저 variable.tf 파일을 만들어봅시다.

variable "vpc_tag_name" {
  description = "vpc tag name"
  type        = string
  default     = "koo-vpc-01"
}
  • 1,2번 과제에서 사용했던 vpc, subnet 코드에서 Tag 네임에 variable을 적용시켜 봅시다.
  • vpc의 tag 부분에 ${var.vpc_tag_name}으로 변경시켜 보겠습니다.
data "aws_availability_zones" "available" {
  state = "available"
}


provider "aws" {
  region  = "ap-northeast-2"
}

resource "aws_vpc" "koovpc" {
  cidr_block       = "10.10.0.0/16"

  tags = {
    Name = "${var.vpc_tag_name}"
  }
}

resource "aws_subnet" "koosubnet1" {
  vpc_id     = aws_vpc.koovpc.id
  cidr_block = "10.10.1.0/24"

  availability_zone = data.aws_availability_zones.available.names[0]

  tags = {
    Name = "subnet1"
  }
}

resource "aws_subnet" "koosubnet2" {
  vpc_id     = aws_vpc.koovpc.id
  cidr_block = "10.10.2.0/24"

  availability_zone = data.aws_availability_zones.available.names[1]

  tags = {
    Name = "subnet2"
  }
}


4번 도전과제 : 

local 변수를 활용하여 리소스(어떤 리소스든지 상관없음)를 배포해보고, 해당 코드를 정리

 

  코드의 중복을 방지하기 위해 module 에서 변수를 정의하는 방법이 local 변수입니다.

 하드 코딩되어 사용된 코드 제거 

변수 재사용성

 

💌 local 변수를 선언하고
locals {
  name = "mytest"
  team = {
    group = "dev"
  }
}

 

  • 위에서 정의한 로컬 변수를 resource block에서 로컬 참조를 통해 사용가능 합니다.
💌 이와같이 사용합니다.
resource "aws_iam_user" "myiamuser1" {
  name = "${local.name}1"
  tags = local.team
}

 

 


5번 도전과제 : 

 

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

 

count

  • 전체 리소스를 반복할 수는 있지만 리소스 내에서 인라인 블록을 반복할 때, count 사용은 지원하지 않습니다.
  • 배열의 중간 항목을 제거하면 모든 항목이 1칸씩 앞으로 당겨집니다.
  • 리소스의 여러 복사본을 만들 때는 count 대신 for_each 를 사용하는 것이 바람직합니다.
  • count.index를 활용하여 VM의 TAG name이 중복되지 않게 설정했습니다.
provider "aws" {
  region = "ap-northeast-2"
}

resource "aws_instance" "example" {
  count = 2
  ami           = "ami-0a0064415cdedc552"
  instance_type = "t2.micro"
  tags = {
    Name = "Server - ${count.index}"
  }
}

for_each

resource "<PROVIDER>_<TYPE>" "<NAME>" {
  for_each = <COLLECTION>

  [CONFIG ...]
}

 

  • 위와 같은 방식으로 for_each를 사용함
  • 리소스에 for_each 를 사용할 때, 리스트는 지원 안함
  • COLLECTION 은 루프를 처리할 집합 또는 맵
  • CONFIG 는 해당 리소스와 관련된 하나 이상의 인수로 구성되는데, CONFIG 내에서 each.key또는 each.value 를 사용하여 COLLECTION 에서 현재 항목의 키와 값에 접근할 수 있음
# public subnet
resource "aws_subnet" "pub_sub" {
  for_each                = var.public_subnet
  vpc_id                  = aws_vpc.vpc.id
  cidr_block              = each.value["cidr"]
  availability_zone       = each.value["az"]
  map_public_ip_on_launch = false

  tags = {
    Name = "${var.tags}-${each.key}"
  }
}
  • variable.tf 를 참조하여 배포
variable "tags" {
  description = "tag name"
  type        = string
  default     = "Koo"
}

variable "public_subnet" {
  type = map(any)
  default = {
    pub-sub-2a = {
      az   = "ap-northeast-2a"
      cidr = "10.10.4.0/24"
      des  = "2a"
    }
    pub-sub-2c = {
      az   = "ap-northeast-2c"
      cidr = "10.10.5.0/24"
      des  = "2c"
    }
  }
}
for_each는 반복을 수행할 때 object key로 접근하므로, index로 접근하는 리스트타입(count)과 비교하여 안전성이 있습니다.

 

for

  • 복합 형식 값의 형태를 변환하는 데 사용
  • 변수의 value값을 일괄적으로 다시 정의해야 할때 사용
  • 예시 )  ec2의 Tag 에 새로운 필드를 통해 생성된 timestamp를 입력 해달라는 요청이 왔습니다. 이 요구사항을 for expression을 이용하여 ec2의 태그를 쉽게 일괄 수정할 수 있습니다. timestamp() 함수와 local 변수를 활용하여 요구사항을 충족시켜 보십시오.
variable "fruits" {
  type        = set(string)
  default     = ["apple", "banana"]
  description = "fruit example"
}

variable "postfix" {
  type        = string
  default     = "test"
  description = "postfix"
}

locals {
  timestamp = "${timestamp()}"
  timestamp_sanitized = "${replace("${local.timestamp}", "/[- TZ:]/", "")}"

}
  • format 함수는 파이썬의 format 함수와 사용 방법이 같습니다.
  • 문자열 포매팅에 대해서는 점프투 파이썬이라는 책에 설명이 좋아서 가져왔습니다.

문자열 포매팅을 공부하기 전에 다음과 같은 문자열을 출력하는 프로그램을 작성했다고 가정해 보자.

"현재 온도는 18도입니다."

시간이 지나서 20도가 되면 다음 문장을 출력한다.

"현재 온도는 20도입니다"

두 문자열은 모두 같은데 20이라는 숫자와 18이라는 숫자만 다르다.

이렇게 문자열 안의 특정한 값을 바꿔야 할 경우가 있을 때 이것을 가능하게 해 주는 것이 바로 문자열 포매팅이다.

쉽게 말해 문자열 포매팅이란 문자열 안에 어떤 값을 삽입하는 방법이다. 

<참조: 점프투 파이썬 >

  • format 함수를 활용하여 두가지 변수의 value값을 합쳤습니다.
  • timestamp는 로컬 변수를 참조하여 Tag 값을 만들었습니다.
provider "aws" {
  region = "ap-northeast-2"
}

resource "aws_instance" "example" {
  for_each = toset([for fruit in var.fruits : format("%s-%s", fruit, var.postfix)])
  ami           = "ami-0a0064415cdedc552"
  instance_type = "t2.micro"
  tags = {
     Name = "${each.key}"
     timestamp = "${local.timestamp_sanitized}"
  }
}

파이썬 format 함수