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

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

AWS 가 아닌 다른 클라우드의 관리형 쿠버네티스 클러스터를 Terraform 으로 올려 두고 있습니다. 네트워크는 별도 모듈로 빼서 VPC 와 서브넷을 만들고, 클러스터 모듈이 그 서브넷을 받아 씁니다. 네트워크 모듈에 azs 로 가용 영역 목록을 주면 그 개수만큼 프라이빗 서브넷이 생깁니다.

GPU 인스턴스는 리전 안에서도 가용 영역(AZ)마다 재고가 다릅니다. 필요한 타입이 지금 쓰는 AZ 두 곳에는 없고 다른 AZ 에만 있어서, 클러스터가 쓰는 네트워크 모듈의 azs 목록에 그 AZ 를 하나 추가했습니다.

서브넷 하나 더 만드는 변경이라 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 를 같은 변수로 묶지 않고 떼어 냈습니다.

variable "cluster_azs" {
  default = ["a", "b"]   # 클러스터는 여기 고정
}

# 네트워크는 ["a", "b", "c"]로 c를 추가하고,
# 클러스터·노드풀엔 cluster_azs에 해당하는 서브넷만 골라 넘긴다
subnet_ids = [for az in var.cluster_azs : module.network.private_subnet_ids[az]]

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

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

AZ 하나 추가가 전체 재생성까지 간 경로

plan 에 must be replaced 가 뜨면 그대로 apply 하지 말고 무엇 때문에 replace 가 걸렸는지부터 되짚습니다. 이번 건은 AZ 하나 추가가 서브넷 목록을 바꿨고, 그 목록이 클러스터의 ForceNew 속성에 닿으면서 클러스터 전체 재생성으로 번졌습니다. 변경한 건 네트워크인데도 결과가 클러스터에서 나온 겁니다.

모듈을 짤 때 모든 서브넷을 다 넘겨 두면 편하지만, 그렇게 해 두면 나중에 AZ 를 하나 늘릴 때 클러스터를 통째로 다시 만들게 됩니다. 네트워크가 쓰는 AZ 와 클러스터가 쓰는 AZ 는 처음부터 다른 변수로 떼어 두면 이 경로가 아예 안 생깁니다.

  1. 불러오는 중