본문으로 건너뛰기
← Systems Notebook / Ops
MLOps Notes01 / 15

온프레미스 Kubernetes를 왜 RKE2로 구축하는가

Kubespray와 RKE2의 운영 방식을 비교하고, RKE2·Helm·Rancher를 구성하며 다음 실습으로 넘어가기 전에 확인할 상태를 살펴봅니다.

이 글의 배경

HPE 엔지니어의 작업 자료를 바탕으로 정리한 글입니다. 개인 실험 기록이나 HPE 공식 문서와는 구분합니다. 본문의 환경과 버전은 글 작성 당시를 기준으로 합니다.

클라우드의 관리형 Kubernetes에서는 API 서버, etcd, 인증서, 컨테이너 런타임의 설치와 재시작을 직접 다룰 일이 적습니다. 온프레미스로 옮기면 이 작업이 운영자의 역할에 포함됩니다. 운영체제 위에 Kubernetes 구성요소를 올리는 것부터 장애 대응, 업그레이드, 인증서와 백업 관리까지 준비해야 합니다.

이때 자주 비교되는 선택지가 Kubespray와 RKE2입니다. 두 도구 모두 프로덕션 클러스터를 자동화하지만 문제를 푸는 방식이 다릅니다. Kubespray는 Ansible로 업스트림 Kubernetes를 조립하고, RKE2는 검증된 구성요소를 하나의 배포판으로 묶어 systemd 서비스로 운영합니다.

“RKE2 설치 명령”을 실행하기 전에 어떤 운영 모델을 선택하는지부터 살펴보겠습니다. 그 판단을 바탕으로 RKE2 단일 서버를 설치하고 Helm과 Rancher까지 구성하는 것이 이 글의 실습 범위입니다. 다음 글에서는 kube-vip, MetalLB, Gateway API로 외부 진입 경로를 만들기 때문에, 이 단계에서는 레거시 Ingress 컨트롤러를 설치하지 않습니다.

이 글에서 다루는 것

  • Kubespray와 RKE2가 각각 무엇을 자동화하는지
  • RKE2의 server, agent, embedded etcd, containerd가 어떻게 연결되는지
  • 설치 전에 결정해야 하는 버전, DNS, 방화벽, HA 항목
  • RKE2 서버와 kubectl 환경을 만드는 전체 절차
  • Helm과 Rancher를 Ingress 없이 설치하는 방법
  • 정상 결과를 확인하는 명령과 대표적인 장애 원인
  • 업그레이드, etcd 백업, 토큰과 kubeconfig 보안 원칙

실습 환경과 치환값

아래 값은 문서용 예시입니다. 192.0.2.0/24는 문서에 쓰도록 예약된 대역이므로 실제 네트워크에서 그대로 통신할 수 없습니다. 명령을 실행하기 전에 자신의 사설망 값으로 치환합니다.

의미 이 글의 예시 치환 기준
첫 server 노드 cp-01 고유한 Linux hostname
첫 server IP 192.0.2.11 NODE_1_IP
Kubernetes API DNS k8s-api.lab.example.com 다음 글에서 control-plane VIP에 연결
Rancher DNS rancher.lab.example.com 다음 글에서 Gateway에 연결
RKE2 버전 v1.35.6+rke2r1 운영 전 RKE2 v1.35 릴리스 노트에서 검증
cert-manager Chart v1.20.2 Rancher 지원 조합과 릴리스 보안 공지를 확인
Rancher Chart 2.14.2 Kubernetes 지원 매트릭스를 확인
조인 토큰 ${RKE2_TOKEN} 코드에 기록하지 않는 공유 비밀

이 글의 단일 노드 실습은 구조 학습을 위한 최소 구성입니다. 운영 HA 구성은 control plane 서버를 홀수 개, 일반적으로 3개로 만들고 고정 등록 주소를 앞에 둡니다. 서버 1대로 실습했다고 해서 그 구성을 그대로 운영 환경에 사용하면 안 됩니다.

Kubespray와 RKE2는 무엇이 다른가

