Certified Kubernetes Administrator (CKA) #7 etcd 백업과 복구: etcdctl snapshot save/restore

쿠버네티스 클러스터의 모든 상태는 한곳에 모입니다. Deployment, Service, Secret, RBAC 규칙, 네임스페이스, 노드 정보까지 클러스터가 기억하는 것 전부가 etcd라는 키값 저장소에 들어 있습니다. apiserver는 사실상 etcd 앞에 놓인 문지기일 뿐이고, 진짜 데이터는 etcd가 쥐고 있습니다. 그래서 etcd가 날아가면 클러스터의 기억 전체가 날아갑니다.

이 사실 때문에 etcd 백업과 복구는 CKA 실기에서 거의 단골로 나옵니다. 채점 포인트가 명확하고 명령 한두 줄의 정확성으로 점수가 갈리는 작업이라, 손에 익혀 두면 확실한 점수원입니다. 반대로 인증서 플래그 하나를 빠뜨리거나 복원 뒤 data-dir 반영을 깜빡하면 통째로 틀립니다. 이번 글에서는 etcdctl snapshot save로 스냅샷을 뜨고 snapshot restore로 되살리는 전 과정을, 함정까지 짚어 정리하겠습니다.

etcd는 어디에 떠 있는가 #

kubeadm으로 세운 클러스터에서 etcd는 control plane 노드 위의 static Pod로 돕니다. static Pod는 kubelet이 디스크의 매니페스트 디렉터리를 직접 감시하며 띄우는 Pod로, apiserver를 거치지 않습니다. etcd의 매니페스트는 다음 위치에 있습니다.

/etc/kubernetes/manifests/etcd.yaml

백업과 복구에 필요한 정보는 모두 이 파일 안에 적혀 있습니다. 외워서 넣는 것이 아니라 매번 이 파일에서 읽어 와야 실수가 없습니다. 다음 세 가지를 찾습니다.

  • --data-dir: etcd가 실제 데이터를 쓰는 디렉터리. 보통 /var/lib/etcd
  • 인증서 경로 세 개: --trusted-ca-file(cacert), --cert-file(cert), --key-file(key)
  • endpoint: etcd가 듣는 주소. 보통 https://127.0.0.1:2379

매니페스트에서 해당 줄만 뽑아 보겠습니다.

grep -E 'data-dir|cert-file|key-file|trusted-ca-file|listen-client-urls' \
  /etc/kubernetes/manifests/etcd.yaml

대략 다음처럼 나옵니다.

    - --data-dir=/var/lib/etcd
    - --cert-file=/etc/kubernetes/pki/etcd/server.crt
    - --key-file=/etc/kubernetes/pki/etcd/server.key
    - --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
    - --listen-client-urls=https://127.0.0.1:2379,https://10.0.0.10:2379

여기서 백업 명령에 들어갈 값이 그대로 결정됩니다. 인증서 경로는 클러스터마다 다를 수 있으므로, 시험장에서 외운 경로를 그대로 쓰지 말고 이 파일에서 확인하는 습관이 안전합니다.

etcdctl 준비 #

명령은 etcdctl로 실행합니다. etcd v3 API를 써야 하므로 환경 변수 ETCDCTL_API=3을 반드시 설정합니다. 최신 버전에서는 v3가 기본이지만, 시험 환경의 버전에 따라 v2로 동작해 명령이 통째로 실패할 수 있으므로 명시하는 편이 안전합니다.

export ETCDCTL_API=3

# etcdctl이 보이는지, 버전 확인
etcdctl version

etcdctl이 없으면 etcd 컨테이너 안에서 실행하거나 패키지로 설치합니다. kubeadm 클러스터의 control plane 노드에는 대개 이미 들어 있습니다.

1단계: 스냅샷 저장 (snapshot save) #

이제 스냅샷을 뜹니다. endpoint와 인증서 세 개를 모두 넘겨야 합니다. 하나라도 빠지면 인증 실패로 명령이 떨어지지 않습니다.

ETCDCTL_API=3 etcdctl snapshot save /opt/snapshot.db \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key

플래그 이름의 대응 관계를 헷갈리지 않아야 합니다. 매니페스트의 --trusted-ca-file이 etcdctl의 --cacert, --cert-file--cert, --key-file--key입니다. 매니페스트 쪽은 etcd 서버가 쓰는 플래그이고, etcdctl 쪽은 클라이언트가 쓰는 플래그라 이름이 다릅니다.

저장이 끝나면 Snapshot saved at /opt/snapshot.db가 출력됩니다. 스냅샷이 제대로 떠졌는지 확인합니다.

ETCDCTL_API=3 etcdctl snapshot status /opt/snapshot.db --write-out=table

다음처럼 해시,키 개수,DB 크기가 표로 나오면 정상입니다.

