DevOps/Terraform

[Terraform] 입력 변수 (Input Variable)

TTOII 2022. 4. 21. 23:32
728x90

✔️ 입력 변수 (Input Variable)

 

Input Variables - Configuration Language | Terraform by HashiCorp

Input variables allow you to customize modules without altering their source code. Learn how to declare, define, and reference variables in configurations.

www.terraform.io

Terraform에서의 변수는 Input Variable이다. 

변수는 variable이라는 블록을 사용하며 " " 안에 변수명을 지정한다.
변수를 정의할 때 몇가지 속성이 있다.

  • description - 변수에 대한 설명
  • type - 변수의 값으로 들어갈 수 있는 타입
  • default - 변수의 기본값

main.tf 파일에 변수를 선언해도 되지만 ansible에서 기능을 분리시켰던 것처럼
variables.tf 라는 파일을 만들어서 유지보수 하기 쉽게 만드는 것이 좋다.

 

변수 선언 예시

variable "instance_name" { 
  description = "Value of the Name tag for the EC2 instance" 
  type = string 
  default = "ExampleAppServerInstance" 
}

 

변수 사용 예시

 resource "aws_instance" "app_server" {
   ami           = "ami-08d70e59c07c61a3a"
   instance_type = "t2.micro"

   tags = {
-    Name = "ExampleAppServerInstance"
+    Name = var.instance_name # 변수를 참조할 때는 "" 을 사용하면 안된다.
   }                          # 값이 그대로 들어가기 때문이다. 
 }

다른 예시를 하나 더 보자

variable "image_id" {
  type = string
}

variable "availability_zone_names" {
  type    = list(string)
  default = ["us-west-1a"]
}

예시를 보면 variable 블록에는 default 값이 없을 수도 있다. 
즉, 이 블록은 변수를 정의하기 위해 선언하는 것이지 값을 정의하기 위한 것이 아니다. 
값을 할당하기 위해서는 변수 값 할당 방법을 이용한다.

 

✔️Arguments

Terraform CLI는 변수 선언에 대해 다음과 같은 선택적 인수를 정의한다.

  • default - 이 변수에 기본적으로 설정할 값
  • type - value의 타입
  • description - 설명
  • validation - 부여한 value 값을 검증하는 코드
  • sensitive - terraform show에서 출력 여부 (default는 출력이다.)
  • nullable - 변수가 모듈내에서 null일 수 있는지의 여부를 지정

일반적으로는 type, default, description을 설정하고 나머지 인자는 부가적인 것이다.

  • type
    • 일반 타입
      • string
        • "app_server"
      • number
        • 1
        • 1.0
      • bool
        • true
        • false
    • 복합 타입
      • list / tuple
        • [a, b, c]
      • map / object → list + dictionary
        • {a = abc, b = xyz}
variables abc {
type = list(string)
# ["a", "b"]
type = list(number)
# [1, 2]
}
  • default : 기본 값
  • description : 설명

배운 내용을 적용시켜보자

코드를 기능적으로 나누면 main.tf, provider.tf, variable.tf 세개의 파일로 분리할 수 있다.
main.tf

resource "aws_instance" "app_server" {
  ami           = "ami-0454bb2fefc7de534"
  instance_type = "t2.micro"

  tags = {
    Name        = var.instance_name
    Environment = "Terraform"
  }

  depends_on = [
    aws_s3_bucket.app_bucket,
  ]

}

# Elastic IP resource
resource "aws_eip" "app_server_eip" {
  instance = aws_instance.app_server.id
  vpc      = true
}


# S3 Bucket
resource "aws_s3_bucket" "app_bucket" {
  bucket = "ssh-20220421"
}

provider.tf

variable "instance_name" {
  type        = string
  description = "Instance Name"
  default     = "App Instance"
}

variable.tf

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.27"
    }
  }
  required_version = ">= 0.14.9"
}

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

잘 실행된다.

