RKE 소개

진웅·2026년 2월 20일

k8s deploy

목록 보기
19/20

RKE2 " 차세대 엔터프라이즈 Kubernetes 배포판

개요

  • RKE2는 Rancher에서 개발한 엔터프라이즈급 Kubernetes 배포판이다.
  • 미국 연방 정부 수준의 보안 및 규정 준수 요건을 충족하도록 설계되었다.
  • 경량 Kubernetes인 K3s 개발 경험을 토대로 만들어졌다.
  • K3s의 사용 편의성은 유지하면서, 엔터프라이즈 환경에서 요구하는 보안성안정성을 갖춘 것이 핵심 특징이다.

RKE2 설계 주요 컨셉

  • RKE2의 가장 중요한 특징은 단일 바이너리 방식이다.
  • Kubernetes 클러스터에 참여할 모든 노드에 단 하나의 바이너리만 설치하면 된다.
  • 설치 후 RKE2가 기동되면 해당 노드의 역할(Server/Agent)에 맞는 에이전트를 자동으로 부트스트랩하고, 필요한 컨텐츠를 네트워크에서 가져온다.

보안 측면에서 세 가지 핵심 요소를 제공한다.

첫째, CIS Kubernetes Benchmark 준수한다.

  • v1.7 또는 v1.8 벤치마크를 통과할 수 있도록 기본 설정 및 구성 옵션을 제공하며, 운영자의 개입을 최소화한다.

둘째, FIPS 140-2 규정 준수를 지원한다.
셋째, 빌드 파이프라인에서 Trivy를 사용하여 구성 요소의 CVE를 정기적으로 스캔한다.

  • FIPS 140-2는 암호화 모듈의 보안성을 검증하는 국제적으로 인정된 표준이다.

컨트롤 플레인 구성 요소는 kubelet이 관리하는 정적 Pod로 실행되며, 내장 컨테이너 런타임은 containerd다.


RKE2 아키텍처

RKE2의 전체 구성 요소

  • K3s 레이어
  • Kubernetes 코어
  • 네트워킹/애드온 레이어


구성 요소 상세

K3s 레이어 — Helm Controller

  • RKE2 내부의 K3s 레이어에서 가장 핵심적인 역할을 하는 건 Helm Controller다.

  • GitOps 스타일의 경량 배포 컨트롤러로, RKE2 클러스터 부팅 시 필수 Helm 차트를 자동으로 설치하고 유지한다.

동작 방식은 단순하다. /var/lib/rancher/rke2/server/manifests 디렉토리를 감시하다가, HelmChart YAML 파일이 생기면 자동으로 Helm chart를 설치/업데이트한다.

tree /var/lib/rancher/rke2/server/manifests
├── rke2-canal-config.yaml
├── rke2-canal.yaml
├── rke2-coredns-config.yaml
├── rke2-coredns.yaml
├── rke2-metrics-server.yaml
└── rke2-runtimeclasses.yaml

Helm Controller와 ArgoCD의 역할 차이를 명확히 구분할 필요가 있다.

구분Helm ControllerArgo CD
목적부트스트랩 (필수 애드온 자동 설치)GitOps (애플리케이션 배포)
트리거디렉토리 파일 감시Git 레포지토리 동기화
사용 시점클러스터 부팅 시애플리케이션 배포 라이프사이클 전반

Kubernetes 코어

표준 Kubernetes 구성 요소를 그대로 포함한다. 컨트롤 플레인은 API Server, Controller Manager, Scheduler로 구성되고, 워커 노드에는 Proxy와 Kubelet이 동작한다.

컨테이너 런타임 스택

etcd → containerd → runc 구조로 동작한다. etcd가 클러스터 상태를 저장하고, containerd가 컨테이너 라이프사이클을 관리하며, runc가 실제 컨테이너 프로세스를 생성한다.

CNI — Canal (기본값)

RKE2의 기본 CNI는 Canal이다. Canal은 Flannel과 Calico를 결합한 하이브리드 CNI로, 네트워크 연결은 Flannel이, 네트워크 정책 및 보안은 Calico가 담당한다.

Canal DaemonSet 파드 내부를 보면 두 컨테이너가 함께 실행되는 것을 확인할 수 있다.

kubectl describe pod -n kube-system -l k8s-app=canal | grep Image: | uniq
  Image: rancher/hardened-calico:v3.31.3-build20260119
  Image: rancher/hardened-flannel:v0.28.0-build20260119

Canal 외에도 Cilium, Calico 단독, Flannel 단독, 그리고 멀티 네트워크를 위한 Multus를 지원한다.

애드온 레이어

