Search
Duplicate
📒

[Terraform] 03-1. 테라폼 블록, 리소스

상태
완료
수업
Terraform
주제
기본개념
4 more properties
참고

HCL(HashiCorp configuration languate)

NOTE
HCL은 하시코프사에서 IaC와 구성정보를 명시하기 위해 개발된 오픈소스 도구이다!
hcl
hashicorp
// 한글 주석 방법1 # 한글 주석 방법2 /* 라인 주석 */ locals { key1 = "value1" # = 는 키값으로 기억 갖고 있어 구분됨 myStr = "TF \u UTF-8" # UTF-8 문자를 지원한다. multiStr = <<EOF # Linux/macOS 에서는 EOF 같은 여러줄의 문자열을 지원한다. Multi Line String with anytext EOF # 여러줄의 스트링은 앞과 끝문자만 동일하면 된다. boolean1 = true # boolean true boolean2 = false # boolean false를 지원한다. decimal = 123 # 기본적으로 숫자는 10진수, octal = 0123 # 앞에 0을 붙이면 8진수로 인식, hexadecimal = "0xD5" # 0x 를 붙이는 숫자는 16진수, scientific = 1e10 # 과학적기법 보드 지원한다. # function 호출 예 myprojectname = format("%s is myproject name", var.project) # 3항 연산자 조건문을 지원한다. credentials = var.credentials == "" ? file(var.credentials_file) : var.credentials }
Bash
복사
HCL 문법
테라폼에서는 HCL이 코드의 영역을 담당하며, HCL은 쉽게 읽을 수 있고 빠르게 배울 수 있는 언어의 특성을 가지고 있다.
JSON, YAML을 사용하지 않고 HCL을 사용하는 이유는, JSON은 길이가 길어지고 주석을 지원하지 않는다는 점, YAML은 구성이 복잡해질수록 구성파악이 어렵다는 점 때문이다.
HCL에서 변수와 문자열 값을 함께 사용하는 인터폴레이션 표현 방식을, JSON을 사용하는 다른 IaC도구와 비교하면 아래의 이미지와 같다.

테라폼 블록

