IaC/Infrastructure Provisioning

3. Terraform 다양한 변수(variable, local, data...output, input) - AWS

Somaz 2023. 4. 9. 20:00
728x90
반응형

Overview

2023.04.04 - [Hashicorp] - 1. Terraform 기초 : 설치 및 .tf 파일 설명

2023.04.06 - [Hashicorp] - 2. Terraform 변수 사용법(use-variable)

 

오늘은 테라폼의 다양한 변수들에 대해 공부해보려고 한다.

https://developer.hashicorp.com/terraform/language/values


1. variable

변수 블록은 Terraform 모듈 또는 구성에 대한 입력 변수를 정의하는 데 사용된다. 이러한 변수를 사용하면 구성을 매개변수화하여 더 유연하고 재사용할 수 있다. 사용자는 Terraform 명령을 실행할 때 이러한 변수에 대한 값을 전달하거나 환경 변수 또는 .tfvars 파일을 사용하여 설정할 수 있다.

 

 

 

예제코드

variable "region" {
  type        = string
  description = "AWS region for the resources"
  default     = "us-west-2"
}

variable "instance_type" {
  type        = string
  description = "EC2 instance type"
  default     = "t2.micro"
}
  • 주의할점 : variable는 변수를 정의해준것이다. 위에 말한것처럼 xxx.tvars 파일에 해당 변수에 입력값을 넣어줘야 한다. 넣어주지 않으면 default값이 자동으로 들어간다.

 

예제코드2(Validation)

Terraform CLI v0.13.0에서 도입되었다.

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 && substr(var.image_id, 0, 4) == "ami-"
    error_message = "The image_id value must be a valid AMI id, starting with \"ami-\"."
  }
}

 

  • validation해당 블록 내에 블록을 추가하여 특정 변수에 대한 사용자 지정 유효성 검사 규칙을 지정할 수 있다 
  • AMI ID의 구문이 올바른지 확인한다.
  • condition : 유효성 검사를 통과하려면 true로 평가되어야 하는 부울 표현식이다. 다음 두 가지를 확인한다.
    • var.image_id의 길이는 4보다 커야 한다. 이렇게 하면 제공된 값의 길이가 최소가 된다.
    • var.image_id의 처음 4자는 "ami-"와 같아야 합니다. 이렇게 하면 제공된 값이 AMI ID에 대한 올바른 접두사를 갖게 된다.
  • error_message: condition이 false로 평가되면 이 오류 메시지가 사용자에게 표시된다.
  • 이 경우 메시지는 image_id 값이 "ami-"로 시작하는 유효한 AMI ID여야 함을 사용자에게 알린다.

 

 


 

2. local

로컬 값은 Terraform 구성 내에서 재사용 가능한 표현식을 정의하는 데 사용된다. 복잡한 표현식을 단순화하거나 중간 결과를 저장하거나 구성을 더 읽기 쉽게 만드는 데 유용하다. 간단하게 설명하자면, 지역변수와 같은 역할이다. 해당 파일에서 정의했으면 해당파일에서만 사용할 수 있다.

 

 

예제코드

locals {
  common_tags = {
    Terraform = "true"
    Environment = var.environment
  }
}

resource "aws_instance" "example" {
  ami           = "ami-0c555b51c2a1d4e55"
  instance_type = var.instance_type

  tags = merge(
    local.common_tags,
    {
      Name = "example-instance"
    },
  )
}

 

예제코드2

AWS의 모든 리소스에 terraform=true 태그를 붙이는 모듈 만들기 (local 함수 사용)

 

  1. 모듈 파일을 저장할 'tags_module'이라는 폴더를 만든다.
  2. tags_module 폴더 안에 다음 내용으로 main.tf 파일을 만든다.
# tags_module/main.tf

variable "additional_tags" {
  type        = map(string)
  description = "Additional tags to be added to the common tags"
  default     = {}
}

