[HashiCorp] Terraform 개념 및 실습

2022. 7. 24. 20:05✅ STUDY/Terraform

안녕하세요 :)

오늘은 Terraform 개념, Terraform CLI, 작동 원리를 알아보고
간단한 인프라를 배포해보겠습니다 🙂


Terraform

- 코드를 통해 인프라를 관리하고 프로비저닝하는 IaC 도구 중 하나
- 해시코프(HashiCorp) 사가 Go 언어로 개발한 오픈 소스 도구
- Terraform 바이너리가 HCL(Hashicorp Configuration langauge)로 된 코드를 파싱하고, 코드에 지정된 클라우드 공급자에 대한 API를 호출하여 리소스를 생성하는 방식

- Go로 작성된 코드는 하나의 바이너리 파일로 컴파일 되며, Terraform 명령어로 실행됨
- Terraform은 클라우드 공급자가 제공하는 API를 사용할 뿐 아니라 AWS에 이미 보유한 API 키 같은 인증 메커니즘도 같이 사용

절차적 언어 vs 선언적 언어 

1. 절차적 언어
앤서블, 셰프 같은 IaC 도구를 절차적 언어로 분류 합니다.
코드는 비슷하게 보이지만 기존 ec2 10대를 배포 하고 나서 5대를 더 추가해 총 15대의 서버를 만들고 싶을 때, 절차적 언어는 이전 상태를 기억하고 있지 않아, 코드를 단순히 수정만 하는 것인데 새로운 15대 서버를 추가 배포하여 총 25대가 됩니다.

2. 선언적 언어
테라폼, 클라우드포메이션 같은 IaC 도구를 선언적 언어로 분류합니다.
선언적 코드를 사용하는 경우에는 원하는 종료 상태를 선언하면 테라폼이 과거에 생성 했던 모든 상태를 인지하여 해당 종료 상태에 도달하는 방법을 파악합니다.


동작 원리

terraform init

terraform 바이너리에는 테라폼의 기본 기능이 포함되어 있지만 모든 공급자(AWS, Azure, Google Cloud Platform 등)에 대한 코드가 포함되어 있지 않습니다.
테라폼을 처음 사용한다면, "terraform init" 명령어를 실행하여 테라폼에 코드를 스캔하도록 지시하고, 어느 공급자인지 확인하고, 필요한 코드를 다운로드 하도록 해야합니다.
기본적으로, 공급자 코드는 테라폼의 .terraform 폴더에 다운로드 됩니다.

terraform plan

plan 명령어를 사용하면, state 파일과 실제 infra를 비교하여 테라폼이 수행할 작업을 확인할 수 있습니다.
실제 운영 환경에 적용하기 전에 코드의 온전성을 검사할 수 있는 좋은 방법입니다.
plan 결과물에서 +가 있으면 리소스 추가, -가 있으면 리소스 삭제, ~가 있으면 리소스 수정, -/+는 대체(기존 것을 삭제하고 새로 만듦)를 의미 합니다.
테라폼이 대체 작업을 수행해야 하는 내용을 파악하려면 plan의 결과에서 "forces replacement" 라는 문구를 찾으면 됩니다.

terraform apply

apply 명령어를 통해 실제 프로비저닝(리소스 배포) 수행합니다.
apply 후, 변경된 인프라 정보를 state 파일에 다시 업데이트 합니다.



실습

[사전 준비]
- terraform으로 배포할 AWS 계정 및 자격증명 연결
- 로컬PC에 terraform 설치
- terraform 코드를 작성할 IDE

📌provider.tf 작성

provider.tf

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

 

📌terraform init 실행
- 위에서 작성한 aws plugin을 설치하도록 terraform init을 실행합니다.

 

📌main.tf 작성
- resource 블록을 사용하여, 실제 생성할 리소스를 정의합니다.
아래 예제는 VPC, Internet-gateway, subnet, public routing table 생성하는 코드 입니다.
각 리소스의 파라미터에 대한 사용법은 https://registry.terraform.io/providers/hashicorp/aws/latest/docs 에서 참고해 작성하시면 됩니다.

# VPC(10.0.0.0/16) 생성
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  tags = {
      "Name" = "milky-vpc"
  }
}

# Internet-gateway를 생성 및 VPC 연결
resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id
  tags   = {
      "Name" = "milky-igw"
  }
}

# Subnet(10.0.0.0/24) 생성
resource "aws_subnet" "main" {
  vpc_id            = aws_vpc.main.id
  availability_zone = "ap-northeast-2a"
  cidr_block        = "10.0.0.0/24"
  tags = {
      "Name" = "milky-public-subnet-a"
  }
}

# public 통신이 가능한 Route table을 생성(internat gateway 부착)
resource "aws_route_table" "main" {
  vpc_id       = aws_vpc.main.id
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.main.id
  }
  tags         = {
      "Name" = "public-route-table"
  }
}

# Route-table에 Subnet 연결
resource "aws_route_table_association" "main" {
  subnet_id      = aws_subnet.main.id
  route_table_id = aws_route_table.main.id
}

 

📌terraform plan 실행
- 현재 코드를 실제 AWS 계정에 프로비저닝 하였을 때, 어떤 결과가 일어날지 확인할 수 있습니다.

 

📌terraform apply 실행
- 터미널에 terraform apply를 실행하고, 수행을 할 것이냐 라는 질문에 yes를 입력합니다.

- apply를 수행하고 나면 "terraform.tfstate" 파일이 생기는 것을 알 수 있습니다.
실제 tf 코드를 파싱해 AWS API를 사용하기 위한 json 형태로 변경합니다.
serial은 해당 상태파일의 버전입니다. tf 코드가 업데이트 될 때마다, serial 번호는 증가합니다.
lineage는 state 파일이 생성되는 초기에 부여되는 고유한 값 입니다.

- AWS Console에서 리소스가 정상적으로 프로비저닝 되었는지 확인합니다.

 

📌코드 추가
- vpc의 태그에 "deploymentBy" : "terraform"을 추가하겠습니다.
아래와 같이 코드를 추가한 후, terraform plan을 진행합니다.
1개의 리소스가 변경될 것이며, vpc에 태그 "deploymentBy" : "terraform"이 추가될 것이라고 출력되었습니다.

- terraform apply 도 진행하여, 실제 인프라에 반영합니다.

- terraform.tfstate 파일의 "serial"을 보면, 기존 6에서 8로 변경된 것을 알 수 있습니다.
코드가 업데이트 되었기 때문에 state file의 버전이 업데이트 되었습니다.

- 또한, 초기 state 파일은 terraform.tfstate.backup 파일로 이동하였습니다.

- 실제 vpc의 태그를 확인해보니, "deploymentBy" : "terraform"이 추가된 것을 알수 있습니다.

 


Terraform을 실제로 실습해보면서 알아보았습니다🎈


참고) https://registry.terraform.io/providers/hashicorp/aws/latest/docs

 

Terraform Registry

 

registry.terraform.io