[Kubernetes] Cluster: RKE2를 이용해 클러스터 구성하기 - 4.1. 수동 업그레이드

8 분 소요

서종호(가시다)님의 On-Premise K8s Hands-on Study 7주차 학습 내용을 기반으로 합니다.


TL;DR

이번 글의 목표는 RKE2 클러스터를 수동으로 업그레이드하는 절차를 이해하는 것이다.

  • 수동 업그레이드 방식: Installation Script, Binary, RPM 세 가지가 있다.
  • 업그레이드 순서: 서버(컨트롤 플레인) 노드를 먼저 업그레이드하고, 그 다음 에이전트(워커) 노드를 업그레이드한다.
  • Installation Script 방식: INSTALL_RKE2_CHANNEL 환경변수로 목표 버전을 지정하고 설치 스크립트를 실행한다.
  • 서비스 재시작 필수: 스크립트 실행 후 반드시 systemctl restart rke2-server 또는 rke2-agent로 프로세스를 재시작해야 한다.
  • 무중단 업그레이드: containerd shim이 입양(adopt)되므로, Pod data path 통신은 업그레이드 중에도 유지된다.


들어가며

이전 글에서 RKE2의 인증서 관리 구조를 살펴봤다. 이번 글에서는 운영 중인 RKE2 클러스터를 업그레이드하는 방법을 다룬다.

수동 업그레이드 시 Kubernetes version skew policy가 적용된다. 중간 마이너 버전을 건너뛰지 않도록 업그레이드 계획을 세워야 한다.

RKE2는 수동 업그레이드를 위해 세 가지 방법을 제공한다.

방법 설명
Installation Script curl -sfL https://get.rke2.io 스크립트를 채널 지정과 함께 실행
Binary 바이너리를 직접 다운로드해서 교체
RPM yum/dnf 패키지 매니저로 업그레이드

이번 글에서는 Installation Script 방식으로 v1.33에서 v1.34로 업그레이드하는 과정을 실습한다.


수동 업그레이드 절차

업그레이드 순서

수동 업그레이드는 다음 순서를 반드시 지켜야 한다.

  1. 서버(컨트롤 플레인) 노드를 하나씩 업그레이드 완료
  2. 에이전트(워커) 노드를 업그레이드

서버 노드가 먼저 업그레이드되어야 하는 이유는 Kubernetes의 버전 호환성 정책(version skew policy) 때문이다. kube-apiserver는 kubelet보다 같거나 높은 마이너 버전이어야 한다. 서버를 먼저 올리면 API 서버가 v1.34가 되고, 워커의 kubelet이 v1.33인 상태는 허용 범위 내다. 반대로 워커를 먼저 올리면 kubelet이 API 서버보다 높은 버전이 되어 문제가 발생할 수 있다.

Installation Script 방식

설치 스크립트에 INSTALL_RKE2_CHANNEL 환경변수로 목표 채널을 지정하면 해당 채널의 최신 안정 버전으로 업그레이드된다. RPM 기반 시스템에서는 내부적으로 dnf/yum을 사용해 패키지를 업그레이드한다.

# 서버 노드
curl -sfL https://get.rke2.io | INSTALL_RKE2_CHANNEL=v1.34 sh -
systemctl restart rke2-server

# 에이전트 노드
curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE=agent INSTALL_RKE2_CHANNEL=v1.34 sh -
systemctl restart rke2-agent

스크립트 실행만으로는 업그레이드가 완료되지 않는다. 반드시 RKE2 프로세스를 재시작해야 한다.

버전 선택 시 GitHub Release 페이지에서 verified 라벨이 붙은 릴리즈를 사용하고, rc(release candidate)가 붙은 버전은 피한다.

채널 대신 특정 버전을 직접 지정할 수도 있다. INSTALL_RKE2_VERSION 환경변수를 사용한다.

curl -sfL https://get.rke2.io | INSTALL_RKE2_VERSION=vX.Y.Z+rke2rN sh -

Binary 방식

바이너리를 직접 다운로드해서 교체하는 방식이다. 에어갭(air-gap) 환경이나 네트워크 제약이 있는 경우에 유용하다.

절차는 다음과 같다.

  1. GitHub Release 페이지에서 목표 버전의 바이너리(tarball)를 다운로드한다.
  2. 다운로드한 바이너리를 설치 경로에 배치한다.
    • tarball 설치: /usr/local/bin/rke2
    • RPM 설치: /usr/bin/rke2
  3. RKE2 프로세스를 재시작한다.
# 서버 노드
systemctl restart rke2-server