두 도구 모두 설치와 확장을 자동화합니다. 그래서 “자동화 여부”보다 무엇을 운영 단위로 삼느냐를 기준으로 비교하는 편이 차이를 이해하기 쉽습니다.

구조 살펴보기 / 01Kubespray와 RKE2의 운영 방식
Ansible 설정Kubespray · inventory와 변수
Kubernetes 구성요소kubeadm·kubelet·런타임
01 / 03
Kubespray의 설정

Kubespray는 Ansible inventory와 변수로 구성요소를 조립합니다.

1

Ansible 설정 → Kubernetes 구성요소구성요소 조립

구성 관계를 차례로 강조합니다. 단계는 실제 실행 순서가 아닙니다.

전체 단계 한눈에 읽기
  1. Kubespray의 설정

    Kubespray는 Ansible inventory와 변수로 구성요소를 조립합니다.

    • Ansible 설정 → Kubernetes 구성요소: 구성요소 조립
  2. 애드온도 같은 설정에서

    런타임과 애드온은 서로 다른 구성 대상입니다. 이 두 갈래는 설치 순서를 뜻하지 않습니다.

    • Ansible 설정 → Kubernetes 구성요소: 구성요소 조립
    • Ansible 설정 → 네트워크·애드온: 애드온 구성
  3. RKE2의 운영 단위

    RKE2는 config.yaml로 서비스를 설정하고 배포판에 묶인 구성요소를 운영합니다.

    • config.yaml → RKE2 서비스: 서비스 설정
    • RKE2 서비스 → 배포판 구성요소: 배포판 운영
도식 원문
flowchart LR
  subgraph K["Kubespray: 구성요소를 조립"]
    A["Ansible inventory와 변수"] --> B["kubeadm·kubelet·런타임"]
    A --> C["CNI·DNS·애드온"]
  end
  subgraph R["RKE2: 배포판을 운영"]
    D["config.yaml"] --> E["rke2-server / rke2-agent"]
    E --> F["containerd·etcd·control plane·CNI"]
  end
판단 축 Kubespray RKE2
결과물 업스트림 Kubernetes를 Ansible로 구성 RKE2 Kubernetes 배포판
운영 인터페이스 inventory, group variables, playbook, SSH config.yaml, systemd, RKE2 CLI
선택 범위 CNI·런타임·애드온을 폭넓게 조합 검증된 기본 조합을 중심으로 선택
변경 책임 조합의 호환성까지 플랫폼 팀이 검증 배포판의 릴리스와 지원 매트릭스를 따름
재현 방식 Ansible 코드와 inventory 설정 파일과 설치 자동화/IaC
적합한 팀 Ansible 역량과 세밀한 표준화가 강한 팀 빠른 구축, 일관된 운영, Rancher 연계가 중요한 팀

Kubespray가 “수동 설치”이고 RKE2가 “자동 설치”인 것은 아닙니다. Kubespray도 강력한 자동화 도구입니다. 업스트림에 가까운 구성과 높은 조합 자유도가 중요한 조직에는 Kubespray가 더 맞을 수 있습니다. 반대로 구성 선택지를 줄이고 systemd 서비스 단위로 일관되게 운영하려면 RKE2가 유리합니다.

RKE2가 단순하게 느껴지는 이유

RKE2 server는 하나의 프로세스처럼 시작하지만 내부에서는 여러 역할을 조정합니다.

  • embedded containerd가 컨테이너 런타임을 담당합니다.
  • server 노드에서는 Kubernetes API 서버와 controller-manager, scheduler, embedded etcd가 static Pod로 실행됩니다.
  • agent 노드에서는 kubelet과 kube-proxy가 실행되고 워크로드를 수용합니다.
  • 기본 CNI와 CoreDNS 같은 패키지 구성요소를 RKE2가 배포합니다.
  • /etc/rancher/rke2/config.yaml이 주요 운영 설정의 기준점이 됩니다.

선택지가 사라진 것은 아닙니다. CNI나 datastore, 패키지 구성요소를 바꿀 수 있지만, 먼저 배포판의 기본 경로를 사용하는 것이 장애 범위를 줄이는 데 도움이 됩니다.

