쿠버네티스는 왜 이렇게 자주 버리는가 — 폐기 목록은 상환 일정표다
쿠버네티스 릴리스 노트를 볼 때 저는 새로 들어온 기능보다 폐기 목록을 먼저 봅니다.
새 기능은 안 써도 그만입니다. 폐기는 다릅니다. 지금 잘 돌아가는 클러스터에 만료일이 찍히는 일이거든요.
2026년 8월 26일에 나온 v1.37(Garhwal)에는 안정화 16개, 베타 23개, 알파 27개가 들어 있습니다. 폐기는 하나입니다. 숫자만 보면 사소해 보입니다. 그런데 그 하나에 세 가지가 묶여 있는데, 셋 다 오래된 클러스터의 기본값이던 것들이더군요.
이번에 만료일이 찍힌 것들
kube-dns가 물러납니다. CoreDNS가 기본이 된 게 v1.13이니 한참 전이지만 그때 만들어 계속 굴려온 클러스터에는 아직 kube-dns가 남아 있을 수 있습니다. 마감은 1.40입니다.
kube-proxy의 IPVS 모드도 폐기됩니다. 대체는 nftables이고 1.43부터는 지원이 끊깁니다. IPVS는 iptables가 규칙 수에 따라 느려지는 문제를 풀려고 들어왔는데, 결국 기대만큼 동작하지 않았다는 게 이번 결정의 배경입니다.
cgroup v1은 사정이 다릅니다. 예고가 아니라 이미 지나간 일입니다. v1.35부터 cgroup v1에 의존하는 노드는 아예 초기화되지 않고, 대체는 cgroup v2입니다.
표로 놓으면 이렇습니다.
| 항목 | 대체 | 마감 |
|---|---|---|
| kube-dns | CoreDNS | 1.40까지 |
| IPVS (kube-proxy) | nftables | 1.43부터 중단 |
| cgroup v1 | cgroup v2 | 1.35부터 이미 노드 초기화 실패 |
셋을 같은 무게로 다루면 안 됩니다
마감 날짜가 서로 다르거든요.
cgroup v1은 이미 마감을 지났습니다. 아직 안 겪었다면 운이 좋았거나 그 버전까지 안 올라간 것뿐입니다. 다음 업그레이드에서 노드가 안 뜨는 형태로 터집니다.
kube-dns는 1.40까지입니다. 릴리스가 대략 분기마다 나오니 실질적으로 아홉 달 안팎이 남았습니다. 그 안에 계획을 세워 옮기면 되는 일입니다.
IPVS는 1.43까지 시간이 더 있습니다. 다만 저는 nftables 전환이 DNS 교체보다 무거운 일이라고 봅니다. 트래픽 경로가 바뀌는 일이라 검증할 것도 많고요.
같은 "폐기 예고"인데 하나는 이미 터진 문제입니다. 하나는 계획할 수 있는 일이고, 나머지 하나는 준비 기간이 긴 대신 준비 자체가 무겁습니다. 릴리스 노트는 이걸 한 줄로 뭉뚱그려 보여줍니다. 읽는 사람이 갈라줘야 합니다.
우리 클러스터가 어느 줄에 서 있는지부터
기사를 읽고 나서 할 일은 문서를 더 읽는 게 아닙니다. 지금 우리 클러스터가 세 항목 중 어디에 걸려 있는지 확인하는 겁니다.
DNS부터 봅니다.
kubectl -n kube-system get deploy -l k8s-app=kube-dns
kubectl -n kube-system get deploy coredns -o jsonpath='{.spec.template.spec.containers[0].image}'
레이블이 k8s-app=kube-dns인 건 함정입니다. CoreDNS도 호환을 위해 같은 레이블을 씁니다. 이미지 이름을 봐야 실제로 무엇이 도는지 알 수 있습니다.
kube-proxy 모드를 봅니다.
kubectl -n kube-system get cm kube-proxy -o yaml | grep -i "mode:"
값이 비어 있으면 iptables입니다. ipvs라고 적혀 있으면 1.43 전에 옮길 준비를 시작해야 합니다.
노드의 cgroup 버전을 봅니다.
kubectl get nodes -o wide
# 노드에 접속해서
stat -fc %T /sys/fs/cgroup/
cgroup2fs가 나오면 v2입니다. tmpfs가 나오면 v1이고요. 이건 다음 업그레이드에서 노드가 못 뜬다는 뜻입니다.
세 명령이면 우리 클러스터가 어느 줄에 서 있는지 나옵니다. 문서를 더 읽는 것보다 이게 먼저입니다.
관리형과 자체 운영은 시간표가 다릅니다
여기서 갈립니다.
EKS, GKE, AKS 같은 관리형을 쓰면 컨트롤 플레인 폐기는 사업자가 처리합니다. 대신 업그레이드 일정이 사업자 캘린더를 따라갑니다. 미룰 수 있는 기간이 정해져 있고 지나면 강제로 올라갑니다.
직접 굴리거나 OpenShift·OKD 같은 배포판을 쓰면 이야기가 달라집니다. 배포판은 업스트림을 그대로 따라가지 않고 몇 버전 뒤에서 검증을 거쳐 따라옵니다. 그래서 업스트림에서 폐기 발표가 나도 당장 우리 클러스터에 적용되지는 않습니다.
다만 이건 유예이지 면제가 아닙니다. 업스트림에서 이미 사라진 기능을 배포판이 영원히 들고 갈 수는 없습니다. 시차만큼 나중에 한꺼번에 옵니다. 여러 버전을 건너뛰는 업그레이드가 유독 힘든 이유이기도 하고요.
폐기는 예고된 청구서입니다
쿠버네티스가 유난히 자주 버리는 것처럼 보이지만 이건 대체로 좋은 신호입니다. 폐기 없이 하위 호환만 쌓는 플랫폼은 결국 아무도 손댈 수 없는 덩어리가 됩니다.
문제는 폐기의 비용이 미루는 쪽에 쌓인다는 점입니다. 예고 시점에 옮기면 계획된 작업이고, 마감이 지나서 옮기면 장애 대응입니다. 같은 작업인데 이름이 달라집니다.
노드가 안 뜨고 나서 cgroup 버전을 확인하는 것과 릴리스 노트를 보고 미리 확인하는 것은 하는 일 자체는 똑같습니다. stat -fc %T /sys/fs/cgroup/ 한 줄입니다. 차이는 그 한 줄을 새벽에 치느냐 낮에 치느냐죠.
그래서 저는 릴리스 노트의 폐기 목록을 새 소식이 아니라 상환 일정표로 읽습니다. 언제까지 무엇을 갚아야 하는지 적힌 표입니다.
다음 릴리스 노트를 받았을 때
세 가지만 하면 됩니다.
첫째, 폐기 목록에서 우리가 쓰는 것을 골라냅니다. 안 쓰는 기능의 폐기는 읽을 필요도 없습니다.
둘째, 각 항목의 마감 버전과 우리 클러스터 버전의 거리를 셉니다. 몇 개 릴리스가 남았는지가 곧 남은 시간입니다.
셋째, 이미 지난 마감이 있는지 확인합니다. 있다면 그건 예고가 아니라 이미 밟은 지뢰입니다. 다음 업그레이드 때 터집니다.
참고로 이번 릴리스에는 반가운 소식도 하나 있습니다. Metrics API가 9년 만에 베타를 벗고 정식 v1이 됐습니다. CPU와 메모리 사용량을 주는 그 API입니다. 9년입니다.
이 글이 도움이 되셨나요?
버튼 하나가 다음 글을 쓰는 힘이 됩니다