LabHub
배우기 러닝패스 코스

쿠버네티스 배포판 — 직접 세운다 · k3s 저장소와 스냅숏 · 이론

k3s 의 저장소는 SQLite 로 시작한다

LabHub 에서 이어서 보기

한 줄 요약

k3s 서버 한 대는 기본으로 SQLite 를 kine 을 거쳐 쓰므로 etcd 스냅숏이 동작하지 않고, --cluster-init 으로 재시작하면 데이터를 보존한 채 내장 etcd 로 옮겨지며, etcd 스냅숏 복원은 서버 토큰이 있어야 쓸 수 있고 스냅숏 이후의 변경을 모두 되돌립니다.

왜 이게 필요했나

쿠버네티스 API 서버는 etcd 에 상태를 저장하도록 만들어졌습니다. 그런데 etcd 는 쿼럼을 위해 여러 대를 전제로 설계된 분산 저장소라, 라즈베리 파이 한 대나 CI 에서 잠깐 쓰는 클러스터에는 무겁습니다.
k3s 는 이 간극을 kine 으로 메웁니다. kine 은 etcd API 를 흉내 내는 얇은 계층이고, 뒤에 SQLite·MySQL·PostgreSQL 같은 일반 데이터베이스를 둡니다. 실측으로 로그를 보면 API 서버가 --etcd-servers=unix://kine.sock 로 떠 있고, k3s 가 Kine available at unix://kine.sock 을 먼저 알립니다.
공식 문서는 SQLite 가 다른 저장소 설정이 없고 디스크에 내장 etcd 데이터도 없을 때 쓰이는 기본값이며, 서버가 여러 대인 클러스터에서는 쓸 수 없다고 적습니다.

문제는 이 기본값이 조용하다는 것입니다. 클러스터는 멀쩡히 돌고, 백업을 붙이려는 날에야 드러납니다.

$ k3s etcd-snapshot savelevel=fatal msg="Error: see server log for details: etcd datastore disabled"

실측 출력입니다. 서버 로그에는 같은 문구가 HTTP 400 응답으로 남습니다. 스냅숏 명령이 k3s 서버에 요청을 보내고, 서버가 "나는 etcd 를 쓰지 않는다" 고 거절한 것입니다.

어떻게 동작하나

SQLite 일 때의 백업은 특별한 명령이 없습니다. 문서대로 /var/lib/rancher/k3s/server/db/ 를 복사하고, 복원할 때 그 내용을 되돌려 놓습니다. 여기에 반드시 서버 토큰 파일 /var/lib/rancher/k3s/server/token 을 함께 보관합니다. 토큰이 저장소 안의 기밀 데이터를 암호화하는 데 쓰이기 때문에, 다른 토큰으로 복원하면 백업을 쓸 수 없습니다.

etcd 로 옮기기는 SQLite 로 돌던 서버를 --cluster-init 으로 다시 기동하는 것이 전부입니다. 실측한 결과는 이렇습니다.

config.yaml 에 cluster-init: true → systemctl restart k3s (API 준비 12초)로그     Migrating content from sqlite to etcd디스크   db/state.db → db/state.db.migrated, db/etcd/ 와 db/snapshots/ 생성노드     node-role.kubernetes.io/etcd=true 가 붙음데이터   재시작 전에 만든 ConfigMap 의 UID 가 그대로

반대 방향은 없습니다. 문서는 디스크에서 etcd 데이터가 발견되면 --cluster-init·--server·--datastore-endpoint 같은 저장소 인자를 무시한다고 적습니다. 한번 etcd 가 되면 인자를 빼도 SQLite 로 돌아가지 않는다는 뜻입니다.

스냅숏은 정기와 수동 두 가지입니다. 정기 스냅숏은 기본으로 0시와 12시(0 */12 * * *)에 떠서 5개를 보관하고 이름이 etcd-snapshot-<노드>-<시각> 입니다. 수동은 k3s etcd-snapshot save 로 뜨며 보관 개수 제한이 없어 직접 지워야 하고, --name 은 이름의 앞부분만 정합니다. 둘 다 --etcd-snapshot-dir 의 기본값인 데이터 디렉터리 아래 db/snapshots 에 저장되고, 실측 경로는 /var/lib/rancher/k3s/server/db/snapshots/lab-before-<노드>-<유닉스시각> 이었습니다. kubectl get etcdsnapshotfile 은 클러스터 전체의 스냅숏을 객체로 보여 줍니다.

복원은 서비스를 멈추고 같은 바이너리를 한 번 따로 실행합니다.

systemctl stop k3sk3s server --cluster-reset --cluster-reset-restore-path=/var/lib/rancher/k3s/server/db/snapshots/<이름># Managed etcd cluster membership has been reset, restart without --cluster-reset flag now.systemctl start k3s

복원은 현재 etcd 데이터를 지우지 않고 db/etcd-old-<시각> 으로 옮긴 뒤 스냅숏을 풀고, 다른 멤버를 모두 빼고 혼자인 클러스터로 만듭니다. 연속 초기화를 막으려고 db/reset-flag 를 만들고, 정상 기동하면 지웁니다. --cluster-reset-restore-path 없이 --cluster-reset 만 주면 스냅숏 복원 없이 멤버십만 초기화됩니다.

현장에서 만나는 모습

실측에서 스냅숏을 뜬 뒤 ConfigMap 하나를 만들고 다른 하나의 값을 바꾼 다음 복원했습니다. 새로 만든 것은 사라졌고 값은 스냅숏 시점으로 돌아갔습니다. 사라진 객체의 UID 는 etcd-old-<시각> 안의 옛 데이터 파일에 바이트로 남아 있었습니다 — 복원이 옛 데이터를 지우지 않는다는 것이 이렇게 확인됩니다. etcd 멤버 이름(db/etcd/name)도 복원 전과 다른 값으로 새로 붙었습니다.

현장에서 흔한 사고는 두 가지입니다. 하나는 "복원했더니 어제 배포한 것이 없다" 입니다. 복원은 되감기라서, 스냅숏 이후에 누가 무엇을 했는지를 먼저 확인하지 않으면 두 번째 장애가 됩니다. 다른 하나는 새 서버에 스냅숏만 옮겨 복원하려다 실패하는 경우입니다. 문서는 다른 호스트에서 복원할 때 원래 서버의 토큰을 --token 으로 넘겨야 한다고 적습니다. 스냅숏은 오브젝트 스토리지에 있는데 토큰은 사라진 노드 디스크에만 있었다면 그 백업은 쓸 수 없습니다.

실무에서 진짜 중요한 것

다음 실습에서 할 것

VM 안의 k3s 에서 저장소가 SQLite 임을 kine 로그와 테이블로 확인하고, 스냅숏이 거절되는 것을 기록합니다. cluster-init 재시작으로 etcd 로 옮겨 표식 ConfigMap 의 UID 가 남는지 보고, 이름을 붙인 스냅숏을 토큰과 함께 백업한 뒤, 스냅숏 이후의 변경을 만들고 복원해 무엇이 사라지고 어디에 남는지 확인합니다.

참고 문서: [Cluster Datastore](https://docs.k3s.io/datastore) · [High Availability Embedded etcd](https://docs.k3s.io/datastore/ha-embedded) · [etcd-snapshot](https://docs.k3s.io/cli/etcd-snapshot) · [Backup and Restore](https://docs.k3s.io/datastore/backup-restore)