Terraform

Show me the Terraform !!

테라폼 이란 ?

  • 테라폼은 HashiCorp 사가 Go 언어로 개발한 IaC 도구 입니다. 
  • 배경
    • 전통적인 인프라는 복잡한 과정과 시간, 비용, 하드웨어가 필요했고, 이를 완전히 뒤엎은 클라우드가 나오며 테라폼이란 IaC (Infrastructure as Code) 도구가 개발되었습니다.
    • IaC 란 코드를 작성 및 실행하여 인프라를 생성, 배포, 수정, 정리하는 것을 말합니다.
    • IaC 도구 별 특징
      • 구성 관리 도구 (ansible, puppet, saltstack)
        • s/w 를 매니징하기 위해 디자인됨
        • 스탠다드한 인프라를 관리
        • 버전 컨트롤, 멱등성
      • 서버 템플릿 도구 (docker, packer, vagrant)
        • 미리 설치된 s/w 와 디펜던시 관리
        • VM 혹은 도커이미지
        • 불변 인프라 (immutable infrastructure)
      • 프로비저닝 도구 (terraform, cloudformation)
        • 불변 인프라 배포
        • 서버, 데이터베이스, 네트워크 등 인프라 전역을 포함
        • 멀티 프로바이더
  • 특징 (features of terraform)
    • 다양한 cloud provider 를 제공합니다. (aws, azure, gcp ...)
    • Hashicorp 의 HCL 언어를 사용하며, 파일 확장자는 .tf 로 작성됩니다. (HCL 은 declarative 언어 입니다)
    • 테라폼은 항상 Current State → Desired State 를 유지합니다. (쿠버네티스의 replica controller 와 유사)
    • 특정리소스가 삭제된 후 terraform apply 를 할 경우 없어진 리소스만 재생성됩니다. (Desired state를 유지)
    • 테라폼 워크플로우
      • 테라폼은 다음과 같은 흐름으로 동작합니다. 
        terraform init → terraform plan → terraform apply → (terraform destroy)
      • 불변 인프라의 특징을 갖고 있으며, 리소스에 변경사항이 생기고 업데이트가 불가능하면 리소스를 삭제 후 재생성 합니다.
  • 설치
    • Linux
sudo apt-get update && sudo apt-get install -y gnupg software-properties-common

wget -O- https://apt.releases.hashicorp.com/gpg | \
    gpg --dearmor | \
    sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg

gpg --no-default-keyring \
    --keyring /usr/share/keyrings/hashicorp-archive-keyring.gpg \
    --fingerprint

echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] \
    https://apt.releases.hashicorp.com $(lsb_release -cs) main" | \
    sudo tee /etc/apt/sources.list.d/hashicorp.list

sudo apt update

# install terraform
sudo apt-get install terraform

# install autocomplete package
terraform -install-autocomplete

HCL Basics

  • Terraform 파일을 작성하는데 사용하는 언어
  • 문법
    • HCL 은 block 과 argument 로 구성되어 있습니다. 
    • 아래는 리소스 블록 예시입니다. "resource" 블록, "aws_instance" 리소스 타입, "example" 리소스 이름 으로 구성되어 있고, ami = "abc123" 라는 arguments 를 갖고 있습니다.
  • 예시
resource "aws_instance" "example" {
  ami = "abc123"
}
  • Terraform fmt 명령어로 파일의 인덴트 및 코드 스타일에 맞게 변형이 가능합니다.
  • blcok 종류
    • terraform
    • provider
    • resource
    • data
    • module
    • local
    • variable
    • output

Terraform Tutorial

  • Terraform을 이용한 인프라 구축은 보통 아래와 같은 수명 주기(라이프 사이클)를 가집니다.
    1. tf 파일 작성
    2. terraform init
    3. terrafrom plan
    4. terraform apply
    5. terraform destroy
  • 테라폼을 사용해 AWS EC2 인스턴스를 생성해 보겠습니다. 
    1. tf 파일 작성
      • provider.tf 파일 생성
        • provider 란 ?
          테라폼과 외부 서비스를 연결해주는 기능을 하는 모듈.  이중 가장 중요한 프로바이더는 단연 클라우드 서비스입 입니다.
        • provider.tf
          provider 파일이름은 임의로 설정 가능하며, 여기서는 provider.tf 를 사용합니다. (아래 내용 기본 템플릿도  terraform registry 페이지에서 확인 가능합니다) 리전과 provider 접근에 필요한 인증정보를 입력합니다. 미 입력시 aws는 "~/.aws" 경로의 정보를 자동으로 읽어와 사용합니다. provider 와 terraform 버전도 고정해서 사용하는 것을 권장합니다. 
# Define required providers
terraform {
  # "> 1.4.0, != 1.4.0, >= 1.4.0" 과 같은 형태로 버전을 제한할 수 있습니다"
  required_version = "0.11.15"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "4.32.0"
    }
  }
}
 
