DDetB.Log
article thumbnail
이 포스팅은 CloudNet@ 팀이 진행하는 테라폼 기초 입문 스터디에 참여하며 ‘테라폼으로 시작하는 IaC’ 책을 기준하여 정리한 글입니다.

Data Sources

데이터 소스는 테라폼으로 정의되지 않은 외부 리소스 또는 저장된 정보를 테라폼 내에서 참조할 때 사용

meta-arguments

  • depends_on : 종속성을 선언하며, 선언된 구성요소와의 생성 시점에 대해 정의
  • count : 선언된 개수에 따라 여러 리소스를 생성
  • for_each : map 또는 set 타입의 데이터 배열의 값을 기준으로 여러 리소스를 생성
  • lifecycle : 리소스의 수명주기 관리

기능 확인

main.tf

resource "local_file" "abc" {
  content  = "123!"
  filename = "${path.module}/abc.txt"
}

data "local_file" "abc" {
  filename = local_file.abc.filename
}

resource "local_file" "def" {
  content  = data.local_file.abc.content
  filename = "${path.module}/def.txt"
}

실행 및 동작 확인

$ terraform plan && terraform apply -auto-approve
...

$ ls -al
total 40
drwxrwxr-x 3 aiden aiden 4096 Jul  9 20:14 .
drwxrwxr-x 3 aiden aiden 4096 Jul  9 20:05 ..
-rw-rw-r-- 1 aiden aiden    4 Jul  9 20:11 abc.txt
-rwxrwxr-x 1 aiden aiden    4 Jul  9 20:11 def.txt  # (참고)권한이 다름
...

$ terraform state list
data.local_file.abc
local_file.abc
local_file.def

$ terraform console
> data.local_file.abc
{
  "content" = "123!"
  "content_base64" = "MTIzIQ=="
  "content_base64sha256" = "WMxIBYDzArMayMQtRw31w8x6vsNdmQmCiKWjrDtWpEk="
  "content_base64sha512" = "p6QsIyFZOgy9Ax+11AnGnnPkYmKvSBMhiAXO3gBcOPQq+A7LWKNmkCaQSScREaBbGh8hxqwIBr+9HspW+BOU2w=="
  "content_md5" = "0610a910e9cd7ec9f78b7e3f4d959e6f"
  "content_sha1" = "5f30576af23a25b7f44fa7f5fdf70325ee389155"
  "content_sha256" = "58cc480580f302b31ac8c42d470df5c3cc7abec35d99098288a5a3ac3b56a449"
  "content_sha512" = "a7a42c2321593a0cbd031fb5d409c69e73e46262af4813218805cede005c38f42af80ecb58a36690269049271111a05b1a1f21c6ac0806bfbd1eca56f81394db"
  "filename" = "./abc.txt"
  "id" = "5f30576af23a25b7f44fa7f5fdf70325ee389155"
}
> local_file.def
{
  "content" = "123!"
  "content_base64" = tostring(null)
  "content_base64sha256" = "WMxIBYDzArMayMQtRw31w8x6vsNdmQmCiKWjrDtWpEk="
  "content_base64sha512" = "p6QsIyFZOgy9Ax+11AnGnnPkYmKvSBMhiAXO3gBcOPQq+A7LWKNmkCaQSScREaBbGh8hxqwIBr+9HspW+BOU2w=="
  "content_md5" = "0610a910e9cd7ec9f78b7e3f4d959e6f"
  "content_sha1" = "5f30576af23a25b7f44fa7f5fdf70325ee389155"
  "content_sha256" = "58cc480580f302b31ac8c42d470df5c3cc7abec35d99098288a5a3ac3b56a449"
  "content_sha512" = "a7a42c2321593a0cbd031fb5d409c69e73e46262af4813218805cede005c38f42af80ecb58a36690269049271111a05b1a1f21c6ac0806bfbd1eca56f81394db"
  "directory_permission" = "0777"
  "file_permission" = "0777"
  "filename" = "./def.txt"
  "id" = "5f30576af23a25b7f44fa7f5fdf70325ee389155"
  "sensitive_content" = (sensitive value)
  "source" = tostring(null)
}

=> 생성한 외부파일 abc.txt를 참조해 data.local_file.abc 데이터 소스로 지정 후, 해당 데이터 소스를 참조하여 local_file.def 생성이 정상적으로 됨을 확인

도전 과제

# Declare the data source
data "aws_availability_zones" "available" {
  state = "available"
}
resource "aws_subnet" "primary" {
  availability_zone = data.aws_availability_zones.available.names[0]
  # e.g. ap-northeast-2a
}
resource "aws_subnet" "secondary" {
  availability_zone = data.aws_availability_zones.available.names[1]
  # e.g. ap-northeast-2b
}

위 리전 내에서 사용 가능한 가용영역 목록 가져오기를 사용한 VPC 리소스 생성 실습 진행, 혹은 아무거나 데이터 소스를 사용한 실습 진행

Task 1

데이터 소스 정의 후 생성

main.tf

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

실행

$ terraform init && terraform plan && terraform apply -auto-approve

Task 2

console을 통해 데이터 소스 확인

$ terraform state list
data.aws_availability_zones.available

$ terraform console
> data.aws_availability_zones.available
{
  "all_availability_zones" = tobool(null)
  "exclude_names" = toset(null) /* of string */
  "exclude_zone_ids" = toset(null) /* of string */
  "filter" = toset(null) /* of object */
  "group_names" = toset([
    "ap-northeast-2",
  ])
  "id" = "ap-northeast-2"
  "names" = tolist([
    "ap-northeast-2a",
    "ap-northeast-2b",
    "ap-northeast-2c",
    "ap-northeast-2d",
  ])
  "state" = "available"
  "timeouts" = null /* object */
  "zone_ids" = tolist([
    "apne2-az1",
    "apne2-az2",
    "apne2-az3",
    "apne2-az4",
  ])
}