설치 전에 결정할 것

1. 단일 노드인가, HA인가

RKE2의 공식 HA 구성은 다음 세 요소로 이루어집니다.

  1. server 노드 앞의 고정 등록 주소
  2. embedded etcd 쿼럼을 위한 홀수 개 server 노드
  3. 필요에 따라 추가하는 agent 노드

노드 조인은 9345/TCP, Kubernetes API 접근은 6443/TCP를 사용합니다. HA에서는 두 포트 모두 고정 주소를 통해 현재 살아 있는 server 노드에 도달해야 합니다. 다음 글에서는 k8s-api.lab.example.com과 control-plane VIP로 이 문제를 해결합니다.

2. Kubernetes와 RKE2 버전을 어떻게 고정할 것인가

설치 스크립트에 버전을 지정하지 않으면 채널의 최신 릴리스를 받게 됩니다. 실습에서는 편하지만 운영 환경에서는 날짜에 따라 결과가 달라집니다. 따라서 릴리스 노트와 Kubernetes 지원 정책을 확인한 뒤 INSTALL_RKE2_VERSION을 고정하고, 개발 환경에서 업그레이드를 먼저 검증합니다.

이 글에 적힌 버전은 2026-07-14 시점의 예시입니다. 실제로 사용할 버전은 앞서 설명한 릴리스 노트와 지원 정책을 확인해 정해야 하며, 이 예시를 글을 읽는 시점의 권장 버전으로 보아서는 안 됩니다.

3. 네트워크 프록시 모드는 기본값으로 시작한다

예전 설치 문서에는 kube-proxy를 IPVS 모드로 바꾸는 예제가 많습니다. Kubernetes 1.35에서 IPVS 프록시 모드는 deprecated 되었으므로 신규 클러스터의 기본 권장값으로 삼지 않습니다.

RKE2의 nftables 지원은 2026년 7월 릴리스부터 제공되지만 아직 experimental이며, CNI별 추가 설정도 필요합니다. 따라서 이 실습은 kube-proxy-arg를 넣지 않고 RKE2 기본값을 유지합니다. nftables를 도입하려면 RKE2 버전 게이트와 CNI 호환성을 별도 환경에서 검증합니다.

4. 호스트 방화벽을 무조건 끄지 않는다

학습 환경에서는 문제를 좁히려고 방화벽을 끄기도 합니다. 운영 환경에서는 이 방법을 일반적인 절차로 적용하지 않고, 필요한 통신이 허용되도록 네트워크 정책을 정해야 합니다. 최소한 다음 흐름이 그 대상입니다.

  • 클라이언트와 노드 → server: 6443/TCP, 9345/TCP
  • server 상호 간: embedded etcd 및 RKE2 공식 요구 포트
  • 노드 상호 간: 선택한 CNI가 요구하는 포트와 프로토콜
  • 노드 → 이미지 레지스트리, DNS, 시간 동기화 서버

정확한 포트는 설치할 RKE2 버전과 CNI를 기준으로 공식 요구 사항에서 확인합니다.

실습 1: 호스트 준비

Ubuntu 계열 Linux server 한 대에서 진행합니다. 다른 배포판은 패키지 명과 방화벽 도구가 다를 수 있습니다.

먼저 hostname, 시간, DNS, 기본 리소스를 확인합니다.

bash
hostnamectl
timedatectl status
getent hosts k8s-api.lab.example.com || true
free -h
df -h /

각 노드 hostname은 반드시 고유해야 합니다. 실습 노드를 cp-01로 정했다면 다음처럼 설정하고 새 세션에서 확인합니다.

bash
sudo hostnamectl set-hostname cp-01
exec bash
hostname

기본 kubelet 설정과 충돌하지 않도록 swap을 비활성화합니다. /etc/fstab의 swap 항목을 제거하거나 주석 처리하는 작업은 시스템별 검토가 필요하므로 자동 치환하지 않습니다.

bash
sudo swapoff -a
swapon --show

