K3s 기반 Kubernetes 3노드 HA 환경에서 노드 한 대를 중지하고 Pod의 복구 과정을 검증했습니다. local-path 볼륨을 사용하는 Pod는 노드 종속성 때문에 Pending 상태에 머물렀고, 공유 스토리지로 전환한 최종 구성에서는 다른 노드에서 약 81초 만에 Ready 상태가 되었습니다. 이 글에서는 해당 결과를 바탕으로 HA 구성 시 함께 고려해야 할 스토리지 조건과 Failover 검증 항목을 정리합니다.
검증 배경과 환경
XGEN 운영 환경에서 노드 중지 후 Pod가 다른 노드에서 실행되지 않고 Pending 상태에 머무르는 문제가 있었습니다. 이와 같은 현상이 어떤 조건에서 발생하는지 확인하기 위해 AWS에 별도의 검증 환경을 구성했습니다.
검증의 핵심은 노드 한 대가 중지되었을 때, 남은 노드에서 기존 데이터를 사용하며 Pod가 다시 실행되는지였습니다. 운영 데이터를 사용하는 대신 시험용 파일을 준비하고, 노드 중지 전후의 배치 상태와 데이터 보존 여부를 확인했습니다.
| 구성 항목 | 시험 조건 |
|---|---|
| 운영체제 | Rocky Linux 9.8 |
| Kubernetes 배포판 | K3s v1.29.3+k3s1 |
| 클러스터 구성 | embedded etcd 기반 서버 노드 3대 |
| 워크로드 배치 | 서버 노드에서 시험용 Pod 실행 |
| 초기 스토리지 | 특정 노드에 종속된 local-path PV |
| 전환 스토리지 | 별도 NFS 서버의 공유 경로 |
| 장애 유발 방식 | EC2 인스턴스 정상 Stop/Start |
K3s 버전은 운영 환경의 조건을 맞추기 위해 선택했습니다. 신규 구축을 위한 권장 버전이 아닌, 이번 재현 시험에 사용한 버전입니다.
3노드 HA 구성과 스토리지의 관계
K3s의 embedded etcd 기반 HA 구성에서는 서버 노드들이 Kubernetes API와 컨트롤 플레인, etcd를 실행합니다.
etcd는 클러스터 상태를 관리하는 저장소로, 상태 변경에 합의하려면 구성원 중 과반수가 필요합니다. 이를 정족수(quorum)라고 합니다. 세 대로 구성하면 한 대가 중지되어도 나머지 두 대로 정족수를 유지할 수 있습니다. K3s HA 구성 문서
하지만 애플리케이션이 PV에 저장한 파일까지 etcd가 복제해주는 것은 아닙니다. 클러스터가 Pod를 관리할 수 있는 상태여도, 데이터를 사용할 수 있는 노드가 사라지면 해당 Pod의 복구는 막힐 수 있습니다.
이번에는 클러스터 관리 기능의 가용성과 애플리케이션 데이터의 접근성을 구분해 확인했습니다.
K3s 클러스터
├─ node1: Control Plane + etcd + 워크로드
├─ node2: Control Plane + etcd + 워크로드
└─ node3: Control Plane + etcd + 워크로드
초기 시험
└─ Pod → PVC → node1의 로컬 저장소
전환 시험
└─ Pod → PVC → NFS 공유 저장소
└─ node1, node2, node3에서 접근
local-path 볼륨을 사용하는 노드 중지
첫 번째 시험에서는 node1의 local-path PV를 사용하는 Pod를 준비했습니다. 다른 노드에는 충분한 자원을 남겨두었고, Pod 자체에는 특정 노드를 지정하는 nodeSelector를 설정하지 않았습니다.
이 상태에서 node1을 중지하자 Pod는 Pending 상태에 머물렀습니다.
원인은 PV에 설정된 nodeAffinity였습니다. 시험에 사용한 PV는 node1에 종속되어 있었고, 실제 데이터도 해당 노드의 로컬 디스크에 저장되어 있었습니다. Kubernetes는 Pod를 배치할 때 연결된 PV의 노드 affinity도 고려하므로, 다른 노드에 여유 자원이 있다는 것만으로는 배치 조건을 충족할 수 없었습니다. Kubernetes PV의 Node Affinity 문서
Pod
└─ PVC
└─ local-path PV
├─ 데이터 위치: node1 로컬 디스크
└─ nodeAffinity: node1
진단 과정에서는 이벤트 메시지만으로 원인을 판단하기 어려웠습니다. 이번 버전과 시험 조건에서는 volume node affinity conflict라는 문구가 직접 표시되지 않았고, 도달 불가능한 노드와 선점으로 해결할 수 없다는 내용이 나타났습니다.
따라서 Pod의 이벤트와 함께 PVC가 연결된 PV의 설정까지 확인해야 했습니다.
kubectl get pods -n <namespace> -o wide
kubectl describe pod <pod-name> -n <namespace>
kubectl get pvc <pvc-name> -n <namespace> -o yaml
kubectl get pv <pv-name> -o yaml
이 시험을 통해 local-path PV의 노드 종속성이 있는 조건에서 유사한 Pending 현상을 재현했습니다. 다만 운영 환경의 원인을 확정하려면 해당 환경의 실제 PV와 스케줄링 조건을 별도로 확인해야 합니다.
공유 스토리지 전환과 재시험
다음 시험에서는 데이터를 NFS 기반 공유 스토리지로 옮겼습니다. Pod가 다른 노드에 배치되어도 동일한 데이터에 접근할 수 있도록 구성했습니다.
먼저 정적 NFS PV와 PVC를 생성하고 시험용 데이터를 복사했습니다. 이후 Pod가 신규 PVC를 사용하도록 변경한 뒤 node1을 다시 중지했습니다.
이번에는 node2에서 Pod가 Ready 상태가 되었으며, 기존 파일의 체크섬과 새로운 파일 쓰기, HTTP 응답을 확인할 수 있었습니다.
전환 과정에서 주의한 점은 공유 경로를 준비하는 작업과 기존 PV를 전환하는 작업이 별개라는 것입니다. 모든 노드에서 같은 NAS 경로에 접근할 수 있게 만들어도 기존 PV의 노드 affinity는 그대로 남아 있었습니다.
이번 시험에서는 신규 PV와 PVC를 준비하고 데이터를 이관한 뒤, Pod의 볼륨 참조를 변경하는 방식으로 진행했습니다.
기존 구성
Pod → 기존 PVC → node1 로컬 디스크
변경 구성
Pod → 신규 PVC → NFS 공유 저장소
검증 대상은 일반 파일을 사용하는 시험용 워크로드였습니다. 데이터베이스의 복제나 동시 쓰기, 장애 후 일관성은 이번 시험에 포함하지 않았습니다.
노드 재시작 후 발견한 설정 원복
정적 NFS PV로 동작을 확인한 뒤에는 PVC 생성 시 공유 경로를 사용하도록 local-path-provisioner의 sharedFileSystemPath 설정도 시험했습니다.
이 구성에서 새로 생성한 PV에는 노드 affinity가 없었고, 노드 중지 후에도 다른 노드에서 데이터를 사용하며 Pod가 실행되었습니다.
하지만 node1을 다시 시작하자 수정했던 기본 local-path-config 설정이 원래 값으로 돌아왔습니다.
K3s는 기본 구성요소를 AddOn으로 관리하며, 패키지에 포함된 매니페스트를 시작 시 다시 작성합니다. 이번 환경에서는 기본 local-path 설정을 직접 변경한 내용이 이 관리 과정에서 원복되었습니다. K3s 기본 구성요소 관리 문서
이미 생성된 PV가 정상적으로 동작하더라도, 이후 생성하는 PVC까지 같은 경로를 사용한다고 볼 수는 없었습니다.
이를 해결하기 위해 NAS용 provisioner를 별도로 배포했습니다. 전용 ConfigMap, provisioner 식별자, StorageClass를 사용해 기본 local-path 구성과 분리했습니다.
수정 후에는 노드를 다시 시작하고 다음 두 가지를 확인했습니다.
- 전용 provisioner의 설정이 유지되는지
- 새 PVC를 생성했을 때 NAS 경로를 사용하는 PV가 만들어지는지
Failover 이후의 Pod 상태뿐 아니라, 복구 이후에도 구성이 유지되는지까지 확인하는 과정이 필요했습니다.
Failover 테스트 결과와 검증 범위
최종 구성에서 node1을 중지한 뒤 node3의 시험용 Pod가 Ready 상태가 되기까지 약 81초가 걸렸습니다.
| 검증 항목 | 결과 |
|---|---|
| 남은 노드에서 Pod가 Ready 상태로 전환 | 확인 |
| 기존 파일의 체크섬 일치 | 확인 |
| 재배치 후 새로운 데이터 쓰기 | 확인 |
| NodePort를 통한 HTTP 응답 | 확인 |
| 원래 노드 복귀 후 활성 시험용 Pod 1개 유지 | 확인 |
| 장애 이후 기록한 데이터 보존 | 확인 |
| 재시작 후 신규 PVC의 NAS 경로 사용 | 확인 |
약 81초는 이번 시험 조건에서 관찰한 값입니다. 시험용 Pod의 NoExecute toleration은 30초로 설정했으며, 이 시간을 운영 서비스의 복구 목표 시간으로 그대로 적용할 수는 없습니다. Pod의 Ready 전환 시간과 사용자가 체감하는 서비스 중단 시간도 구분해야 합니다.
또한 이번 시험에는 다음과 같은 범위 제한이 있습니다.
- EC2 정상 Stop/Start를 사용했으며, 갑작스러운 전원 상실이나 네트워크 단절은 시험하지 않았습니다.
- NFS 서버는 한 대였으므로 공유 스토리지 자체의 HA는 검증하지 않았습니다.
- 일반 파일 기반 시험으로, 데이터베이스의 Failover와 데이터 일관성을 검증하지 않았습니다.
- 외부 진입점의 자동 전환을 포함한 전체 서비스 경로의 가용성은 검증하지 않았습니다.
따라서 이번 결과는 워크로드 노드 중지 후, 다른 노드에서 공유 데이터로 Pod를 재실행할 수 있음을 확인한 결과로 해석해야 합니다.
HA 구성에서 확인해야 할 조건
이번 검증에서는 노드 수만으로 확인하기 어려운 조건들이 드러났습니다. local-path PV를 사용하는 상태에서는 데이터의 노드 종속성이 Pod 재배치를 막았고, 공유 스토리지로 전환한 뒤에는 노드 재시작에 따른 설정 원복 문제가 나타났습니다.
이를 통해 HA 구성을 점검할 때는 클러스터 상태 관리, 워크로드 배치, 데이터 접근, 복구 후 설정 유지까지 연결해서 확인해야 한다는 점을 배웠습니다.
후속 검증에서는 공유 스토리지 자체의 장애와 외부 요청 경로, 데이터베이스별 복구 동작을 다룰 필요가 있습니다. 이번에 확인한 조건과 남은 범위를 구분해두면, 운영 환경에서 어떤 장애까지 대응할 수 있는지 더 구체적으로 설명할 수 있을 것입니다.

