LabHub
学习 学习路径 课程

Kubernetes 发行版 — 自己搭

执行快照命令时才发现数据存储是 SQLite

在 LabHub 中继续学习

한국어 원문으로 표시합니다.

목표

k3s 서버 한 대의 저장소가 SQLite(kine) 임을 확인하고, etcd 스냅숏이 거절되는 이유를 본 뒤 --cluster-init 재시작으로 내장 etcd 로 옮깁니다. 스냅숏을 토큰과 함께 백업하고 --cluster-reset 으로 복원해, 스냅숏 이후의 변경이 사라지고 이전 데이터가 어디에 남는지 기록합니다.

왜 중요한가

k3s 는 한 대로 시작하면 etcd 대신 SQLite 를 씁니다. 가볍고 빠르지만 여러 서버가 공유할 수 없고, k3s etcd-snapshot 같은 etcd 도구가 동작하지 않습니다. 그래서 "백업을 붙이자" 는 날에 처음으로 저장소가 무엇인지 확인하게 되고, 그때 선택지는 파일을 통째로 복사하는 SQLite 백업이거나 etcd 로 옮기는 것입니다. etcd 로 옮기는 것은 재시작 한 번이지만, 복원은 "그 시점으로 되돌리기" 라서 스냅숏 이후에 만든 것은 사라집니다. 그리고 서버 토큰이 없으면 스냅숏은 쓸모가 없습니다. 이 실습은 그 세 가지 — 저장소 확인, 이전, 복원이 되돌리는 범위 — 를 진짜 k3s 에서 한 번씩 겪게 합니다. etcd 를 처음부터 쓰는 k0s 실습과 달리 저장소를 바꾸는 과정 자체를 다룹니다.

단계

  1. 네임스페이스 k3s-ds 에 ConfigMap marker(stage=sqlite)를 만드세요. 그리고 /root/k3s-ds/datastore.jsondatastore(sqlite 또는 etcd), db_files(/var/lib/rancher/k3s/server/db 의 파일 이름을 정렬한 배열), kine_table(state.db 안의 테이블 이름 중 kine 이 쓰는 것), kine_endpoint(k3s 로그의 Kine available at 뒤의 주소), marker_uid(marker 의 UID)를 적으세요.
  2. 지금 상태에서 k3s etcd-snapshot save 를 실행하고 표준 출력과 표준 오류를 함께 /root/k3s-ds/snapshot-refused.txt 에 저장하세요. 그리고 /root/k3s-ds/sqlite-backup.txt 에 SQLite 저장소를 백업하려면 복사해야 하는 디렉터리와 파일의 절대 경로를 한 줄에 하나씩 적으세요.
  3. /etc/rancher/k3s/config.yamlcluster-init: true 를 적고 k3s 를 재시작하세요. marker 가 살아 있는지 확인하고 /root/k3s-ds/migrate.jsonmarker_uid(재시작 뒤 marker 의 UID), sqlite_file_now(db 디렉터리에서 원래 state.db 가 바뀐 이름), node_roles(노드의 node-role.kubernetes.io/ 라벨 이름을 정렬한 배열, 예: ["control-plane"]), member_name(db/etcd/name 파일의 내용)을 적으세요.
  4. marker 의 stagesnapshotted 로 바꾼 다음 k3s etcd-snapshot save --name lab-before 로 스냅숏을 뜨세요. /root/k3s-ds/snapshot.jsonname(만들어진 스냅숏 이름 전체), path(파일 절대 경로), size(바이트, 정수), sha256(파일의 SHA-256)을 적으세요.
  5. /root/k3s-ds/backup/ 디렉터리에 4단계의 스냅숏 파일(같은 이름)과 서버 토큰 파일(token 이라는 이름, 권한 600)을 복사하세요. /root/k3s-ds/token-backup.jsontoken_source(토큰 원본의 절대 경로), token_sha256(토큰 파일의 SHA-256), snapshot_sha256(백업한 스냅숏의 SHA-256)을 적으세요. 토큰 값 자체는 어디에도 적지 않습니다.
  6. 스냅숏 뒤에 네임스페이스 k3s-ds 에 ConfigMap after-snap(x=1)을 만들고 marker 의 stagechanged 로 바꾸세요. /root/k3s-ds/after.jsonafter_uid(after-snap 의 UID), after_created(그 creationTimestamp), marker_stage(지금 marker 의 stage)를 적으세요.
  7. k3s 를 멈추고 k3s server --cluster-reset --cluster-reset-restore-path=<4단계 스냅숏 경로> 로 복원한 뒤(출력 전체를 /root/k3s-ds/reset.log 에 저장) k3s 를 다시 시작하세요. /root/k3s-ds/restore.jsonold_dir(복원이 이전 etcd 데이터를 옮긴 디렉터리 이름), restart_hint(reset.log 에서 k3s 가 다음에 할 일을 알려 준 문장 중 restart without 이 든 부분까지의 첫 문장), after_snap_exists(불리언), marker_stage(복원 뒤 marker 의 stage), member_name(복원 뒤 db/etcd/name 의 내용)을 적으세요.
  8. /root/k3s-ds/report.jsondatastore_now(sqlite 또는 etcd), lost_objects(복원으로 사라진 ConfigMap 이름을 정렬한 배열), marker_stage(지금 값), snapshot_dir(스냅숏이 저장된 디렉터리 절대 경로), restore_needs_token(다른 서버에서 복원할 때 원래 토큰이 필요한지, 불리언), member_name_changed(복원 전후 etcd 멤버 이름이 바뀌었는지, 불리언)를 적으세요.