# Configure the aws provider
provider "aws" {
  # Configuration options
  region = "us-east-1"
 
  # 아래처럼 인증정보를 파일에 직접 입력하여 관리하는 방식은 권장하지 않습니다.
  # access_key = "my-access-key"
  # secret_key = "my-secret-key"
}

 

  - main.tf 파일 작성
resource블록은 aws의 ec2, vpc, rds 와 같이 실제 관리할 오브젝트 내용이 담긴 블록입니다.

resource "aws_instance" "my_instance" {
  ami           = "ami-026b57f3c383c2eec"
  instance_type = "t3.micro"
 
  tags = {
    Name = "MyInstance"
  }
}

  - 유효성 검사
terraform validate 명령어를 입력하여 작성한 파일이 유효한지 체크할 수 있습니다.

  - 스타일 규칙
terraform fmt 명령어를 사용해 .tf 파일을 자동으로 포맷팅 해줍니다.

 

  2. terraform init
테라폼이 선언된 프로바이더 플러그인을 설치합니다. (terraform version 명령어를 통해 프로젝트에 사용중인 프로바이더 버전을 확인할 수 있습니다. )

terraform init 
terraform version

  3. terraform plan
plan 명령어를 실행하면 현재 정의되어 있는 리소스들을 실제로 프로바이더에 적용했을 때 어떤 작업이 수행될지 계획을 보여줍니다. (.terraform 폴더에 다운받음) 테라폼을 사용할 땐 반드시 plan 으로 변경될 사항을 한번 더 점검하고 apply 하는것을 권장드립니다. 명령어 실행후 출력되는 내용의 (+) 가 있는 항목은 추가, (-) 가 있는 항목은 삭제, (~) 가 있는 항목은 수정, (-/+) 은 대체(replace) 된다는 의미 입니다.

terraform plan
  4. terraform apply
모든 .tf 파일을 읽어 current state 를 desired state 와 동일하게 만드는 작업을 수행합니다. 
terraform apply
 
# 생성된 리소스 정보 확인
terraform show

apply를 실행하면 현재 위치한 경로에 자동으로 tfstate 라는 파일이 생성됩니다.
상태 파일에는 실제 생성된 리소스에 대한 정보들이 담겨 있습니다.
이 파일을 기반으로 테라폼을 실행할 때마다 AWS 에서 이 EC2 인스턴스의 최신 상태를 가져와서 테라폼의 구성과 비교하여 어느 변경 사항을 적용해야 하는지 결정할 수 있습니다.

  5. terraform destroy
생성한 모든 리소스를 삭제합니다. 

terraform destroy

Variable

  • 변수 블록을 사용하여 변수를 입력받을수 있습니다. 
  • 변수 블록의 argument 로 default, description, type 이 있습니다. 
  • variable 로 사용가능한 타입은 다음과 같습니다.
    • string, number, bool, list, set, map, object, tuple
  • 변수 주입 우선순위
    -var or -var-file > *.auto.tfvars > .tfvars > env variables
  • 사용 예시
    • 아래는 local_file 이라는 provider 를 사용하여 로컬에 txt 파일을 만드는 예시입니다.
  • main.tf
# main.tf
resource "local_file" "dog" {
  filename = "/terraform/dog.txt"
  content  = var.dog_name
}
 
resource "local_file" "cat" {
  filename = "/terraform/cat.txt"
  content  = var.cat_name
}
  • variable.tf 
    변수블록에 default 값을 입력하지 않으면 apply 실행 시 prompt에서 변수값을 입력 받습니다. 
    변수블록 내부에 validation 블록을 추가해 조건과 에러가 발생하면 출력될 메시지를 정의할 수 있습니다. 
# variable 블록에 validation 블록을 inline 배치하여 제약을 걸수있습니다.
variable "dog_name" {
  type = string
  default = "andrew"
 
  # 세글자 이상의 값만 허용
  validation {
    condition     = length(var.dog_name) > 3
    error_message = "The dog name value must be longer than 3 characters"
  }
 
}
 
variable "cat_name" {
  type = string
  default = "chacha"
}

Terraform commands

  • terraform validate
    • tf 파일의 문법체크를 해줌
  • terraform fmt
    • tf 파일의 라인정리
  • terraform show
    • terraform show --json 리소스의 현재 상태를 확인할수 있다
  • terraform providers
    • 현재 폴더에서 사용중인 모든 provider를 출력
  • terraform output
    terraform output <특정 키>
    • tf 파일에 입력한 output value 를 출력
  • terraform refresh
    • 테라폼으로 생성된 리소스에 외부적요인으로 인한 변경사항이 있을경우 이를 tfstsate 파일에 업데이트