더보기
[vagrant@controller 01]$ terraform plan

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:

  # aws_eip.app_server_eip will be created
  + resource "aws_eip" "app_server_eip" {
      + allocation_id        = (known after apply)
      + association_id       = (known after apply)
      + carrier_ip           = (known after apply)
      + customer_owned_ip    = (known after apply)
      + domain               = (known after apply)
      + id                   = (known after apply)
      + instance             = (known after apply)
      + network_border_group = (known after apply)
      + network_interface    = (known after apply)
      + private_dns          = (known after apply)
      + private_ip           = (known after apply)
      + public_dns           = (known after apply)
      + public_ip            = (known after apply)
      + public_ipv4_pool     = (known after apply)
      + tags_all             = (known after apply)
      + vpc                  = true
    }

  # aws_instance.app_server will be created
  + resource "aws_instance" "app_server" {
      + ami                                  = "ami-0454bb2fefc7de534"
      + arn                                  = (known after apply)
      + associate_public_ip_address          = (known after apply)
      + availability_zone                    = (known after apply)
      + cpu_core_count                       = (known after apply)
      + cpu_threads_per_core                 = (known after apply)
      + disable_api_termination              = (known after apply)
      + ebs_optimized                        = (known after apply)
      + get_password_data                    = false
      + host_id                              = (known after apply)
      + id                                   = (known after apply)
      + instance_initiated_shutdown_behavior = (known after apply)
      + instance_state                       = (known after apply)
      + instance_type                        = "t2.micro"
      + ipv6_address_count                   = (known after apply)
      + ipv6_addresses                       = (known after apply)
      + key_name                             = (known after apply)
      + monitoring                           = (known after apply)
      + outpost_arn                          = (known after apply)
      + password_data                        = (known after apply)
      + placement_group                      = (known after apply)
      + placement_partition_number           = (known after apply)
      + primary_network_interface_id         = (known after apply)
      + private_dns                          = (known after apply)
      + private_ip                           = (known after apply)
      + public_dns                           = (known after apply)
      + public_ip                            = (known after apply)
      + secondary_private_ips                = (known after apply)
      + security_groups                      = (known after apply)
      + source_dest_check                    = true
      + subnet_id                            = (known after apply)
      + tags                                 = {
          + "Environment" = "Terraform"
          + "Name"        = "App Instance"
        }
      + tags_all                             = {
          + "Environment" = "Terraform"
          + "Name"        = "App Instance"
        }
      + tenancy                              = (known after apply)
      + user_data                            = (known after apply)
      + user_data_base64                     = (known after apply)
      + vpc_security_group_ids               = (known after apply)

      + capacity_reservation_specification {
          + capacity_reservation_preference = (known after apply)

          + capacity_reservation_target {
              + capacity_reservation_id = (known after apply)
            }
        }

      + ebs_block_device {
          + delete_on_termination = (known after apply)
          + device_name           = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + snapshot_id           = (known after apply)
          + tags                  = (known after apply)
          + throughput            = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }

      + enclave_options {
          + enabled = (known after apply)
        }

      + ephemeral_block_device {
          + device_name  = (known after apply)
          + no_device    = (known after apply)
          + virtual_name = (known after apply)
        }

      + metadata_options {
          + http_endpoint               = (known after apply)
          + http_put_response_hop_limit = (known after apply)
          + http_tokens                 = (known after apply)
          + instance_metadata_tags      = (known after apply)
        }

      + network_interface {
          + delete_on_termination = (known after apply)
          + device_index          = (known after apply)
          + network_interface_id  = (known after apply)
        }

      + root_block_device {
          + delete_on_termination = (known after apply)
          + device_name           = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + tags                  = (known after apply)
          + throughput            = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }
    }

  # aws_s3_bucket.app_bucket will be created
  + resource "aws_s3_bucket" "app_bucket" {
      + acceleration_status         = (known after apply)
      + acl                         = "private"
      + arn                         = (known after apply)
      + bucket                      = "ssh-20220421"
      + bucket_domain_name          = (known after apply)
      + bucket_regional_domain_name = (known after apply)
      + force_destroy               = false
      + hosted_zone_id              = (known after apply)
      + id                          = (known after apply)
      + object_lock_enabled         = (known after apply)
      + region                      = (known after apply)
      + request_payer               = (known after apply)
      + tags_all                    = (known after apply)
      + website_domain              = (known after apply)
      + website_endpoint            = (known after apply)

      + object_lock_configuration {
          + object_lock_enabled = (known after apply)

          + rule {
              + default_retention {
                  + days  = (known after apply)
                  + mode  = (known after apply)
                  + years = (known after apply)
                }
            }
        }

      + versioning {
          + enabled    = (known after apply)
          + mfa_delete = (known after apply)
        }
    }

Plan: 3 to add, 0 to change, 0 to destroy.

 

✔️ 변수 값 할당

✔️ -var 옵션

variable.tf 의 default 값을 지우고 태그 정보를 확인하면 태그의 Name이 xyz로 출력된다.

[vagrant@controller 01]$ terraform plan -var "instance_name=xyz"
 + tags                                 = {
          + "Environment" = "Terraform"
          + "Name"        = "xyz"
        }
      + tags_all                             = {
          + "Environment" = "Terraform"
          + "Name"        = "xyz"
        }

하지만 variable.tf 에서 default가 있어도 해당 명령을 실행하면

[vagrant@controller 01]$ terraform plan -var "instance_name=xyz"

default = "App Instance" 값은 무시되며 xyz가 출력된다.

정리하자면 변수 파일에 선언된 변수보다 -var 옵션의 우선순위가 더 높다.

 

✔️ terraform.tfvars 파일

Terraform에서 -var 옵션보다는 terraform.tfvars 파일을 자주 사용한다.

[vagrant@controller 01]$ code terraform.tfvars
[vagrant@controller 01]$ cat terraform.tfvars
instance_name = "xyz123"
+ tags                                 = {
          + "Environment" = "Terraform"
          + "Name"        = "xyz123"
        }
      + tags_all                             = {
          + "Environment" = "Terraform"
          + "Name"        = "xyz123"
        }
728x90