두 번째 명령의 출력이 비어 있으면 현재 세션에서 swap이 꺼진 상태입니다. 이 결과만으로 재부팅 후의 상태까지 알 수는 없으므로, 재부팅한 뒤에도 반드시 다시 확인합니다.

필수 도구를 준비합니다.

bash
sudo apt-get update
sudo apt-get install -y curl ca-certificates openssl bash-completion

RKE2 설치 전에는 노드가 외부 레지스트리와 내부 서비스 DNS를 모두 해석하는지 먼저 확인합니다. 이 결과를 살피지 않은 채 DNS 설정 파일을 강제로 삭제하거나 systemd-resolved를 일괄 비활성화하지 않습니다.

실습 2: RKE2 server 설치

1. 설정 파일 작성

bash
export RKE2_VERSION='v1.35.6+rke2r1'
export K8S_API_FQDN='k8s-api.lab.example.com'
export RANCHER_FQDN='rancher.lab.example.com'

sudo install -d -m 0755 /etc/rancher/rke2
sudo install -m 0600 /dev/null /etc/rancher/rke2/config.yaml

RKE2가 생성하는 조인 토큰을 사용할 것이므로 이 단계에서는 token:을 직접 기록하지 않습니다. API 인증서에는 다음 글에서 사용할 고정 DNS를 미리 넣고, 기본 Ingress 컨트롤러는 설치하지 않습니다.

bash
sudo tee /etc/rancher/rke2/config.yaml >/dev/null <<EOF
tls-san:
  - ${K8S_API_FQDN}
ingress-controller: none
write-kubeconfig-mode: "0600"
EOF

여기에 IPVS 커널 모듈이나 proxy-mode=ipvs 설정을 추가하지 않습니다. RKE2 기본 네트워킹을 그대로 검증하는 것이 이 글의 기준선입니다.

2. 버전을 고정해 설치

bash
curl -sfL https://get.rke2.io | \
  sudo env INSTALL_RKE2_VERSION="${RKE2_VERSION}" sh -

sudo systemctl enable --now rke2-server

첫 시작은 시스템 이미지를 내려받고 control plane을 구성하므로 시간이 걸릴 수 있습니다. 진행 상황은 journald에서 확인합니다.

bash
sudo systemctl status rke2-server --no-pager
sudo journalctl -u rke2-server -n 100 --no-pager

정상이라면 서비스가 active (running) 상태가 되고 /etc/rancher/rke2/rke2.yaml과 /var/lib/rancher/rke2/server/node-token이 생성됩니다.

3. kubectl 환경 구성

RKE2가 제공하는 kubectl을 PATH에 연결하고 관리자 kubeconfig를 사용자 홈에 복사합니다.

bash
sudo ln -sfn /var/lib/rancher/rke2/bin/kubectl /usr/local/bin/kubectl
mkdir -p "${HOME}/.kube"
sudo cp /etc/rancher/rke2/rke2.yaml "${HOME}/.kube/config"
sudo chown "$(id -u):$(id -g)" "${HOME}/.kube/config"
chmod 0600 "${HOME}/.kube/config"

이 kubeconfig는 사실상 클러스터 관리자 자격증명입니다. 메신저나 공개 저장소로 복사하지 않습니다. 외부 관리 PC로 옮길 때는 파일의 server: 주소를 다음 글에서 만드는 API DNS로 바꾸고, 파일 전달 경로도 암호화합니다.

클러스터를 확인합니다.

bash
kubectl get nodes -o wide
kubectl get pods -A
kubectl get --raw='/readyz?verbose'

예상 결과는 다음과 같습니다.

  • cp-01 노드의 STATUS가 Ready입니다.
  • kube-system의 CoreDNS, CNI, control-plane 관련 파드가 정상 상태입니다.
  • /readyz 세부 항목이 ok로 끝납니다.
  • 별도의 Ingress 컨트롤러 파드는 존재하지 않습니다.

실습 3: Helm 설치

Helm은 Kubernetes 리소스 묶음을 버전이 있는 Chart로 설치·업그레이드하는 클라이언트입니다. RKE2 내부의 Helm controller는 패키지 구성요소를 관리합니다. 사용자가 직접 Chart를 배포할 때 쓰는 Helm CLI는 별도로 준비해 두면 두 역할을 구분하기 쉽습니다.

