★★cloudNet@ 팀의 가시다 님이 진행하는 Terraform 101 Study 4기 내용과
한빛미디어 테라폼으로 시작하는 IaC 책을 참고하여 정리하였습니다.
프로바이더

▶ 프로바이더 소개

  • 테라폼은 terraform 바이너리 파일을 시작으로 로컬 환경에나 배포 서버와 같은 원격 환경에서 원하는 대상을 호출하는 방식으로 실행
    이 때 '원하는 대상'은 호출하는 방식이 서로 다르지만 대상의 공급자, 즉 프로바이더가 제공하는 API를 호출해 상호작용을 한다
    여기서 테라폼이 대상과의 상호작용을 할 수 있도록 하는 것이 '프로바이더'
  • 각 프로바이더의 API 구현은 서로 다르지만 테라폼의 고유 문법으로 동일한 동작을 수행하도록 구현되어 있다
    프로바이더는 플러그인 형태로 테라폼에 결합되어 대상이 되는 클라우드, SaaS, 기타 서비스 API를 사용해 동작을 수행
    각 프로바이더는 테라폼이 관리하는 리소스 유형과 데이터 소스를 사용할 수 있도록 연결
  • 테라폼은 프로바이더 없이는 어떤 종류의 인프라와 서비스도 관리할 수 없다
    대부분의 프로바이더는 대상 인프라 환경이나 서비스 환경에 대한 리소스를 관리하므로, 프로바이더를 구성할 때는 대상과의 연결 인증에(AWS 자격증명 등) 필요한 정보가 제공되어야 한다
  • 각 프로바이더는 테라폼 실행 파일과는 별도로 자체 관리되고 게시
    테라폼 지스트리 사이트에서 주요 프로바이더와 관련 문서 확인 가능
    https://registry.terraform.io/browse/providers
 

Terraform Registry

 

registry.terraform.io

▶ 프로바이더 구성

* 로컬 이름과 프로바이더 지정

  • terraform 블록의 required_providers 블록 내에 <로컬 이름> = {} 으로 여러 개의 프로바이더를 정의할 수 있다
    여기서 사용되는 로컬 이름은 테라폼 모듈 내에서 고유
    로컬 이름과 리소스 접두사는 독립적으로 선언, 각 프로바이더의 소스 경로가 지정되면 프로바이더의 고유 접두사가 제공
    만약, 동일한 접두사를 사용하는 프로바이더가 선언되는 경우로컬 이름을 달리해 관련 리소스에서 어떤 프로바이더를 사용하는지 명시적으로 지정할 수 있다
  • 예를 들어 다음의 main.tf에서처럼 동일한 http 이름을 사용하는 다수의 프로바이더가 있는 경우 각 프로바이더에 고유한 이름을 부여하고 리소스와 데이터 소스에 어떤 프로바이더를 사용할지 provider 인수에 명시
    (단, 동일한 source에 대해 다수의 정의는 불가)
  • 동일한 http 접두사를 사용하는 다수의 프로바이더 사용 정의
terraform {
  required_providers {
    architech-http = {
      source = "architect-team/http"
      version = "~> 3.0"
    }
    http = {
      source = "hashicorp/http"
    }
    aws-http = {
      source = "terraform-aws-modules/http"
    }
  }
}

data "http" "example" {
  provider = aws-http
  url = "https://checkpoint-api.hashicorp.com/v1/check/terraform"

  request_headers = {
    Accept = "application/json"
  }
}

 

* 단일 프로바이더의 다중 정의

  • 동일한 프로바이더를 사용하지만 다른 조건을 갖는 경우, 사용되는 리소스마다 별도로 선언된 프로바이더를 지정해야 하는 경우가 있다. 예를 들면, AWS 프로바이더를 사용하는데 서로 다른 권한의 IAM을 갖는 Access ID 또는 대상 리전을 지정해야 하는 경우
    이때는 프로바이더 선언에서 alias를 명시하고 사용하는 리소스와 데이터 소스에서는 provider 메타인수를 사용해 특정 프로바이더를 지정할 수 있다
    provider 메타인수에 지정되지 않은 경우 alias가 없는 프로바이더가 기본 프로바이더로 동작
  • main.tf 파일 생성

main.tf
배포 후 결과 확인

 

