Terraform

Terraform - 변수, 출력

본 포스트는, Terraform Up & Running 테라폼 - OREILLY를 참고했습니다.

이전 포스트에서 생성한 EC2를 변수와 출력을 이용해서 조금 더 프로그래밍적으로 만들고자 합니다.

변수

많은 프로그래밍에서 DRY원칙 ( Don’t Repeat Yourself )가 있습니다.

즉 똑같은 일을 두번하지 말라는 말입니다.

테라폼에서도 이를 위해 변수를 생성하고 이를 이용할 수 있습니다.

이전 포스트에서 생성한 EC2에서 변수를 사용하는 방법을 설명하고자 합니다.


기본 사용법

variable "var_name" {
  description = "var's description"
  type = number
  default = 42
}

기본적으로 변수는, description, type, default이렇게 3개로 이루어져 있습니다.

default의 경우 선택적으로 설정하는데, 만약 default값이 설정되어 있지 않는다면 terraform apply시 입력받습니다.

variable "number_example" {
  description = "An example of a number variable in Terraform"
  type = number
}

예시로 살펴보면 위와 같이 작성하고 terraform apply를 입력했다면,

$ terraform apply
var.number_example
  An example of a number variable in Terraform

  Enter a value:

위와 같이, description과 value를 입력하라는 내용이 나옵니다.

만약 default를 선언하고 값을 입력 때, 변경하고 싶다면,

$ terraform apply -var="number_example"=2

위와 같이 입력할 수 있습니다.

number

variable "number_example" {
  description = "An example of a number variable in Terraform"
  type = number
  default = 42
}

먼저 위에서 살펴본 number type입니다.

숫자를 변수로 사용할 때 사용합니다.


string

variable "string_example" {
  description = "An example of a string variable in Terraform"
  type = string
  default = "example"
}

다음으론 문자열 타입입니다.

문자열을 입력받을 때 사용합니다.


list - string

variable "list_example" {
  description = "An example of list in Terraform"
  type = list
  default = ["a", "b", "c"]
}

리스트를 변수로 사용할 수 있는데, 여기서 list는 string의 List임을 참고하세요


list(number)

variable "list_numeric_example" {
  type = list(number)
  default = [1,2,3]
}

만약 Number list를 사용하고 싶다면, 괄호를 통해 number라고 입력합니다.


map

variable "map_example" {
  type = map(string)

  default = {
    key1 = "value1"
    key2 = "value2"
    key3 = "value3"
  }
}

맵을 이용해서 키 밸류를 변수로 사용할 수도 있는데, 위와 같이 사용합니다.


object

variable "object_example" {
  type = object({
    name = string
    age = number
    tags = list(string)
    enabled = bool
  })

  default = {
    name = "value1"
    age = 42
    tags = ["a", "b", "c"]
    enabled = true
  }
}

마지막으로 object 타입입니다. C언어의 구조체랑 비슷한 구조를 가져서 익숙합니다.

map이나 object를 사용한다면, cli를 통해서 입력받기는 어려울 것 같고, default를 사용할 것 같습니다.


포트번호를 변수로 받기

이전 포스트에서 만들었던 EC2는 8080 포트를 고정으로 받고 8080로 접속했다면, 이번에는 이를 변수로 받고 사용할 예정입니다.

# var.tf
variable "server_port" {
  description = "The port hte server will use for HTTP requests"
  type = number
}

먼저 server_port라는 변수를 선언했습니다.

default값은 따로 설정하지 않아서, 직접 입력받도록 유도했습니다.

# main.tf
provider "aws" {
  region = "ap-northeast-2"
}

resource "aws_instance" "ec2" {
  ami = "ami-0ea5eb4b05645aa8a"
  instance_type = "t3.nano"

  tags = {
    Name = "terraform-example"
  }

  user_data = <<-EOF
                #!/bin/bash
                echo "Hello, world" > index.html
                nohup busybox httpd -f -p ${var.server_port} &
                EOF
  vpc_security_group_ids = [aws_security_group.instance.id]
}

resource "aws_security_group" "instance" {
  name = "terraform-example-instance"
  ingress {
    from_port = var.server_port
    to_port = var.server_port
    protocol = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

이전에 사용했던 코드에서 변수로 변경했습니다.

주목해야할 부분은 변수를 사용하는 부분입니다.

from_port = var.server_port

변수를 사용할 때는 var이후 .변수이름을 통해서 사용합니다.

User_data에 보면 ${var.server_port}가 있는데, 여기서 var.sever_port만 작성하면 문자열로 인식해서 오류를 일으킵니다. 이를 변수라고 인지시키기 위해서 ${var.server_port} 를 사용합니다.

이렇게 구성하고 terraform apply를 입력합니다.

$ terraform apply
var.server_port
  The port hte server will use for HTTP requests

  Enter a value: 8000

저는 8000번 포트를 입력하고 yes를 입력했습니다.

$ curl http://[public ip]:8000
Hello, world

이제 정상적으로 생성되었는지 테스트합니다.


Output

처음 terraform을 접했을 때, var이랑 output이 뭔 차이를 가지는 지 궁금했습니다.

var의 경우 변수고, output의 경우 출력문이라고 생각하면 편합니다.

생성한 EC2의 접속주소를 출력하도록 output을 만들어보겠습니다.

# output.tf

output "test_ip" {
  description = "This is test_ip"
  value = "${aws_instance.ec2.public_ip}:${var.server_port}"
}

value의 경우 생성될 instance의 public ip와 입력받을 port를 출력하도록 구성했습니다.

이제 다시 terraform apply이후 8000를 입력해줍니다.

정상적으로 생성이 된 후, 설정한 Output이 출력됨을 알 수 있습니다.

Outputs:

test_ip = "3.35.167.31:8000"

간단한 var와 ouput사용법을 알아봤습니다.

둘다 유용하게 사용될 듯합니다.

이전과 동일하게 더 이상 안쓸 리소스는 과금을 피하기 위해서 주석처리 후 apply해줍니다.

terraform destroy

destroy명령어를 통해서 지울 수도 있습니다. (단 undo가 불가능 하니 신중하게 동작하세요.)