공식 설치 스크립트를 내려받고 실행합니다. 운영 환경에서는 실행 전에 스크립트 내용과 배포 경로를 검토합니다.

bash
curl -fsSLo get-helm.sh \
  https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-4
chmod 0700 get-helm.sh
./get-helm.sh
helm version

현재 클러스터를 읽을 수 있는지 확인합니다.

bash
helm list -A

오류 없이 릴리스 목록이 출력되면 Helm이 ~/.kube/config를 정상 사용하고 있습니다.

실습 4: Rancher 설치

Rancher는 여러 Kubernetes 클러스터를 관리하는 상위 관리면으로, Kubernetes 자체와는 역할이 다릅니다. 이 실습에서는 현재 RKE2 클러스터에 Rancher 서버를 설치합니다. 외부 노출은 다음 글의 NGINX Gateway Fabric으로 구성하므로 Rancher Chart에서는 Ingress 생성을 끕니다.

1. cert-manager 설치

bash
export CERT_MANAGER_VERSION='v1.20.2'

helm repo add jetstack https://charts.jetstack.io
helm repo update

helm upgrade --install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --version "${CERT_MANAGER_VERSION}" \
  --set crds.enabled=true \
  --wait --timeout 10m
bash
kubectl -n cert-manager get pods
kubectl get crd certificates.cert-manager.io

모든 cert-manager 파드가 Running이고 CRD가 조회되어야 다음 단계로 진행합니다.

2. Rancher Chart 설치

bash
export RANCHER_FQDN='rancher.lab.example.com'
export RANCHER_CHART_VERSION='2.14.2'

helm repo add rancher-stable \
  https://releases.rancher.com/server-charts/stable
helm repo update

helm upgrade --install rancher rancher-stable/rancher \
  --namespace cattle-system \
  --create-namespace \
  --version "${RANCHER_CHART_VERSION}" \
  --set-string hostname="${RANCHER_FQDN}" \
  --set ingress.enabled=false \
  --set replicas=1 \
  --wait --timeout 15m

replicas=1은 단일 노드 실습값입니다. 3개 server/agent에 분산할 수 있는 운영 클러스터에서는 장애 도메인과 anti-affinity를 고려해 복제 수를 높입니다.

위 설치 명령은 부트스트랩 암호를 명령행에 평문으로 넣지 않는 구성입니다. 처음 접속할 때만 Chart가 생성한 값을 확인하고, 접속 후에는 즉시 새 관리자 암호로 바꿉니다.

bash
kubectl -n cattle-system get secret bootstrap-secret \
  -o go-template='{{.data.bootstrapPassword | base64decode}}{{"\n"}}'

터미널 공유·녹화 환경에서는 이 명령을 실행하지 않습니다. 출력값을 문서나 셸 스크립트에 저장해서도 안 됩니다.

3. Rancher의 내부 상태 확인

아직 외부 Gateway가 없으므로 브라우저 접속은 되지 않는 것이 정상입니다. Kubernetes 내부 상태부터 확인합니다.

bash
kubectl -n cattle-system rollout status deployment/rancher --timeout=10m
kubectl -n cattle-system get deployment,pod,service
kubectl -n cattle-system get service rancher

rancher Deployment가 Available이고 Service가 ClusterIP로 존재하면 이 단계의 내부 설치 상태를 확인한 것입니다. 브라우저에서 사용할 외부 경로는 다음 글에서 구성하며, rancher.lab.example.com HTTPRoute를 이 Service의 80번 포트에 연결합니다.

HA로 확장할 때 달라지는 것

단일 server를 3대 HA로 확장하려면 VM 두 대를 추가하는 것과 함께 고정 등록 주소, etcd 쿼럼, 워크로드 배치를 정해야 합니다. 아래에서 각 항목이 달라지는 이유를 살펴보겠습니다.

고정 등록 주소

추가 server와 agent의 config.yaml은 다음 형태가 됩니다.