NOTE
terraform으로 인프라를 구성하기 위해서 다양한 선언 블록이 존재한다!
terraform { required_version = "~> 1.3.0" # 테라폼 요구버전 required_providers { # 프로바이더 요구버전 local = { source = "hashicorp/local" version = ">= 2.0.0" } aws = { version = "4.2.0" } } cloud { # 클라우드 블록 hostname = "app.terraform.io" organization = "my-org" workspaces { name = "my-app-prod" } } backend "local" { # State 저장위치 지정 path = "state/terraform.tfstate" # state를 보관하는 위치를 지정 } }
Bash
복사
테라폼의 구성을 명시하는데 사용하며, 일반적으로 테라폼/프로바이더의 버전과 같은 값들은 자동으로 설정되지만, 협업을 위해 버전을 명시하고 실행오류를 최소화할것을 권장한다.

테라폼 버전

NOTE
# version = Major.Minor.Patch version = 1.3.4
YAML
복사
시맨틱 버전
Major 버전 : 내부 동작의 API가 변경 또는 삭제되거나 하위호환이 되지 않는 버전
Minor 버전 : 신규 기능이 추가되거나 개선되고 호환이 가능한 버전
Patch 버전 : 버그 및 일부 기능이 개선된 하위 호환이 가능한 버전
테라폼 버전의 비교연산자
= 또는 연산자 없음 : 지정된 버전만을 허용하고 다른 조건과 병기할 수 있다.
: 지정된 버전을 제외한다.낸505
>, ≥, <, ≤ : 지정한 버전과 비교해서 조건에 맞는 경우 허용한다.
~> : 지정한 버전에서 가장 자리수가 낮은 구성요소만 증가하는것을 허용한다. ( x.y인 경우 y 버전에 대해서만 )
1.0.0 : 테라폼 v1.0.0만을 허용한다.
≥ 1.0.0 : 테라폼 1.0.0 이상의 모든 버전을 허용한다.
~> 1.0.0 : 테라폼 v1.0.0을 포함한 v1.0.x 버전을 허용한다.
≥ 1.0 < 2.0.0 : 테라폼 v1.0.0 이상 v2.0.0 미만인 버전을 허용한다.

백엔드 블록

NOTE
백엔드 블록의 구성은 테라폼 실행 시 저장되는 State(상태 파일)의 저장위치를 선언한다.
terraform { backend "local" { path = "state/terraform.tfstate" # state 저장위치 지정 } }
Bash
복사
테라폼은 하나의 백엔드만 허용하며, 테라폼은 state의 데이터를 사용해 코드로 관리된 리소스를 탐색/추적한다. 또한 작업자 간의 협업을 고려한다면 생성한 리소스의 상태 저장 파일을 공유할 수 있는 외부 백엔드 저장소가 필요하다.
local에 지정해도되고, AWS S3, Google Cloud Storage등 다양한 방법이 지원된다.
# 1번째 터미널에서 main.tf수정하고 apply 진행 (yes는 하지않는다.) terraform apply # 2번째 터미널에서 apply 진행(에러) terraform apply
Bash
복사
.terraform.tfstae.lock.info 생성
2번째 터미널에서 apply를 하면 lock문제 발생
공유되는 백엔드에 state가 관리되면 테라폼이 실행되는 동안 .terraform.tfstate.lock.info 파일이 생성되면서 해당 state를 동시에 사용하지 못하게 막아준다.
# 이전구성 유지 -migrate-state는 terraform.tfstate의 이전 구성에서 최신의 state스냅샵을 읽고 기록된 정보로 새 구성 terraform init -migrate-state # 새로 초기화 -reconfigure는 init을 실행하기전 terraform.tstate 파일을 삭제해 초기화 terraform init -reconfigure
Bash
복사
state관련 명령어

.tfstate를  다루는 방법

NOTE
# tfstate파일이 관리하고 있는 인프라 확인 terraform state list # tfstate가 관리하는 reource 상세정보 terraform state show ~ # plan시 원하는 reource만 진행 terraform plan -target ~ # apply시 원하는 reource만 진행 terraform apply -target ~
Ruby
복사
terraform state list를 사용한 결과 생성된 reosource에 대해서 나옴

실습 코드(s3 backend 설정)

NOTE
terraform { backend "s3" { bucket = "scofe-terraform-save" # s3 bucket 이름 key = "terraform/ssafy3/terraform.tfstate" # s3 내에서 저장되는 경로를 의미합니다. region = "ap-northeast-2" encrypt = true dynamodb_table = "terraform-lock" # dynamodb } }
Ruby
복사
s3에 설정
resource "aws_s3_bucket" "tfstate" { # S3 bucket for backend bucket = "scofe-terraform-save" versioning { enabled = true # Prevent from deleting tfstate file } } # DynamoDB for terraform state lock resource "aws_dynamodb_table" "terraform_state_lock" { name = "terraform-lock" hash_key = "LockID" billing_mode = "PAY_PER_REQUEST" attribute { name = "LockID" type = "S" } }
Ruby
복사
terraform state를 저장하는데 사용할 S3와 DynamoDB
이미 생성된 .tfsate가 있는경우 복사할건지 물어봄
S3에 적용된 tfsate 코드

테라폼 리소스 블록

NOTE
리소스 블록은 선언된 항목을 생성하는 동작을 수행하며 테라폼이 프로버지닝 도구라는 측면에서 가장 중요한 요소다.
# resource "<리소스 유형>" "<이름>" { # <인수> = <값> # } resource "local_file" "abc" { # local_file 생성 content = "123" filename = "${path.module}/abc.txt" } resource "aws_instance" "web" { # aws_instance 생성 ami = "ami-a1b2c3d4" instance_type = "t2.micro" }
Bash
복사
리소스 이름은 1번째 언더스코어인 _를 기준으로 프로바이더 이름_프로바이더에서 제공하는 리소스 유형을 의미한다.
리소스 유형이 선언되면 뒤에는 고유한 이름을 붙입니다. 이름은 동일한 유형에 대해 식별자 역할을 하기 때문에, 유형이 같은 경우에는 같은 이름을 사용할 수 없습니다.
이름 뒤에는 리소스 유형에 대한 구성 인수들이 중괄호 내에 선언됩니다. 유형에 인수가 필요하지 않은 경우도 있지만, 그 경우에도 중괄호는 입력합니다.

종속성

NOTE
테라폼의 종속성은 resource, module 선언으로 프로비저닝되는 각 요소의 생성 순서를 구분짓는다.
resource "local_file" "abc" { # abc 파일 생성 content = "1234" filename = "${path.module}/abc.txt" } resource "local_file" "def" { # depends_on = [ local_file.abc ] content = local_file.abc.content # local.file.abc의 속성값을 참조(연관관계 생성) filename = "${path.module}/def.txt" }
YAML
복사
리소스간 종속성이 생겨서 abc파일이 먼저 생성된다. (원래는 병렬적으로 실행됨)
기본적으로 다른 소스에서 값을 가져올 때, 작업자가 의도하지 않았지만 자동으로 연관 관계가 생성되는 암시적 종속성이 있다.
만약 강제로 리소스 간 명시적 종속성을 부여하려면, depends_on이라는 메타인수를 사용한다.

수명주기

NOTE
리소스의 기본 생명주기를 의도적으로 변경하는 메타인수이다!
create_before_destroy(bool) : 리소스 수정시 신규 리소스를 우선생성하고 기존삭제
resource "local_file" "abc" { content = "1234" filename = "${path.module}/abc.txt" lifecycle { create_before_destroy = true # 생성 후 삭제 } }
YAML
복사
기존 파일을 수정했으나, 동일한 파일을 삭제하게되므로 최종적으로 abc파일이 삭제됨
테라폼의 기본 수명주기는 삭제 후 생성이기 때문에 의도적으로 수정된 리소스를 먼저 생성하기를 원할 수 있다.
리소스가 기존 리소스로 인해 생성이 실패되면 둘다 삭제될 수 있으니 주의하자.
리소스의 명시적 구분이 이름이나 ID인 경우 기존 리소스에 할당되어 있기 때문에 실패
생성 후 삭제시 동일한 리소스에 대한 삭제 명령이 수행되어 모두 삭제
prevent_destroy(bool) : 리소스 요소에 선언된 인수의 변경사항을 테라폼 실행시 무시
resource "local_file" "abc" { content = "123" filename = "${path.module}/abc.txt" lifecycle { prevent_destroy = true # 삭제 방지 } }
YAML
복사
기존 생명주기(삭제 → 생성)에 따라 수행되는 리소스에 삭제가 진행되지않아서 실패한다.
작업자가 의도적으로 특정 리소스의 삭제를 방지하고 싶은 경우에 사용한다.
ignore_changes(list) : 리소스 요소에 선언된 인수의 변경사항을 테라폼 실행시 무시
resource "local_file" "abc" { content = "lifecycle test" filename = "${path.module}/abc.txt" lifecycle { ignore_changes = [ content ] # 삭제 방지 } }
YAML
복사
파일 content내용이 수정되지 않음
리소스 요소의 인수를 지정해 수정 계획에 변경사항이 반영되지 않도록 하는것이다.
모두 무시하고 싶다면 [all]로 설정할 수 있다.
precondition : 리소스 요소에 선언된 인수의 조건을 검증
variable "file_name" { default = "step1.txt" } resource "local_file" "abc" { content = "lifecycle test" filename = "${path.module}/${var.file_name}" # step1.txt 지정 lifecycle { precondition { condition = var.file_name == "step6.txt" # 파일이름이 step6.txt여야 한다. error_message = "file name is not step6.txt" } } }
YAML
복사
리소스 생성 이전에 입력된 이수 값을 검증하는데 사용한다.
미리 약속된 값 이외의 값 또는 필수로 명시해야 하는 인수 값을 검증할 수 있다.
postcondition : Plan과 Apply 이후의 결과를 속성값으로 검
resource "local_file" "step7" { content = "" # 내용이 비어있음 filename = "${path.module}/step7.txt" lifecycle { postcondition { condition = self.content != "" # 내용이 비어있으면 안된다. error_message = "content cannot empty" } } } output "step7_content" { value = local_file.step7.id }
YAML
복사
프로비저닝 변경 이후 결과를 검증함과 동시에 의존성을 가지는 다른 구성의 변경을 막는 효과가 있다.