locals {
  common_tags = {
    Terraform = "true"
  }
}

output "tags" {
  value = merge(local.common_tags, var.additional_tags)
}
  • additional_tags를 가져와 terraform=true 태그를 포함하는 common_tags 로컬 값과 병합한다.
  • 병합된 태그는 'tags'라는 출력 변수로 노출된다.
  • type  = map(string)
    • 변수는 키와 값이 모두 문자열인 맵(키-값 쌍의 모음)이어야 함을 지정한다.
    • 이 값을 정의함으로써 Terraform은 이 변수에 대해 제공된 입력 값이 문자열 키와 값이 있는 map임을 확인한다.

 

그리고 기본 Terraform 구성에서 tags 모듈을 호출하고 출력을 사용하여 AWS 리소스에 태그를 적용할 수 있다.

# main.tf

provider "aws" {
  region = var.region
  profile = var.aws_profile
}

module "tags" {
  source = "../tags_module"
  additional_tags = {
    Environment = var.environment
  }
}

resource "aws_security_group" "allow_ssh" {
  name        = "allow_ssh"
  description = "Allow SSH inbound traffic"

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = [var.my_public_ip]
  }

  tags = module.tags.tags
}

resource "aws_instance" "ec2" {
  ami           = "ami-03221589fd7c8f183" # This is an example Amazon Linux 2 AMI ID; replace with the appropriate AMI ID for your region
  instance_type = var.instance_type
  key_name      = var.key_pair_name

  vpc_security_group_ids = [aws_security_group.allow_ssh.id]

  tags = module.tags.tags
}
  • Environment 태그가 모듈에 전달되고 모듈의 출력이 aws_security_groupaws_instance 리소스 모두에 대한 tags 속성으로 사용된다.

 


3. data

Terraform의 데이터 소스를 사용하면 외부 소스(예: API 또는 원격 파일) 또는 Terraform 외부에서 관리되는 기존 인프라에서 정보를 가져올 수 있다. 리소스를 직접 관리하지 않고도 구성에서 사용할 데이터를 수집할 수 있다.

 

 

예제코드

data "aws_ami" "amazon_linux" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["amzn2-ami-hvm-*-x86_64-gp2"]
  }
}

resource "aws_instance" "example" {
  ami           = data.aws_ami.amazon_linux.id
  instance_type = var.instance_type

  tags = merge(
    local.common_tags,
    {
      Name = "example-instance"
    },
  )
}
  • data "aws_ami" "amazon_linux": 이 데이터 블록은 최신 Amazon Linux 2 AMI에 대한 Amazon 머신 이미지(AMI) ID를 가져오는 데 사용된다.
  • 이름 패턴 amzn2-ami-hvm-*-x86_64-gp2를 기반으로 사용 가능한 AMI를 필터링하고 AMI의 소유자는 "amazon"(공식 Amazon Linux AMI임을 나타냄)으로 설정된다.
  • most_recent 속성은 true로 설정되어 지정된 패턴과 일치하는 사용 가능한 최신 AMI를 가져온다.
  • resource "aws_instance" "example": 이 리소스 블록은 data "aws_ami" "amazon_linux" 블록에서 가져온 AMI ID를 사용하여 EC2 인스턴스를 생성하는 데 사용된다.
  • instance_type은 변수(var.instance_type)를 통해 제공되며 사용자가 Terraform 구성을 적용할 때 인스턴스 유형을 사용자 정의할 수 있다.

 

예제코드2 (Ubuntu 20.04)

data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"] # Canonical, the official owner of Ubuntu AMIs

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
  }
}