구성 요소역할
CoreDNS클러스터 내부 DNS
Ingress NGINX ControllerHTTP(S) 인그레스 처리
Traefik대안 인그레스 컨트롤러
Metrics Server리소스 사용량 수집 (HPA 기반)
Helm패키지 관리

RKE2 vs K3s — 차이점

RKE2는 K3s에서 출발했지만 목적이 다르다.

  • K3s는 엣지, IoT, 개발 환경처럼 리소스가 제한된 환경에 최적화된 경량 배포판이다.
  • RKE2는 그 사용 편의성을 유지하면서 엔터프라이즈 환경, 특히 보안 규제가 엄격한 환경(금융, 정부, 국방)에서 운영 가능하도록 보안 기본값과 규정 준수 기능을 대폭 강화했다.

단순하게 말하면, K3s의 개발 경험(DX) + 엔터프라이즈 보안 요건을 모두 잡은 배포판이 RKE2다.


RKE2 Process Lifecycle — 부팅부터 데몬 실행까지

  • RKE2가 기동될 때 내부적으로 어떤 순서로 구성 요소가 올라오는지 추적한다.
  • 크게 4단계로 나뉜다:
    Content Bootstrap → Initialize Server → Initialize Agent → Daemon Process.

1단계: Content Bootstrap — 런타임 이미지에서 모든 것을 꺼낸다

  • RKE2의 시작점은 rke2-runtime 컨테이너 이미지다.
  • 이 이미지 하나에 바이너리와 Helm 차트가 모두 담겨 있다.

런타임 이미지 위치 결정

  • RKE2는 먼저 /var/lib/rancher/rke2/agent/images/ 디렉토리를 스캔해서 *.tar 파일을 찾는다.
  • 없으면 DockerHub에서 가져온다. 어떤 이미지를 써야 하는지는 runtime-image.txt에 명시되어 있다.
cat /var/lib/rancher/rke2/agent/images/runtime-image.txt
index.docker.io/rancher/rke2-runtime:v1.34.3-rke2r3

해당 디렉토리에는 각 컴포넌트별 이미지 참조 파일도 함께 있다.

tree /var/lib/rancher/rke2/agent/images/
├── etcd-image.txt
├── kube-apiserver-image.txt
├── kube-controller-manager-image.txt
├── kube-proxy-image.txt
├── kube-scheduler-image.txt
└── runtime-image.txt

런타임 이미지 내부 구조

rke2-runtime 이미지는 두 가지를 담고 있다.

# rke2-runtime 이미지 내부
├── bin/
│   ├── containerd
│   ├── containerd-shim-runc-v2
│   ├── crictl
│   ├── ctr
│   ├── kubectl
│   ├── kubelet
│   └── runc
└── charts/
    ├── rke2-canal.yaml
    ├── rke2-cilium.yaml
    ├── rke2-coredns.yaml
    ├── rke2-ingress-nginx.yaml
    ├── rke2-metrics-server.yaml
    ├── rke2-traefik.yaml
    └── ... (19개 차트)

RKE2가 정상 작동하려면 런타임 이미지는 최소한 containerd, containerd-shim-runc-v2, kubelet, runc 네 가지를 제공해야 한다. 운영 도구로는 crictl, ctr, kubectl도 포함된다.

바이너리 추출 및 배치

이미지에서 /bin/을 추출해서 아래 경로로 평탄화한다. ${RKE2_DATA_KEY}는 이미지 버전을 식별하는 고유 문자열이다.

/var/lib/rancher/rke2/data/${RKE2_DATA_KEY}/bin/
# 예시
/var/lib/rancher/rke2/data/v1.34.3-rke2r3-5b8349de68df/bin/
├── containerd
├── containerd-shim-runc-v2
├── crictl
├── ctr
├── kubectl
├── kubelet
└── runc

차트 추출 및 manifests 배치

바이너리 추출 완료 후, 이미지의 charts/에서 실제로 활성화할 차트만 /var/lib/rancher/rke2/server/manifests/로 복사한다. 기본 CNI(Canal)와 필수 애드온만 배치되는 것을 확인할 수 있다.

tree /var/lib/rancher/rke2/server/manifests/
├── rke2-canal-config.yaml
├── rke2-canal.yaml
├── rke2-coredns-config.yaml
├── rke2-coredns.yaml
├── rke2-metrics-server.yaml
└── rke2-runtimeclasses.yaml

2단계: Initialize Server — 컨트롤 플레인 컴포넌트 기동

임베디드 K3s 엔진 서버에는 특수 에이전트 프로세스가 포함되어 있다.
노드의 컨테이너 런타임이 올라올 때까지 다음 단계는 지연된다.

컴포넌트 준비 순서 (Prepare Components)

