Terraform

freshness·2024년 7월 31일

HashiCorp 사의 코드형 인프라스트럭처 (Infrastructure as Code) 도구

클라우드부터 온프레미스 리소스, 하위 수준의 컴퓨팅, 스토리지, 네트워킹 리소스 상위 수준의 DNS 및 SaaS를 배포 및 관리

Terraform 워크플로우

  1. 구성 파일 작성
  2. 계획
  3. 적용

Terraform 설치

  1. AWS 설정
    1. aws-cli 설치
      1. aws-cli install 을 검색해 aws 에서 제안하는 방법으로 설치
      2. aws --version 을 입력해 버전 확인 및 설치 확인
    2. access key 발급
      1. AWS 에 접속 후 사용할 계정의 Access Key 발급
      2. aws configure를 통해 Access Key 및 정보 입력
      3. cat .aws/credentials - 설정된 config 정보 확인
      4. aws sts get-caller-identity - 현재 접속된 aws 유저 정보
      5. aws s3 ls - 내 계정에 존재하는 s3 리스트 확인
  2. Terraform 설치
    1. Terraform 사이트의 다운로드 가이드를 통해 OS와 버전에 맞는 방법으로 설치
    2. terraform --version - 설치 후 테라폼 버전 확인

구성 파일

Terraform 인프라를 정의하기 위해 사용 하는 파일

  • .tf 또는 JSON 기반의 Terraform 구성 파일인 .tf.json 을 사용
  • UTF-8 인코딩 사용
  • 현재 작업 디렉토리의 모든 구성 파일을 읽어 하나의 문서로 처리하기 때문에 단일 구성 파일을 정의하거나 여러 구성 파일을 분리하여 정의하는 것은 동작에 큰 영향이 없다.
  • 프로바이더, 프로바이더 요구사항, 리소스 등을 정의
  • 별다른 방식을 명시하지 않는 경우 병렬 처리
  • 블록 정의 형식
    <BLOCK_TYPE> "<BLOCK_LABEL>" ... {
    	<ARGUMENT>
    }
    • BLOCK_TYPE : 리소스 형식
    • BLOCK_LABEL : 블록 형식에 따라 0개 이상을 지정
    • ARGUMENT : 블록의 구성 정보 정의
  • 프로바이더 요구사항(옵션)
    • 프로바이더 플러그인을 사용해 원격 시스템(클라우드 등)과 상호작용

리소스 관리

  • terraform init - 작성 완료된 .tf 파일을 기준으로 초기화
    • 초기화 = 인프라에 리소스를 배포하기 위해 구성에서 사용 된 프로바이더 플러그인 다운로드
    • 프로바이더 플러그인은 해당 디렉토리의 .terraform/ 디렉토리에 설치
  • terraform valid - 작성된 .tf 파일의 검증
  • terraform plan - 작업 직전 현재 구성에서 필요한 변경사항이 계획대로 진행되는 것인지 확인하기 위해 사용
  • terraform apply - .tf 파일의 설정대로 프로세스 진행
  • terraform show - 상태 확인
  • terraform fmt <terraform.tf> - 작성된 .tf 파일의 스타일 수정(=Python black)

