
HashiCorp에서 Go 언어로 개발한 오픈소스 IaC(Infrastructure as Code) 도구이다. IaC의 의미는 코드를 통해 인프라를 관리하는 것으로, 이는 클라우드 도입을 활성화하고 가속화하기 위해 사용된다. 이를 이해하기 위해서는 기존의 인프라 관리 방법을 먼저 이해해야 한다.
하나의 인프라를 구성하기 위해 클라우드의 GUI에 접속하여 버튼을 눌러 설정하는 과정을 수동 프로비저닝이라고 한다. 이 과정은 오류가 발생하기 쉽고 비효율적이며 확장성이 부족하다.
예를 들어, EC2 인스턴스를 생성할 때 잘못된 인스턴스 타입을 선택하면, 생성 후 중지시켜 변경을 요청하거나 새로 생성해야 할 수도 있다.
또한 동일한 인스턴스 타입이지만 메모리 용량만 다른 인스턴스를 생성하려는 경우, 처음부터 일일이 클릭하여 설정해주어야만 한다. 이처럼 확장성이 떨어지고, 이러한 인프라 환경 구축 과정이 비효율적이라는 것을 알 수 있다.
이러한 인프라 환경 구축 과정을 코드로 자동화 가능한 것이 바로 테라폼이다. 테라폼의 언어는 선언적으로 되어있다. 리소스와 인프라를 정의하고 인프라의 수명 주기를 관리할 수 있다.
학교 수업에서는 보통 클라우드 환경이 필요하다면 GCP 크레딧을 제공해준다. 보통 크레딧은 프로젝트를 하다보면 금방 다 쓰게 되고, 결국 다른 팀원의 GCP로 모든 인프라 환경을 옮겨야하는 상황이 종종 발생했다. 하나의 GCE를 사용하는 경우에는 몇 번의 클릭이 그저 귀찮았지만, 마이크로서비스 아키텍처를 도입한 쿠버네티스 기반 환경의 서비스를 옮기려는 순간 귀찮음의 문제를 벗어났다. 자동화가 매우 간절해졌다.
MacOS 기준
$ brew update
$ brew tap hashicorp/tap
$ brew install hashicorp/tap/terraform
이후 설치 확인
$ terraform --help
Docker를 사용하여 Nginx 서버를 프로비저닝 해보자.
$ mkdir learn-terraform-docker-container // 프로젝트 디렉토리 생성
$ cd learn-terraform-docker-container // 디렉토리로 이동
$ vi main.tf
main.tf 파일을 생성 후 예시 Terraform 구성을 붙여넣는다.
여기서 main.tf는 Terraform 리소스와 데이터 소스 및 모듈을 포함하는 기본 구성 파일이다.
생성, 업데이트 또는 삭제하려는 인프라를 설명하는 파일이라고 생각하면 된다.
main.tf에 정의된 리소스는 terraform apply 명령어를 실행할 때 생성되거나 수정된다.
terraform {
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "~> 3.0.1"
}
}
}
provider "docker" {}
resource "docker_image" "nginx" {
name = "nginx"
keep_locally = false
}
resource "docker_container" "nginx" {
image = docker_image.nginx.image_id
name = "tutorial"
ports {
internal = 80
external = 8000
}
}
tf 파일을 보면 익숙하지 않은 개념들이 있다. 이를 먼저 익혀보고자 한다.
실제로 생성할 인프라 자원을 의미한다.
블록 resource에서 정의하는 내용은 resource type과 local name이다.
local name은 모듈 내에서만 사용 가능하고, 해당 리소스의 식별자 역할을 하기 때문에 모듈 내에서 고유해야한다.
resource 뒤에 첫 번째로 오는 것이 resource type이고, 두 번째로 오는 것이 local name이다.
resource "aws_instance" "web" {
}
Terraform으로 정의할 Infrastructure provider를 의미한다.
required_providers
required_providers 내에서 필요한 Provider를 정의한다.
해당 서버는 Docker를 필요로 하기 때문에 docker를 정의해준다.
required_providers는 local name, source, version으로 구성된다.
각 local name은 하나의 provider를 활성화하고, source는 사용하려는 provider의 글로벌 source 주소를 정의한다.
version은 모듈이 호환되는 provider의 버전을 제약조건으로 정의한다.
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "~> 3.0.1"
}
}
Provider Configuration
provider를 사용하기 전에 Endpoint URL 혹은 기타 설정을 필요로 하기 때문에, 해당 설정을 구성하는 방법이다.
기존 required_provides 내에서 provider를 정의한 local name을 통해 접근하여 설정들을 정의 가능하다.
아래와 같이 local name을 명시하고 해당 블록 내에서 설정을 추가해주면 된다.
provider "docker" {}
인프라를 프로비저닝한 후에 생성된 자원을 output 부분으로 뽑아서 remote state에 활용 가능하다.
terraform 의 상태를 저장할 공간을 지정하는 부분이다. 현재 배포된 최신 상태를 외부에 저장한다.
대표적으로 AWS S3를 활용한다.
공통적으로 활용할 수 있는 인프라 코드를 한 곳으로 모아서 정의하는 부분으로, 일반적인 모듈의 개념과 같다.
변수만 바꿔서 동일한 리소스를 쉽게 정의할 수 있어 편리하다.
remote state를 사용하면 VPC, IAM 등과 같은 공용 서비스를 다른 서비스에서 참조 가능하다.
tfstate파일이 저장되어있는 backend 정보를 명시하면, terraform이 해당 backend에서 output 정보를 가져올 수 있다.
tfstate 파일에는 최신 테라폼 상태 정보가 저장되어있다.
전체적인 흐름을 이해해보자면
필요한 infrastructure을 provider를 통해 가져오고, resource 정의를 통해서 실제로 생성한다.
자주 사용되는 인프라 코드 부분은 모듈을 통해 정의하여 사용한다.
이후 실제 생성된 자원을 output 부분으로 뽑아내고, 이를 backend에 저장 후 사용 가능하다.
remote state를 통해서 backend에 저장된 output 정보를 가져와서 사용 가능하다.
3가지의 형상이 존재한다.
1. Local 코드 : 현재 작성 중인 코드
2. AWS 인프라 : 실제로 AWS에 배포되어 있는 인프라
3. Backend에 저장된 상태 : 가장 최근에 배포한 테라폼 코드 형상
중요한 것은 AWS 실제 인프라와 Backend에 저장된 상태가 100% 일치하도록 만드는 것이다.
1번 코드에서 인프라를 정의하고, 2번 인프라로 프로비전 후 backend에 최신 코드를 저장한다.
해당 과정을 자세히 알아보기 전에 자원 관리 기준으로 설정과 상태의 차이를 알아두는 것이 좋다.
설정은 .tf파일을 의미하고, 상태는 .tfstate 파일을 의미한다.
인프라를 변경하고 새롭게 생성하기 위해서는 설정을 통해 접근해야 한다.
.tf 파일을 작성하고 실제 적용을 하면 리소스에 해당 내용이 적용되고, 적용된 내용이 상태 파일에 기록된다.
만약 반대로 기존 인프라 설정을 가져와서 변경을 원한다면, 상태 파일을 가져오고 이에 대한 설정 파일을 따로 만들어주어야 한다.
인프라 등록
.tf 파일 작성 > apply > .tfstate에 저장
기존 인프라 수정
import > .tfstate 파일에 상태 저장됨 > .tf 파일 작성 > apply
( aws에 한해서 terraforming 명령어를 통해 더 간단하게 가능 )
이를 위한 과정은 다음과 같다.
출처
https://terraform101.inflearn.devopsart.dev/preparation/terraform-basic/
https://registry.terraform.io/providers/hashicorp/aws/latest/docs
https://blog.outsider.ne.kr/1292#google_vignette
https://somaz.tistory.com/185