* 프로바이더 요구사항 정의

  • 테라폼 실행 시 요구되는 프로바이더 요구사항은 terraform 블록의 required_providers 블록에 여러 개를 정의할 수 있다
  • source에는 프로바이더 다운로드 경로를 지정하고 version은 버전 제약을 명시
  • 프로바이더 요구사항 정의 블록
terraform {
  required_providers {
    <프로바이더 로컬 이름> = {
      source = [<호스트 주소>/]<네임스페이스>/<유형>
      version = <버전 제약>
    }
    ...
  }
}

- 호스트 주소 : 프로바이더를 배포하는 주소로서 기본값은 registry.terraform.io

- 네임스페이스 : 지정된 레지스트리 내에서 구분하는 네임스페이스로, 공개된 레지스트리 및 Terraform Cloud의 비공개 레지스트리의 프로바이더를 게시하는 조작을 의미

- 유형 : 프로바이더에서 관리되는 플랫폼이나 서비스 이름으로 일반적으로 접두사와 일치하나 일부 예외가 있을 수 있음

  • 프로바이더는 기능이나 조건이 시간이 지남에 따라 변경될 수 있다
    이 같은 변경에 특정 버전을 명시하거나 버전 호환성을 정의할 때, version에 명시할 수 있다
    이 값이 생략되는 경우 terraform init을 하는 당시의 가장 최신 버전으로 선택된다

 

* 프로바이더 설치

  • 테라폼을 실행하기 전 terraform init 명령을 통해 정의된 프로바이더를 다운로드, 복사, 캐시에서 읽어오게 된다.
    항상 지정된 구성에 대해 동일한 프로바이더를 설치하도록 하려면 테라폼 구성에 사용되는 프로바이더에 대해 명시적으로 terraform 블록에 정의하거나 .terraform.lock.hcl 잠금 파일을 코드 저장소에 공유하는 방안이 요구
  • 2장에서 살펴본 것처럼 required_providers에 지정된 프로바이더가 있는 경우 코드상 구성에서 사용 여부에 관계없이 프로바이더를 다운로드하게 되고, required_providers에 지정하지 않더라도 테라폼 구성 코드사에서 사용된 프로바이더를 테라폼에서 추론해 최신 버전의 프로바이더를 다운로드

 

* 프로바이더 간 전환 여부

  • 클라우드를 대상으로 테라폼을 사용하는 경우 다른 클라우드 프로바이더로 전환이 가능한가?
    => 불가능
  • 테라폼은 인프라에 대한 단일 프로비저닝 도구로 사용되지만 대상이 되는 환경은 서로 다른 API로 구현된 프로바이더가 제공
  • 프로바이더 간 대응되는 리소스 예시

 

프로바이더 에코시스템

▶ 테라폼의 에코시스템은 사용자가 사용하는 방식과 구조에 테라폼을 적용할 수 있도록 설계

  • 에코시스템을 위한 테라폼 통합은 워크플로 파트너와 인프라 파트너로 나눈다
  • 워크플로 파트너는 테라폼 실행 및 Terraform Cloud/Enterprise와 연계하여 동작하는 기능을 제공하는 항목으로 이루어짐
  • 대표적으로 테라폼 구성을 관리하기 위한 VCS를 제공하는 깃허브, 깃랩, 비트버킷, 애저 데브옵스가 항목에 해당
  • 프로바이더의 경우 인프라 파트너로 해당
  • 인프라 파트너는 사용자가 테라폼으로 대상 플랫폼의 API로 상호작용 가능한 리소스를 관리할 수 있도록 한다
  • 인프라 파트너의 분류와 프로바이더 대상은 다음과 같다
    - 퍼블릭 클라우드 : IaaS, SaaS 및 PaaS를 포함한 다양한 서비스를 제공하는 대규모 글로벌 클라우드 제공
    - 컨테이너 오케스트레이션 : 컨테이너 프로비저닝 및 배포를 지원
    - IaaS(Infrastructure-as-a-Service) : 스토리지, 네트워킹 및 가상화와 같은 솔루션을 제공하는 인프라 및 IaaS 제공
    - 보안 및 인증 : 인증 및 보안 모니터링 플랫폼
    - 자산 관리 : 소프트웨어 라이선스, 하드웨어 자산 및 클라우드 리소스를 비롯한 주요 조직 및 IT 리소스의 자산 관리를 제공
    - CI/CD : 지속적인 통합 및 지속적인 제공/배포
    - 로깅 및 모니터링 : 로거, 측정 도구 및 모니터링 서비스와 같은 서비스를 구성하고 관리하는 기능
    - 유틸리티 : 임의 값 생성, 파일 생성, http 상호 작용 및 시간 기반 리소스와 같은 도우미 기능
    - 클라우드 자동화 : 구성 관리와 같은 전문화된 클라우드 인프라 자동화 관리 기능
    - 데이터 관리 : 데이터 센터 스토리지, 백업 및 복구 솔루션
    - 네트워킹 : 라우팅, 스위칭, 방화벽 및 SD-WAN 솔루션과 같은 네트워크별 하드웨어 및 가상화된 제품과 통합
    - VCS(버전 제어 시스템) : Terraform 내에서 VCS(버전 제어 시스템) 프로젝트, 팀 및 리포지토리에 중점
    - 통신 및 메시징 : 통신, 이메일 및 메시징 플랫폼과 통합
    - 데이터베이스 : 데이터베이스 리소스를 프로비저닝 및 구성하는 기능
    - PaaS(Platform-as-a-Service) : 다양한 하드웨어, 소프트웨어 및 애플리케이션 개발 도구를 제공하는 플랫폼 및 PaaS
    - 웹 서비스 : 웹 호스팅, 웹 성능, CDN 및 DNS 서비스
