K3s Secret 암호화 확인: Enabled인데 Rotation Stage가 start일 때
K3s에서 Secret 저장 암호화를 켠 뒤 상태를 확인하면 Encryption Status: Enabled와 Current Rotation Stage: start가 함께 나올 수 있다. Enabled는 켜졌다는 뜻인데 start는 아직 시작 단계처럼 보여, 설정이 덜 끝난 것인지 헷갈리기 쉽다.
OCI A1에서 K3s를 운영하며 확인한 출력도 이 조합이었다. 결론부터 말하면 start만으로 암호화 실패나 멈춘 키 회전을 판정할 수 없다. 암호화 활성화 여부, 회전 단계, 서버 간 설정 일치 여부를 나누어 읽어야 한다.
이 글은 2026년 11월 4일에 남긴 상태·파일 권한 점검 기록과 2026년 11월 9일 확인한 공식 문서를 기준으로 작성했다. 실제 키 회전, 기존 Secret 전체의 원시 저장값 검사, 백업 복원 시험은 이번 기록에 포함되지 않는다.
1. 실제 확인한 환경과 출력
기존 구성은 OCI A1에 K3s 설치하기: 기존 Docker와 NPM을 유지한 쿠버네티스 구성에 정리했다. Docker와 Nginx Proxy Manager를 유지하면서 단일 서버에 K3s를 추가했고, 설치 설정에 다음 항목을 넣었다.
secrets-encryption: true
당시 환경은 OCI Ampere A1, ARM64, Ubuntu 24.04 LTS였다. 2026년 10월 27~28일 설치 기록의 K3s 버전은 v1.36.5+k3s1이다. 이 버전을 현재 버전으로 간주하지 않고, 이후 점검에서는 다시 확인한다.
11월 4일에는 다음 명령의 결과를 확인했다.
sudo k3s secrets-encrypt status
Encryption Status: Enabled
Current Rotation Stage: start
Server Encryption Hashes: All hashes match
Active Key Type Name
------ -------- ----
* AES-CBC aescbckey
같은 점검에서 /var/lib/rancher/k3s/server/db/state.db가 존재했고, 확인한 etcd 경로는 없었다. 따라서 아래 파일 점검은 당시 단일 서버 SQLite 구성에 맞춘 것이다. 다른 서버에서도 state.db가 있다는 이유만으로 현재 데이터 저장 방식을 단정하지 말고, 실제 실행 설정과 함께 확인해야 한다.
2. Enabled·start·All hashes match는 서로 다른 질문에 답한다
| 출력 | 읽어야 할 의미 | 이 값만으로 결론 내릴 수 없는 것 |
|---|---|---|
Encryption Status: Enabled |
해당 노드에서 Secret 암호화가 활성화된 상태 | 과거의 모든 Secret이 재암호화됐는지 |
Current Rotation Stage: start |
노드에 기록된 현재 키 회전 단계 | 장애 발생 또는 진행 중인 회전의 정지 여부 |
All hashes match |
서버들의 로컬 암호화 설정 상태가 일치하는지에 관한 결과 | 모든 데이터의 암호화·백업 무결성 |
키 앞의 * |
새 Secret을 암호화하는 데 사용하는 활성 키 | 이전 키로 저장된 데이터가 남아 있는지 |
K3s 공식 상태 명령 문서의 단일 서버 예시에도 Enabled, start, All hashes match가 함께 나온다. start라는 문자열을 없애려고 회전을 실행할 이유는 없다. 회전을 의도적으로 시작한 적이 있는지, 어떤 절차의 어느 단계였는지를 먼저 확인한다.
해시 항목은 특히 여러 K3s 서버가 있는 HA 구성에서 의미가 있다. 공식 문서는 서버마다 암호화 설정이 다르면 해시가 일치하지 않을 수 있다고 설명한다. 단일 서버의 All hashes match를 여러 노드의 동기화 검증이나 복구 시험까지 통과했다는 뜻으로 확대하면 안 된다.
3. 변경 전에 현재 상태를 다시 기록한다
아래 명령은 서비스 재시작이나 키 변경 없이 현재 상태를 읽는다. 기본 데이터 경로를 사용하는 환경을 기준으로 하며, 사용자 지정 data-dir를 사용한다면 뒤의 파일 경로도 바꿔야 한다.
date -Is
uname -m
sudo k3s --version
sudo systemctl is-active k3s
sudo k3s kubectl get nodes -o wide
sudo k3s secrets-encrypt status
점검 기록에는 실행 시각, K3s 버전, 노드 상태, 암호화 상태 출력과 활성 키 이름을 함께 남긴다. 공개할 때는 노드명과 IP 등 운영 식별자를 가린다. systemctl이 active여도 노드가 Ready인지까지 별도로 확인한다.
기본 설정 파일에 해당 항목이 있는지는 필요한 줄만 읽을 수 있다.
sudo grep -nE \
'^[[:space:]]*secrets-encryption:' \
/etc/rancher/k3s/config.yaml
이 검색에 결과가 없다고 암호화가 꺼졌다고 단정하면 안 된다. 실행 인자나 별도의 설정 파일을 사용하는 환경일 수 있다. 설정 파일의 한 줄과 실제 status 출력이 서로 맞는지 확인하고, 다르다면 적용 경로를 조사한다.
확인할 것은 단순하다. 현재 버전이 무엇인지, 노드가 준비 상태인지, 암호화가 활성화됐는지, 어떤 키가 활성인지다. 이전 점검 결과가 정상이라는 이유로 오늘의 결과를 대신하지 않는다.
4. 암호화 키와 토큰은 내용 대신 권한을 확인한다
K3s는 Secret 암호화 설정을 /var/lib/rancher/k3s/server/cred/encryption-config.json에 생성한다. 이 파일에는 키 재료가 들어가므로 점검용 캡처를 만들기 위해 내용을 출력할 필요가 없다. 생성 과정과 기본 제공자는 공식 Secrets Encryption 설정 문서에서 확인할 수 있다.
다음과 같이 소유자와 접근 권한만 확인한다.
sudo stat -c '%a %U:%G %n' \
/var/lib/rancher/k3s/server \
/var/lib/rancher/k3s/server/db \
/var/lib/rancher/k3s/server/db/state.db \
/var/lib/rancher/k3s/server/cred \
/var/lib/rancher/k3s/server/cred/encryption-config.json \
/var/lib/rancher/k3s/server/token
2026년 11월 4일 기록에서는 다음 값이 확인됐다. 아래는 모든 환경에 강제로 적용할 권한 목록이 아니라, 그날 확인한 결과다.
| 대상 | 소유자 | 권한 |
|---|---|---|
server/, server/db/, server/cred/ |
root:root |
0700 |
server/db/state.db |
root:root |
0644 |
server/cred/encryption-config.json |
root:root |
0600 |
server/token |
root:root |
0600 |
파일의 숫자 하나만 보고 접근 가능 범위를 판정하지 않도록, 상위 디렉터리까지 함께 기록했다. state.db의 0644만 떼어 보여 주거나, 반대로 키 파일이 0600이므로 전체 시스템이 안전하다고 단정하지 않는다. 이 글의 확인 범위는 기록에 남은 소유자와 권한까지다.
암호화 설정 파일 전체, 서버 토큰, 실제 Secret 값은 블로그나 공개 이슈에 붙이지 않는다. 필요한 설명은 키 이름·상태·권한으로 충분하다.
5. 키 회전 완료와 암호화 활성화는 별도로 확인한다
K3s 공식 문서는 현재 회전 절차로 rotate-keys를 설명하며, 완료 확인 예시에 reencrypt_finished를 사용한다. 그러나 이 글의 서버에서 실제 회전을 수행해 그 상태까지 확인한 것은 아니다.
따라서 이번 기록의 판정은 점검 당시 암호화 활성화와 활성 키를 확인했다는 것까지다. “키 회전을 완료했다” 또는 “기존 Secret을 모두 재암호화했다”는 결과를 덧붙이지 않는다.
실제 회전이 필요하다면 공식 Encryption Key Rotation 절차를 현재 버전과 단일 서버·HA 구성에 맞춰 확인한다. 기존 클러스터에서 처음 암호화를 켜는 절차와 이미 활성화된 클러스터의 키를 바꾸는 절차도 구분해야 한다. 상태 확인용 명령 묶음에 회전이나 재시작 명령을 섞지 않는 편이 기록을 해석하기 쉽다.
6. SQLite 백업은 DB 디렉터리와 서버 토큰을 함께 본다
K3s Backup and Restore 문서는 SQLite 구성의 백업 대상으로 /var/lib/rancher/k3s/server/db/를 안내한다. 여기에 서버 토큰 /var/lib/rancher/k3s/server/token도 함께 보관해야 한다. 복원할 때 동일한 토큰이 필요하기 때문이다.
이번 글에서는 DB 복사나 복원 명령을 실행한 결과를 제시하지 않는다. 실제 변경을 준비한다면 다음을 먼저 정한다.
- 현재 저장소가 SQLite인지, embedded etcd인지, 외부 DB인지
- 복사 시점의 일관성을 확보할 방법과 서비스 중단 여부
- DB와 해당 서버 토큰을 함께 복원할 수 있는지
- 백업 접근 권한과 암호화된 보관 방식
- 격리된 환경에서 복원 후 Secret을 정상적으로 읽을 수 있는지
백업 파일이 존재한다는 사실과 복원 성공은 다르다. Ghost·MySQL 백업 무결성 점검에서 다룬 확인 방식처럼, 복구에 필요한 구성요소와 실제 복원 결과를 구분해 기록하는 것이 좋다. Ghost·MySQL용 절차를 K3s에 그대로 적용하지는 않는다.
7. 실제 저장 암호화는 어떻게 추가 검증할까
status와 파일 권한을 확인해도 특정 Secret의 원시 저장값까지 본 것은 아니다. Kubernetes의 저장 데이터 암호화 검증 문서는 새 Secret을 만든 뒤 저장소에서 암호화 접두사를 확인하고, API로 정상 복호화되는지도 확인하는 방식을 설명한다.
추가 실험은 실제 비밀값 대신 폐기 가능한 canary 값을 쓰고, 운영 서버와 분리한 환경에서 진행할 수 있다. 다음은 실행을 완료한 결과가 아니라 검증 설계다.
- 실제 운영 버전을 다시 확인하고 동일한 버전·저장소 종류의 실험 환경을 준비한다.
- 충돌하지 않는 전용 네임스페이스에 임의 마커를 담은 Secret 하나를 만든다.
- API로 읽은 값을 디코딩해 원래 마커와 비교한다.
- 해당 Secret의 현재 저장 레코드를 식별하고, 활성 제공자에 맞는 암호화 형식과 키 이름을 확인한다.
aescbc의 예시는k8s:enc:aescbc:v1:이다. - 변경 전후 상태와 실험 조건을 기록하고 실험 자원을 정리한다.
공식 문서의 원시 조회 예시는 etcd 기준이다. SQLite를 쓰는 K3s에 etcdctl 명령을 그대로 복사할 수는 없다. 또한 DB 파일 전체에서 암호화 접두사 하나를 찾았다는 사실만으로 방금 만든 Secret이 암호화됐다고 판정해서도 안 된다. 평문 검색에서 값이 안 나오는 것 역시 단독 증거로 충분하지 않다. 정확한 대상 레코드와 API 왕복 결과를 연결해야 한다.
새 Secret 한 개의 검증과 기존 데이터 전체의 검증도 별개다. 이번 운영 기록에는 그 추가 검증 결과가 없으므로, 저장소 전체의 암호화 완료를 주장하지 않는다.
8. 이 점검이 답하지 않는 질문
저장 암호화 상태가 활성화되어 있어도 API 권한, 파일 접근 통제, 외부 노출, 백업 보호까지 자동으로 해결되는 것은 아니다. 외부 접속 경로는 외부 노출 포트와 방화벽 상태 확인처럼 별도로 점검한다.
이번에 확인한 범위는 Enabled, start, All hashes match, 활성 키와 관련 파일 권한이다. 여기서 다음 행동을 결정하려면 질문을 나누면 된다. 암호화가 켜졌는지는 상태 출력으로, 회전을 완료했는지는 변경 이력과 완료 단계로, 특정 데이터가 암호화됐는지는 저장 레코드 검사로, 백업이 쓸 수 있는지는 복원 시험으로 확인한다.
참고 문서
공식 문서 확인일: 2026년 11월 9일