변수

  • 입력 변수
    • 테라폼 구성 파일의 재사용성, 팀 공유, Git 등의 버전제어에 적합하도록 변경 가능한 구성을 변수화 할 수 있다.
    • 변수 입력 예시
      // 기본
      variable "<var1>" {
      	default = "value"
      }
      
      // 타입 지정1
      variable "<var2>" {
      	type = string
      	description = "value"
      }
      
      // 타입 지정2
      variable "<var3>" {
      	type = list(string)
      	default = [
      		"<value1>",
      		"<value2>"
      	]
      }
      
      // 타입 지정3
      variable "<var4>" {
      	type = map
      	default = {
      		<key1> = "<value1>"
      		<key2> = "<value2>"
      	}
      }
    • 변수 유형
      • string
      • number
      • bool
      • 복합
        • list / tuple (= 목록)
        • map / object (=Key, Value)
    • 입력 변수의 값 할당 방법
      • terraform 명령의 -var 옵션
        • terraform apply -var="<var1>=<value1>"
        • terraform apply -var="<var2>=['<value1>', '<value2>']"
      • *.tfvars 변수 파일 정의
        • .tfvars 파일안에 직접 변수와 값을 지정한다.

          <var1>="<value1>"
          <var2>="<value2>"
      • 쉘 환경 변수
        • 테라폼은 TFVAR 환경변수를 읽어 선언된 변수 이름에 값을 제공한다.
        • export TF_VAR_<var1>=<file>
      • 변수 적용 순서
        1. 쉘 환경 변수
        2. *.tfvars 변수 파일
        3. *.tfvars.json 변수 파일
        4. .auto.tfvars 및 .auto.tfvars.json 변수 파일
        5. terraform 명령의 -var, -var-file 옵션
      • 입력 변수 사용 예
        • 변수가 위치할 곳에 var. 를 입력 후 변수이름을 입력해준다.
        • instance_type = var.instance_type
  • 출력
    • output 블록으로 정의

    • 구성 파일에 출력 블록을 만들어 값을 정의하면 특정 정보를 쉽게 확인할 수 있다.

    • 출력 값 예

      output "pubIic.ip" {
      	description = "Public IP of Instance"
      	value = aws_instance.my_instance.public_ip
      }
      
      output "elastic_ip" {
      	description = "Elastic IP of Instance"
      	value = aws_eip.my_eip.public_ip
      }
    • terraform output - 출력값 확인

      로컬 값

      자주 사용하는 문자열 및 표현식에 이름을 할당해 구성파일에서 사용할 수 있는 값(=지역변수)

    • locals 블록으로 정의

    • 단순 문자열, 입력 변수, 리소스 속성, 다른 로컬 값을 포함 가능

    • local.<NAME> 형식으로 사용

      resource "aws_instance" "example" {
      	tags = local.common_tags
      }
      
      variable "project_name" {
      	type = string
      	default = "my_project"
      }
      
      variable "environment" {
      	type = string
      	default = "dev"
      }
      
      locals {
      	common_tags = {
      		Name = "${var.project_name}-${var.environment}"
      		Project = var.project_name
      		Environment = var.environment
      	}
      }

      데이터 소스

      리소스의 데이터를 가져올 수 있는 기능

      data 블록으로 정의

      data "aws_ami" "example" {
      	most_recent = true
      
      	owners = ["self"]
      	tags = {
      		Name = "app-server"
      		Tested = "true"
      	}
      }
    • 사용 방법

      • data... 로 사용 및 참조

        resource "aws_instance" "web" {
        	ami = data.aws_ami.web.id
        	instance_type = "t1.micro"
        }

구성 관리 및 프로비저너

Cloud-init 구성 관리

  • 클라우드 또는 가상화 솔루션의 배포 이미지에는 대부분 cloud-init 소프트웨어가 포함되어 있다.
  • 리소스 배포 중 cloud-config 및 쉘 스크립트를 실행해 시스템을 구성 관리 할 수 있다.
resource "aws_instance" "my_instance" {
	ami = data.aws_ami.ubuntu_focal.id
	instance_type = t2.micro
	vpc_security_group_ids = [aws_security_group.my_sg_web.id]
	
	/*
	# 파일 함수로 user_data 제공
	user_data = file("./web_deploy.sh")
	*/
	
	# 데이터 소스로 user_data 제공
	user_data = data.template_file.myweb_deploy.rendered
	
	
	
	tags = local.common_tags
}

data "template_file" "myweb_deploy"{
	template = file("./web_deploy.sh")
}

# EC2 보안그룹 설정
resource "aws_security_group" "my_sg_web" {
	name = "allow-web”
	egress {
		from_port = 0
		to_port = 0
		protocol - "-1"
		cidr_blocks = ["0.0.0.0/0"]
	}
	
	ingress {
		from port = 80
		to_port = 80
		protocol = "tcp"
		cidr_blocks = ["0.0.0.0/0"]
	}
}

프로비저너

테라폼에서 제공하는 구성 관리 기능(리눅스-SSH, 윈도우-WinRM 과 같은 연결 설정 필요)

  • 일반적으로 인스턴스 리소스 구성 관리는 cloud-init을 사용, 프로비저너는 차선
  • 일반 프로비저너
    • file : 파일 및 디렉토리 복사
    • local_exec : 테라폼이 실행되는 로컬에서 실행
      • 실행은 내 컴퓨터지만 다른 노드의 정보가 필요할 때 주로 실행
    • remote_exec : 원격 인스턴스에서 실행
  • 벤더 프로비저너
    • chef : chef 구성 관리 도구
    • habitat : Chef Habitat
    • purpet : 퍼펫 구성 관리 도구
    • salt-masterless : SaltStack 구성 관리 도구
  • local-exec 를 제외한 프로비저너는 SSH 및 WinRM 연결 필수
    • 프로비저너 연결 예시

      # file
      provisionor "file" {
      	source = "conf/myapp.conf"
      	destination = "/etc/myapp.conf"
      	
      	connection {
      		type = "ssh"
      		user = "root"
      		password = "${var.root_password}"
      		host = "$(var.host)"
      	}
      }
      
      # remote-exec
      provisioner "remote=exec" {
      	inline = [
      		"chmod +x /tmp/web_deploy.sh"
      		"/tmp/web_deploy.sh"
      	]
      }
      
      # local-exec
      provisioner "local-exec" {
      	command = "echo ${self.public_ip}" > ipaddr.txt
      }