# 에이전트 노드
systemctl restart rke2-agent

기존 설치가 tarball 방식인지 RPM 방식인지에 따라 바이너리 경로가 다르다. which rke2로 현재 바이너리 경로를 확인한 후 해당 경로에 새 바이너리를 덮어쓴다.

RPM 방식

RPM 기반 시스템(RHEL, CentOS, Rocky Linux, SLES 등)에서 패키지 매니저를 직접 사용하는 방식이다.

# 서버 노드
yum update rke2-server
systemctl restart rke2-server

# 에이전트 노드
yum update rke2-agent
systemctl restart rke2-agent

SLES 계열에서는 zypper를 사용한다.

zypper update rke2-server  # 또는 rke2-agent

SELinux를 사용 중이라면 SELinux 패키지도 함께 업데이트한다.

yum update rke2-selinux

Installation Script 방식이 내부적으로 RPM 방식을 사용하므로, 두 방식의 실질적인 차이는 리포지토리 설정을 스크립트가 자동으로 해주느냐, 관리자가 직접 관리하느냐에 있다.


실습: Installation Script

환경 확인

실습 환경은 서버 노드 1대(node1)와 에이전트 노드 1대(node2)로 구성되어 있다.

[root@week07-k8s-node1 ~]# kubectl get node
NAME               STATUS   ROLES                       AGE   VERSION
week07-k8s-node1   Ready    control-plane,etcd,master   26h   v1.33.8+rke2r1
week07-k8s-node2   Ready    <none>                      22h   v1.33.8+rke2r1

[root@week07-k8s-node1 ~]# rke2 --version
rke2 version v1.33.8+rke2r1 (eb75e3c1774cee5a584259d6fee77eb8cfa9b430)
go version go1.24.12 X:boringcrypto

업그레이드 대상 채널 정보를 확인한다.

[root@week07-k8s-node1 ~]# curl -s https://update.rke2.io/v1-release/channels | jq '.data[] | select(.id == "v1.34")'
{
  "id": "v1.34",
  "type": "channel",
  "links": {
    "self": "https://update.rke2.io/v1-release/channels/v1.34"
  },
  "name": "v1.34",
  "latest": "v1.34.4+rke2r1",
  "latestRegexp": "v1\\.34\\..*",
  "excludeRegexp": "^[^+]+-"
}

v1.34 채널의 최신 안정 버전은 v1.34.4+rke2r1이다.

모니터링 준비

업그레이드 진행 중 클러스터 상태를 관찰하기 위해 여러 터미널에서 모니터링을 건다.

# 어플리케이션 통신 모니터링
while true; do curl -s http://192.168.10.12:30000 | grep Hostname; date; sleep 1; done

# 파드 상태 모니터링 (최근 생성된 파드가 상단에 오도록)
watch -d "kubectl get pod -n kube-system -owide --sort-by=.metadata.creationTimestamp | tac"

# 노드 상태 모니터링
watch -d "kubectl get node"

# etcd 멤버 상태 모니터링
watch -d etcdctl \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/var/lib/rancher/rke2/server/tls/etcd/server-ca.crt \
  --cert=/var/lib/rancher/rke2/server/tls/etcd/client.crt \
  --key=/var/lib/rancher/rke2/server/tls/etcd/client.key \
  member list --write-out=table

서버 노드 업그레이드

스크립트 실행

서버 노드(node1)에서 설치 스크립트를 실행한다.

[root@week07-k8s-node1 ~]# curl -sfL https://get.rke2.io | INSTALL_RKE2_CHANNEL=v1.34 sh -
[INFO]  using stable RPM repositories
[INFO]  using 1.34 series from channel stable
...
Package rke2-server-1.33.8~rke2r1-0.el9.aarch64 is already installed.
Dependencies resolved.
==========================================================================================================================
 Package                 Architecture        Version                           Repository                            Size
==========================================================================================================================
Upgrading:
 rke2-common             aarch64             1.34.4~rke2r1-0.el9               rancher-rke2-1.34-stable              25 M
 rke2-server             aarch64             1.34.4~rke2r1-0.el9               rancher-rke2-1.34-stable             8.3 k

Transaction Summary
==========================================================================================================================
Upgrade  2 Packages
...
Complete!

rke2-commonrke2-server 패키지가 1.33.8에서 1.34.4로 업그레이드된다. RPM 기반이므로 내부적으로 dnf가 패키지를 교체한다.

버전 확인

[root@week07-k8s-node1 ~]# rke2 --version
rke2 version v1.34.4+rke2r1 (c6b97dc03cefec17e8454a6f45b29f4e3d0a81d6)
go version go1.24.12 X:boringcrypto

