Terraform 스터디 (3)

Ganplank·2026년 1월 25일

Terraform스터디

목록 보기
1/3
post-thumbnail

Section 6: Advanced Terraform

6.1. Interpolation

  • 보간법이라고 변수 사용을 위해 쌍다옴표 안에 $ 표시 중괄호로해서 변수를 설정할 수 있는데 요즘은 보간법은 string이랑 섞어쓸때만 사용하고 변수단독만있으면 쌍따움표없이 그냥 사용해도 알아서 변수로 인식해준다.

6.2. Conditionals

조건문 사용

CONDITION ? TRUEVAL : FALSEVAL

예시:

resource "aws_instance" "myinstance" {
	count = "${var.env=="prod" ? 2 : 1}"
}

6.3. Demo

module "vpc-prod" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "5.19.0"

  name = "vpc-prod"
  cidr = "10.0.0.0/16"

  azs             = ["${var.AWS_REGION}a", "${var.AWS_REGION}b", "${var.AWS_REGION}c"]
  private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
  public_subnets  = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]

  enable_nat_gateway = false
  enable_vpn_gateway = false

  tags = {
    Terraform   = "true"
    Environment = "prod"
  }
}

module "vpc-dev" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "5.19.0"

  name = "vpc-dev"
  cidr = "10.0.0.0/16"

  azs             = ["${var.AWS_REGION}a", "${var.AWS_REGION}b", "${var.AWS_REGION}c"]
  private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
  public_subnets  = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]

  enable_nat_gateway = false
  enable_vpn_gateway = false

  tags = {
    Terraform   = "true"
    Environment = "dev"
  }
}
  • Terraform에서 제공하는 terraform-aws-modules/vpc/aws를 사용해서 모듈을 사용해 쉽게 VPC를 만들수 있다.
data "aws_ami" "ubuntu" {
  most_recent = true

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

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }

  owners = ["099720109477"] # Canonical
}

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

  # the VPC subnet
  subnet_id = var.ENV == "prod" ? module.vpc-prod.public_subnets[0] : module.vpc-dev.public_subnets[0]

  # the security group
  vpc_security_group_ids = [var.ENV == "prod" ? aws_security_group.allow-ssh-prod.id : aws_security_group.allow-ssh-dev.id]

  # the public SSH key
  key_name = aws_key_pair.mykeypair.key_name
}
  • subnet_id : 변수가 prod와 같아서 참이면 vpc-pro.public subnets 첫번째 값을 할당하고 거짓이면 vpc-dev.public_subnet 첫번째 값을 할당
  • vpc_security_group_ids : 변수 값에 따라 보안 정책 할당
  • 해당 디렉터리에서 terraform init 후 ssh-key 생성한 다음 terraform apply 적용 시 인스턴스 2개 생성에 따른 알맞은 설정값 확인

6.4. Functions

Terraform 리소스 built-in function 사용할 수 있도록 지원한다. index(list, elem), join(delim, list) 등등.. 이름을보면 용도를 대충 유추할 수 있는 빌트인함수들이다.

6.5. DEMO

Terraform 0.12버전이후 부터 map,list 같은 함수는 가독성 때문에 없어지고 다른 형태의 쓰임새로 대체되었다.
Terraform console.exe 다운로드 후 console연결 이후 빌트인함수들을 사용

6.6. DEMO

Terraform variable 은 아래와 같이 type이랑 default 변수에 값을 넣을 수 있다.
default가 없는 경우 terraform apply -var="map1={...}" 명령어 입력 또는 .tfvars 파일에 따로 설정해줘야 한다.
그래서 API Key, 프로젝트 별 고유이름 등 보안을 신경써야하는 경우 default를 생략하고 직접 입력한다.

  • 사용 예시
  1. vars.tf

    variable "AWS_REGION" {
      type    = string
      default = "eu-west-1"
    }
    variable "project_tags" {
      type          = map(string)
      default       = {
        Component   = "Frontend"
        Environment = "Production"
      }
    }
  2. ebs.tf

    resource "aws_ebs_volume" "example" {
      availability_zone = "eu-west-1a"
      size              = 8
    
      tags = {for k, v in merge({ Name = "Myvolume" }, var.project_tags): k => lower(v)}
    }
    • => : HCL for문 화살표 연산자로 왼쪽의 값을 오른쪽의 형태로 변환해서 Mapping 하겠다는 의미
    • : 기준 왼쪽 입력, 오른쪽 출력
  3. terraform plan 입력 출력 결과 일부

  • merge()함수로 리스트에 "Name"="myvolume" VALUE는 소문자로 치환 후 추가확인

6.7. DEMO

Terraform에서 dynamic 블록을 사용해 코드를 효율적으로 줄일 수 있다.
똑같은 설정을 여러 번 복사, 붙여넣기 하는 대신 리스트를 돌면서 자동으로 설정해주는 반복문을 사용할수있다.

  • 사용예시1

    resource "aws_security_group" "example" {
      name = "example" # can use expressions here
    
      dynamic "ingress" {
        for_each = [22, 443]
        content {
          from_port   = ingress.value
          to_port     = ingress.value
          protocol    = "tcp"
        }
      }
    }
    • for_each 리스트에 있는 값이 content블록에 작성된 ingress.value 에 반복되어 설정된다.
  • 사용예시2
    보통 값을 for_each에 직접 설정하기보다 별도 variable를 미리선언 후 KEY:VALUE형태로 사용한다.

    variable "ports" {
      type = map(list(string))
      default = {
        "22" = [ "127.0.0.1/32", "192.168.0.0/24" ]
        "443" = [ "0.0.0.0/0" ]
      }
    }
    
    resource "aws_security_group" "example" {
      name = "example" # can use expressions here
    
      dynamic "ingress" {
        for_each = var.ports
        content {
          from_port   = ingress.key
          to_port     = ingress.key
          cidr_blocks = ingress.value
          protocol    = "tcp"
        }
      }
    }

