본문 바로가기
  • lakescript
카테고리 없음

[T101] 2-2. Terraform - Variable

by lakescript 2024. 6. 18.

 

더보기

이 스터디는 CloudNet@에서 진행하는 T101 스터디를 참여하면서 공부하는 내용을 기록하는 블로그 포스팅입니다.

CloudNet@에서 제공해주는 자료들과 테라폼으로 시작하는 IaC 를 바탕으로 작성되었습니다.

 

입력 변수 (variable)

입력 변수는 인프라를 구성하는 데 필요한 속성 값을 정의해 코드의 변경 없이 여러 인프라를 생성하는 데 사용됩니다. 일반적인 애플리케이션 코드에서의 변수 선언 방식과 달리 terraform에서는 plan 수행 시 값을 입력합니다.

선언 방식이 다양한 이유는 테라폼 실행 환경, 실행 방식에 따라 입력 변수 값을 선언하도록 하여 동일한 코드로 다수의 프로비저닝을 수행하도록 설계하기 위함입니다.

 

변수 선언 방식

변수는 variable로 시작되는 블록으로 구성됩니다. 

variable "<이름>" {
 <인수> = <값>
}

variable "image_id" {
 type = string
}

변수 블록 뒤의 이름 값은 동일 모듈 내 모든 변수 선언에서 고유해야 하며, 이 이름으로 다른 코드 내에서 참조됩니다.

변수 이름으로 사용 불가능한 이름
: source, version, providers, count, for_each, lifecycle, depends_on, locals
테라폼 코드 구성에 미리 예약되어 있어 변수 이름으로 사용 불가능합니다.

 

변수 정의 시 사용가능한 메타 인수

default

  • 변수에 할당되는 기본값 정의
  • 변수 값을 전달하는 여러 가지 방법을 지정하지 않으면 기본값이 전달됨
  • 기본값이 없으면 대화식으로 사용자에게 변수에 대한 정보를 물어봄

type

  • 변수에 허용되는 값 유형 정의
  • string number bool list map set object tuple 와 유형을 지정하지 않으면 any 유형으로 간주

description

  • 입력 변수의 설명

validation

  • 변수 선언의 제약조건을 추가해 유효성 검사 규칙을 정의

sensitive

  • 민감한 변수 값임을 알리고 테라폼의 출력문에서 값 노출을 제한 (암호 등 민감 데이터의 경우)

nullable

  • 변수에 값이 없어도 됨을 지정

변수 유형

기본 유형

string

글자 유형

variable "string" {
  type        = string
  description = "var String"
  default     = "myString"
}

 

number

숫자 유형

variable "number" {
  type    = number
  default = 123
}

 

bool

true or false

variable "boolean" {
  default = true
}

 

any

명시적으로 모든 유형이 허용됨을 표시

집합 유형

list (<유형>): index 기반 집합

variable "list" {
  default = [
      "google",
      "facebook",
      "amazon"
    ]
}


output "list_index_0" {
  value = var.list.0
}

output "list_all" {
  vaule = [
    for name in var.list :
        upper(name)
  ]
}

 

 

map (<유형>): key = value 기반 집합이며 key값 기준 정렬

variable "map" {
  default = {
      aws = "amazon",
      azure = "microsoft",
      gcp = "google"
    }
}

 

 

set (<유형>): 값 기반 집합이며 정렬 key값 기준 정렬

variable "set" {
  type = set(string)
  default = [
      "google",
      "facebook",
      "amazon"
  ]
}

 

 

object ({<인수 이름>=<유형>, …})

variable "object" {
  type = object({name=string, age=number})
  default = {
    name = "abc"
    age = 12
  }
}

 

 

tuple ([<유형>, …])

variable "tuple" {
  type = tuple([string, number, bool])
  default = ["abc", 123, true]
}

 

list와 set은 선언하는 형태가 비슷하지만 참조 방식이 index와 key로 각각 차이가 있고, map과 set의 경우 선언된 값이 정렬되는 특징을 가집니다.

 

variable "ingress_rules" {
  type = list(object({
    port = number,
    description = optional(string),
    protocol = optional(string, "tcp"),
  }))
  default = [
    {port = 80, description = "web"},
    {port = 53, description = "udp"}
  ]
}

 

유효성 검사

입력되는 변수 타입 지정 외에 terraform 0.13.0 버전 부터 사용자 지정 유효성 검사가 가능합니다. 변수 블록 내에 validation 블록에서 조건인 condition에 지정되는 규칙이 true 또는 false를 반환해야 하며, error_message는 condition 값의 결과가 false인 경우 출력되는 메시지를 정의합니다. regex 함수는 대상의 문자열에 정규식을 적용하고 일치하는 문자열을 반환하는데, 여기에 can 함수를 함께 사용하면 정규식에 일치하지 않는 경우의 오류를 검출합니다. 또한, validation 블록은 중복으로 선언할 수 있다. 

 

variable "image_id" {
  type        = string
  description = "string"

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

  validation {
    condition     = can(regex("^ami-", var.image_id))
    error_message = "must ami ! "
  }
}

 