바이너리 버전은 이미 v1.34.4로 교체되었지만, 아직 프로세스를 재시작하지 않았으므로 실행 중인 컴포넌트는 여전히 v1.33.8이다.

[root@week07-k8s-node1 ~]# kubectl version --short
Client Version: v1.34.4
Server Version: v1.33.8

Server Version이 이전 버전(v1.33.8)인 동안 rke2 --version은 새 바이너리 버전(v1.34.4)을 가리킨다. systemctl restart rke2-server 후에는 둘 다 v1.34.4로 맞춰진다.

RPM 리포지토리 변경 확인

스크립트 실행 후 dnf 리포지토리도 v1.34 채널로 변경된다.

[root@week07-k8s-node1 ~]# dnf repolist
repo id                                                      repo name
appstream                                                    Rocky Linux 9 - AppStream
baseos                                                       Rocky Linux 9 - BaseOS
extras                                                       Rocky Linux 9 - Extras
rancher-rke2-1.34-stable                                     Rancher RKE2 1.34 (v1.34)
rancher-rke2-common-stable                                   Rancher RKE2 Common (v1.34)

기존 rancher-rke2-1.33-stablerancher-rke2-1.34-stable로 교체되었다.

서비스 재시작

공식 문서에 명시된 대로, 스크립트 실행 후 반드시 프로세스를 재시작해야 한다.

[root@week07-k8s-node1 ~]# systemctl restart rke2-server

재시작 시 kube-system 네임스페이스의 파드들이 순차적으로 재생성된다.

  • 1차: etcd, kube-apiserver, kube-proxy
  • 2차: kube-scheduler, kube-controller-manager

API 서버도 잠시 끊기지만, 곧 v1.34 버전으로 다시 올라온다.

[root@week07-k8s-node1 ~]# kubectl get pod -n kube-system --sort-by=.metadata.creationTimestamp | tac
helm-install-rke2-canal-whl5f                0/1     Completed   0          104s
helm-install-rke2-coredns-qw272              0/1     Completed   0          104s
helm-install-rke2-metrics-server-k2lgn       0/1     Completed   0          104s
helm-install-rke2-runtimeclasses-lmhvj       0/1     Completed   0          104s
kube-controller-manager-week07-k8s-node1     1/1     Running     0          2m2s
kube-scheduler-week07-k8s-node1              1/1     Running     0          2m5s
kube-proxy-week07-k8s-node1                  1/1     Running     0          2m51s
etcd-week07-k8s-node1                        1/1     Running     0          2m51s
kube-apiserver-week07-k8s-node1              1/1     Running     0          2m51s
kube-proxy-week07-k8s-node2                  1/1     Running     0          22h
rke2-canal-cfzvq                             2/2     Running     0          22h
rke2-metrics-server-fdcdf575d-kqg72          1/1     Running     0          26h
rke2-canal-mqjm6                             2/2     Running     0          26h
rke2-coredns-rke2-coredns-559595db99-tsxnc   1/1     Running     0          26h
NAME                                         READY   STATUS      RESTARTS   AGE

서버 노드(node1)의 파드들은 새로 기동되었고, 워커 노드(node2)의 파드들은 아직 이전 상태를 유지하고 있다.

확인할 점은 AGE파드 이름에 붙은 노드 이름이다. 서버 노드(node1)에 있는 컨트롤 플레인 파드(etcd, kube-apiserver, kube-scheduler, kube-controller-manager, kube-proxy-week07-k8s-node1)는 AGE가 2~3분대로 짧아서 방금 재기동된 것이고, 워커 노드(node2) 쪽 파드(-week07-k8s-node2 또는 node2에 스케줄된 Canal/CoreDNS 등)는 AGE가 22h~26h로 그대로라 아직 재시작하지 않은 상태임을 알 수 있다.

노드 상태 확인

[root@week07-k8s-node1 ~]# kubectl get node -o wide
NAME               STATUS   ROLES                       AGE   VERSION          INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                      KERNEL-VERSION                  CONTAINER-RUNTIME
week07-k8s-node1   Ready    control-plane,etcd,master   26h   v1.34.4+rke2r1   192.168.10.11   <none>        Rocky Linux 9.6 (Blue Onyx)   5.14.0-570.52.1.el9_6.aarch64   containerd://2.1.5-k3s1
week07-k8s-node2   Ready    <none>                      22h   v1.33.8+rke2r1   10.0.2.15       <none>        Rocky Linux 9.6 (Blue Onyx)   5.14.0-570.52.1.el9_6.aarch64   containerd://2.1.5-k3s1