참고

이 클러스터의 저장소는 무엇인가

네임스페이스 k3s-ds 에 ConfigMap marker(stage=sqlite)를 만드세요. 그리고 /root/k3s-ds/datastore.jsondatastore(sqlite 또는 etcd), db_files(/var/lib/rancher/k3s/server/db 의 파일 이름을 정렬한 배열), kine_table(state.db 안의 테이블 이름 중 kine 이 쓰는 것), kine_endpoint(k3s 로그의 Kine available at 뒤의 주소), marker_uid(marker 의 UID)를 적으세요.

k3s 는 SQLite 를 직접 API 서버에 붙이지 않고, etcd API 를 흉내 내는 kine 을 가운데 둡니다. API 서버의 --etcd-servers 가 무엇을 가리키는지 로그에서 보세요. 테이블 이름은 sqlite3 <파일> .tables 로 볼 수 있습니다.

스냅숏 명령을 걸었는데 저장소가 SQLite 였다

지금 상태에서 k3s etcd-snapshot save 를 실행하고 표준 출력과 표준 오류를 함께 /root/k3s-ds/snapshot-refused.txt 에 저장하세요. 그리고 /root/k3s-ds/sqlite-backup.txt 에 SQLite 저장소를 백업하려면 복사해야 하는 디렉터리와 파일의 절대 경로를 한 줄에 하나씩 적으세요.

etcd-snapshot 은 서버에 요청을 보내고 서버가 내장 etcd 로 스냅숏을 뜹니다. 저장소가 SQLite 면 서버가 거절하고 자세한 이유는 서버 로그에 남깁니다. SQLite 는 특별한 명령 없이 파일을 복사해 백업하는데, 저장소 안의 기밀 데이터를 암호화하는 값도 함께 보관해야 합니다.

재시작 한 번으로 etcd 로 옮긴다

/etc/rancher/k3s/config.yamlcluster-init: true 를 적고 k3s 를 재시작하세요. marker 가 살아 있는지 확인하고 /root/k3s-ds/migrate.jsonmarker_uid(재시작 뒤 marker 의 UID), sqlite_file_now(db 디렉터리에서 원래 state.db 가 바뀐 이름), node_roles(노드의 node-role.kubernetes.io/ 라벨 이름을 정렬한 배열, 예: ["control-plane"]), member_name(db/etcd/name 파일의 내용)을 적으세요.

SQLite 로 돌던 서버를 cluster-init 으로 기동하면 k3s 가 SQLite 의 내용을 etcd 로 옮깁니다. 이미 etcd 데이터가 디스크에 있으면 이 인자는 무시됩니다. 로그의 Migrating content from sqlite to etcd 를 찾아보세요.