yaml
server: https://k8s-api.lab.example.com:9345
token: ${RKE2_TOKEN}
tls-san:
  - k8s-api.lab.example.com
ingress-controller: none

token:에 문자열 ${RKE2_TOKEN}을 그대로 쓰라는 뜻이 아닙니다. 배포 자동화나 보호된 파일을 통해 실제 비밀을 주입해야 합니다. 모든 server 노드의 cluster CIDR, service CIDR, CNI처럼 중요한 설정은 반드시 일치해야 합니다. 불일치하면 조인 과정에서 critical configuration value mismatch 오류가 납니다.

etcd 쿼럼

embedded etcd에서 3대는 2대가 살아야 쿼럼을 유지합니다. 4대를 만든다고 허용 장애 수가 2대로 늘지 않습니다. 그래서 일반적인 시작점은 홀수인 3대입니다. control plane 노드를 서로 다른 물리 호스트나 전원 장애 도메인에 배치해야 숫자상의 HA가 실제 HA가 됩니다.

server 노드의 워크로드 배치

RKE2 server는 기본적으로 스케줄 가능합니다. 작은 실습에서는 control plane과 워크로드를 함께 실행할 수 있지만, 운영 환경에서는 agent 노드를 별도로 두고 taint와 toleration 정책을 설계합니다. 다만 모든 server를 taint한 채 시스템 애드온이 배치될 agent가 없으면 핵심 파드가 Pending이 될 수 있으므로 순서를 계획해야 합니다.

검증 체크리스트

다음 항목이 모두 충족되어야 이 글의 실습이 끝난 것입니다.

bash
sudo systemctl is-active rke2-server
kubectl wait node/cp-01 --for=condition=Ready --timeout=5m
kubectl get --raw='/readyz'
helm list -A
kubectl -n cert-manager wait deployment --all \
  --for=condition=Available --timeout=5m
kubectl -n cattle-system wait deployment/rancher \
  --for=condition=Available --timeout=10m

예상 출력의 핵심은 다음과 같습니다.

text
active
node/cp-01 condition met
ok
deployment.apps/rancher condition met

helm list -A에는 cert-manager와 rancher 릴리스가 보여야 합니다. 준비되지 않은 항목이 있다면 “시간이 지나면 되겠지”라고 넘기지 않고, 이벤트와 로그에서 어느 단계가 진행되지 않는지 확인합니다.

자주 만나는 문제

rke2-server가 시작되지 않는다

bash
sudo systemctl status rke2-server --no-pager
sudo journalctl -u rke2-server -n 200 --no-pager
sudo ss -lntp | grep -E ':(6443|9345)\b'
  • swap이 다시 켜졌는지 확인합니다.
  • hostname이 다른 노드와 중복되지 않는지 확인합니다.
  • 이미지 레지스트리 DNS와 TLS 연결이 되는지 확인합니다.
  • /etc/rancher/rke2/config.yaml의 YAML 들여쓰기와 지원 옵션을 확인합니다.
  • 이전 클러스터의 datastore가 남은 노드를 재사용했다면 새 server: 값이 무시될 수 있습니다. 데이터 삭제는 파괴적이므로 원인을 확인한 뒤 별도 복구 계획으로 처리합니다.

노드는 Ready인데 CoreDNS나 CNI가 준비되지 않는다

bash
kubectl -n kube-system get pods -o wide
kubectl -n kube-system get events --sort-by=.lastTimestamp
sudo journalctl -u rke2-server -n 200 --no-pager

호스트 방화벽, MTU, NetworkManager가 CNI 인터페이스를 관리하는 문제, 커널 모듈·sysctl 요구 사항을 우선 확인합니다. 무작정 방화벽을 끄기 전에 어떤 패킷이 차단되는지 기록합니다.

kubectl이 인증서 오류를 낸다

외부 kubeconfig의 server:를 DNS로 바꿨는데 그 이름이 tls-san에 없다면 인증서 검증이 실패합니다. config.yaml의 tls-san을 고친 뒤 RKE2 인증서 갱신 절차를 확인합니다. --insecure-skip-tls-verify로 상시 우회하지 않습니다.

