Terraform ForceNew — 가용 영역(AZ) 추가에 클러스터 전체 재생성

클라우드·인프라2분조회

클라우드에서는 서버를 여러 가용 영역(Availability Zone, 줄여서 AZ)에 나눠 둡니다. AZ 는 물리적으로 떨어진 데이터센터 묶음이라, 한 곳에 장애가 나도 다른 AZ 가 버팁니다. 네트워크(AWS 로 치면 VPC·서브넷)도 보통 AZ 마다 서브넷을 하나씩 둡니다.

특정 AZ 에만 있는 GPU 노드가 필요해서, 관리형 쿠버네티스 클러스터의 네트워크 모듈(azs)에 그 AZ 를 하나 추가했습니다. 서브넷 하나 더 만드는 작은 변경이라고 생각했는데, terraform plan 결과가 예상 밖이었습니다.

Plan: 15 to add, 0 to change, 3 to destroy

  # managed_kubernetes_cluster.main must be replaced
  # node_pool.a must be replaced
  # node_pool.b must be replaced

클러스터와 노드풀을 통째로 다시 만든다고 합니다. 서브넷 하나 추가에.

원인 — 모든 서브넷을 클러스터에 전달

프로바이더 버그가 아니라 모듈 설계 문제였습니다. 모듈이 클러스터와 노드풀에 모든 프라이빗 서브넷을 넘기고 있었습니다.

subnet_ids = values(module.network.private_subnet_ids)

AZ 를 추가하면 private-c 서브넷이 생기고, 그러면 이 subnet_ids 목록이 바뀝니다. 그런데 이 관리형 쿠버네티스는 클러스터의 vpc_info.subnets 변경을 ForceNew 로 취급합니다. 즉 서브넷 목록이 바뀌면 클러스터를 새로 만들어야 하는 속성입니다. 네트워크에 AZ 를 더한 게 클러스터 재생성으로 번진 겁니다.

해결 — 네트워크 AZ와 클러스터 AZ 분리

네트워크가 쓰는 AZ 와 클러스터가 쓰는 AZ 를 같은 변수로 묶지 않고 떼어 냈습니다.

variable "cluster_azs" {
  default = ["a", "b"]   # 클러스터는 여기 고정
}
# 네트워크는 ["a", "b", "c"]로 c를 추가하되,
# 클러스터/노드풀엔 cluster_azs에 해당하는 서브넷만 넘긴다

이러면 private-c 는 생기지만 클러스터에 넘기는 서브넷 목록은 안 변해서, replace 0 으로 AZ 만 추가됩니다.

-target 으로 서브넷만 만들고 넘어가는 우회는 안 썼습니다. 그러면 설정과 상태가 영구적으로 어긋난 채 남아서, 다음 사람이 plan 을 볼 때마다 헷갈립니다.

AZ 하나 추가가 전체 재생성으로 번지는 경로

관리형 리소스에서 무심한 목록 변경이 ForceNew 를 건드릴 수 있습니다. AZ 하나 추가처럼 작아 보이는 변경도, 그게 클러스터의 ForceNew 속성(subnet_ids)에 닿으면 전체 재생성으로 번집니다. planmust be replaced 를 절대 그냥 apply 하지 말고, 무엇이 그 replace 를 유발하는지 되짚어야 합니다. 그리고 모듈을 짤 때 “모든 서브넷을 다 넘기는” 편의가, 나중에 AZ 를 늘릴 때 전체 재생성으로 돌아옵니다 — 네트워크 차원과 클러스터 차원의 AZ 는 분리해 두는 게 안전합니다.

  1. 불러오는 중