Proxmox Cluster와 K8s
Table Of Contents
Proxmox Cluster와 K8s
서론
예전부터 Proxmox 홈서버를 관리하면서 노드들을 클러스터링하여 사용했다. Proxmox 클러스터는 몇 가지 장점이 있고 그건 충분이 홈서버 관리 측면에서 쓸만한 기능들이었다.
그러나 얼마 전 Proxmox 클러스터와 관련해 좀 당황스러운 경험을 했고 그 후 하이퍼바이저 레벨의 클러스터링은 하지 않기로 결정하였다. 이전 글에서는 VM 위에 k8s 노드를 올리는 이야기를 했으니, 이번엔 왜 그 VM들이 올라가는 하이퍼바이저를 모두 따로 구성하게 되었는지 소개하고자 한다.
문제 발생
회사 워크샵 전날 밤, Proxmox 클러스터가 깨지는 일이 발생했다. 갑작스레 노드끼리 통신이 안되어 쿼럼 달성이 안되고 때문에 일부 vm들이 뜨지 못하고 있었다. 그 VM들은 k8s 노드였고 k8s 위에 올라가 있던 스터디 팀 위키, Gitea, Harbor 등이 올바르게 뜨지 못하고 있었다. 실패한 노드가 아닌 정상 노드에서 파드들을 스케줄링하려 했지만 노드 자원 부족으로 그러지 못하고 있었다.
다행히 중요한 데이터는 nfs로 연결된 NAS에 있었지만 statefulset으로 구성된 앱 DB 데이터들은 longhorn으로 노드 자체 저장공간에 있었으니, 실패한 노드에 있던 정보는 접근 불가능했다.
물리 서버들을 하나 씩 꺼보며 점검한 결과, 한 서버가 클러스터 전체에 영향을 미치고 있다는 사실을 알게 되었다. 그 서버를 끄면 Proxmox 클러스터가 정상 작동했으니, 그 노드가 PVE 공유 스토리지에 무언가 독을 풀고 있음이었다.
대처
해당 물리 서버는 가장 많은 자원을 갖고 있는 사실 상 유일한 서버였고, 다른 서버들은 n150 저사양 서버였다. 다른 서버에는 간신히 control plane VM만 있었던 것이다. 클러스터에 접속할 수 없으니 VM 마이그레이션도 불가능했고, 쿼럼이 충족이 안되니 백업, 복원도 불가능했다. 결국 서버 초기화 및 재배포 외에 답이 없었다.
워크샵 기간 동안은 매우 바빴기 때문에 서버를 관리할 시간이 없었고, 결국 위키와 내 서비스들은 며칠 간 다운타임을 맞Proxmox이할 수 밖에 없었다.
점검
워크샵에서 돌아오고 내 홈서버 클러스터 아키텍처에 대해 다시 생각해보았다. Proxmox 클러스터링은 관리 편의성, VM 마이그레이션, 공유 스토리지 사용 등의 이유로 설정해오고 있었는데, 이번 경험을 통해 단 한 개의 노드 실패로 인해 전체 클러스터가 깨질 수 있음을 알았다. 본디 Proxmox 정족수는 일부 노드의 실패가 전체 클러스터의 실패로 이어지지 않기 위한 기능이었지만, 한 노드가 공유 스토리지를 오염시키면 전체 클러스터가 깨진다. 오히려 실패 지점을 늘려버린 것이다.
그래서 Proxmox 클러스터링의 장점을 한 번 생각해보았다.
HA
대표적인 장점이다. 한 노드에서 VM이 죽었을 때 HA가 설정되어 있고 ceph 같은 고성능 공유 스토리지에 배포되어 있었다면, 다른 살아있는 노드에서 그 VM이 뜨도록 할 수 있는 기능이다. k8s에서의 HA와 비교하면, k8s는 파드 단위이고 Proxmox는 VM, LXC 단위라는 것이 다르다.
그러나 나는 네트워크 전체가 1Gbps라 ceph를 구성하지도 않았고 HA를 설정한 VM도 없었다. 오히려 HA가 필요한 서비스들은 k8s 위에 이미 있던지 아니면 HAProxy/keepalived 처럼 애플리케이션 레벨에서 동작하고 있었다.
VM 라이브 마이그레이션
클러스터링 시 VM이나 LXC를 다른 노드로 옮기거나 복사할 수 있다. VM을 돌리는 노드의 자원을 효율적으로 사용하기 위해서는 자주 VM을 다른 여유로운 노드로 옮기곤 한다. 아니면 부품 업그레이드 같이 한 노드를 껐다 켜야하는 일이 발생하면 그 노드에서 돌던 VM, LXC들을 다른 노드로 옮기고 진행하기도 한다.
확실히 이 기능은 나에게 중요한 기능이다. 홈서버 환경은 노드 자원이 충분하지 않고 자주 노드를 끄곤 한다. 그러나 리버스 프록시나 로드벨런서 같은 VM들은 이와 상관 없이 동작해야 한다. VM 마이그레이션은 그 상황에서 좋은 돌파구를 마련해주었다.
공유 스토리지
클러스터에 연결한 스토리지의 옵션을 켜면 연결된 노드가 살아있는 한 다른 노드도 사용할 수 있는 공유 스토리지로 사용할 수 있다.
그러나 나는 노드들이 1Gbps로 연결되어 있어 빠른 공유 스토리지 이용이 불가능하고, 대용량 NAS 스토리지가 이미 있으니 굳이 이걸 쓸 필요가 없었다. 심지어 그 공유 스토리지가 있는 노드가 죽으면 다른 노드가 접근할 수 없으므로 공유는 가능하지만 가용성이 바닥인 느린 스토리지에 불과했다.
관리 콘솔 통합
클러스터링을 하면 클러스터 중 노드 하나의 WebUI에서 다른 모든 노드들을 관리할 수 있다. 접속한 노드가 목표 노드에 대한 비밀키를 알고 있고 그걸 사용해 명령을 내리는 것이다. 생각보다 유용한 기능이지만, 없다고 또 사용 불가능하지도 않은 기능이긴 하다.
Proxmox Datacenter Manager
그럼 이제 클러스터링이 꼭 내게 필요한지 생각해봐야 한다. 위 내용에 의하면 클러스터링의 가장 큰 장점인 HA는 아예 사용하지 않고, 그나마 VM 마이그레이션이 좀 중요한 정도였다. 다른 방법들을 찾아보던 중, 최근 1.0으로 출시한 Proxmox Datacenter Manager를 알게 되었다.
이 솔루션은 별도의 물리 서버에 설치해 여러 클러스터나 PVE 노드에 연결하여 관리할 수 있다. 기존 PVE 클러스터의 모든 기능을 제공하진 않지만, VM 라이브 마이그레이션, 액세스 제어, 메트릭 확인 등을 할 수 있다.
관리 문서를 살펴보며 이게 정말 내게 필요한 방법이라고 생각했다. 어차피 이번에 고성능 서버들이 생겼으니 Proxmox는 거기에만 설치하고, 기존 저사양 서버에 이걸 설치하면 딱이라고 느꼈다. 결론적으로 설치해서 잘 연결해 쓰고 있고, VM 마이그레이션도 쉽고 빠르게 동작하는걸 확인했다.
Proxmox 클러스터링에 대해
과연 Proxmox 수준의 클러스터링이 필요한지 많은 생각을 하게 되었다. 경험했듯 특정 노드가 클러스터를 깨지게 만들기도 하고, Proxmox Datacenter Manager도 나온 마당에 굳이 hypervisor 단위 클러스터의 필요성에 의문을 가지게 되었다. 많은 해외 포럼들에서 HA를 핵심적인 기능으로 소개하고 있고 나도 그게 PVE 클러스터의 중요한 기능이라고 생각한다.
그렇지만 HA라는게 굳이 VM 단위로 보장되어야만 하는건 아니라고 생각한다. 컨테이너 단위라면 k8s로 달성할 수 있고, 네트워크 서비스의 HA는 이미 관련 서비스들이 HA를 고려해 설계되었다. 내 컨트롤 플레인들에 트래픽을 전달하는 HAProxy와 keepalived를 예로 들 수 있을 것 같다. 이들은 서로 다른 물리 서버에 위치해 있고 한 놈이 죽으면 다른 놈이 VIP를 이어받아 트래픽을 라우팅한다. 이렇게 HA는 VM위에 올라간 다른 솔루션으로 충분히 달성할 수 있다는게 내 결론이었다.
특히 서버 위에 올라간 핵심 서비스들이 k8s 위에 올라간 지금, VM에 굳이 높은 가용성이 필요하진 않다. 몇몇 VM, 심지어 한 물리 서버가 죽어도 파드 뿐만 아니라 PV까지(longhorn을 쓰고 있다) 모두 가용성을 유지할 수 있다. 그러니 Proxmox 클러스터링은 굳이 필요없는 복잡성을 인프라에 추가하는 꼴 뿐이었다.
결론
워크샵 기간 동안 클러스터 생각이 계속 났다. 내 친구들도 내 서버에 접속해 게임을 하거나 다른 서비스들을 쓰고 있었으니 일종의 ‘고객’에게 가용성을 보장해주지 못하는 상황이었기 때문이다. 그 후 얻은 결론은 k8s 클러스터든 Proxmox 클러스터든 클러스터는 단 하나의 레이어만 만들어 놓는게 이상적이라는 것이다. 클러스터 레이어가 여러 개가 되면 하위 클러스터의 문제가 상위 클러스터로 고스란히 전파되는 상황이 벌어지기 때문이다.
또한 한 가지 변화가 있었는데 지금까지는 순수한 k8s 클러스터를 VM들 위에 올렸었는데, dev, prod, argocd라는 클러스터 3개를 구성했더니 98GB에 달하는 경이로운 메모리 사용량을 보였기 때문에, 이 참에 k3s로 노드 스택을 변경했다. kubeadm으로도 충분히 쉽게 클러스터 초기화가 가능했지만 k3s를 사용하니 containerd나 runc, CNI 같은 컴포넌트를 알아서 설치해줘서 굉장히 편했다. 메모리 사용량도 일부 줄어들었지만, 사실 크게 달라진 것 같진 않았고(ㅠ) 그냥 다른 노드들에도 k8s VM을 올려 더욱 분산하는 선에서 만족하기로 했다.
앞으로도 할 일이 많이 남아있다. Prometheus로 메트릭들을 수집해 게임서버가 죽었을 때 디스코드 알림이 가도록 세팅도 해보고 싶고, 리버스프록시의 HA도 구성해야 한다. 관련 진행상황도 공유할 수 있으면 좋겠다.