+----------+----------+------------+------------+
|   HASH   | REVISION | TOTAL KEYS | TOTAL SIZE |
+----------+----------+------------+------------+
| fe01cf57 |    24390 |       1287 |     5.4 MB |
+----------+----------+------------+------------+

snapshot status는 인증서가 필요 없습니다. 이미 떠 둔 파일을 읽기만 하기 때문입니다. 반대로 snapshot save는 살아 있는 etcd에 접속해 데이터를 받아 오므로 endpoint와 인증서가 모두 필요합니다.

2단계: 스냅샷 복원 (snapshot restore) #

복구는 떠 둔 스냅샷 파일에서 새로운 data-dir로 데이터를 풀어내는 작업입니다. 기존 data-dir에 덮어쓰지 않고 별도 디렉터리에 복원한 뒤, etcd가 그 디렉터리를 보도록 매니페스트를 바꾸는 방식이 안전합니다.

ETCDCTL_API=3 etcdctl snapshot restore /opt/snapshot.db \
  --data-dir=/var/lib/etcd-restore

여기서 중요한 점이 있습니다. snapshot restore는 살아 있는 etcd에 접속하지 않고 파일에서 로컬 디렉터리로 데이터를 푸는 오프라인 작업입니다. 그래서 --endpoints나 인증서 플래그가 필요 없습니다. 시험에서 습관적으로 인증서를 붙이는 사람이 있는데, restore에는 무해하지만 본질적으로 불필요합니다. 정작 필요한 것은 --data-dir 하나입니다.

명령이 끝나면 /var/lib/etcd-restore 안에 member 디렉터리가 생기고, 그 안에 복원된 etcd 데이터가 들어갑니다.

3단계: etcd가 복원된 디렉터리를 보게 한다 #

복원만 한다고 클러스터가 돌아오지 않습니다. 살아 있는 etcd는 여전히 옛 data-dir(/var/lib/etcd)을 보고 있기 때문입니다. etcd static Pod가 새 디렉터리를 바라보도록 매니페스트를 고쳐야 합니다. 고칠 곳은 두 군데입니다.

먼저 /etc/kubernetes/manifests/etcd.yaml을 엽니다. data-dir은 컨테이너 인자와 hostPath 볼륨 두 곳에 나타납니다.

컨테이너 인자의 --data-dir은 그대로 둬도 됩니다. 이 값은 컨테이너 내부 경로이기 때문입니다. 실제로 바꿀 곳은 호스트 디렉터리를 컨테이너에 마운트하는 volume의 hostPath입니다.

  volumes:
  - hostPath:
      path: /var/lib/etcd-restore   # 기존 /var/lib/etcd에서 변경
      type: DirectoryOrCreate
    name: etcd-data

name: etcd-data 볼륨이 컨테이너 안에서 --data-dir이 가리키는 경로(/var/lib/etcd)에 마운트됩니다. 따라서 hostPath만 복원 디렉터리로 바꾸면, 컨테이너 안의 etcd는 같은 경로(/var/lib/etcd)에서 데이터를 보지만 호스트 입장에서는 복원된 디렉터리를 읽게 됩니다. volumeMounts의 mountPath와 컨테이너 인자 --data-dir은 손대지 않는 것이 가장 단순한 방법입니다.

4단계: etcd 재기동과 확인 #

매니페스트를 저장하면 kubelet이 변경을 감지해 etcd Pod를 재생성합니다. static Pod이므로 kubectl apply 같은 명령이 필요 없습니다. 파일을 고치는 것만으로 kubelet이 옛 컨테이너를 죽이고 새 인자로 다시 띄웁니다.

매니페스트를 저장하면 kubelet이 잠시 뒤 새 etcd를 올립니다. 반영이 느리면 매니페스트를 디렉터리 밖으로 잠깐 옮겼다가 다시 넣어 강제로 재로딩할 수 있습니다.

# 강제 재로딩이 필요할 때
mv /etc/kubernetes/manifests/etcd.yaml /tmp/etcd.yaml
# 잠시 뒤
mv /tmp/etcd.yaml /etc/kubernetes/manifests/etcd.yaml

etcd가 새 데이터로 떠 오르면 apiserver가 다시 etcd에 붙고, 클러스터 상태가 스냅샷 시점으로 돌아옵니다. 컨테이너가 떠 있는지, apiserver가 응답하는지 확인합니다.

# crictl로 etcd 컨테이너 상태
crictl ps | grep etcd

# kubelet 로그로 재기동 추적
journalctl -u kubelet -f

# apiserver가 돌아왔으면 클러스터가 응답한다
kubectl get nodes
kubectl get pods -A

kubectl get 명령이 스냅샷 시점의 리소스를 보여 주면 복구가 끝난 것입니다.