Rancher 파드가 Pending이다

bash
kubectl -n cattle-system get pod -o wide
kubectl -n cattle-system describe pod -l app=rancher
kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints

단일 노드의 자원 부족, taint, 이미지 pull 실패를 확인합니다. cert-manager가 준비되기 전에 Rancher를 설치했다면 관련 webhook과 certificate 이벤트도 함께 봅니다.

Rancher URL이 열리지 않는다

이 단계에서는 ingress.enabled=false로 설치하므로 외부 진입점이 없습니다. 따라서 Rancher URL이 열리지 않는 것만으로 내부 설치 실패라고 판단하지 않습니다. 임시로 임의의 NodePort나 레거시 Ingress를 추가하지 않고, 다음 글에서 MetalLB와 Gateway API로 접속 경로를 구성합니다.

운영과 보안에서 놓치기 쉬운 것

조인 토큰과 kubeconfig는 백업 대상이자 비밀이다

RKE2 token은 새 노드 조인뿐 아니라 재해 복구에서 bootstrap 데이터를 해독하는 데도 중요합니다. etcd 스냅샷만 있고 원래 token이 없으면 새 호스트 복구가 실패할 수 있습니다. token과 관리자 kubeconfig는 비밀 저장소에 별도로 보관하며, 누가 접근했는지 감사할 수 있도록 관리합니다.

etcd 스냅샷을 “생성”이 아니라 “복구”까지 시험한다

RKE2는 embedded etcd의 예약 스냅샷을 기본 제공하고 필요할 때 수동 스냅샷도 만들 수 있습니다.

bash
sudo rke2 etcd-snapshot save --name before-platform-change
sudo rke2 etcd-snapshot list

스냅샷을 같은 노드 디스크에만 두면 노드와 함께 잃을 수 있습니다. S3 호환 오브젝트 스토리지 같은 별도 장애 도메인으로 복제하고, 격리된 환경에서 복구 훈련을 합니다. 수동 스냅샷은 자동 보존 정책이 없으므로 정리 정책도 필요합니다.

업그레이드는 한 번에 한 minor 버전과 한 노드씩

업그레이드 전에는 릴리스 노트, deprecated API, CNI와 Rancher 지원 매트릭스를 확인합니다. etcd 스냅샷을 남기고 server를 순차적으로 올린 뒤 agent를 올립니다. 단순히 설치 스크립트를 다시 실행했다고 업그레이드 검증이 끝난 것은 아닙니다. API readiness, 노드 상태, 시스템 파드, 실제 애플리케이션 요청까지 확인합니다.

원격 설치 스크립트와 이미지 공급망

curl | sh는 학습에는 간단하지만 운영 자동화에서는 버전, 다운로드 위치, 체크섬을 고정하고 내부 미러를 사용하는 편이 낫습니다. RKE2와 Helm 설치물, Rancher Chart, 컨테이너 이미지가 어떤 경로로 들어오는지 기록하고 변경 승인을 거칩니다.

요약

  • Kubespray는 Ansible로 업스트림 Kubernetes를 세밀하게 조립하고, RKE2는 검증된 배포판을 systemd 중심으로 운영합니다.
  • RKE2를 선택해도 HA 주소, etcd 쿼럼, 백업, 방화벽, 버전 정책에 대한 운영 책임은 사라지지 않습니다.
  • 신규 구성에서 kube-proxy IPVS 모드를 기본값으로 권장하지 않습니다. 이 글은 RKE2 기본값을 유지합니다.
  • 이 글의 실습 범위는 RKE2 server, kubectl, Helm, cert-manager, Rancher 설치까지입니다. Rancher 외부 노출은 다음 글에서 이어갑니다.
  • 토큰과 kubeconfig를 비밀로 다루고, etcd 스냅샷은 반드시 별도 장애 도메인과 복구 훈련까지 연결해야 합니다.

이전 글: 전체 시리즈 목차
다음 글: Kubernetes 트래픽은 어디로 들어오는가 — kube-vip, MetalLB, Gateway API

공식 참고자료