서버 노드는 v1.34.4로 업그레이드되었고, 워커 노드는 아직 v1.33.8이다. 마이너 버전이 1 차이 나는 상태는 Kubernetes version skew policy 허용 범위 내다.

컨테이너 이미지 확인

[root@week07-k8s-node1 ~]# kubectl get pods -n kube-system \
  -o custom-columns=\
POD:.metadata.name,\
CONTAINERS:.spec.containers[*].name,\
IMAGES:.spec.containers[*].image
POD                                          CONTAINERS                 IMAGES
etcd-week07-k8s-node1                        etcd                       index.docker.io/rancher/hardened-etcd:v3.6.7-k3s1-build20260126
kube-apiserver-week07-k8s-node1              kube-apiserver             index.docker.io/rancher/hardened-kubernetes:v1.34.4-rke2r1-build20260210
kube-controller-manager-week07-k8s-node1     kube-controller-manager    index.docker.io/rancher/hardened-kubernetes:v1.34.4-rke2r1-build20260210
kube-proxy-week07-k8s-node1                  kube-proxy                 index.docker.io/rancher/hardened-kubernetes:v1.34.4-rke2r1-build20260210
kube-proxy-week07-k8s-node2                  kube-proxy                 index.docker.io/rancher/hardened-kubernetes:v1.33.8-rke2r1-build20260210
kube-scheduler-week07-k8s-node1              kube-scheduler             index.docker.io/rancher/hardened-kubernetes:v1.34.4-rke2r1-build20260210
...

서버 노드의 컨트롤 플레인 컴포넌트들이 v1.34.4-rke2r1 이미지로 교체된 것을 확인할 수 있다. 워커 노드의 kube-proxy는 아직 v1.33.8-rke2r1이다.

어플리케이션 영향

스크립트 실행 과정에서 어플리케이션 통신에는 영향이 없었다. containerd shim이 입양되기 때문에, RKE2 프로세스가 재시작되더라도 이미 실행 중인 컨테이너의 data path는 유지된다.

에이전트 노드 업그레이드

스크립트 실행

에이전트 노드(node2)에서 설치 스크립트를 실행한다. INSTALL_RKE2_TYPE=agent를 지정해야 한다.

[root@week07-k8s-node2 ~]# rke2 --version
rke2 version v1.33.8+rke2r1 (eb75e3c1774cee5a584259d6fee77eb8cfa9b430)
go version go1.24.12 X:boringcrypto

[root@week07-k8s-node2 ~]# curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE=agent INSTALL_RKE2_CHANNEL=v1.34 sh -
[INFO]  using stable RPM repositories
[INFO]  using 1.34 series from channel stable
...
Dependencies resolved.
=========================================================================================================================
 Package                 Architecture        Version                          Repository                            Size
=========================================================================================================================
Upgrading:
 rke2-agent              aarch64             1.34.4~rke2r1-0.el9              rancher-rke2-1.34-stable             8.3 k
 rke2-common             aarch64             1.34.4~rke2r1-0.el9              rancher-rke2-1.34-stable              25 M
...
Complete!

버전 확인 및 서비스 재시작

[root@week07-k8s-node2 ~]# rke2 --version
rke2 version v1.34.4+rke2r1 (c6b97dc03cefec17e8454a6f45b29f4e3d0a81d6)
go version go1.24.12 X:boringcrypto

[root@week07-k8s-node2 ~]# systemctl restart rke2-agent

에이전트 노드도 서버 노드와 마찬가지로 RPM 리포지토리가 v1.34로 변경된다.

[root@week07-k8s-node2 ~]# dnf repolist
repo id                                                     repo name
appstream                                                   Rocky Linux 9 - AppStream
baseos                                                      Rocky Linux 9 - BaseOS
extras                                                      Rocky Linux 9 - Extras
rancher-rke2-1.34-stable                                    Rancher RKE2 1.34 (v1.34)
rancher-rke2-common-stable                                  Rancher RKE2 Common (v1.34)

최종 확인

노드 버전 확인

서버 노드(node1)에서 전체 클러스터 상태를 확인한다.

