Terraform은 tfstate 파일 기반으로 동작한다.
1. main.tf에 정의된 인프라스트럭쳐
2. tfstate 파일에 정의된 인프라스트럭쳐
위 2가지를 대조한 뒤, terraform plan 명령어를 수행하면 tfstate에 정의된 인프라스트럭쳐와 main.tf에 정의한 인프라스트럭쳐를 맞추려고 한다.
예를 들어, 예전에 Terraform 코드로 생성한 IAM User가 아래와 같이 존재한다고 가정해보자.
resource "aws_iam_user" "user1" {
name = "user1"
}
resource "aws_iam_user" "user2" {
name = "user2"
}
IAM User : user1, user2가 존재할 것이다.
이 상태에서 user1, user2를 유지하되 count 함수를 사용하고 싶다고 가정해보자.
variable "users" {
description = "Create IAM Users"
type = list
default = ["user1", "user2"]
}
resource "aws_iam_user" "users" {
count = length(var.users)
name = element(var.users, count.index)
}
IAM User : user1, user2를 정의하는 코드지만, 테라폼은 위 둘을 다른 코드로 인식한다.
왜냐하면 aws_iam_user.user1, aws_iam_user.user2와 aws_iam_user.users는 테라폼에게 엄연히 다른 리소스이기 때문이다.
즉, 의미적으로 똑같은데 terraform plan을 하게 되면 기존 리소스를 destroy하고 apply를 수행하게 된다.
=> terraform state mv를 통해 해결할 수 있음
=> 테라폼 코드를 리팩터링 할 때 많이 사용하게 된다.
terraform state mv [options] SOURCE DESTINATION
Ref : https://www.terraform.io/cli/commands/state/mv
=> 대상 주소에 지정된 주소와 일치하는 항목을 이동한다.
=> 간단한 자원 이름 변경, 항목을 모듈로 이동하거나 모듈 전체로 이동하는데 사용할 수 있다.
=> 또한 완전하 새로운 상태로 이동할 수 있으므로 하나의 구성을 여러 개의 개별 관리형 Terraform 구성으로 리팩터링 하는 데에도 사용할 수 있다.
Example
1. 자원 이름 바꾸기
$ terraform state mv aws_instance.foo aws_instance.bar
2. 자원을 모듈로 이동
$ terraform state mv aws_instance.foo module.web
3. 모듈을 모듈로 이동
$ terraform state mv module.foo module.parent.module.foo
4. 모듈을 다른 상태로 이동
$ terraform state mv -state-out=other.tfstate \
module.web module.web
사용 Case
[1] 배경 : 기존에 사용하던 resource 파일을 다음과 같이 리팩터링 하고자 함
별도의 resource 2개 만들지 말고, for_each 함수를 사용하여 리팩터링
[2] 조치 방안
➜ common git:(dev) ✗ terraform state mv 'aws_route53_record.www_cname_pingping95_shop' 'aws_route53_record.cname_pingping95_shop[0]'
Move "aws_route53_record.www_cname_pingping95_shop" to "aws_route53_record.cname_pingping95_shop[0]"
Successfully moved 1 object(s).
➜ common git:(dev) ✗ terraform state mv 'aws_route53_record.test_cname_pingping95_shop' 'aws_route53_record.cname_pingping95_shop[1]'
Move "aws_route53_record.test_cname_pingping95_shop" to "aws_route53_record.cname_pingping95_shop[1]"
Successfully moved 1 object(s).
➜ common git:(dev) ✗ terraform state list
aws_acm_certificate.pingping2_shop
aws_acm_certificate.pingping2_shop-virginia
aws_acm_certificate_validation.pingping2_shop_validation
aws_acm_certificate_validation.pingping2_shop_validation-virginia
aws_route53_record.cname_pingping95_shop[0]
aws_route53_record.cname_pingping95_shop[1]
aws_route53_record.pingping2_shop_acm_cname["pingping2.shop"]
aws_route53_record.pingping2_shop_acm_cname["www.pingping2.shop"]
aws_route53_record.pingping2_shop_acm_cname-virginia["pingping2.shop"]
aws_route53_record.pingping2_shop_acm_cname-virginia["test.pingping2.shop"]
aws_route53_zone.pingping2_shop
aws_s3_account_public_access_block.ftstate
aws_s3_bucket.tfstate
# 다시 (실수로 [0], [1] 이런 식으로 변경하였음)
➜ common git:(dev) ✗ terraform state mv 'aws_route53_record.cname_pingping95_shop[0]' 'aws_route53_record.cname_pingping95_shop["www"]'
Move "aws_route53_record.cname_pingping95_shop[0]" to "aws_route53_record.cname_pingping95_shop[\"www\"]"
Successfully moved 1 object(s).
➜ common git:(dev) ✗ terraform state mv 'aws_route53_record.cname_pingping95_shop[1]' 'aws_route53_record.cname_pingping95_shop["test"]'
Move "aws_route53_record.cname_pingping95_shop[1]" to "aws_route53_record.cname_pingping95_shop[\"test\"]"
Successfully moved 1 object(s).
➜ common git:(dev) ✗ terraform state list
aws_acm_certificate.pingping2_shop
aws_acm_certificate.pingping2_shop-virginia
aws_acm_certificate_validation.pingping2_shop_validation
aws_acm_certificate_validation.pingping2_shop_validation-virginia
aws_route53_record.cname_pingping95_shop["test"]
aws_route53_record.cname_pingping95_shop["www"]
aws_route53_record.pingping2_shop_acm_cname["pingping2.shop"]
aws_route53_record.pingping2_shop_acm_cname["www.pingping2.shop"]
aws_route53_record.pingping2_shop_acm_cname-virginia["pingping2.shop"]
aws_route53_record.pingping2_shop_acm_cname-virginia["test.pingping2.shop"]
aws_route53_zone.pingping2_shop
aws_s3_account_public_access_block.ftstate
aws_s3_bucket.tfstate
[3] 확인
형상이 정상적으로 변경되었으며, 별도의 리소스 교체(Destory → Apply) 없이 변경을 완료함
'DevOps' 카테고리의 다른 글
[Github Action] Self hosted runner에서 Gradle, Docker image cache #1 - EBS, PVC로 캐시하기 (2) | 2022.12.17 |
---|---|
[Istio] EKS에서 Okta와 AWS ALB, Istio를 활용하여 인증, 인가 처리하기 (0) | 2022.11.06 |
[Envoy] Envoy Proxy Architecture (0) | 2022.06.25 |
[Terraform] Atlantis를 통한 Git 협업 #1 - Demo (0) | 2022.05.14 |
[Ansible] 기본 개념 정리 (0) | 2021.11.14 |