프로바이더 경험해보기

▶ [실습] 2개의 리전에 Ubuntu EC2 배포 

provider_data.tf - 리전 별 AMI ID값이 다르므로 필터 활용

 

ec2.tf - 리전, ami 참조
배포 후 결과 확인

 

* 2가지 주의 사항

1. Warning 1 : Multiregion is hard 프로덕션 수준의 멀티 리전은 어렵다
- Active-Active 멀티 리전 서비스를 위해서 '지역간 지연 시간, 고유 ID, 최종 일관성' 등 여러가지 고려사항이 많아서 쉽지 않다

2. Warning 2 : Use aliases sparingly Alias를 빈번하게 사용하지 말자
- 별칭을 사용하여 두 리전에 배포하는 단일 테라폼 모듈은 한 리전이 다운 시, plan과 apply 시도가 실패
- 프로덕션 환경은 멀티 리전의 별칭을 사용하는 것보다는, 3장에서 설명한 것 처럼 환경을 완전히 격리

State의 목적과 의미

▶ 상태 파일 확인 실습

vpc.tf
terraform.tfstate 정보

 

vpc.tf 코드 내 tag 수정 시
vpc.tf 코드 내 tag 값 수정(2번 수정)

 

▶ 이론 내용

  • 상태 파일은 배포할 때마다 변경되는 프라이빗 API로, 오직 테라폼 내부에서 사용하기 위한 것
  • 테라폼 상태 파일을 직접 편집하거나 직접 읽는 코드로 작성해서는 안된다

* 팀 단위에서 테라폼 운영 시 문제점

1. 상태 파일을 저장하는 공유 스토리지 shared storage for state files

  • 각 팀원이 동일한 테라폼 상태 파일 사용을 위해서, 공유 위치에 저장이 필요

2. 상태 파일 잠금 Locking state files

  • 잠금 기능 없이 두 팀원이 동시에 테라폼 실행 시 여러 테라폼 프로세스가 상태 파일을 동시에 업데이트하여 충돌 가능(경쟁 상태 race condition)

3. 상태 파일 격리 lsolating state files

  • 예를 들면 테스트 dev와 검증 stage과 상용 production 각 환경에 대한 격리가 필요

* 상태 파일 공유로 버전 관리 시스템 비추천

1. 수동 오류 Manual error

  • 테라폼을 실행하기 전에 최신 변경 사항을 가져오거나 실행하고 나서 push 하는 것을 잊기 쉽습니다.
  • 팀의 누군가가 이전 버전의 상태 파일로 테라폼을 실행하고, 그 결과 실수로 이전 버전으로 롤백하거나 이전에 배포된 인프라를 복제하는 문제가 발생할 수 있음

2. 잠금 Locking

  • 대부분의 버전 관리 시스템은 여러 명의 팀 구성원이 동시에 하나의 상태 파일에 terraform apply 명령을 실행하지 못하게 하는 잠금 기능이 제공되지 않음

3. 시크릿 Secrets

  • 테라폼 상태 파일의 모든 데이터는 평문으로 저장됨. 민감 정보가 노출될 위험

