준비물
aws로그인 https://console.aws.amazon.com/
명령서버에서 사용할 pem키 필요
access-key 필요
secret-key 필요
테라폼 코드는 여러가지 블록으로 구분이 된다.
테라폼 블록,프로바이더 버전,백엔드 블럭, 리소스 블럭
1
테라폼의 버전을 관리하는것이다.
테라폼 버전이나 프로바이더 버전과 같은 값들은 자동으로 설정되지만, 함께 작업할 때는 버전을 명시적으로 선언하고 필요한 조건을 입력하여 실행 오류를 최소화 한다.
코드 생성당시 버전과 같거나 비슷해야 추후 실행시 오류가 적다.
참고 코드
terraform {
required_version = "~> 1.3.0" # 테라폼 버전
required_providers { # 프로바이더 버전을 나열
random = {
version = ">= 3.0.0, < 3.1.0"
}
aws = {
version = "4.2.0"
}
}
cloud { # Cloud/Enterprise 같은 원격 실행을 위한 정보
organization = "<MY_ORG_NAME>"
workspaces {
name = "my-first-workspace"
}
}
backend "local" { # state를 보관하는 위치를 지정
path = "relative/path/to/terraform.tfstate"
}
}
// 테라폼
// 프로바이더
// 백엔드
2
버전 체계
# version = Major.Minor.Patch
version = 1.3.4
테라폼 버전 관리 - 선언 방식의 의미 ?
>= 1.0.0
테라폼 v1.0.0 이상의 모든 버전을 허용한다
~> 1.0.0.
테라폼 v1.0.0을 포함한 v1.0.x 버전을 하용하고 v1.x는 허용하지 않는다
>= 1.0, < 2.0.0
테라폼 v1.0.0 이상 v2.0.0 미만인 버전을 허용한다
3
mkdir 03
cd 03
4
# 현재 버전 정보 확인
terraform version
Terraform v1.5.2
// 1.0 이하로 설정 해보자. 지금 버전은 1.5.2 이다.
vi main.tf
terraform {
required_version = "< 1.0.0"
}
resource "local_file" "abc" {
content = "abc!"
filename = "${path.module}/abc.txt"
}
# 실행 결과는?
terraform init
...
에러.
나는 1.5라 에러남.
[root@myeks2-bastion-EC2 03]# terraform init
Initializing the backend...
╷
│ Error: Unsupported Terraform Core version
│
│ on main.tf line 3, in terraform:
│ 3: required_version = "< 1.0.0"
│
│ This configuration does not support Terraform version 1.5.2. To proceed, either choose another supported Terraform version
│ or update this version constraint. Version constraints are normally set for good reason, so updating the constraint may
│ lead to other errors or unexpected behavior.
╵
6
수정
1.0 이상
terraform {
required_version = ">= 1.0.0"
}
resource "local_file" "abc" {
content = "abc!"
filename = "${path.module}/abc.txt"
}
7
# 실행 결과는?
terraform init
성공
[root@myeks2-bastion-EC2 03]# terraform init
Initializing the backend...
Initializing provider plugins...
- Finding latest version of hashicorp/local...
- Installing hashicorp/local v2.4.0...
- Installed hashicorp/local v2.4.0 (signed by HashiCorp)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Terraform has been successfully initialized!
1
프로바이더 버전 보기
https://registry.terraform.io/browse/providers
사용하고자 하는 프로바이더 클릭 예) AWS
오른쪽위 USE Provider 클릭하여 설정법도 볼수 있다.
2
LOCAL PROVIDER 버전 확인하자.
2.4.0
https://registry.terraform.io/providers/hashicorp/local/latest
프로바이더 버전을 100으로 지정해 보자.
에러 난다.
terraform {
required_version = ">= 1.0.0"
required_providers {
local = {
source = "hashicorp/local"
version = ">=100.0.0"
}
}
}
resource "local_file" "abc" {
content = "123!"
filename = "${path.module}/abc.txt"
}
# 실행 결과는?
terraform init -upgrade
에러
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/local versions matching ">= 100.0.0"...
╷
│ Error: Failed to query available provider packages
│
│ Could not retrieve the list of available versions for provider hashicorp/local: no available releases match the given
│ constraints >= 100.0.0
3
2.0 이상으로 변경
terraform {
required_version = ">= 1.0.0"
required_providers {
local = {
source = "hashicorp/local"
version = ">= 2.0.0"
}
}
}
resource "local_file" "abc" {
content = "123!"
filename = "${path.module}/abc.txt"
}
# 실행 결과는?
terraform init -upgrade
잘됨.
1
백엔드 블록의 구성은 테라폼 실행 시 저장되는 State(상태 파일)의 저장 위치를 선언한다.
하나의 백엔드만 허용한다는 점이다.
테라폼은 State의 데이터를 사용해 코드로 관리된 리소스를 탐색하고 추적한다.
2
기본적으로 활성화되는 백엔드는 local이다.
상태를 작업자의 로컬 환경에 저장하고 관리하는 방식이다.
3
resource "local_file" "abc" {
content = "123456!"
filename = "${path.module}/abc.txt"
}
# 터미널1
terraform apply
...
Enter a value: 대기
# 터미널2
terraform apply
...
ls -a
# 터미널1 취소 후 apply
terraform apply -auto-approve
ls terraform.tfstate*
terraform.tfstate terraform.tfstate.backup
# 리소스 확인
terraform state list
# State 파일 정보 확인
cat terraform.tfstate
4
백엔드가 설정되면 다시 init 명령을 수행해 State의 위치를 재설정해야 한다
terraform {
backend "local" {
path = "state/terraform.tfstate"
}
}
resource "local_file" "abc" {
content = "123456!"
filename = "${path.module}/abc.txt"
}
5
# init 시 백엔드 변경에 따른 마이그레이션 안내
terraform init
...
Enter a value: yes
...
#
ls terraform.tfstate*
tree state
cat state/terraform.tfstate | jq
cat state/terraform.tfstate | jq -r .serial
#
terraform apply -auto-approve
6
terraform {
backend "local" {
path = "state/terraform.tfstate"
}
}
resource "local_file" "abc" {
content = "123456789!"
filename = "${path.module}/abc.txt"
}
7
#
terraform plan
terraform apply -auto-approve
#
cat abc.txt
ls terraform.tfstate*
tree state
cat state/terraform.tfstate | jq
cat state/terraform.tfstate | jq -r .serial
# 이전 사용 state 파일 삭제 후 확인
rm -rf terraform.tfstate*
ls -al
#
terraform plan
terraform apply -auto-approve
cat abc.txt
1
cd
mkdir 03re
cd 03re
2
resource 블럭은 resource 로 시작한다.
resource "<리소스 유형>" "<이름>" {
<인수> = <값>
}
resource "local_file" "abc" {
content = "123"
filename = "${path.module}/abc.txt"
}
3
vi main.tf
resource "local_file" "abc" {
content = "123"
filename = "${path.module}/abc.txt"
}
resource "aws_instance" "web" {
ami = "ami-a1b2c3d4"
instance_type = "t2.micro"
}
// 리소스 유형은 local 이다. local provider 로 file 유형이다.
// aws언더바로 시작 = aws의 인스턴스이다.
// web 은 이름이다. 이름은 테라폼이 구분하는 이름이다. 동일한 이름이 있으며 충돌 난다.
// { 중괄호 } 는 인수의 값 내용이다.
4
# init 시 프로바이더 선언 없이도 리소스 추가로 자동 인식된 프로바이더 요구사항과 초기화
terraform init
tree .terraform
// 프로바이더 지정을 안하더라도 프로바이더가 다운로도 되었다.
// 코드를 보면 리소스 다음에 프로바이더가 나온다. 그래서 관련 라이블러리가 다운로드 된다.
resource "aws_instance" "web" {
5
종속성 확인해보자 !!!
로컬 풇로바이더로 다 바꿔보자.
resource "local_file" "abc" {
content = "123!"
filename = "${path.module}/abc.txt"
}
resource "local_file" "def" {
content = "456!"
filename = "${path.module}/def.txt"
}
// 동일한 리소스 유형이지만 이름을 구분한다. abc , def 이름으로 구분한다.
6
(선택)
VS Code 사용시에는 확장 프로그램 graphviz 설치하자.
그래프 형태로 연관 종속성을 보여 주는 플러그인이다.
7
배포
terraform apply -auto-approve
8
확인
2개의 파일이 만들어진다.
ls *.txt
abc.txt def.txt
// 로컬_파일 , 점 이름으로 생성이 된다.
terraform state list
local_file.abc
local_file.def
9
(선택)
VS Code 사용시
terraform graph
파일로 만들어보자.
terraform graph > graph-2.dot
파일을 클릭하고 VS Code 오른쪽위 DOT 클릭하면 그래프가 나온다.
지금은 2개 리소스가 병렬로 만들어진다!
10
제거
terraform destroy -auto-approve
11
리소스 참조값을 설정해 두 개의 리소스 간 암시적 종속성 부여 해보자!
resource "local_file" "abc" {
content = "123!"
filename = "${path.module}/abc.txt"
}
resource "local_file" "def" {
content = local_file.abc.content
filename = "${path.module}/def.txt"
}
terraform apply -auto-approve
생성 순서가 달라진다.
순차적으로 생성된다.
abc 만들고 def가 만들어진다!
abc에 의존된게 def 이다.
def만들때 abc 참고한다.
확인
ls *.txt
terraform state list
[root@myeks2-bastion-EC2 03-re]# ls *.txt
abc.txt def.txt
[root@myeks2-bastion-EC2 03-re]# terraform state list
local_file.abc
local_file.def
terraform destroy -auto-approve
12
종속성 관련 코드가 있다! depends_on
리소스 자체를 depends_on 지정 가능하다.
def는 abc만들고 만들어라.
resource "local_file" "abc" {
content = "123!"
filename = "${path.module}/abc.txt"
}
resource "local_file" "def" {
depends_on = [
local_file.abc
]
content = "456!"
filename = "${path.module}/def.txt"
}
13
terraform apply -auto-approve
[root@myeks2-bastion-EC2 03re]# more abc.txt
123!
[root@myeks2-bastion-EC2 03re]# more def.txt
456!
14
리소스 속성 참고 ?
1
테라폼의 기본 수명주기는 삭제후 새로 생성한다.
리소스 수정 시 신규 리소스를 우선 생성하고, 기존 리소스를 삭제하도록 하자.
기본 사례와 옵션을 잘못준 사례를 2가지를 알아보자.
파일을 생성후 삭제하면, 날아가 버리는 잘못된 예제도 알아보자.
2
mkdir life
cd life
3
기본 사례 false 일때.
resource "local_file" "abc" {
content = "lifecycle - step 1"
filename = "${path.module}/abc.txt"
lifecycle {
create_before_destroy = false
}
}
4
#
terraform init && terraform plan && terraform apply -auto-approve
terraform state list
# 파일 내용 확인
cat abc.txt
lifecycle - step 1
// 기본값은 false 이다
5
컨텐트 내용 수정해보자.
resource "local_file" "abc" {
content = "lifecycle - step 1111111111111111"
filename = "${path.module}/abc.txt"
lifecycle {
create_before_destroy = false
}
}
6
#
terraform plan && terraform apply -auto-approve
...
-/+ destroy and then create replacement
Terraform will perform the following actions:
# local_file.abc must be replaced
-/+ resource "local_file" "abc" {
~ content = "lifecycle - step 1" -> "lifecycle - step 1111111111111111" # forces replacement
...
replace 된다.
제거후 새로 만든다.
# 파일 내용 확인
cat abc.txt
lifecycle - step 11111111111111
7
내용 수정 저장
resource "local_file" "abc" {
content = "lifecycle - step 2"
filename = "${path.module}/abc.txt"
lifecycle {
create_before_destroy = true
}
}
// 컨텐츠 내용을 true로 변경하고 생성해보자.
파일을 만들고 삭제한다.
파일이 삭제 되어 버린다!!!
만든거도 삭제된다. (장애 상태) - 인스턴스 만들고 삭제 - -
terraform plan && terraform apply -auto-approve
terraform destroy -auto-approve
8
다시 apply 하면 만들어진다.
해당 리소스를 삭제 Destroy 하려 할 때 명시적으로 거부
1
resource "local_file" "abc" {
content = "lifecycle - step 3"
filename = "${path.module}/abc.txt"
lifecycle {
prevent_destroy = true
}
}
2
#
terraform plan
terraform apply -auto-approve
...
│ Error: Instance cannot be destroyed
│
│ on main.tf line 1:
│ 1: resource "local_file" "abc" {
...
// 삭제 방지를 true로 해놓는다.
// 실행하면 에러가 난다. 테라폼은 삭제후 다시 만들어야 하는데 삭제가 안되므로 에러가 난다.
코드를 수정하고 다시 실행하자.
terraform apply -auto-approve
3
cat abc.txt
lifecycle - step 3
ignore_changes 리소스 요소의 인수를 지정해 수정 계획에 변경 사항이 반영되지 않도록 하는 것
content 내용을 수정하자. 4로
1
resource "local_file" "abc" {
content = "lifecycle - step 4"
filename = "${path.module}/abc.txt"
lifecycle {
ignore_changes = []
}
}
2
terraform apply -auto-approve
cat abc.txt
lifecycle - step 4
3
content 내용을 다시 수정하자.
5로 수정하자.
resource "local_file" "abc" {
content = "lifecycle - step 5"
filename = "${path.module}/abc.txt"
lifecycle {
ignore_changes = [
content
]
}
}
// content 는 유지해줘
4
#
terraform apply -auto-approve
cat abc.txt
lifecycle - step 4
// 변경되지 않음!!!
리소스 생성 이전에 검사하는것이다.
리소스 생성 이전에 입력된 인수 값을 검증하는 데 사용해 프로비저닝 이전에 미리 약속된 값 이외의 값 또는 필수로 명시해야 하는 인수 값을 검증
1
variable "file_name" {
default = "step0.txt"
}
resource "local_file" "abc" {
content = "lifecycle - step 6"
filename = "${path.module}/${var.file_name}"
lifecycle {
precondition {
condition = var.file_name == "step6.txt"
error_message = "file name is not \"step6.txt\""
}
}
}
// 컨디션 파일이름이 step6.txt 이여야 한다.
// 그런데, 디폴트라 step0.txt 이다.
// 에러 메시지를 뿌려준다.
2
#
terraform plan
local_file.abc: Refreshing state... [id=63cd1a0c571d59f5b4337364e612786cc63c1bb8]
Planning failed. Terraform encountered an error while generating this plan.
╷
│ Error: Resource precondition failed
│
│ on main.tf line 22, in resource "local_file" "abc":
│ 22: condition = var.file_name == "step6.txt"
│ ├────────────────
│ │ var.file_name is "step0.txt"
│
│ file name is not "step6.txt"
╵
3
클라우드 인프라의 VM을 생성할 때 내부적으로 검증된 이미지 아이디를 사용하는지 등과 같은 구성을 미리 확인하고 사전에 잘못된 프로비저닝을 실행할 수 없도록 구성할 수 있다.
프로비저닝 변경 이후 결과를 검증함과 동시에 의존성을 갖는 다른 구성의 변경을 맞는 효과
1
resource "local_file" "abc" {
content = ""
filename = "${path.module}/step7.txt"
lifecycle {
postcondition {
condition = self.content != ""
error_message = "content cannot empty"
}
}
}
output "step7_content" {
value = local_file.abc.id
}
// 변경 이후의 결과
//
2
# postcondition 조건에 맞지 않아 에러 발생
terraform apply -auto-approve
terraform state list
cat step7.txt
3
컨텐츠를 채운다.
적용한다.
정상 처리된다.
resource "local_file" "abc" {
content = "step7 file ok"
filename = "${path.module}/step7.txt"
lifecycle {
postcondition {
condition = self.content != ""
error_message = "content cannot empty"
}
}
}
output "step7_content" {
value = local_file.abc.id
}
4
terraform apply -auto-approve
terraform state list
cat step7.txt
https://brunch.co.kr/@topasvga/3360
https://brunch.co.kr/@topasvga/3347
https://gasidaseo.notion.site/gasidaseo/CloudNet-Blog-c9dfa44a27ff431dafdd2edacc8a1863
감사합니다.