Alias 명시하고 provider 메타인수를 이용해 provider를 지정할 수 있습니다.
provider "aws" {
alias = "seoul" // alias 지정
region = "ap-northeast-2"
}
resource "aws_instance" "app_server2" {
provider = aws.seoul // provider 지정
ami = "ami-0ea4d4b8dc1e46212"
instance_type = "t2.micro"
}
프로바이더 요구사항 정의
프로바이더에 대한 source에 다운로드 경로 정의하고 version에 프로바이더 버전을 명시 할 수 있습니다.
// ec2.tf
```
resource "aws_instance" "region_1" {
provider = aws.region_1 // 첫번째 region 에 ec2를 생성하게 끔 region을 설정합니다.
ami = data.aws_ami.ubuntu_region_1.id
instance_type = "t2.micro"
}
resource "aws_instance" "region_2" {
provider = aws.region_2 // 두번째 region 에 ec2를 생성하게 끔 region을 설정합니다.
ami = data.aws_ami.ubuntu_region_2.id
instance_type = "t2.micro"
}
```
// provider_data.tf
```
provider "aws" {
region = "ap-northeast-2"
alias = "region_1"
}
provider "aws" {
region = "ap-southeast-1"
alias = "region_2"
}
data "aws_region" "region_1" {
provider = aws.region_1
}
data "aws_region" "region_2" {
provider = aws.region_2
}
data "aws_ami" "ubuntu_region_1" {
provider = aws.region_1 // 다음과 같이 region 1에서 사용되는 provider를 사용합니다.
most_recent = true
owners = ["099720109477"] # Canonical
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
}
}
data "aws_ami" "ubuntu_region_2" {
provider = aws.region_2 // 다음과 같이 region 2에서 사용되는 provider를 사용합니다.
most_recent = true
owners = ["099720109477"] # Canonical
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
}
}
```
// 다음 코드를 실행하면 ec2가 각각의 region 에 생성되있는것을 확인 할 수 있다.
aws ec2 describe-instances --region ap-northeast-2 --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text
2가지 주의사항
첫번째 주의사항: 프로덕션 수준의 멀티 리전은 어렵다
지역간 지연시간, 고유ID, 최종 일관성 등 고려사항이 많아서 어렵다.
두번째 주의사항: Alias를 빈번하게 사용하지 말자
별칭 사용하여 두 리전에 배포하는 모듈은 한 리전이 다운 시에 Apply가 실패한다.
workspace나 디렉토리를 이용해서 완전 분리하는것이 별칭으로 분리하는것보다 나은 선택이다.
2. State
테라폼 상태관리의 중요성에 대한 카톡
상태관리를 어떻게 해야할지 정확히 알아야합니다.
s3 버저닝과 import로 복구하는 면이 인상적입니다.
2.1 State의 목적과 의미
[실습] 상태 파일 확인
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_vpc" "myvpc" {
cidr_block = "10.10.0.0/16"
tags = {
Name = "t101-study" // 해당 값을 변경할 예정
}
}
// tf 파일을 프로비젼이후에 serial 값이 1인것을 확인할 수 있습니다.
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_vpc" "myvpc" {
cidr_block = "10.10.0.0/16"
tags = {
Name = "tf-state" // 해당값을 바꾸고 다시 apply 하게되면 serial 값은 증가 할 것입니다.
}
}
// serial 값이 3으로 변경되었습니다.
상태 파일은 terraform에서 내부 API로 변경되는 상태를 저장하기 위한 파일로 직접 편집하거나 코드로 작성해서는 안됩니다.
상태값에 따라 여러번 실행해도 결과가 동일하게끔 멱등성을 보장하게끔 실행됩니다.
팀 단위에서 테라폼 운영시 문제사항
파일을 저장하는 공유 스토리지 필요
상태 파일 잠금
동시에 작업될 시에 충돌 가능
상태 파일 격리
환경별 상태파일 격리 필요
지원되는 원격 백엔드
AWS, Azure Blob, Google Cloud Storage, Postgresql, k8s secret 등 원격으로 apply 이후에 저장이 가능하다.
수동 오류 해결: plan/ apply 실행 시마다 파일을 로드해서 apply후에 자동으로 저장한다. (버전관리시스템은 수동으로 update를 해줘야한다.)
잠금: 버전 관리시스템에서 여러명의 구성원들이 동시에 하나의 상태파일에 대해서 apply 못하게 잠금기능을 제공합니다. -lock-timeout=30s (상태파일 동시 업데이트로 충돌이 가능하다.)
시크릿: 테라폼 상태의 모든 데이터는 평문으로 tf.state에 저장될때, 암호화하는 기능을 지원 (VCS 는 모든 데이터 평문 저장함)
테라폼 구성 파일을 기존 존재하는 State 파일과 비교해서 실행계획을 세워서 생성, 수정, 삭제를 하게 됩니다.
테라폼 state 흐름
각 리소스에서 발생할 수 있는 상태변화
[실습] 유형별 상태변화 및 복구 방법
유형
구성 리소스 정의(*.tf)
State 구성 데이터
실제 리소스
기본 예상 동작
1
있음
리소스 생성
2
있음
있음
리소스 생성
3
있음
있음
있음
동작 없음
4
있음
있음
리소스 삭제
5
있음
동작 없음
유형1 : 신규 리소스 정의 → Apply ⇒ 리소스 생성
// main.tf
```
locals {
name = "mytest"
}
resource "aws_iam_user" "myiamuser1" {
name = "${local.name}1"
}
resource "aws_iam_user" "myiamuser2" {
name = "${local.name}2"
}
```
// 두번 실행시에도 멱등성을 유지하는것을 확인 할 수 있습니다. (추가 수정, 실행 없음)
유형2 : 실제 리소스 수동 제거 → Apply ⇒ 리소스 생성
// 실제 리소스 수동 제거
aws iam delete-user --user-name mytest1
aws iam delete-user --user-name mytest2
terraform plan
// 삭제이후에는 다시 생성해야 되는것을 명시해 줍니다.
terraform plan
terraform plan -refresh=false // 해당 refresh는 aws 와 같은
// 인프러스트럭쳐에 실제로 리소스가 프로비져닝 되있는지 확인합니다.
cat terraform.tfstate | jq .serial
유형3 : Apply → Apply ← 코드, State, 형상 모두 일치한 경우
// terraform apply -auto-approve
// terraform apply -auto-approve
두번 apply를 하게되면 형상이 모두 일치할 때, 다음과 같은 결과가 나오게 됩니다.
유형4 : 코드에서 일부 리소스 삭제 → Apply
locals {
name = "mytest"
}
resource "aws_iam_user" "myiamuser1" {
name = "${local.name}1"
}
// myiamuser2을 명시하지 않았을때 다음과 같은 값이 나옵니다.
유형6 : 실수로 tfstate 파일 삭제 → plan/apply
rm -rf terraform.tfstate* /tfstate 파일들 모두 삭제
terraform plan -refresh=false // tfstate만 보고 판별할 경우
terraform plan // 두개다 새로운 유저를 만드려고합니다.
// 위 상황에서 복구하는 방법은? import가 있습니다.
terraform import aws_iam_user.myiamuser1 mytest1