이름을 붙여 스냅숏을 뜬다

marker 의 stagesnapshotted 로 바꾼 다음 k3s etcd-snapshot save --name lab-before 로 스냅숏을 뜨세요. /root/k3s-ds/snapshot.jsonname(만들어진 스냅숏 이름 전체), path(파일 절대 경로), size(바이트, 정수), sha256(파일의 SHA-256)을 적으세요.

--name 은 이름의 앞부분만 정하고 k3s 가 노드 이름과 시각을 덧붙입니다. 저장 위치는 --etcd-snapshot-dir 의 기본값입니다. k3s etcd-snapshot lskubectl get etcdsnapshotfile 이 같은 스냅숏을 보여 줍니다.

스냅숏만으로는 복원할 수 없다

/root/k3s-ds/backup/ 디렉터리에 4단계의 스냅숏 파일(같은 이름)과 서버 토큰 파일(token 이라는 이름, 권한 600)을 복사하세요. /root/k3s-ds/token-backup.jsontoken_source(토큰 원본의 절대 경로), token_sha256(토큰 파일의 SHA-256), snapshot_sha256(백업한 스냅숏의 SHA-256)을 적으세요. 토큰 값 자체는 어디에도 적지 않습니다.

k3s 는 서버 토큰으로 저장소 안의 기밀 부트스트랩 데이터를 암호화합니다. 다른 토큰으로 복원하면 스냅숏을 쓸 수 없습니다. 복사할 때 권한이 넓어지지 않게 하세요.

스냅숏 뒤에 생긴 것들

스냅숏 뒤에 네임스페이스 k3s-ds 에 ConfigMap after-snap(x=1)을 만들고 marker 의 stagechanged 로 바꾸세요. /root/k3s-ds/after.jsonafter_uid(after-snap 의 UID), after_created(그 creationTimestamp), marker_stage(지금 marker 의 stage)를 적으세요.

다음 단계의 복원이 이 둘을 어떻게 만드는지 보려는 것입니다. 복원 뒤에도 이 기록이 진짜였는지 확인할 수 있게 UID 와 시각을 정확히 적습니다.

복원하자 스냅숏 뒤의 변경이 사라졌다

k3s 를 멈추고 k3s server --cluster-reset --cluster-reset-restore-path=<4단계 스냅숏 경로> 로 복원한 뒤(출력 전체를 /root/k3s-ds/reset.log 에 저장) k3s 를 다시 시작하세요. /root/k3s-ds/restore.jsonold_dir(복원이 이전 etcd 데이터를 옮긴 디렉터리 이름), restart_hint(reset.log 에서 k3s 가 다음에 할 일을 알려 준 문장 중 restart without 이 든 부분까지의 첫 문장), after_snap_exists(불리언), marker_stage(복원 뒤 marker 의 stage), member_name(복원 뒤 db/etcd/name 의 내용)을 적으세요.

복원은 서비스가 멈춘 상태에서 같은 바이너리를 한 번 따로 실행하는 것입니다. 끝나면 스스로 종료하며 다시 시작하라고 알립니다. 이전 데이터는 지우지 않고 옆으로 옮겨 둡니다. 연속된 초기화를 막는 표식 파일이 생겼다가 정상 기동하면 지워집니다.

무엇이 남고 무엇이 사라졌나

/root/k3s-ds/report.jsondatastore_now(sqlite 또는 etcd), lost_objects(복원으로 사라진 ConfigMap 이름을 정렬한 배열), marker_stage(지금 값), snapshot_dir(스냅숏이 저장된 디렉터리 절대 경로), restore_needs_token(다른 서버에서 복원할 때 원래 토큰이 필요한지, 불리언), member_name_changed(복원 전후 etcd 멤버 이름이 바뀌었는지, 불리언)를 적으세요.

앞 단계의 json 과 지금 디스크·클러스터를 근거로 적습니다. 채점기는 같은 값을 기록 파일·etcd-old 디렉터리·클러스터에서 다시 계산합니다.