resource "aws_instance" "example" {
  ami           = data.aws_ami.ubuntu.id
  instance_type = "t2.micro"

  tags = merge(
    local.common_tags,
    {
      Name = "example-instance"
    },
  )
}

 

  • owners는 aws_ami 데이터 소스 블록의 필드이다.
  • 'owners' 필드는 AMI 소유자의 계정 ID를 기반으로 AMI를 필터링하는 데 사용된다.
  • 'owners' 필드에 계정 ID를 지정하면 해당 계정이 소유한 AMI만 가져올 수 있다.
  • 이 특정 코드 블록에서 owners 필드에는 ["099720109477"] 값이 있으며 이는 AWS에서 Ubuntu AMI의 공식 소유자이자 유지 관리자인 Canonical의 계정 ID이다.
  • 'owners' 필드를 Canonical의 계정 ID로 설정하면 데이터 소스가 EC2 인스턴스 생성을 위해 최신 공식 Ubuntu 20.04(Focal Fossa) AMI만 가져오도록 할 수 있다.

 

아래의 소스에서 ami 부분만 변경해서 실행한 결과입니다.

main.tf 파일만 예시로 보여드립니다. 나머지 파일들도 전부 생성해줘야 합니다. 아래의 github에 있습니다.

https://github.com/somaz94/terraform-study-aws/tree/main/use-data-block

somaz@AD01769994:~/PrivateWork/terraform-study/use-data-block$ cat main.tf
provider "aws" {
  region  = var.region
  profile = var.aws_profile

  default_tags {
    tags = {
      Terraform   = var.terraform
      Environment = var.environment
    }
  }
}

resource "aws_security_group" "allow_ssh" {
  name        = "allow_ssh"
  description = "Allow SSH inbound traffic"

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = [var.my_public_ip]
  }
}

data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"] # Canonical, the official owner of Ubuntu AMIs

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
  }
}

resource "aws_instance" "ec2" {
  ami           = data.aws_ami.ubuntu.id # This is an example Amazon Linux 2 AMI ID; replace with the appropriate AMI ID for your region
  instance_type = var.instance_type
  key_name      = var.key_pair_name

  vpc_security_group_ids = [aws_security_group.allow_ssh.id]
}

 

 

somaz@AD01769994:~/PrivateWork/terraform-study/use-variable$ terraform init

somaz@AD01769994:~/PrivateWork/terraform-study/use-variable$ terraform fmt
main.tf
terraform.tfvars

somaz@AD01769994:~/PrivateWork/terraform-study/use-variable$ terraform validate
Success! The configuration is valid.

somaz@AD01769994:~/PrivateWork/terraform-study/use-variable$ terraform plan
data.aws_ami.ubuntu: Reading...
data.aws_ami.ubuntu: Read complete after 0s [id=ami-0c6e5afdd23291f73]
...

somaz@AD01769994:~/PrivateWork/terraform-study/use-variable$ terraform apply
data.aws_ami.ubuntu: Reading...
aws_security_group.allow_ssh: Refreshing state... [id=sg-02170f94bd5b24448]
data.aws_ami.ubuntu: Read complete after 0s [id=ami-0c6e5afdd23291f73]
...

somaz@AD01769994:~/PrivateWork/terraform-study/use-variable$ terraform state list
data.aws_ami.ubuntu
aws_instance.ec2
aws_security_group.allow_ssh

 

somaz@AD01769994:~/PrivateWork/terraform-study/use-variable$ ssh -i ~/.ssh/somazkey.pem ubuntu@3.37.129.246

ubuntu@ip-172-31-34-2:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.6 LTS
Release:        20.04
Codename:       focal

somaz@AD01769994:~/PrivateWork/terraform-study/use-variable$ terraform destroy
data.aws_ami.ubuntu: Reading...
aws_security_group.allow_ssh: Refreshing state... [id=sg-02170f94bd5b24448]
data.aws_ami.ubuntu: Read complete after 0s [id=ami-0c6e5afdd23291f73]
aws_instance.ec2: Refreshing state... [id=i-06123bdaa7b4a8854]
  • 리소스를 삭제해줍니다.

 

 


Reference

locals

 

outputs

 

variables

 

Input Variables

 

Data Sources

 

 

728x90
반응형