terraform apply 한 후 var.image_id에 대한 값을 입력받는 프롬프트가 활성화됩니다.


ami 입력해보겠습니다.

 

설정한 validation인 2개에 전부 통과하지 못했습니다.

 

이번엔 amazon-linux-1234로 입력해보겠습니다.

 

아까와 다르게 이번엔 1개의 validation만 통과하지 못한 것을 확인하실 수 있습니다.

 

 

ami-1234로 입력하게되면 길이가 4개 초과해야한다는 validation과 [ami-]를 포함해야 한다는 validation을 모두 통과하여 정상적으로 apply 되는 것을 확인하실 수 있습니다.

 

변수 참조

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

variable "my_password"{}

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

 

content에 var.my_password로 variable에 선언된 my_password를 참조하는 코드를 작성합니다.

 

terraform init -upgrade && terraform apply -auto-approve

 

 

var.my_password에 값을 입력하는 프롬프트가 활성화되어 값을 입력하면 local_file이 생성됩니다. 

 

 

위에서 입력한 값이 잘 들어가 있는지 확인이 가능합니다!

 

이번엔 다른 값을 입력해보겠습니다.

 

one만 입력해서 apply를 진행합니다.

 

이렇듯 variable을 resource내에서 참조하여 사용하실 수 있습니다.

 

민감한 변수 취급

민감한 입력 변수를 위해 테라폼 0.14.0 버전부터 입력 변수의 민감 여부를 선언할 수 있습니다. 

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

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

 

위에서 작성한 코드에서 variable에 sensitive=true를 추가한 후 terraform apply를 진행합니다.

 

기본값(default)이 추가되어 입력받는 항목은 발생하지 않지만 terraform plan에서 참조되는 변수값이 sensitive로 가려서 출력되는 것을 확인하실 수 있습니다. 즉, 프로비저닝을 완료한 경우 출력에서는 값이 표현되지 않았지만 실제 생성되는 리소스 결과물에서는 지정한 값이 입력된 것을 확인하실 수 있습니다. 

민감한 변수로 지정해도 terraform.tfstate 파일에는 결과물이 평문으로 보여지기 때문에 sensitive 설정을 했다해도 보안에 유의해야 합니다.

 

변수 입력 방식과 우선 순위

variable의 목적은 코드 내용을 수정하지 않고 테라폼의 모듈적 특성을 통해 입력되는 변수로 재사용성을 높이는 데에 있습니다. 특히 입력 변수라는 명칭에 맞게 사용자는 프로비저닝 실행시에 원하는 값으로 변수에 정의할 수도 있습니다. 또한, 선언되는 방식에 따라 변수의 우선순위가 있으므로 이를 적절하게 사용하여 로컬 환경과 빌드 서버 환경에서의 옵션을 다르게 하거나 프로비저닝 파이프라인을 구성하는 경우 외부 값을 변수에 지정할 수도 있습니다. 

 

우선 순위 1 (가장 낮음)

variable "my_var" {}

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

variable에 변수값이 없어서 입력을 받아야 하는 변수

 

우선 순위 2

variable "my_var" {
  default = "var2"
}

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

variable 블록의 default 값으로 할당 되어 있는 변수

 

우선 순위 3

export TF_VAR_my_var=var3

시스템 환경 변수의 접두사에 TF_VAR_가 포함되면 그 뒤의 문자열을 변수 이름으로 인식합니다. 

 

우선 순위 4

echo 'my_var="var4"' > terraform.tfvars

root 모듈의 main.tf 파일과 같은 위치에 terraform.tfvars 파일을 생성해 변수에 대한 값을 추가합니다.

 

우선 순위 5

# *.auto.tfvars
echo 'my_var="var5_a"' > a.auto.tfvars

# *.auto.tfvars.json
cat <<EOF > c.auto.tfvars.json
{
  "my_var" : "var6_c"
}
EOF

terraform.tfvars와 같은 위치에 *.auto.tfvars, *.auto.tfvars.json의 이름에 맞게 생성

 

우선 순위 6 (가장 강함)

terraform apply -auto-approve -var=my_var=var7

terraform apply -auto-approve -var=my_var=var7 -var=my_var=var8

terraform apply -var-file="var9.txt"

 

CLI 실행 시 -var 인수에 지정하거나 -var-file로 파일 지정

.tfvars 확장자로 생성된 파일에 변수를 미리 기입하면 실행 시 입력해야 하는 변수 값을 하나의 파일에서 관리할 수 있다는 장점이 있습니다. Terraform Cloud에서는 워크스페이스 메뉴에서 Variables로 변수를 정의할 수 있는데, 이때 자동으로 생성되는 파일이 terraform.tfvars입니다. 따라서 로컬 작업 환경에서 동일한 파일을 사용하면 덮어씌여져 의도한 입력 변수 값이 선언되지 않으므로 *.auto.tfvars 형태의 파일을 지원하여 사용자가 의도한 변수의 우선 순위가 높아지게 구성해야 합니다.