* 지원되는 원격 백엔드 : AWS S3, Azure Blob Storage, Google Cloud Storage, Consul, Postgres database, K8s scret 등
1. 수동 오류 해결 : plan/apply 실행 시 마다 해당 백엔드에서 파일을 자동으로 로드, apply 후 상태 파일을 백엔드에 자동 저장

2. 잠금 : apply 실행 시 테라폼은 자동으로 잠금을 활성화, -lock-timeout=<TIME>로 대기 시간 설정 저장 가능

3. 시크릿 : 대부분 원격 백엔드는 기본적으로 데이터를 보내거나 상태 파일을 저장할 때 암호화하는 기능을 지원

 

▶ State 역할

  • State에는 테라폼 구성과 실제를 동기화하고 각 리소스에 고유한 아이디(리소스 주소)로 맵핑
  • 리소스 종속성과 같은 메타데이터를 저장하고 추적
  • 테라폼 구성으로 프로비저닝 결과를 캐싱하는 역할을 수행

main.tf

 

tfstate 파일 조회

 

random_password 조회
VSCODE로 random_password 확인

  • 테라폼에서는 JSON 형태로 작성된 State를 통해 속성과 인수를 읽고 확인할 수 있다.
    테라폼에서는 type과 name으로 고유한 리소스를 분류하며, 해당 리소스의 속성과 인수를 구성과 비교해 대상 리소스를 생성, 수정, 삭제
  • State는 테라폼만을 위한 API로 정의할 수도 있다. Plan을 실행하면 암묵적으로 refresh 동작을 수행하면서 리소스 생성의 대상(클라우드 등)과 State를 기준으로 비교하는 과정을 거친다. 이 작업은 프로비저닝 대상의 응답 속도와 기존 작성된 State의 리소스 양에 따라 속도 차이가 발생
    대량의 리소스를 관리해야 하는 경우 Plan 명령에서 -refresh=false 플래그를 사용해 State를 기준으로 실행계획을 생성하고, 이를 실행에 활용해 대상 환경과의 동기화 과정을 생략할 수 있다.
# 실행 계획 생성 시 저장되어 있는 State와 실제 형상을 비교하는 기본 실행
time terraform plan

# 실행 계획 생성 시 실제 형상과 비교하지 않고 실행 계획을 생성하는 -refresh=false 옵션
time terraform plan -refresh=false

 

State 동기화

: 테라폼 구성 파일은 기존 State와 구성을 비교해 실행 계획에서 생성, 수정, 삭제 여부를 결정

  • 테라폼 구성과 State 흐름 : Plan과 Apply 중 각 리소스에 발생할 수 있는 네 가지 사항, 아래 실행 계획 출력 기호와 의미
기호 의미
+ Create
- Destroy
-/+ Replace
~ Update in-place

 

  • Replace 동작은 기본값을 삭제 후 생성하지만 lifecycle의 create_before_destory 옵션을 통해 생성 후 삭세 설정 가능

▶ 유형 별 실습 + 문제상황 -> 복구 import 
: 테라폼 구성에 추가된 리소스와 State에 따라 어떤 동작이 발생하는지 확인

유형 구성 리소스 정의(*.tf) State 구성 데이터 실제 리소스 기본 예상 동작
1 있음     리소스 생성
2 있음 있음   리소스 생성
3 있음 있음 있음 동작 없음
4   있음 있음 리소스 삭제
5     있음 동작 없음

 

[유형1 : 신규 리소스 정의 -> Apply => 리소스 생성]

main.tf

 

apply 후 리소스 생성 확인
유형 3(멱등성) 확인

 

[유형2 : 실제 리소스 수동 제거 -> Apply => 리소스 생성]

리소스 수동 삭제
terraform plan -refresh=false

 

[유형3 : Apply -> Apply <- 코드, State, 형상 모두 일치한 경우] : 동작 없음(멱등성)

serial 값도 동일

 

[유형4 : 코드에서 일부 리소스 삭제 -> Apply ]

main.tf 수정
terraform apply

 

[유형6 : 실수로 tfstate 파일 삭제 -> plan/apply ]

tfstate 파일 삭제
terraform plan -refresh=false

 

terraform apply

 

 

[유형 7 : 실수로 tfstate 파일 삭제 시 -> import로 tfstate 파일 복구]

terraform import


* 테라폼 레지스트리의 프로바이더 목록에는 유지 보수 및 게시에 대한 권한에 따라 Tier 정보 제공
https://registry.terraform.io/browse/providers

 

Terraform Registry

 

registry.terraform.io