모듈

여러 리소스의 모음으로 디렉토리에 저장된 .tf, .tf.json 파일의 모음으로 구성되며 테라폼의 구성을 패키지화 해 재사용성을 높이는 역할을 한다.

  • 루트 모듈 : 지금까지 작업 디렉토리에서 작성한 구성 파일이 있는 디렉토리
  • 자식 모듈 : 다른 모듈을 호출해 해당 리소스를 구성해 포함 가능
  • terraform init - 구성에 필요한 모듈을 다운로드
  • module 블록으로 정의 및 호출
    • terraform registry의 module을 검색하면 예시 샘플을 확인할 수 있음
      module "my_vpc" {
          source = "terraform-aws-modules/vpc/aws"
      
          name = var.vpc_name
          cidr = var.vpc_cidr
      
          azs = var.vpc_aza // 가용영역
          private_subnets = var.vpc_private_subnets
          public_subnets = var.vpc_public_subnets
      
          enable_nat_gateway = true
          enable_vpn_gateway = true
      
          tags = {
              Terraform = "true"
              Environment = "dev"
          }
      }

반복

  • 1개의 리소스 = 1개의 개체를 구성
  • 하나의 리소스로 여러개의 개체를 구성하려면 COUNT 의 메타 속성을 정의해 반복할 수 있다.
  • 예제
    resource "aws_instance" "server" {
    	count = 4
    	
    	ami = ""
    	instance_type = "t2.micro
    	
    	tags = {
    		Name = "Server ${count.index}"
    	}
    }
  • 위 리소스의 결과로 4개의 EC2 서버가 생성된다.
  • COUNT는 index 만을 속성으로 가지며 파이썬의 리스트 처럼 [0] 부터 맨 끝의 -1까지 존재한다.
  • 리소스를 참조할 땐 <TYPE>.<NAME>[<INDEX>] 형태로 참조한다.

원격 상태 저장

  • 테라폼 구성의 상태는 로컬 작업 디렉토리의 terraform.tfstate 파일에 저장된다.
  • 구성 변경에 대한 상태 정보를 공유 저장소를 사용해 팀원들과 같은 상태로 유지할 수 있다.
  • 이러한 원격 상태 저장소는 백엔드 라고 한다.
  • 백엔드는 테라폼 블록 내 backend 블록으로 구성하며 원격 상태 저장소는 Terraform cloud를 이용해서 상태를 저장할 수 있다.
  • terraform cloud 에서 저장소 생성 시 backend 블록의 예시를 제공해주기 때문에 예시를 참조해서 원격 상태 저장소를 테라폼에 등록하면 된다.

Terraform cloud 로그인

  • terraform cloud 에 가입 후 조직(=Organization)과 작업공간(=Workspace) 를 만든 후 CLI 에서 로그인을 진행한다
  • terraform login 을 입력 후 출력에서 제공하는 https://app.terraform.io ~ 로 시작하는 URL을 선택해 로그인에 필요한 value를 받아 Enter a value 에 그대로 붙여넣기 하면 terraform cloud에 로그인 할 수 있다.
  • 이후 일반적인 테라폼 작업을 진행 하면서 apply 작업을 진행하면 원격 저장소에 상태가 업로드 되고, destroy 작업을 진행하면 업로드 했던 상태가 다시 지워진다.

Packer

자동화된 이미지 빌더로 여러 플랫폼에 대해 동일한 머신 이미지를 생성 할 수 있다.

일반적으로 클라우드 인프라에 사용할 수 있는 골든 이미지를 생성

  • Packer 파일의 확장자는 .pkr.hcl 이며 packer 블록 외에는 테라폼의 .tf, .tf.json과 동일한 형태로 구성을 작성한다.

0개의 댓글