> data.aws_availability_zones.available.id
"ap-northeast-2"

> data.aws_availability_zones.available.names
tolist([
  "ap-northeast-2a",
  "ap-northeast-2b",
  "ap-northeast-2c",
  "ap-northeast-2d",
])

Task 3

 

main.tf 수정

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

resource "aws_vpc" "vpc1" {
  cidr_block = "10.10.1.0/24"
  tags = {
    "Name" = "vpc1"
  }
}

resource "aws_vpc" "vpc2" {
  cidr_block = "10.10.2.0/24"
  tags = {
    "Name" = "vpc2"
  }
}

resource "aws_subnet" "primary" {
  # ap-northeast-2a
  availability_zone = data.aws_availability_zones.available.names[0]
  vpc_id = aws_vpc.vpc1.id
  cidr_block = aws_vpc.vpc1.cidr_block
}

resource "aws_subnet" "secondary" {
  # ap-northeast-2b
  availability_zone = data.aws_availability_zones.available.names[1]
  vpc_id = aws_vpc.vpc2.id
  cidr_block = aws_vpc.vpc2.cidr_block
}

실행 및 확인

$ terraform apply -auto-approve
...

$ terraform state list
data.aws_availability_zones.available
aws_subnet.primary
aws_subnet.secondary
aws_vpc.vpc1
aws_vpc.vpc2

AWS 콘솔 확인

=> 데이터 소스를 이용해 사용 가능한 가용영역 목록을 가져와 VPC 정상적으로 생성 완료

Variables

입력 변수(Variables)는 인프라를 구성하는 데 필요한 속성 값을 정의해 코드의 변경 없이 여러 인프라를 생성하는 데 목적이 있음

meta-arguments

  • default : 변수 값을 전달하는 여러 가지 방법을 지정하지 않으면 기본값이 전달됨, 기본값이 없으면 대화식으로 사용자에게 변수에 대한 정보를 물어봄
  • type : 변수에 허용되는 값 유형 정의, string number bool list map set object tuple 와 유형을 지정하지 않으면 any 유형으로 간주
  • description : 입력 변수의 설명
  • validation : 변수 선언의 제약조건을 추가해 유효성 검사 규칙을 정의
  • sensitive : 민감한 변수 값임을 알리고 테라폼의 출력문에서 값 노출을 제한 (암호 등 민감 데이터의 경우)
  • nullable : 변수에 값이 없어도 됨을 지정

변수 유형

기본 유형

  • string : 문자 유형
  • number : 숫자 유형
  • bool : true/false
  • any : 모든 유형을 허용

집합 유형

  • list (<유형>): 인덱스 기반 집합
  • map (<유형>): key = value 형태의 집합
  • set (<유형>): 고유한 값들의 집합
  • object ({<인수 이름>=<유형>, …})
  • tuple ([<유형>, …])

기능 확인

유효성 검사

입력되는 변수 타입 지정 이외에도, 사용자 지정 유효성 검사가 가능.

main.tf

variable "image_id" {
  type        = string
  description = "The id of the machine image (AMI) to use for the server."

  validation {
    condition     = length(var.image_id) > 4
    error_message = "The image_id value must exceed 4."
  }

  validation {
    # regex(...) fails if it cannot find a match
    condition     = can(regex("^ami-", var.image_id))
    error_message = "The image_id value must starting with \"ami-\"."
  }
}

실행 및 확인

$ terraform apply -auto-approve

var.image_id
  The id of the machine image (AMI) to use for the server.

  Enter a value: ami
  
╷
│ Error: Invalid value for variable
│ 
│   on main.tf line 1:
│    1: variable "image_id" {
│     ├────────────────
│     │ var.image_id is "ami"
│ 
│ The image_id value must exceed 4.
│ 
│ This was checked by the validation rule at main.tf:5,3-13.
╵
╷
│ Error: Invalid value for variable
│ 
│   on main.tf line 1:
│    1: variable "image_id" {
│     ├────────────────
│     │ var.image_id is "ami"
│ 
│ The image_id value must starting with "ami-".
│ 
│ This was checked by the validation rule at main.tf:10,3-13.

=> validation 1. 입력 받은 문자가 4자리 초과되지 않아 에러 발생

=> validation 2. 입력 받은 문자가 ami- 로 시작하지 않아 에러 발생

변수 참조

variable은 코드 내에서 var.<이름>으로 참조

main.tf

variable "my_password" {}

resource "local_file" "abc" {
  content  = var.my_password
  filename = "${path.module}/abc.txt"
}

실행 및 확인

$ terraform init -upgrade
...

$ terraform apply -auto-approve
var.my_password
  Enter a value: qwe123

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # local_file.abc will be created
  + resource "local_file" "abc" {
      + content              = "qwe123"   # 입력 받은 변수
...

$ cat abc.txt
qwe123

=> 변수를 입력받아 content로 지정 및 abc.txt로 저장됨을 확인

main.tf

variable "my_password" {
  default   = "password"
  sensitive = true
}

resource "local_file" "abc" {
  content  = var.my_password
  filename = "${path.module}/abc.txt"
}

실행 및 확인

$ terraform apply -auto-approve
...
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # local_file.abc must be replaced
-/+ resource "local_file" "abc" {
      # Warning: this attribute value will be marked as sensitive and will not
      # display in UI output after applying this change.
      ~ content              = (sensitive value) # forces replacement
...

=> sensitive = true 지정 시 터미널에서 가려짐. 하지만, terraform.tfstate 파일에는 결과물이 평문으로 기록되므로 State 파일 보안에 유의할 것!

profile

DDetB.Log

@DDetMok

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!