Tfstate

  • terraform apply 명령어를 실행할 때마다 명령어를 실행한 경로에 .tfstate 파일이 생성 됩니다.
  • terraform.tfstate 는 json 파일로 실제 인프라 환경에 배포된 메타데이터 정보를 담고 있습니다.
  • terraform backend 설정
    • terraform backend 는 terraform 의 state file을 저장하는 정책입니다. 기본적으로 로컬 저장소에 생성하지만 설정에 따라 s3, consul, etcd 등 다양한 backend type을 사용할 수 있습니다.
    • 사용 이유 ?
      • locking : terraform 코드를 팀 단위로 관리하면 보안 및 동일한 내용을 공유하는 것이 중요합니다. 원격 저장소를 사용함으로써 동시에 일관된 내용을 제공하고 동시에 파일을 수정하는 이슈를 막을수 있습니다.
      • backup : 로컬 저장소에 저장하면 유실의 위험성이 있습니다. s3 와 같은 원격저장소를 사용하여 state 파일의 유실을 방지합니다. 
    • 구현방법

Workspace

  • workspace 는 동일한 테라폼 코드를 사용하여 같은 사양의 리소스를 여러개 만들수 있도록 환경을 나누는 기능입니다.
  • 마치 깃의 브랜치와 같이 동일한 코드를 여러 환경에서 재사용 가능하도록 합니다. 
# 워크스페이스 생성
$ terraform workspace new demo
# 생성한 워크스페이스로 이동
$ terraform workspace select demo
# 테라폼 파일 작성
# terraform.workspace 변수에 작업중인 워크스페이스명이 주입됩니다.
$ vi main.tf
resource "aws_s3_bucket" "main" {
  bucket = "workspace-test${terraform.workspace == "default" ? "-default" : "-${terraform.workspace}"}"
  acl    = "private"
}
 
 
 
# variable 맵 타입 데이터를 사용하여 워크스페이스마다 값을 다르게 할당하는 법
variable "ami" {
  type = map
  default = {
    "projectA" = "ami-111222"
    "projectB" = "ami-333444"
  }
}
 
# projectA workspace
resource "aws_instance" "projectA"{
  ami = lookup(var.ami, terraform.workspace)
  ...
}
# projectB workspace
resource "aws_instance" "projectB"{
  ami = lookup(var.ami, terraform.workspace)
  ...
}

Module

  • 모듈은 관련 있는 요소를 모아 하나의 패키지를 만들어 제공하는 기능으로서 코드의 재사용성을 높일수 있습니다.
  • module 블록을 선언하고 모듈의 경로를 입력하면 코드를 불러올 수 있습니다. 
  • 모듈은 되도록 작은 단위로 분리하여 관리하는게 혹시나 발생할 수 있는 코드간의 충돌을 방지하는데 도움이 됩니다.
  • 테라폼 디렉토리 구조는 모듈을 포함한 파일레이아웃 구조로 구성하는 것이 관리에 용이합니다. 
  • 예시

모듈 디렉터리 구조

 

├── dev
 │   ├── main.tf
 │   └── variables.tf
└── module
    ├── main.tf
    └── variables.tf

 

 

(module 파일)

/module/main.tf

resource "local_file" "test" {
    filename = var.file_name
    content = var.file_content
}
 
 

/module/variables.tf

variable "file_name" {
 
}
variable "file_content" {
 
}

(dev 환경) 
/dev/main.tf  

모듈 블록의 source 에 모듈이 위치한 경로를 입력 합니다. 

module "local_file_creater" {
    source = "../module"
 
    file_name = var.file_name
    file_content = var.file_content
}

/dev/variables.tf

variable "file_name" {
    default = "devfile"
}
variable "file_content" {
    default = "in dev environment"
}
  • dev 폴더에서 terraform apply 를 실행하면 source 에 명시한 경로에서 코드를 가져와 dev 환경의 variable을 주입하여 리소스를 생성합니다.
  • 동일 리소스를 대상으로 workspace 를 사용하면 dev,stage,prod 환경을 분리할 수 있지만, 실수가 유발될수 있습니다. 이를 방지하기 위해 파일 레이아웃 단위로 격리하는 것이 권장 됩니다.
    • 각 테라폼 구성 파일을 분리된 폴더에 넣습니다. (dev,stage,prod)
    • 서로 다른 인증 메커니즘과 액세스제어를 사용하여 각 환경에 서로다른 백엔드를 구성한다.
    • 실제로 격리 수준을 높이려면 구성요소 수준으로 내려가는 것이 바람직하다. (일반적으로 함께 배포되는 일관된 리소스 집합)
      • dev, stage, prod
        • vpc
          • variable.tf
          • outputs.tf
          • main.tf
        • service
          • variable.tf
          • outputs.tf
          • main.tf
        • data-storage
          • variable.tf
          • outputs.tf
          • main.tf
  • 모듈 작성 예시는 저의 깃헙을 참조해 주세요
  • https://github.com/itsogkyc/terraform-study 
 

GitHub - itsogkyc/terraform-study

Contribute to itsogkyc/terraform-study development by creating an account on GitHub.

github.com