외부 etcd인 경우 #

여기까지는 #4에서 다룬 stacked etcd(etcd가 control plane 노드의 static Pod로 도는 구성)를 전제로 했습니다. #5외부 etcd cluster는 차이가 있습니다. etcd가 별도 노드에서 systemd 서비스로 돌기 때문에, 매니페스트 수정이 아니라 systemctl stop etcd 〜 복원 〜 etcd 설정 파일의 data-dir 변경 〜 systemctl start etcd 흐름으로 진행하며, save/restore 명령 자체는 동일합니다.

함정 #

CKA 실기에서 이 작업을 틀리는 패턴은 거의 정해져 있습니다.

  • ETCDCTL_API=3 누락: v2로 동작하면 snapshot 하위 명령 자체가 다르게 해석되어 실패합니다. 명령 맨 앞에 ETCDCTL_API=3을 붙이거나 export로 고정합니다.
  • 인증서 플래그 누락: snapshot save는 endpoint와 cacert/cert/key 세 인증서를 모두 요구합니다. 하나만 빠져도 인증 실패로 떨어집니다. 경로는 외우지 말고 매니페스트에서 확인합니다.
  • restore에 인증서를 넣으려 함: 반대로 snapshot restore는 파일 기반 오프라인 작업이라 endpoint,인증서가 필요 없습니다. 정작 필요한 --data-dir을 빠뜨리지 않는 것이 핵심입니다.
  • restore 후 data-dir 반영 안 함: 가장 흔한 실수입니다. 복원만 하고 매니페스트의 hostPath를 새 디렉터리로 바꾸지 않으면, etcd는 옛 데이터를 계속 보므로 클러스터가 복구되지 않습니다.
  • 플래그 이름 혼동: 서버 쪽 --trusted-ca-file/--cert-file/--key-file과 클라이언트 쪽 --cacert/--cert/--key를 섞어 씁니다. etcdctl에는 클라이언트 이름을 씁니다.
  • 저장 경로 확인 안 함: 문제가 지정한 스냅샷 경로(예: /opt/snapshot.db)와 다른 곳에 저장하면 채점에서 빠집니다. snapshot status로 떠진 파일을 확인합니다.

시험 포인트 #

  • etcd 백업,복구는 CKA 단골 출제 항목이며, 명령의 정확성으로 점수가 갈립니다.
  • 백업: ETCDCTL_API=3 etcdctl snapshot save <파일> --endpoints --cacert --cert --key. 모든 인증서를 매니페스트에서 확인해 넣습니다.
  • 복원: ETCDCTL_API=3 etcdctl snapshot restore <파일> --data-dir=<새 디렉터리>. endpoint,인증서 불필요, --data-dir 필수입니다.
  • 복원 뒤 /etc/kubernetes/manifests/etcd.yaml의 hostPath를 새 data-dir로 바꿔야 kubelet이 etcd를 새 데이터로 재기동합니다.
  • snapshot status --write-out=table로 떠진 스냅샷의 무결성을 확인합니다.
  • 외부 etcd는 매니페스트 대신 systemd로 stop/start하며, save/restore 명령은 같습니다.

정리 #

이번 글에서 잡은 것:

  • etcd는 클러스터 상태의 단일 저장소. etcd 백업이 곧 클러스터 백업입니다.
  • 백업 3요소: ETCDCTL_API=3, endpoint(https://127.0.0.1:2379), 인증서 세 개. 경로는 /etc/kubernetes/manifests/etcd.yaml에서 읽어 옵니다.
  • 복구 흐름: snapshot restore로 새 data-dir에 복원 → 매니페스트 hostPath 변경 → kubelet이 etcd 재기동 → apiserver 복구.
  • 함정: API 버전 누락, 인증서 플래그 누락, restore 후 data-dir 미반영.

이제 etcd를 잃어도 스냅샷 한 개면 클러스터를 시점 복구할 수 있습니다. 백업의 짝은 인증서입니다. etcd 데이터가 살아 있어도 인증서가 만료되면 apiserver와 etcd가 서로를 믿지 못해 통신이 끊깁니다.

다음: 인증서 관리 #

#8 인증서 관리: PKI, kubeconfig, 인증서 갱신에서는 kubeadm이 만들어 두는 PKI 구조(ca.crt를 정점으로 한 인증서 체인), kubeconfig 파일이 어떻게 인증 정보를 담는지, 그리고 만료된 인증서를 kubeadm certs renew로 갱신하는 절차를 정리하겠습니다. CKA 트러블슈팅에서 인증서 만료는 apiserver가 통째로 죽는 원인으로 자주 등장하므로, 만료 여부를 확인하고 되살리는 감각을 손에 익히겠습니다.

X