6.8. Project Structure

실무에서는 개발과 운영환경은 분리해서 terraform구조를 만들어서 관리한다. multiple AWS accounts으로 개발/운영 계정을 따로 관리하는게 가장 좋다.
하나의 계정만 사용이 가능하다면 위와 같은 구조에서 각각 다른 디렉터리에서 terraform apply 수행으로 변수값에 따라 인스턴스를 생성 조건을 다르게 할 수 있다.

  • prod/prod.tf
  • dev/dev.tf
  • module/instance.tf

6.9. Terraform Lock file

Terraform은 provider dependency lockfile 을 0.14부터 사용한다. 해당 파일은 terraform init 할 때 terraform.lcok.hcl 명으로 생각성된다.
해당 파일에 providers와 modules의 버전이 기록되서 lockfile을 git에 commit해서 버전 관리를 해야하고 해당 파일 기준으로 롤백이나 자동화 운영을 할 수 있다. lockfile은 또한 체크섭을 따로 저장해서 아카이브를 다운로드를 받을 때 무결성을 확인할 수 있다.
Terraform에서 provider 정보를 변경하는 경우 Terraform lock파일이 업데이트된다.

6.10. State manipulation

terraform state 명령어로 state파일을 조작하는 방법

명령어Description
terraform state liststate 조회
terraform state mv상태안에서 이동 또는 이름명 수정
terraform state pulloutput을 stdout하거나 현재 state를 pull
terraform state pushlocal file을 push해서 state를 덮어씀
terraform state replace-providerstate 파일에 provider 정보를 교체
terraform state rmstate로부터 item을 삭제
terraform state showstate의 item 조회

State 조작할 때의 몇가지 use cases

  • 버전 간 업그레이드할 때 0.11 -> 0.12 -> 0.13
  • 테라폼에서 재생성하지 않고 리소스 이름 변경할 때
  • 기본 리소스를 유지하면서 for_each를 사용해서 리소스 KEY를 변경할 때
  • 리스트 안에 리소스의 포지션을 변경
  • 리소스 관리는 멈추지만 리소스를 삭제하고 싶지 않을때 (terraform state rm)

terraoform state 파일을 좀 더 보기쉽게 커맨드를 사용할 수 있다.
먼저 terraform state list 입력 후 출력되는 파라미터를 terraform state show [parameter] 명령어로 조회 시 다른 리소스에서 사용할 수 있는 속성들을 얻을 수 있다.

만약 리소스 파라미터이름을 변경하고 (ex: "aws_ssm_parameter" "myparameter" -> "myparameter2") terraform apply 명령어를 실행하면 기존 myparameter는 삭제되고 myparameter2가 새로 생성된다.

terraform state mv aws_ssm_parameter.myparameter aws_ssm_parameter.myparameter2 명령어 입력하면 기존 오브젝트의 이름이 삭제없이 변경된다.

6.10. Terraform with Packer

Packer는 AMI를 생성하는 도구인데 인스턴스에서 소프트웨어를 프로비저닝할때 이전에는 테라폼을 쉘 명령어와 셰프와 함께 사용했지만 Packer로 대체해서 사용이 가능하다.

Packer

  • 템플릿을 기반으로 AWS AMI를 구축할 수 있는 명령어 도구이다.
  • 인스턴스를 부팅하고 나서 소프트웨어를 설치하는 대신에 필요한 모든 소프트웨어를 활성화해서 AMI를 생성할 수 있다.
  • 이 방법을 사용하면 인스턴스의 부팅시간이 빨라질 수 있다. 소프트웨어를 설치하는 기본 이미지를 부팅하는 대신 설치된 모든 소프트웨어를 사용해서 빠르게 AMI를 부팅할 수 있다.
  • 수평으로 확장된 앱 계층 또는 클러스터를 실행할 때 일반적으로 사용되는 접근 방법이다.

6.11. DevOps using terraform

Intergrating terraform and packer within your workflow

DevOps using terraform

  • Terraform과 Packer같은 툴은 소프트웨어 개발 생명주기를 사용될 수 있다.
  • 구축과 테스트를 실행하기 위해서 젠킨스와 밤부와 같은 지속적인 통합 도구가 자주 사용된다.
  • 따라서 출시, 프로비저닝 그리고 배포는 버전 제어인 깃, 지속적인 통합인 젠킨스를 통해서 수행할 수 있고 젠킨스 내에서 Terraform과 Packer를 통합할 수 있다.
  • 결과적으로 Packer를 사용해서 아마존 이미지를 생성한 다음 Terraform을 통해 인스터스를 실행할거다.
  • 파이프라인 전체 흐름을 통합도리 수 있고 개발자가 새로운 기능을 푸시하거나 출시를 수행하거나 테스트 가능성이 있을 때마다 실행될 수 있다.
profile
안녕?

0개의 댓글