컨트롤 플레인 컴포넌트는 의존 관계에 따라 순차적으로 정적 파드 정의를 작성한다. 각각 goroutine을 통해 비동기로 대기하다가 선행 조건이 충족되면 /var/lib/rancher/rke2/agent/pod-manifests/에 YAML을 기록한다.

컴포넌트대기 조건정적 파드 작성
kube-apiserveretcd 준비 완료pod-manifests/kube-apiserver.yaml
kube-controller-managerkube-apiserver 준비 완료pod-manifests/kube-controller-manager.yaml
kube-schedulerkube-apiserver 준비 완료pod-manifests/kube-scheduler.yaml
etcdkubelet 준비 완료pod-manifests/etcd.yaml
helm-controllerkube-apiserver 준비 완료(embedded, goroutine으로 시작)

실제 파일 상태를 보면 작성 순서가 타임스탬프에 그대로 찍혀있다.

ls -ltr /var/lib/rancher/rke2/agent/pod-manifests/
-rw-r--r--. 1 root root 3279 Feb 14 16:32 etcd.yaml
-rw-r--r--. 1 root root 2325 Feb 14 16:32 kube-proxy.yaml
-rw-r--r--. 1 root root 9337 Feb 14 16:33 kube-apiserver.yaml
-rw-r--r--. 1 root root 3724 Feb 14 16:33 kube-scheduler.yaml
-rw-r--r--. 1 root root 6325 Feb 14 16:33 kube-controller-manager.yaml

클러스터 시작 (Start Cluster)

컴포넌트 준비가 끝나면 goroutine으로 HTTP 서버를 띄워서 다른 서버/에이전트 노드의 합류 요청을 수신한다. 이 시점부터 클러스터 초기화 또는 기존 클러스터 조인이 시작된다.

systemd 서비스 단위 파일 핵심 설정

# /usr/lib/systemd/system/rke2-server.service
ExecStart=/usr/bin/rke2 server

KillMode=process   # rke2 프로세스만 종료, 자식 프로세스(containerd, shim 등)는 systemd가 건드리지 않음
Delegate=yes       # cgroup 관리를 systemd가 아닌 rke2 자신이 직접 담당
Restart=always
RestartSec=5s

KillMode=process가 핵심이다. rke2 바이너리가 종료되더라도 containerd와 컨테이너 shim 프로세스는 살아있어 실행 중인 컨테이너가 즉시 중단되지 않는다. Delegate=yes는 cgroup 계층 구조를 rke2가 직접 관리하도록 위임해서, Kubernetes의 파드별 리소스 격리가 제대로 동작하게 한다.

rke2-server 프로세스 트리

pstree -al
├─rke2
│   ├─containerd -c /var/lib/rancher/rke2/agent/etc/containerd/config.toml
│   ├─kubelet --containerd=/run/k3s/containerd/containerd.sock ...
│   └─{rke2 worker threads}

3단계: Initialize Agent — 컨테이너 런타임과 노드 에이전트 기동

에이전트 프로세스의 진입점이다. 서버 노드의 경우 임베디드 K3s 엔진이 직접 호출한다.

Container Runtime

containerd 프로세스를 생성하고 종료를 감시한다. containerd가 종료되면 rke2 프로세스 자체도 종료된다.

Node Agent

kubelet을 spawn해서 감시(supervise)한다. kubelet이 종료되면 rke2가 재시작을 시도한다. kubelet이 정상 작동하기 시작하면, pod-manifests/에 있는 모든 정적 파드가 순서대로 기동된다.

서버 노드의 경우 etcd → kube-apiserver 순서로 연속 기동되고, 이후 나머지 컴포넌트들이 kube-apiserver에 연결되어 처리를 시작한다.

Server Charts — Helm Controller 적용

서버 노드에서 helm-controller가 활성화되면, /var/lib/rancher/rke2/server/manifests/의 차트들을 클러스터에 순서대로 적용한다.

차트종류비고
rke2-canal / cilium / calico / flannelDaemonSetCNI, bootstrap
rke2-corednsDeploymentbootstrap
rke2-ingress-nginx / traefikDeployment인그레스
rke2-metrics-serverDeploymentHPA 기반
rke2-runtimeclasses런타임 클래스 등록
rke2-snapshot-controllerDeployment볼륨 스냅샷

4단계: Daemon Process — 무기한 실행

  • Initialize Agent까지 완료되면 RKE2 프로세스는 데몬 상태로 전환된다. - SIGTERM 또는 SIGKILL을 받거나, 관리 중인 컨테이너 프로세스가 종료될 때까지 무기한 실행된다.


전체 부팅 흐름 요약

참고 링크

profile
bytebliss

0개의 댓글