업그레이드와 복구¶
말목은 관측한 클러스터 상태를 기준으로 업그레이드와 중단된 실행을 이어갑니다.
RKE2 업그레이드¶
목표 버전을 검토하고 환경에 맞게 지정합니다.
노드를 한 대씩 업그레이드하고 Ready로 돌아온 뒤 다음 노드로 넘어갑니다.
검증 범위
서버 3대 구성은 구축, 서버 하나를 잃는 장애, 그리고 업그레이드까지
검증했습니다. 매트릭스 upgrade-three가 한 마이너 버전으로 구축한 뒤
한 대씩 다음 버전으로 올리고, 이후 모든 kubelet이 새 버전을 보고합니다.
각 행이 무엇을 담는지는
검증 매트릭스에서 확인하십시오.
반입 자재로 업그레이드하기¶
문서에 kubernetes.artifactPath가 있으면 업그레이드는 각 노드의 그 디렉터리에서
설치하고 아무것도 내려받지 않습니다. 그 디렉터리에는 구축할 때의 릴리스가 들어
있으므로, 업그레이드 전에 모든 노드에서 내용을 목표 릴리스의 자재로 바꿔
넣습니다. install.sh, rke2.linux-<arch>.tar.gz, sha256sum-<arch>.txt,
그리고 폐쇄망이면 이미지 아카이브(rke2-images.linux-<arch>.tar.zst, Cilium
데이터플레인이면 rke2-images-cilium.linux-<arch>.tar.zst)까지입니다.
어떤 노드도 drain하기 전에 UP-006이 각 노드의 디렉터리를 읽고, tarball 안의
rke2 바이너리를 실행해 버전을 확인합니다. 디렉터리가 없거나, 빠진 파일이
있거나, 읽을 수 없거나, 다른 릴리스가 들어 있으면 해당 노드를 지목해 업그레이드를
멈추며 아무것도 바꾸지 않습니다. RKE2 자재 이름에는 버전이 없어서, 구축용으로
놓아 둔 디렉터리와 업그레이드용으로 바꿔 넣은 디렉터리를 구별하는 방법은 이것뿐입니다.
검증 범위
매트릭스 케이스가 아닌 수동 실행으로 실제 장비에서 검증했습니다. 서버 1대와
에이전트 1대를 반입 자재로 v1.35.8+rke2r1에 구축했고, 디렉터리에 v1.35.8이
남아 있는 동안에는 UP-006이 아무것도 바꾸지 않고 거부했으며, 디렉터리를
교체한 뒤 v1.36.4+rke2r1로 올렸습니다. 처음에는 노드 자신의 외부 통신만,
두 번째는 파드 통신까지 막았고, 두 번째에는 서버 설치 단계와 에이전트 재시작
단계에서 각각 실행을 끊은 뒤 아래 방법으로 마쳤습니다. 서버 3대는 매트릭스
케이스 airgap-ha 입니다. 옛 릴리스가 남은 상태에서 UP-006 이 거부했고,
이어서 두 번째 서버의 drain 이 시작될 때 tarball 을 치웠습니다. 실행은 그
서버에서 멈추고 그렇게 보고했으며, 나머지 두 대가 쿼럼을 유지해 VIP 경유
쓰기가 성공했고, tarball 을 되돌린 두 번째 실행이 세 대 모두를 cordon 없이
마쳤습니다.
이 변경 이전 릴리스는 업그레이드할 때 반입 자재 경로를 아예 읽지 않았습니다.
중단된 업그레이드 마치기¶
같은 malmok upgrade --to 를 다시 실행합니다. --resume RUN_ID 를 붙여도 되고
붙이지 않아도 됩니다. 서버가 먼저 올라가므로, 서버 뒤에서 멈춘 업그레이드는
컨트롤 플레인이 목표 버전이고 에이전트가 뒤처져 있거나 cordon된 노드가 남은
상태가 됩니다. 이 상태에서는 사전 검사가 통과하고 실행이 남은 노드를 마칩니다.
클러스터가 이미 목표 버전으로 보고하는 노드는 다시 drain하지 않고 uncordon은
그대로 실행하므로, 둘 사이에서 멈춘 노드도 다시 작업을 받습니다. 모든 노드가
목표 버전이고 작업을 받는 상태일 때만 UP-002가 거부합니다. 이 수정 전에는
그 상태에서 다시 실행하면 "새 버전이 아님"으로 거부되어 에이전트가 그대로
남았습니다.
중단 후 재개¶
실행마다 상태와 JSONL 이벤트를 기록합니다. 말목이 출력한 실행 ID를 지정합니다.
입력 문서의 해시가 달라졌다면 재개를 거부합니다. 중단된 작업이 다른 목표 설정으로 완료되는 것을 방지하기 위한 동작입니다.
같은 문서 재적용¶
각 단계는 변경 전에 목표 상태에 도달했는지 확인합니다. 같은 문서를 재적용하면 이미 충족한 작업은 건너뛰며 필요한 변경만 수행합니다.
VIP 가 있는 클러스터에서 서버를 멈출 때¶
rke2-killall.sh 는 RKE2 의 컨테이너를 강제로 죽여서 멈추고, kube-vip 도 그중
하나입니다. 그렇게 죽은 kube-vip 은 VIP 를 내려놓을 틈이 없어서, RKE2 가
멈춘 뒤에도 그 서버의 네트워크 카드에 VIP 주소가 남습니다. 다른 서버가 VIP 를
넘겨받아도, 멈춘 서버의 kube-vip 이 다시 뜨기 전까지는 — RKE2 를 다시 켜거나
기계를 재부팅하기 전까지는 — 두 서버가 같은 주소에 응답합니다. 멈춘 서버에서
보낸 요청은 자기 자신에게 가서 거부되고, 같은 네트워크의 다른 기계도 그쪽으로
갈 수 있습니다.
추정이 아니라 측정한 것입니다. 서버 3대 장애 케이스에서, 멈춘 서버는 다른 서버가 VIP 를 가져간 뒤로도 30초 동안 주소를 쥐고 있었고, 자기 kube-vip 이 다시 뜨고 나서야 내려놓았습니다.
멈춘 채로 둘 서버라면 주소를 떼어 두십시오. 먼저 어느 인터페이스에 붙어 있는지 찾고, 지웁니다.
재부팅하면 저절로 떨어집니다. 서버가 통째로 죽는 장애에서는 이 문제가 남지 않는 이유입니다.
스냅숏으로 etcd 복구¶
말목에는 복구 명령이 없습니다. 복구는 RKE2 자체의 cluster reset이며, 아래 절차는 랩에서 리허설한 그대로입니다.
서버 밖에 보관할 것¶
- 스냅숏 파일:
kubernetes.etcd.snapshotTarget또는/var/lib/rancher/rke2/server/db/snapshots - 서버 토큰:
/var/lib/rancher/rke2/server/token /etc/rancher/rke2/:config.yaml,registries.yaml/var/lib/rancher/rke2/server/manifests/: 말목이 기록한 매니페스트- RKE2 버전, 폐쇄망이라면 해당 릴리스 자재
스냅숏과 토큰이 함께 있으면 클러스터 비밀값을 풀 수 있습니다
스냅숏에는 클러스터 CA 키와 비밀값이 들어 있습니다. 스냅숏과 서버 토큰을 함께 가진 사람은 이를 읽을 수 있으므로 둘 다 보호하고, 가능하면 따로 보관하십시오.
작업 전에 스냅숏을 직접 뜨려면:
같은 서버에서 복구¶
SNAPSHOT을 파일 이름으로 바꿉니다.
sudo systemctl stop rke2-server
sudo rke2 server --cluster-reset --cluster-reset-restore-path=/var/lib/rancher/rke2/server/db/snapshots/SNAPSHOT
sudo systemctl start rke2-server
reset은 끝나면 스스로 종료합니다. 마지막 줄 "Managed etcd cluster membership has been reset, restart without --cluster-reset flag now"는 error 수준으로 찍히지만 정상 종료입니다.
서버를 잃었을 때¶
같은 주소의 대체 서버에서:
- 같은 RKE2 버전을 설치합니다. 폐쇄망이면
INSTALL_RKE2_ARTIFACT_PATH로 반입 자재에서 설치합니다. /etc/rancher/rke2/와/var/lib/rancher/rke2/server/manifests/를 되돌립니다.- 스냅숏 파일을
/var/lib/rancher/rke2/server/db/snapshots/아래에 둡니다. - 보관한 토큰으로 reset한 뒤 서비스를 시작합니다.
TOKEN_FILE은 토큰을 둔 위치입니다.
config.yaml에 토큰이 있다면 보관한 토큰과 같아야 하며, 다르면 RKE2가 시작되지
않습니다. 에이전트는 등록 주소를 바라보고 에이전트 토큰을 갖고 있으므로 스스로
다시 붙습니다.
서버가 여러 대일 때¶
모든 서버를 멈추고, 한 대를 스냅숏으로 reset 해 시작한 뒤, 나머지 서버는
데이터베이스를 지우고 다시 합류시킵니다. 그래야 복구된 상태를 받아 오고, 옛
상태로 다수결을 뒤집지 않습니다. reset 은 topology.servers 의 첫 서버에서
합니다. 그 서버의 config.yaml 에는 server: 가 없고, 나머지는 등록 주소로
합류합니다.
-
모든 서버에서 RKE2를 완전히 멈춥니다.
systemctl stop만으로는 etcd 를 포함한 컨테이너가 계속 돕니다. -
VIP 가 있으면, 아직 VIP 를 쥐고 있는 서버에서 떼어냅니다. VIP 가 있는 클러스터에서 서버를 멈출 때와 같습니다. 강제로 종료된 kube-vip 는 주소를 인터페이스에 남겨 두고, 그 서버에 아무것도 listen 하지 않는 동안 다른 서버의 합류가 거부됩니다.
-
첫 서버에서 스냅숏으로 reset 하고 시작합니다.
-
VIP 가 있으면, 나머지를 시작하기 전에 VIP 가 응답할 때까지 기다립니다. 첫 서버가 올라온 것과 VIP 가 돌아온 것은 다릅니다. kube-vip 는 자기 파드가 뜬 뒤에 주소를 잡습니다. 돌아오면
pong이 출력됩니다. -
나머지 서버마다 한 대씩, 데이터베이스를 지우고 RKE2를 시작한 뒤 그 서버의 API 서버가
ok를 답할 때까지 기다립니다.
노드 목록이 아니라 서버마다 물어보십시오. reset 직후의 노드 목록은 스냅숏 시점의 것이라, 랩에서는 두 서버가 멈춰 있는데도 모두 Ready 로 보였습니다.
검증 범위
매트릭스 케이스가 아닌 수동 리허설입니다. 랩에서 서버 1대와 에이전트 1대,
v1.36.4, 외부 통신 허용 상태로 했습니다. 같은 서버에서 복구한 경우와, 같은
서버를 초기화한 뒤 보관한 토큰·설정·매니페스트로 재설치해 복구한 경우 모두,
스냅숏 전에 만든 ConfigMap은 돌아오고 스냅숏 후에 만든 것은 사라졌으며 두
노드가 Ready, 에이전트도 다시 붙었습니다. 이어서 노드와 파드 통신을 막은
채, 막 에어갭 업그레이드를 마친 클러스터에서 두 경우를 다시 해 같은 결과를
얻었습니다. 서버 3대는 매트릭스 케이스 airgap-ha 입니다. VIP 아래 서버
3대, 노드와 파드 통신 차단, 업그레이드 뒤 위 절차로 복구해 스냅숏 전
표식은 돌아오고 후 표식은 사라졌으며 모든 서버가 ready 를 답했습니다.
VIP 관련 두 단계는 그것 없이 케이스가 실패해서 들어간 것입니다. 내장 레지스트리 미러를 쓰는 클러스터에서는
rke2 etcd-snapshot save가 "Unknown flag --embedded-registry found in
config.yaml, skipping"을 출력하지만, 스냅숏 생성과 복구는 정상이었습니다.
근거부터 확인¶
인증서 유지보수를 준비한다면 v0.96.4 이상의 읽기 전용 만료 점검도 활용할 수 있습니다. RKE2 재시작이나 인증서 갱신은 하지 않으며, 별도의 실행 기록을 만들어 해당 ID로 보고서를 생성할 수 있습니다.
오류를 진단할 때는 진단 코드와 해당 실행의 events.jsonl 마지막 부분을 확인합니다.
폐기한 코드 번호는 재사용하지 않으므로 이전 리포트와 티켓에서도 의미가 유지됩니다.