[root@week07-k8s-node1 ~]# kubectl get node -owide
NAME               STATUS   ROLES                       AGE   VERSION          INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                      KERNEL-VERSION                  CONTAINER-RUNTIME
week07-k8s-node1   Ready    control-plane,etcd,master   26h   v1.34.4+rke2r1   192.168.10.11   <none>        Rocky Linux 9.6 (Blue Onyx)   5.14.0-570.52.1.el9_6.aarch64   containerd://2.1.5-k3s1
week07-k8s-node2   Ready    <none>                      22h   v1.34.4+rke2r1   10.0.2.15       <none>        Rocky Linux 9.6 (Blue Onyx)   5.14.0-570.52.1.el9_6.aarch64   containerd://2.1.5-k3s1

두 노드 모두 v1.34.4+rke2r1로 업그레이드 완료되었다.

파드 상태 확인

[root@week07-k8s-node1 ~]# kubectl get pod -n kube-system --sort-by=.metadata.creationTimestamp | tac
kube-proxy-week07-k8s-node2                  1/1     Running     0          97s
kube-proxy-week07-k8s-node1                  1/1     Running     0          7m43s
helm-install-rke2-canal-whl5f                0/1     Completed   0          11m
helm-install-rke2-coredns-qw272              0/1     Completed   0          11m
helm-install-rke2-metrics-server-k2lgn       0/1     Completed   0          11m
helm-install-rke2-runtimeclasses-lmhvj       0/1     Completed   0          11m
kube-controller-manager-week07-k8s-node1     1/1     Running     0          12m
kube-scheduler-week07-k8s-node1              1/1     Running     0          12m
etcd-week07-k8s-node1                        1/1     Running     0          12m
kube-apiserver-week07-k8s-node1              1/1     Running     0          12m
rke2-canal-cfzvq                             2/2     Running     0          22h
rke2-metrics-server-fdcdf575d-kqg72          1/1     Running     0          26h
rke2-canal-mqjm6                             2/2     Running     0          26h
rke2-coredns-rke2-coredns-559595db99-tsxnc   1/1     Running     0          26h
NAME                                         READY   STATUS      RESTARTS   AGE

워커 노드에서는 kube-proxy만 새로 재기동되었다. 서버 노드처럼 etcd나 API 서버 같은 컨트롤 플레인 컴포넌트가 없으므로, 에이전트 노드의 업그레이드 영향 범위는 상대적으로 작다.

컨테이너 이미지 확인

[root@week07-k8s-node1 ~]# kubectl get pods -n kube-system -o custom-columns="POD_NAME:.metadata.name,IMAGES:.spec.containers[*].image"
POD_NAME                                     IMAGES
etcd-week07-k8s-node1                        index.docker.io/rancher/hardened-etcd:v3.6.7-k3s1-build20260126
...
kube-apiserver-week07-k8s-node1              index.docker.io/rancher/hardened-kubernetes:v1.34.4-rke2r1-build20260210
kube-controller-manager-week07-k8s-node1     index.docker.io/rancher/hardened-kubernetes:v1.34.4-rke2r1-build20260210
kube-proxy-week07-k8s-node1                  index.docker.io/rancher/hardened-kubernetes:v1.34.4-rke2r1-build20260210
kube-proxy-week07-k8s-node2                  index.docker.io/rancher/hardened-kubernetes:v1.34.4-rke2r1-build20260210
kube-scheduler-week07-k8s-node1              index.docker.io/rancher/hardened-kubernetes:v1.34.4-rke2r1-build20260210
...

워커 노드의 kube-proxy도 v1.34.4-rke2r1로 업그레이드되었다.

kubeconfig 확인

버전 업그레이드 시 kubeconfig(admin 인증서)가 변경되는지 확인한다.

[root@week07-k8s-node1 ~]# diff /etc/rancher/rke2/rke2.yaml ~/.kube/config
13a14
> preferences: {}

인증서 로테이션과 달리, 버전 업그레이드만으로는 kubeconfig의 client-certificate-data가 변경되지 않는다. kubeconfig 갱신이 필요하지 않다.


결과

RKE2 클러스터를 Installation Script 방식으로 v1.33.8에서 v1.34.4로 수동 업그레이드했다.

항목 내용
업그레이드 순서 서버 노드 먼저, 에이전트 노드 나중에
스크립트 실행 결과 RPM 패키지 교체 + dnf 리포지토리 채널 변경
서비스 재시작 필수 — 재시작 시 컨트롤 플레인 파드 순차 재생성
서버 노드 재생성 순서 etcd, apiserver, kube-proxy → scheduler, controller-manager
에이전트 노드 영향 kube-proxy만 재기동
어플리케이션 영향 무중단 — containerd shim 입양으로 data path 유지
kubeconfig 변경 없음 — 버전 업그레이드만으로는 인증서가 변경되지 않음


참고



hit count

댓글남기기