티스토리 뷰
이 포스팅은 Cloud@net 가시다님의 스터디 강의 내용을 요약한 자료입니다.
무단 베포를 금지합니다.
RKE2 소개
소개 : Rancher 에서 개발한 엔터프라이즈 K8S 배포판, 미국 연방 정부 부문의 보안 및 규정 준수 - Docs
- 운영자의 개입을 최소화하면서 클러스터가 CIS Kubernetes Benchmark v1.7 또는 v1.8 을 통과할 수 있도록 기본 설정 및 구성 옵션을 제공합니다 .
- FIPS 140-2 규정 준수를 지원합니다.
- 빌드 파이프라인에서 trivy를 사용하여 구성 요소의 CVE를 정기적으로 검사합니다.
- RKE2는 컨트롤 플레인 구성 요소를 kubelet이 관리하는 정적 Pod로 실행합니다. 내장 컨테이너 런타임은 containerd입니다.
- 이 배포판은 독립 실행형으로 실행되거나 Rancher에 통합되어 실행될 수 있습니다.
아키텍처 : https://docs.rke2.io/architecture
Anatomy of a Next Generation Kubernetes Distribution | RKE2
Architecture Overview
docs.rke2.io

- RKE2는 경량 Kubernetes 배포판인 K3s를 개발하고 유지 관리하면서 얻은 교훈을 바탕으로, K3s의 사용 편의성을 유지하면서도 엔터프라이즈 환경에 적합한 배포판을 구축한 제품입니다.
- 즉, RKE2는 가장 간단하게 말하면 Kubernetes 클러스터에 참여할 모든 노드에 설치 및 구성해야 하는 단일 바이너리 파일입니다.
- 일단 시작되면 RKE2는 각 노드의 역할에 맞는 에이전트를 부트스트랩하고 관리하는 동시에 네트워크에서 필요한 콘텐츠를 가져올 수 있습니다
RKE2 구성요소
- K3S
- Helm Controller : GitOps 스타일 경량 배포기, A simple way to manage helm charts with Custom Resource Definitions in k8s - Docs
- RKE2 클러스터가 올라올 때 필수 Helm 차트를 자동으로 설치·유지하는 내장 배포 컨트롤러.
- manifests 디렉토리 감시 방식 : /var/lib/rancher/rke2/server/manifests 디렉토리에 (HelmChart) YAML 파일만 떨어뜨리면 Helm Controller에 의해 자동으로 Helm chart를 (다운로드)/설치/업데이트.
- Helm Controller : GitOps 스타일 경량 배포기, A simple way to manage helm charts with Custom Resource Definitions in k8s - Docs
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 Ctrl 부트스트랩 (부팅 시 필수 애드온 자동 설치) vs Argo CD GitOps (애플리케이션 배포).
Kubernetes 구성요소 기능 요약
1-1. API Server (kube-apiserver)
- 쿠버네티스의 관문(Front Door) 역할
- kubectl, Controller, Scheduler 등 모든 컴포넌트가 API Server를 통해 통신
- 클러스터 상태 조회/변경 요청을 받아서 검증 후 저장(etcd 반영)
- 인증(Authentication), 인가(Authorization), Admission(정책 적용)도 담당
1-2. Controller Manager (kube-controller-manager)
- 클러스터가 원하는 상태(Desired State) 를 유지하도록 계속 감시/조정
- 예:
- Deployment Controller → 파드 개수 맞추기
- Node Controller → 노드 상태 확인
- ReplicaSet Controller → 복제본 유지
- Job Controller → 배치 작업 완료 관리
1-3. Scheduler (kube-scheduler)
- 새로 생성될 Pod를 어느 노드에 배치할지 결정
- CPU/메모리 여유, taint/toleration, affinity/anti-affinity, topology 등을 고려
- 실제 실행은 kubelet이 하고, scheduler는 배치 결정만 수행
1-4. Proxy (kube-proxy)
- 각 노드에서 Service 네트워킹 구현
- Service IP(ClusterIP)로 들어온 트래픽을 실제 Pod로 전달
- 보통 iptables 또는 ipvs 기반 룰 생성
- 로드밸런싱(간단한 분산) 역할도 수행
1-5. Kubelet (kubelet)
- 노드 에이전트 (각 워커 노드에 실행)
- API Server에서 할당된 PodSpec을 보고 실제로 컨테이너 실행 상태 유지
- container runtime(containerd 등)와 연동하여 컨테이너 생성/삭제/헬스체크
- Pod 상태를 API Server에 보고
1-6. etcd
- 쿠버네티스의 분산 Key-Value 저장소
- 클러스터의 모든 상태 정보(리소스 정의, 설정, 메타데이터 등)를 저장
- Control Plane의 “단일 진실 공급원(Source of Truth)”
- 고가용성(HA) 구성 시 매우 중요하며 백업/복구 전략 필수
1-7. runc
- OCI(Open Container Initiative) 표준 기반의 저수준 컨테이너 실행기
- 실제로는 컨테이너 프로세스를 Linux namespace/cgroup으로 격리해 실행
- 사용자가 직접 다루기보다는 보통 containerd가 내부적으로 사용
1-8. containerd / CRI
containerd
- 고수준 컨테이너 런타임
- 이미지 pull, 스냅샷, 컨테이너 lifecycle 관리 담당
- 내부적으로 runc를 사용해 실제 컨테이너 실행
1-9. CRI (Container Runtime Interface)
- 쿠버네티스가 런타임과 통신하기 위한 표준 인터페이스
- kubelet은 CRI를 통해 containerd 같은 런타임을 제어
- 덕분에 런타임 교체/호환성이 좋아짐
1-10. CNI (Container Network Interface)
- Pod 네트워크를 구성하기 위한 플러그인 표준
- Pod에 IP 부여, 네트워크 연결, 라우팅/오버레이, 정책 연계 등을 담당
- “쿠버네티스 기본 기능”이 아니라 CNI 플러그인이 실제 네트워크를 구현함
1-11. CoreDNS
- 클러스터 내부 DNS 서버
- Service 이름(my-service.default.svc.cluster.local)을 IP로 변환
- Pod가 다른 서비스 찾을 때 핵심 역할
- 필요 시 외부 DNS 포워딩도 가능
1-12. ngress NGINX Controller / Traefik
둘 다 외부 HTTP/HTTPS 요청을 클러스터 내부 서비스로 라우팅하는 Ingress Controller입니다.
Ingress NGINX Controller
- NGINX 기반, 가장 보편적
- 기능/레퍼런스 많고 운영 사례 풍부
- 세밀한 튜닝과 annotation 기반 설정이 강점
Process Lifecycle
Content Boostrap
- RKE2 런타임 이미지로 부터 sources binaries and manifests 추출하여, 서버 노드와 에이전트 노드를 모두 실행.
- (참고) rke2-runtime 컨테이너 내부에 파일 확인 : 바이너리, HelmChart
crictl images
IMAGE TAG IMAGE ID SIZE
docker.io/rancher/rke2-runtime v1.34.3-rke2r3 30afde048693a 91.6MB
tree
├── bin
│ ├── containerd
│ ├── containerd-shim-runc-v2
│ ├── crictl
│ ├── ctr
│ ├── kubectl
│ ├── kubelet
│ └── runc
├── charts
│ ├── harvester-cloud-provider.yaml
│ ├── harvester-csi-driver.yaml
│ ├── rancher-vsphere-cpi.yaml
│ ├── rancher-vsphere-csi.yaml
│ ├── rke2-calico-crd.yaml
│ ├── rke2-calico.yaml
│ ├── rke2-canal.yaml
│ ├── rke2-cilium.yaml
│ ├── rke2-coredns.yaml
│ ├── rke2-flannel.yaml
│ ├── rke2-ingress-nginx.yaml
│ ├── rke2-metrics-server.yaml
│ ├── rke2-multus.yaml
│ ├── rke2-runtimeclasses.yaml
│ ├── rke2-snapshot-controller-crd.yaml
│ ├── rke2-snapshot-controller.yaml
│ ├── rke2-snapshot-validation-webhook.yaml
│ ├── rke2-traefik-crd.yaml
│ └── rke2-traefik.yaml
- RKE2 런타임 이미지는 /var/lib/rancher/rke2/agent/images/*.tar 에서 스캔하며(태그는 rke2 --version 출력), 이를 찾을 수 없는 경우 DockerHub 에서 찾습니다.
(참고) /var/lib/rancher/rke2/agent/images/ 에 runtime-image.txt 파일 확인
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
cat /var/lib/rancher/rke2/agent/images/runtime-image.txt
index.docker.io/rancher/rke2-runtime:v1.34.3-rke2r3
- 그런 다음 RKE2는 런타임 이미지에서 /bin/을 추출하여 /var/lib/rancher/rke2/data/${RKE2_DATA_KEY}/bin 으로 평탄화합니다.
- 여기서 ${RKE2_DATA_KEY}는 이미지를 식별(버전)하는 고유 문자열을 나타냅니다.
(참고) /var/lib/rancher/rke2/data/ 확인
tree /var/lib/rancher/rke2/data/
└── v1.34.3-rke2r3-5b8349de68df
├── bin
│ ├── containerd
│ ├── containerd-shim-runc-v2
│ ├── crictl
│ ├── ctr
│ ├── kubectl
│ ├── kubelet
│ └── runc
└── charts
├── harvester-cloud-provider.yaml
├── harvester-csi-driver.yaml
├── rancher-vsphere-cpi.yaml
├── rancher-vsphere-csi.yaml
├── rke2-calico-crd.yaml
├── rke2-calico.yaml
├── rke2-canal.yaml
├── rke2-cilium.yaml
├── rke2-coredns.yaml
├── rke2-flannel.yaml
├── rke2-ingress-nginx.yaml
├── rke2-metrics-server.yaml
├── rke2-multus.yaml
├── rke2-runtimeclasses.yaml
├── rke2-snapshot-controller-crd.yaml
├── rke2-snapshot-controller.yaml
├── rke2-snapshot-validation-webhook.yaml
├── rke2-traefik-crd.yaml
└── rke2-traefik.yaml
- RKE2가 예상대로 작동하려면 런타임 이미지는 최소한 다음을 제공해야 합니다.
- containerd (CRI)
- containerd-shim (shims wrap runc tasks and do not stop when containerd does)
- containerd-shim-runc-v1
- containerd-shim-runc-v2
- kubelet (쿠버네티스 노드 에이전트)
- runc (OCI 런타임)
- 런타임 이미지에는 다음과 같은 운영 도구도 포함되어 있습니다.
- **ctr**containerd (저수준 유지보수 및 점검)
- crictl (낮은 수준의 CRI 유지 관리 및 점검)
- kubectl (쿠버네티스 클러스터 유지 관리 및 점검)
- **socat**containerd ( 포트 포워딩 에 필요함 )
- 바이너리 파일 압축 해제가 완료되면 RKE2는 이미지에서 차트를 추출하여 해당 /var/lib/rancher/rke2/server/manifests디렉터리에 저장합니다.
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
Initialize Server
임베디드 K3s 엔진 서버에는 특수 에이전트 프로세스가 포함되어 있어 노드 컨테이너 런타임 node container runtime 이 시작될 때까지 다음 시작이 연기됩니다.
(참고) /var/lib/rancher/rke2/agent/pod-manifests/ static pod
ls -ltr /var/lib/rancher/rke2/agent/pod-manifests/
total 32
-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
Prepare Components
- kube-apiserver
- Kube-apiserver 이미지가 아직 존재하지 않는 경우, Goroutine을 회전시켜 etcd를 기다린 다음 /var/lib/rancher/rke2/agent/pod-manifests/에 정적 포드 정의 static pod definition 를 작성합니다.
- kube-controller-manager
- kube-controller-manager 이미지가 아직 존재하지 않는 경우, goroutine을 회전시켜 kube-apiserver를 기다린 다음 /var/lib/rancher/rke2/agent/pod-manifests/에 정적 포드 정의를 작성합니다.
- kube-scheduler
- kube-scheduler 이미지가 아직 없는 경우, 고루틴을 회전시켜 kube-apiserver를 기다린 다음 /var/lib/rancher/rke2/agent/pod-manifests/에 정적 포드 정의를 작성합니다.
Start Cluster
Spin up an HTTP server in a goroutine to listen for other cluster servers/agents then initialize/join the cluster.
- etcd
- 이미 존재하지 않는 경우 etcd 이미지를 가져와서 Goroutine을 회전시켜 kubelet을 기다린 다음 /var/lib/rancher/rke2/agent/pod-manifests/에 정적 포드 정의를 작성합니다.
- helm-controller
- kube-apiserver가 준비될 때까지 기다린 후 Goroutine을 회전시켜 내장된 헬름 컨트롤러 embedded helm-controller 를 시작합니다.
rke2-server 프로세스
#
pstree -al
├─rke2
│ ├─containerd -c /var/lib/rancher/rke2/agent/etc/containerd/config.toml
│ │ └─12*[{containerd}]
│ ├─kubelet --volume-plugin-dir=/var/lib/kubelet/volumeplugins --file-check-frequency=5s --sync-frequency=30s --config-dir=/var/lib/rancher/rke2/agent/etc/kubelet.conf.d --containerd=/run/k3s/containerd/containerd.sock --hostname-override=k8s-node1 --kubeconfig=/var/lib/rancher/rke2/agent/kubelet.kubeconfig --node-ip=192.168.10.11 --node-labels= --read-only-port=0
│ │ └─14*[{kubelet}]
│ └─12*[{rke2}]
systemctl status rke2-server.service --no-pager
● rke2-server.service - Rancher Kubernetes Engine v2 (server)
Loaded: loaded (/usr/lib/systemd/system/rke2-server.service; enabled; preset: disabled)
Active: active (running) since Sat 2026-02-14 16:33:49 KST; 1h 37min ago
Docs: https://github.com/rancher/rke2#readme
Process: 6346 ExecStartPre=/sbin/modprobe br_netfilter (code=exited, status=0/SUCCESS)
Process: 6347 ExecStartPre=/sbin/modprobe overlay (code=exited, status=0/SUCCESS)
Main PID: 6348 (rke2)
Tasks: 146
Memory: 1.1G
CPU: 5min 15.217s
CGroup: /system.slice/rke2-server.service
├─6348 "/usr/bin/rke2 server"
├─6367 containerd -c /var/lib/rancher/rke2/agent/etc/containerd/config.toml
├─6426 kubelet --volume-plugin-dir=/var/lib/kubelet/volumeplugins --file-check-frequency=5s --sync-frequency…
├─6483 /var/lib/rancher/rke2/data/v1.34.3-rke2r3-5b8349de68df/bin/containerd-shim-runc-v2 -namespace k8s.io …
├─6484 /var/lib/rancher/rke2/data/v1.34.3-rke2r3-5b8349de68df/bin/containerd-shim-runc-v2 -namespace k8s.io …
...
# systemd unit 파일 확인
cat /usr/lib/systemd/system/rke2-server.service
[Unit]
Description=Rancher Kubernetes Engine v2 (server)
Documentation=https://github.com/rancher/rke2#readme
Wants=network-online.target
After=network-online.target
Conflicts=rke2-agent.service
[Install]
WantedBy=multi-user.target
[Service]
Type=notify
EnvironmentFile=-/etc/default/%N
EnvironmentFile=-/etc/sysconfig/%N
EnvironmentFile=-/usr/lib/systemd/system/%N.env
KillMode=process # "나만 죽이고, 내가 띄운 애들까지는 systemd가 건드리지 마" - RKE2, containerd 같은 애들은 내부적으로 여러 자식 프로세스 shim, runc, container 프로세스를 관리함. 물론 완전 무중단은 아니지만, 충격 최소화
Delegate=yes # "cgroup(리소스 제어)는 내가 직접 관리할게" - cgroup(리눅스 리소스 그룹) 관리를 systemd가 아니라 자기 자신이 직접 하도록 위임(delegate) 하겠다는 의미.
LimitNOFILE=1048576
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
TimeoutStartSec=0
Restart=always
RestartSec=5s
ExecStartPre=-/sbin/modprobe br_netfilter
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/bin/rke2 server
ExecStopPost=-/bin/sh -c "systemd-cgls /system.slice/%n | grep -Eo '[0-9]+ (containerd|kubelet)' | awk '{print $1}' | xargs -r kill"
Initialize Agent
- kubelet : Spawn and supervise the kubelet process.
- kubelet이 종료되면 rke2가 재시작을 시도합니다. kubelet이 작동하면 사용 가능한 모든 정적 포드가 시작됩니다.
- 서버의 경우, etcd와 kube-apiserver가 연속적으로 시작되어 정적 포드를 통해 시작된 나머지 구성 요소들이 kube-apiserver에 연결되어 처리를 시작할 수 있게 됩니다.
Server Charts
- On server nodes, the helm-controller can now apply to the cluster any charts found /var/lib/rancher/rke2/server/manifests.
- rke2*-**canal.yaml or rke2-cilium.yaml or rke2-calico.yaml or rke2-flannel.**yaml or rke2-**multus.*yaml (daemonset, bootstrap)
- rke2-coredns.yaml (deployment, bootstrap)
- rke2-ingress-nginx.yaml and/or rke2-traefik.yaml and rke2-traefik-crd.yaml (deployment)
- rke2-metrics-server.yaml (deployment)
- rke2-runtimeclasses.yaml (deployment)
- rke2-snapshot-controller-crd.yaml, rke2-snapshot-controller.yaml and rke2-snapshot-validation-webhook.yaml (deployment)
- Daemon Process : 이제 RKE2 프로세스는 SIGTERM 또는 SIGKILL을 받거나 컨테이너 프로세스가 종료될 때까지 무기한으로 실행됨.
서버 노드 부팅 시 과정

에이전트 노드 부팅 시 과정

RKE2 실습
Vagrantfile : Rocky Linux 9
# Base Image https://portal.cloud.hashicorp.com/vagrant/discover/bento/rockylinux-9
BOX_IMAGE = "bento/rockylinux-9" # "bento/rockylinux-10.0"
BOX_VERSION = "202510.26.0"
N = 2 # max number of Node
Vagrant.configure("2") do |config|
# Nodes
(1..N).each do |i|
config.vm.define "k8s-node#{i}" do |subconfig|
subconfig.vm.box = BOX_IMAGE
subconfig.vm.box_version = BOX_VERSION
subconfig.vm.provider "virtualbox" do |vb|
vb.customize ["modifyvm", :id, "--groups", "/RKE2-Lab"]
vb.customize ["modifyvm", :id, "--nicpromisc2", "allow-all"]
vb.name = "k8s-node#{i}"
vb.cpus = 4
vb.memory = 4096
vb.linked_clone = true
end
subconfig.vm.host_name = "k8s-node#{i}"
subconfig.vm.network "private_network", ip: "192.168.10.1#{i}"
subconfig.vm.network "forwarded_port", guest: 22, host: "6000#{i}", auto_correct: true, id: "ssh"
subconfig.vm.synced_folder "./", "/vagrant", disabled: true
subconfig.vm.provision "shell", path: "init_cfg.sh" , args: [ N ]
end
end
end
init_cfg.sh
#!/usr/bin/env bash
echo ">>>> Initial Config Start <<<<"
echo "[TASK 1] Change Timezone and Enable NTP"
timedatectl set-local-rtc 0
timedatectl set-timezone Asia/Seoul
echo "[TASK 2] Disable firewalld and selinux"
systemctl disable --now firewalld >/dev/null 2>&1
setenforce 0
sed -i 's/^SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config
echo "[TASK 3] Disable and turn off SWAP & Delete swap partitions"
swapoff -a
sed -i '/swap/d' /etc/fstab
sfdisk --delete /dev/sda 2 >/dev/null 2>&1
partprobe /dev/sda >/dev/null 2>&1
echo "[TASK 4] Config kernel & module"
cat << EOF > /etc/modules-load.d/k8s.conf
overlay
br_netfilter
#vxlan
EOF
modprobe overlay >/dev/null 2>&1
modprobe br_netfilter >/dev/null 2>&1
#modprobe vxlan >/dev/null 2>&1
cat << EOF >/etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system >/dev/null 2>&1
echo "[TASK 5] Setting Local DNS Using Hosts file"
sed -i '/^127\.0\.\(1\|2\)\.1/d' /etc/hosts
for (( i=1; i<=$1; i++ )); do echo "192.168.10.1$i k8s-node$i" >> /etc/hosts; done
echo "[TASK 6] Install Helm"
curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | DESIRED_VERSION=v3.20.0 bash >/dev/null 2>&1
echo "[TASK 7] Setting SSHD"
cat << EOF >> /etc/ssh/sshd_config
PermitRootLogin yes
PasswordAuthentication yes
EOF
systemctl restart sshd >/dev/null 2>&1
echo "[TASK 8] Install packages"
dnf install -y conntrack python3-pip git >/dev/null 2>&1
echo "[TASK 9] NetworkManager to ignore calico/flannel related network interfaces"
# https://docs.rke2.io/known_issues#networkmanager
cat << EOF > /etc/NetworkManager/conf.d/k8s.conf
[keyfile]
unmanaged-devices=interface-name:flannel*;interface-name:cali*;interface-name:tunl*;interface-name:vxlan.calico;interface-name:vxlan-v6.calico;interface-name:wireguard.cali;interface-name:wg-v6.cali
EOF
systemctl reload NetworkManager
echo "[TASK 11] Install K9s"
CLI_ARCH=amd64
if [ "$(uname -m)" = "aarch64" ]; then CLI_ARCH=arm64; fi
wget -P /tmp https://github.com/derailed/k9s/releases/latest/download/k9s_linux_${CLI_ARCH}.tar.gz >/dev/null 2>&1
tar -xzf /tmp/k9s_linux_${CLI_ARCH}.tar.gz -C /tmp
chown root:root /tmp/k9s
mv /tmp/k9s /usr/local/bin/
chmod +x /usr/local/bin/k9s
echo "[TASK 12] ETC"
echo "sudo su -" >> /home/vagrant/.bashrc
echo ">>>> Initial Config End <<<<"
mkdir k8s-rke2
cd k8s-rke2
curl -O https://raw.githubusercontent.com/gasida/vagrant-lab/refs/heads/main/k8s-rke2/Vagrantfile
curl -O https://raw.githubusercontent.com/gasida/vagrant-lab/refs/heads/main/k8s-rke2/init_cfg.sh
vagrant up
vagrant status
RKE2 서버 노드 설치 - Docs, Rocky Linux 9 사용
설치 스크립트
#!/bin/sh
set -e
if [ "${DEBUG}" = 1 ]; then
set -x
fi
# Usage:
# curl ... | ENV_VAR=... sh -
# or
# ENV_VAR=... ./install.sh
#
# Environment variables:
#
# - INSTALL_RKE2_CHANNEL
# Channel to use for fetching rke2 download URL.
# Defaults to 'stable'.
#
# - INSTALL_RKE2_METHOD
# The installation method to use.
# Default is on RPM-based systems is "rpm", all else "tar".
#
# - INSTALL_RKE2_TYPE
# Type of rke2 service. Can be either "server" or "agent".
# Default is "server".
#
# - INSTALL_RKE2_EXEC
# This is an alias for INSTALL_RKE2_TYPE, included for compatibility with K3s.
# If both are set, INSTALL_RKE2_TYPE is preferred.
#
# - INSTALL_RKE2_VERSION
# Version of rke2 to download.
#
# - INSTALL_RKE2_RPM_RELEASE_VERSION
# Version of the rke2 RPM release to install.
# Format would be like "1.el7" or "2.el8"
#
# - INSTALL_RKE2_TAR_PREFIX
# Installation prefix when using the tar installation method.
# Default is /usr/local, unless /usr/local is read-only or has a dedicated mount point,
# in which case /opt/rke2 is used instead.
#
# - INSTALL_RKE2_COMMIT
# Commit of RKE2 to download from temporary cloud storage.
# For developer & QA use only
#
# - INSTALL_RKE2_AGENT_IMAGES_DIR
# Installation path for airgap images when installing from CI commit
# Default is /var/lib/rancher/rke2/agent/images
#
# - INSTALL_RKE2_ARTIFACT_URL
# URL prefix for RKE2 release artifacts.
# Default is https://github.com/rancher/rke2/releases/download
#
# - INSTALL_RKE2_ARTIFACT_PATH
# If set, the install script will use the local path for sourcing the rke2.linux-$SUFFIX and sha256sum-$ARCH.txt files
# rather than the downloading the files from the internet.
# Default is not set.
#
# - INSTALL_RKE2_SKIP_RELOAD
# If set, the install script will skip reloading systemctl daemon after the tar has been extracted and systemd units
# have been moved.
# Default is not set.
#
# - INSTALL_RKE2_SKIP_FAPOLICY
# If set, the install script will skip adding fapolicy rules
# Default is not set.
# info logs the given argument at info log level.
info() {
echo "[INFO] " "$@"
}
# warn logs the given argument at warn log level.
warn() {
echo "[WARN] " "$@" >&2
}
# fatal logs the given argument at fatal log level.
fatal() {
echo "[ERROR] " "$@" >&2
if [ -n "${SUFFIX}" ]; then
echo "[ALT] Please visit 'https://github.com/rancher/rke2/releases' directly and download the latest rke2.${SUFFIX}.tar.gz" >&2
fi
exit 1
}
# check_target_mountpoint return success if the target directory is on a dedicated mount point
check_target_mountpoint() {
mountpoint -q "${INSTALL_RKE2_TAR_PREFIX}"
}
# check_target_ro returns success if the target directory is read-only
check_target_ro() {
touch "${INSTALL_RKE2_TAR_PREFIX}"/.rke2-ro-test && rm -rf "${INSTALL_RKE2_TAR_PREFIX}"/.rke2-ro-test
test $? -ne 0
}
# setup_env defines needed environment variables.
setup_env() {
STORAGE_URL="https://rke2-ci-builds.s3.dualstack.us-east-1.amazonaws.com"
DEFAULT_TAR_PREFIX="/usr/local"
# --- bail if we are not root ---
if [ ! $(id -u) -eq 0 ]; then
fatal "You need to be root to perform this install"
fi
# --- make sure artifact url prefix has a value
if [ -z "${INSTALL_RKE2_ARTIFACT_URL}" ]; then
INSTALL_RKE2_ARTIFACT_URL="https://github.com/rancher/rke2/releases/download"
fi
# --- make sure install channel has a value
if [ -z "${INSTALL_RKE2_CHANNEL}" ]; then
INSTALL_RKE2_CHANNEL="stable"
fi
# --- make sure install type has a value
if [ -z "${INSTALL_RKE2_TYPE}" ]; then
INSTALL_RKE2_TYPE="${INSTALL_RKE2_EXEC:-server}"
fi
# --- use rpm install method if available by default
if [ -z "${INSTALL_RKE2_ARTIFACT_PATH}" ] && [ -z "${INSTALL_RKE2_COMMIT}" ] && [ -z "${INSTALL_RKE2_METHOD}" ] && command -v yum >/dev/null 2>&1; then
INSTALL_RKE2_METHOD="rpm"
fi
# --- install tarball to /usr/local by default, except if /usr/local is on a separate partition or is read-only
# --- in which case we go into /opt/rke2.
if [ -z "${INSTALL_RKE2_TAR_PREFIX}" ]; then
INSTALL_RKE2_TAR_PREFIX=${DEFAULT_TAR_PREFIX}
if check_target_mountpoint || check_target_ro; then
INSTALL_RKE2_TAR_PREFIX="/opt/rke2"
warn "${DEFAULT_TAR_PREFIX} is read-only or a mount point; installing to ${INSTALL_RKE2_TAR_PREFIX}"
fi
fi
if [ -z "${INSTALL_RKE2_AGENT_IMAGES_DIR}" ]; then
INSTALL_RKE2_AGENT_IMAGES_DIR="/var/lib/rancher/rke2/agent/images"
fi
}
# check_method_conflict will exit with an error if the user attempts to install
# via tar method on a host with existing RPMs.
check_method_conflict() {
. /etc/os-release
case ${INSTALL_RKE2_METHOD} in
yum | rpm | dnf)
if [ "${ID_LIKE%%[ ]*}" = "suse" ]; then
if [ -f ${INSTALL_RKE2_TAR_PREFIX}/bin/rke2 ]; then
fatal "Cannot perform ${INSTALL_RKE2_METHOD:-rpm} install on host with existing tarball installation - please run rke2-uninstall.sh first"
fi
fi
return
;;
*)
if rpm -q rke2-common >/dev/null 2>&1; then
fatal "Cannot perform ${INSTALL_RKE2_METHOD:-tar} install on host with existing RKE2 RPMs - please run rke2-uninstall.sh first"
fi
;;
esac
}
# setup_arch set arch and suffix,
# fatal if architecture not supported.
setup_arch() {
case ${ARCH:=$(uname -m)} in
x86_64|amd64)
ARCH=amd64
SUFFIX=$(uname -s | tr '[:upper:]' '[:lower:]')-${ARCH}
;;
aarch64|arm64)
ARCH=arm64
SUFFIX=$(uname -s | tr '[:upper:]' '[:lower:]')-${ARCH}
;;
s390x)
ARCH=s390x
SUFFIX=$(uname -s | tr '[:upper:]' '[:lower:]')-${ARCH}
;;
*)
fatal "unsupported architecture ${ARCH}"
;;
esac
}
# verify_downloader verifies existence of
# network downloader executable.
verify_downloader() {
cmd="$(command -v "${1}")"
if [ -z "${cmd}" ]; then
return 1
fi
if [ ! -x "${cmd}" ]; then
return 1
fi
# Set verified executable as our downloader program and return success
DOWNLOADER=${cmd}
return 0
}
# verify_fapolicyd verifies existence of
# fapolicyd and fagenrules executables and make sure that fapolicyd service is running.
verify_fapolicyd() {
cmd="$(command -v "fapolicyd")"
if [ -z "${cmd}" ]; then
return 1
fi
cmd="$(command -v "fagenrules")"
if [ -z "${cmd}" ]; then
return 1
fi
systemctl is-active --quiet fapolicyd || return 1
return 0
}
# setup_tmp creates a temporary directory
# and cleans up when done.
setup_tmp() {
TMP_DIR=$(mktemp -d -t rke2-install.XXXXXXXXXX)
TMP_CHECKSUMS=${TMP_DIR}/rke2.checksums
TMP_TARBALL=${TMP_DIR}/rke2.tarball
TMP_AIRGAP_CHECKSUMS=${TMP_DIR}/rke2-images.checksums
TMP_AIRGAP_TARBALL=${TMP_DIR}/rke2-images.tarball
cleanup() {
code=$?
set +e
trap - EXIT
rm -rf "${TMP_DIR}"
exit $code
}
trap cleanup INT EXIT
}
# --- use desired rke2 version if defined or find version from channel ---
get_release_version() {
if [ -z "${INSTALL_RKE2_COMMIT}" ] && [ -z "${INSTALL_RKE2_VERSION}" ]; then
info "finding release for channel ${INSTALL_RKE2_CHANNEL}"
INSTALL_RKE2_CHANNEL_URL=${INSTALL_RKE2_CHANNEL_URL:-'https://update.rke2.io/v1-release/channels'}
version_url="${INSTALL_RKE2_CHANNEL_URL}/${INSTALL_RKE2_CHANNEL}"
case ${DOWNLOADER} in
*curl)
version=$(${DOWNLOADER} -w "%{url_effective}" -L -s -S "${version_url}" -o /dev/null | sed -e 's|.*/||')
;;
*wget)
version=$(${DOWNLOADER} -SqO /dev/null "${version_url}" 2>&1 | grep -i Location | sed -e 's|.*/||')
;;
*)
fatal "Unsupported downloader executable '${DOWNLOADER}'"
;;
esac
INSTALL_RKE2_VERSION="${version}"
fi
}
# check_download performs a HEAD request to see if a file exists at a given url
check_download() {
case ${DOWNLOADER} in
*curl)
curl -o "/dev/null" -fsLI -X HEAD "$1"
;;
*wget)
wget -q --spider "$1"
;;
*)
fatal "downloader executable not supported: '${DOWNLOADER}'"
;;
esac
}
# download downloads a file from a url using either curl or wget
download() {
if [ $# -ne 2 ]; then
fatal "download needs exactly 2 arguments"
fi
case ${DOWNLOADER} in
*curl)
curl -o "$1" -fsSL "$2"
;;
*wget)
wget -qO "$1" "$2"
;;
*)
fatal "downloader executable not supported: '${DOWNLOADER}'"
;;
esac
# Abort if download command failed
if [ $? -ne 0 ]; then
fatal "download failed"
fi
}
# download_checksums downloads hash from github url.
download_checksums() {
version_urlsafe="$(echo ${INSTALL_RKE2_VERSION} | sed 's/\+/%2B/g')"
if [ -n "${INSTALL_RKE2_COMMIT}" ]; then
CHECKSUMS_URL=${STORAGE_URL}/rke2.${SUFFIX}-${INSTALL_RKE2_COMMIT}.tar.gz.sha256sum
else
CHECKSUMS_URL=${INSTALL_RKE2_ARTIFACT_URL}/${version_urlsafe}/sha256sum-${ARCH}.txt
fi
info "downloading checksums at ${CHECKSUMS_URL}"
download "${TMP_CHECKSUMS}" "${CHECKSUMS_URL}"
CHECKSUM_EXPECTED=$(grep "rke2.${SUFFIX}.tar.gz" "${TMP_CHECKSUMS}" | awk '{print $1}')
}
# download_tarball downloads binary from github url.
download_tarball() {
version_urlsafe="$(echo ${INSTALL_RKE2_VERSION} | sed 's/\+/%2B/g')"
if [ -n "${INSTALL_RKE2_COMMIT}" ]; then
TARBALL_URL=${STORAGE_URL}/rke2.${SUFFIX}-${INSTALL_RKE2_COMMIT}.tar.gz
else
TARBALL_URL=${INSTALL_RKE2_ARTIFACT_URL}/${version_urlsafe}/rke2.${SUFFIX}.tar.gz
fi
info "downloading tarball at ${TARBALL_URL}"
download "${TMP_TARBALL}" "${TARBALL_URL}"
}
# download_dev_rpm downloads dev rpm from remote repository
download_dev_rpm() {
if [ -z "${INSTALL_RKE2_COMMIT}" ]; then
fatal 'Development rpm requires a commit hash'
fi
DEST="${1}"
RPM_FILE=$(basename "${DEST}")
RPM_URL="${STORAGE_URL}/${RPM_FILE}"
info "downloading rpm at ${RPM_URL}"
download "${DEST}" "${RPM_URL}"
}
# stage_local_checksums stages the local checksum hash for validation.
stage_local_checksums() {
info "staging local checksums from ${INSTALL_RKE2_ARTIFACT_PATH}/sha256sum-${ARCH}.txt"
cp -f "${INSTALL_RKE2_ARTIFACT_PATH}/sha256sum-${ARCH}.txt" "${TMP_CHECKSUMS}"
CHECKSUM_EXPECTED=$(grep "rke2.${SUFFIX}.tar.gz" "${TMP_CHECKSUMS}" | awk '{print $1}')
if [ -f "${INSTALL_RKE2_ARTIFACT_PATH}/rke2-images.${SUFFIX}.tar.zst" ]; then
AIRGAP_CHECKSUM_EXPECTED=$(grep "rke2-images.${SUFFIX}.tar.zst" "${TMP_CHECKSUMS}" | awk '{print $1}')
elif [ -f "${INSTALL_RKE2_ARTIFACT_PATH}/rke2-images.${SUFFIX}.tar.gz" ]; then
AIRGAP_CHECKSUM_EXPECTED=$(grep "rke2-images.${SUFFIX}.tar.gz" "${TMP_CHECKSUMS}" | awk '{print $1}')
fi
}
# stage_local_tarball stages the local tarball.
stage_local_tarball() {
info "staging tarball from ${INSTALL_RKE2_ARTIFACT_PATH}/rke2.${SUFFIX}.tar.gz"
cp -f "${INSTALL_RKE2_ARTIFACT_PATH}/rke2.${SUFFIX}.tar.gz" "${TMP_TARBALL}"
}
# stage_local_airgap_tarball stages the local checksum hash for validation.
stage_local_airgap_tarball() {
if [ -f "${INSTALL_RKE2_ARTIFACT_PATH}/rke2-images.${SUFFIX}.tar.zst" ]; then
info "staging zst airgap image tarball from ${INSTALL_RKE2_ARTIFACT_PATH}/rke2-images.${SUFFIX}.tar.zst"
cp -f "${INSTALL_RKE2_ARTIFACT_PATH}/rke2-images.${SUFFIX}.tar.zst" "${TMP_AIRGAP_TARBALL}"
AIRGAP_TARBALL_FORMAT=zst
elif [ -f "${INSTALL_RKE2_ARTIFACT_PATH}/rke2-images.${SUFFIX}.tar.gz" ]; then
info "staging gzip airgap image tarball from ${INSTALL_RKE2_ARTIFACT_PATH}/rke2-images.${SUFFIX}.tar.gz"
cp -f "${INSTALL_RKE2_ARTIFACT_PATH}/rke2-images.${SUFFIX}.tar.gz" "${TMP_AIRGAP_TARBALL}"
AIRGAP_TARBALL_FORMAT=gz
fi
}
# verify_tarball verifies the downloaded installer checksum.
verify_tarball() {
info "verifying tarball"
CHECKSUM_ACTUAL=$(sha256sum "${TMP_TARBALL}" | awk '{print $1}')
if [ "${CHECKSUM_EXPECTED}" != "${CHECKSUM_ACTUAL}" ]; then
fatal "download sha256 does not match ${CHECKSUM_EXPECTED}, got ${CHECKSUM_ACTUAL}"
fi
}
# unpack_tarball extracts the tarball, correcting paths and moving systemd units as necessary
unpack_tarball() {
info "unpacking tarball file to ${INSTALL_RKE2_TAR_PREFIX}"
mkdir -p ${INSTALL_RKE2_TAR_PREFIX}
tar xzf "${TMP_TARBALL}" -C "${INSTALL_RKE2_TAR_PREFIX}"
if [ "${INSTALL_RKE2_TAR_PREFIX}" != "${DEFAULT_TAR_PREFIX}" ]; then
info "updating tarball contents to reflect install path"
sed -i "s|${DEFAULT_TAR_PREFIX}|${INSTALL_RKE2_TAR_PREFIX}|" ${INSTALL_RKE2_TAR_PREFIX}/lib/systemd/system/rke2-*.service ${INSTALL_RKE2_TAR_PREFIX}/bin/rke2-uninstall.sh
info "moving systemd units to /etc/systemd/system"
mv -f ${INSTALL_RKE2_TAR_PREFIX}/lib/systemd/system/rke2-*.service /etc/systemd/system/
info "install complete; you may want to run: export PATH=\$PATH:${INSTALL_RKE2_TAR_PREFIX}/bin"
fi
}
# download_airgap_checksums downloads the checksum file for the airgap image tarball
# and prepares the checksum value for later validation.
download_airgap_checksums() {
if [ -z "${INSTALL_RKE2_COMMIT}" ]; then
return
fi
AIRGAP_CHECKSUMS_URL=${STORAGE_URL}/rke2-images.${SUFFIX}-${INSTALL_RKE2_COMMIT}.tar.zst.sha256sum
# try for zst first; if that fails use gz for older release branches
if ! check_download "${AIRGAP_CHECKSUMS_URL}"; then
AIRGAP_CHECKSUMS_URL=${STORAGE_URL}/rke2-images.${SUFFIX}-${INSTALL_RKE2_COMMIT}.tar.gz.sha256sum
fi
info "downloading airgap checksums at ${AIRGAP_CHECKSUMS_URL}"
download "${TMP_AIRGAP_CHECKSUMS}" "${AIRGAP_CHECKSUMS_URL}"
AIRGAP_CHECKSUM_EXPECTED=$(grep "rke2-images.${SUFFIX}.tar" "${TMP_AIRGAP_CHECKSUMS}" | awk '{print $1}')
}
# download_airgap_tarball downloads the airgap image tarball.
download_airgap_tarball() {
if [ -z "${INSTALL_RKE2_COMMIT}" ]; then
return
fi
AIRGAP_TARBALL_URL=${STORAGE_URL}/rke2-images.${SUFFIX}-${INSTALL_RKE2_COMMIT}.tar.zst
# try for zst first; if that fails use gz for older release branches
if ! check_download "${AIRGAP_TARBALL_URL}"; then
AIRGAP_TARBALL_URL=${STORAGE_URL}/rke2-images.${SUFFIX}-${INSTALL_RKE2_COMMIT}.tar.gz
fi
info "downloading airgap tarball at ${AIRGAP_TARBALL_URL}"
download "${TMP_AIRGAP_TARBALL}" "${AIRGAP_TARBALL_URL}"
}
# verify_airgap_tarball compares the airgap image tarball checksum to the value
# calculated by CI when the file was uploaded.
verify_airgap_tarball() {
if [ -z "${AIRGAP_CHECKSUM_EXPECTED}" ]; then
return
fi
info "verifying airgap tarball"
AIRGAP_CHECKSUM_ACTUAL=$(sha256sum "${TMP_AIRGAP_TARBALL}" | awk '{print $1}')
if [ "${AIRGAP_CHECKSUM_EXPECTED}" != "${AIRGAP_CHECKSUM_ACTUAL}" ]; then
fatal "download sha256 does not match ${AIRGAP_CHECKSUM_EXPECTED}, got ${AIRGAP_CHECKSUM_ACTUAL}"
fi
}
# install_airgap_tarball moves the airgap image tarball into place.
install_airgap_tarball() {
if [ -z "${AIRGAP_CHECKSUM_EXPECTED}" ]; then
return
fi
mkdir -p "${INSTALL_RKE2_AGENT_IMAGES_DIR}"
# releases that provide zst artifacts can read from the compressed archive; older releases
# that produce only gzip artifacts need to have the tarball decompressed ahead of time
if grep -sqF '.tar.zst' "${TMP_AIRGAP_CHECKSUMS}" || [ "${AIRGAP_TARBALL_FORMAT}" = "zst" ]; then
info "installing airgap tarball to ${INSTALL_RKE2_AGENT_IMAGES_DIR}"
mv -f "${TMP_AIRGAP_TARBALL}" "${INSTALL_RKE2_AGENT_IMAGES_DIR}/rke2-images.${SUFFIX}.tar.zst"
else
info "decompressing airgap tarball to ${INSTALL_RKE2_AGENT_IMAGES_DIR}"
gzip -dc "${TMP_AIRGAP_TARBALL}" > "${INSTALL_RKE2_AGENT_IMAGES_DIR}/rke2-images.${SUFFIX}.tar"
fi
# Search for and install additional rke2 images
for IMAGE in "${INSTALL_RKE2_ARTIFACT_PATH}"/rke2-images-*."${SUFFIX}"*; do
if [ -f "${IMAGE}" ]; then
info "Installing airgap image from ${IMAGE}"
cp "${IMAGE}" "${INSTALL_RKE2_AGENT_IMAGES_DIR}"
fi
done
}
# install_dev_rpm orchestrates the installation of RKE2 unsigned development rpms
install_dev_rpm() {
rpm_installer="${1:-yum}"
distro="${2:-centos7}"
[ -z "${TMP_DIR}" ] && setup_tmp
case "${rpm_installer}" in
*zypper*)
${rpm_installer} install --allow-unsigned-rpm -y \
"${STORAGE_URL}/rke2-common-${INSTALL_RKE2_COMMIT}.${distro}.rpm" \
"${STORAGE_URL}/rke2-${INSTALL_RKE2_TYPE}-${INSTALL_RKE2_COMMIT}.${distro}.rpm"
;;
*)
download_dev_rpm "${TMP_DIR}/rke2-common-${INSTALL_RKE2_COMMIT}.${distro}.rpm"
download_dev_rpm "${TMP_DIR}/rke2-${INSTALL_RKE2_TYPE}-${INSTALL_RKE2_COMMIT}.${distro}.rpm"
${rpm_installer} install -y "${TMP_DIR}"/*.rpm
;;
esac
if [ -f "${INSTALL_RKE2_ARTIFACT_PATH}/rke2-images.${SUFFIX}.tar.zst" ]; then
return
fi
download_airgap_checksums
download_airgap_tarball
verify_airgap_tarball
install_airgap_tarball
}
# do_install_rpm builds a yum repo config from the channel and version to be installed,
# and calls yum to install the required packages.
do_install_rpm() {
. /etc/os-release
if [ -r /etc/redhat-release ] || [ -r /etc/centos-release ] || [ -r /etc/oracle-release ] || [ -r /etc/system-release ] || [ "${ID_LIKE%%[ ]*}" = "suse" ]; then
repodir=/etc/yum.repos.d
if [ -d /etc/zypp/repos.d ]; then
repodir=/etc/zypp/repos.d
fi
if [ "${ID_LIKE%%[ ]*}" = "suse" ]; then
# create the /var/lib/rpm-state in SLE systems to fix the prein selinux macro
if [ "${TRANSACTIONAL_UPDATE=false}" != "true" ] && [ -x /usr/sbin/transactional-update ]; then
transactional_update_run="transactional-update --no-selfupdate -d run"
fi
${transactional_update_run} mkdir -p /var/lib/rpm-state
# configure infix and rpm_installer
rpm_site_infix=microos
if [ "${VARIANT_ID:-}" = sle-micro ] || [ "${ID:-}" = sle-micro ] || [ "${ID:-}" = sl-micro ]; then
rpm_site_infix=slemicro
package_installer=zypper
fi
rpm_installer="zypper --gpg-auto-import-keys"
if [ "${TRANSACTIONAL_UPDATE=false}" != "true" ] && [ -x /usr/sbin/transactional-update ]; then
rpm_installer="transactional-update --no-selfupdate -d run ${rpm_installer}"
fi
else
maj_ver=$(echo "$VERSION_ID" | sed -E -e "s/^([0-9]+)\.?[0-9]*$/\1/")
case ${maj_ver} in
7|8|9|10)
:
;;
2023) # detect amazon linux 2023 distro
maj_ver="8"
;;
*) # set default distro to centos 8, for edge cases such as fedora
maj_ver="8"
;;
esac
rpm_site_infix=centos/${maj_ver}
rpm_installer="yum"
fi
fi
case "${INSTALL_RKE2_CHANNEL}" in
v*.*)
# We are operating with a version-based channel, so we should parse our version out
rke2_majmin=$(echo "${INSTALL_RKE2_CHANNEL}" | sed -E -e "s/^v([0-9]+\.[0-9]+).*/\1/")
rke2_rpm_channel=$(echo "${INSTALL_RKE2_CHANNEL}" | sed -E -e "s/^v[0-9]+\.[0-9]+-(.*)/\1/")
# If our regex fails to capture a "sane" channel out of the specified channel, fall back to `stable`
if [ "${rke2_rpm_channel}" = ${INSTALL_RKE2_CHANNEL} ]; then
info "using stable RPM repositories"
rke2_rpm_channel="stable"
fi
;;
*)
get_release_version
rke2_majmin=$(echo "${INSTALL_RKE2_VERSION}" | sed -E -e "s/^v([0-9]+\.[0-9]+).*/\1/")
rke2_rpm_channel=${1}
;;
esac
info "using ${rke2_majmin} series from channel ${rke2_rpm_channel}"
rpm_site="rpm.rancher.io"
if [ "${rke2_rpm_channel}" = "testing" ]; then
rpm_site="rpm-${rke2_rpm_channel}.rancher.io"
fi
rm -f ${repodir}/rancher-rke2*.repo
cat <<-EOF >"${repodir}/rancher-rke2.repo"
[rancher-rke2-common-${rke2_rpm_channel}]
name=Rancher RKE2 Common (${1})
baseurl=https://${rpm_site}/rke2/${rke2_rpm_channel}/common/${rpm_site_infix}/noarch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://${rpm_site}/public.key
EOF
if [ -z "${INSTALL_RKE2_COMMIT}" ]; then
cat <<-EOF >>"${repodir}/rancher-rke2.repo"
[rancher-rke2-${rke2_majmin}-${rke2_rpm_channel}]
name=Rancher RKE2 ${rke2_majmin} (${1})
baseurl=https://${rpm_site}/rke2/${rke2_rpm_channel}/${rke2_majmin}/${rpm_site_infix}/$(uname -m)
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://${rpm_site}/public.key
EOF
fi
if rpm -q --quiet rke2-selinux; then
# remove rke2-selinux module in el9 before upgrade to allow container-selinux to upgrade safely
if check_available_upgrades container-selinux && check_available_upgrades rke2-selinux && check_breaking_version container-selinux 2 189; then
MODULE_PRIORITY=$(semodule --list=full | grep rke2 | cut -f1 -d" ")
if [ -n "${MODULE_PRIORITY}" ]; then
semodule -X $MODULE_PRIORITY -r rke2 || true
fi
fi
fi
if [ -z "${INSTALL_RKE2_VERSION}" ] && [ -z "${INSTALL_RKE2_COMMIT}" ]; then
${rpm_installer} install -y "rke2-${INSTALL_RKE2_TYPE}"
elif [ -n "${INSTALL_RKE2_COMMIT}" ]; then
rel_distro="$(echo "${rpm_site_infix}" | tr -d /)"
install_dev_rpm "${rpm_installer}" "${rel_distro}"
else
rke2_rpm_version=$(echo "${INSTALL_RKE2_VERSION}" | sed -E -e "s/[\+-]/~/g" | sed -E -e "s/v(.*)/\1/")
if [ -n "${INSTALL_RKE2_RPM_RELEASE_VERSION}" ]; then
${rpm_installer} install -y "rke2-${INSTALL_RKE2_TYPE}-${rke2_rpm_version}-${INSTALL_RKE2_RPM_RELEASE_VERSION}"
else
${rpm_installer} install -y "rke2-${INSTALL_RKE2_TYPE}-${rke2_rpm_version}"
fi
fi
}
check_breaking_version() {
maj=$2
min=$3
current_maj=$(rpm -qi $1 | awk -F': ' '/Version/ {print $2}' | sed -E -e "s/^([0-9]+)\.([0-9]+).*/\1/")
current_min=$(rpm -qi $1 | awk -F': ' '/Version/ {print $2}' | sed -E -e "s/^([0-9]+)\.([0-9]+).*/\2/")
if [ "${current_maj}" == "${maj}" ] && [ $current_min -le $min ]; then
return 0
fi
return 1
}
check_available_upgrades() {
. /etc/os-release
set +e
if [ "${ID_LIKE%%[ ]*}" = "suse" ]; then
available_upgrades=$(zypper -q -t -s 11 se -s -u --type package $1 | tail -n 1 | grep -v "No matching" | awk '{print $3}')
else
available_upgrades=$(yum -q --refresh list $1 --upgrades | tail -n 1 | awk '{print $2}')
fi
set -e
if [ -n "${available_upgrades}" ]; then
return 0
fi
return 1
}
do_install_tar() {
setup_tmp
if [ -n "${INSTALL_RKE2_ARTIFACT_PATH}" ]; then
stage_local_checksums
stage_local_airgap_tarball
stage_local_tarball
else
get_release_version
info "using ${INSTALL_RKE2_VERSION:-commit $INSTALL_RKE2_COMMIT} as release"
download_airgap_checksums
download_airgap_tarball
download_checksums
download_tarball
fi
verify_airgap_tarball
install_airgap_tarball
verify_tarball
unpack_tarball
if [ -z "${INSTALL_RKE2_SKIP_RELOAD}" ]; then
systemctl daemon-reload
fi
}
setup_fapolicy_rules() {
if [ -r /etc/redhat-release ] || [ -r /etc/centos-release ] || [ -r /etc/oracle-release ] || [ -r /etc/rocky-release ] || [ -r /etc/system-release ]; then
verify_fapolicyd || return 0
# setting rke2 fapolicyd rules
cat <<-EOF >"/etc/fapolicyd/rules.d/80-rke2.rules"
allow perm=any all : dir=/var/lib/rancher/
allow perm=any all : dir=/opt/cni/
allow perm=any all : dir=/run/k3s/
allow perm=any all : dir=/var/lib/kubelet/
EOF
if [ -z "${INSTALL_RKE2_SKIP_RELOAD}" ]; then
fagenrules --load || fatal "failed to load rke2 fapolicyd rules"
systemctl restart fapolicyd
fi
fi
}
do_install() {
setup_env
check_method_conflict
setup_arch
if [ -z "${INSTALL_RKE2_ARTIFACT_PATH}" ]; then
verify_downloader curl || verify_downloader wget || fatal "can not find curl or wget for downloading files"
fi
case ${INSTALL_RKE2_METHOD} in
yum | rpm | dnf)
do_install_rpm "${INSTALL_RKE2_CHANNEL}"
;;
*)
do_install_tar "${INSTALL_RKE2_CHANNEL}"
;;
esac
if [ -z "${INSTALL_RKE2_SKIP_FAPOLICY}" ]; then
setup_fapolicy_rules
fi
}
do_install
exit 0
- Configuring the Linux Installation Script : 설치에 적용할 수 있는 환경변수 - Docs
- INSTALL_RKE2_VERSION : GitHub에서 다운로드할 RKE2 버전 - stable(기본값),
- INSTALL_RKE2_TYPE : 생성할 systemd 서비스의 유형 - server(기본값), agent
- INSTALL_RKE2_CHANNEL_URL : RKE2 다운로드 URL을 가져오기 위한 채널 URL - https://update.rke2.io/v1-release/channels (기본값)
- INSTALL_RKE2_CHANNEL : RKE2 다운로드 URL을 가져오는 데 사용할 채널 - stable(기본값), latest, testing
- INSTALL_RKE2_METHOD : 사용할 설치 방법 - rpm(RPM 기반 시스템 경우 기본값), tar(그외 경우 기본값)
# systemd 기반 시스템에 서비스로 편리하게 설치할 수 있는 설치 스크립트를 제공 : 서비스와 바이너리 파일이 컴퓨터에 설치
# https://docs.rke2.io/install/methods
curl -sfL https://get.rke2.io --output install.sh
chmod +x install.sh
INSTALL_RKE2_CHANNEL=v1.33 ./install.sh
...
Installed:
rke2-common-1.33.7~rke2r3-0.el9.aarch64 rke2-selinux-0.22-1.el9.noarch rke2-server-1.33.7~rke2r3-0.el9.aa
# rke2 버전 확인
rke2 --version
rke2 version v1.33.7+rke2r3 (7e4fd1a82edf497cab91c220144619bbad659cf4)
go version go1.24.11 X:boringcrypto
# repo 추가 확인
dnf repolist
rancher-rke2-1.33-stable Rancher RKE2 1.33 (v1.33)
rancher-rke2-common-stable Rancher RKE2 Common (v1.33)
tree /etc/yum.repos.d/
cat /etc/yum.repos.d/rancher-rke2.repo
[rancher-rke2-common-stable]
name=Rancher RKE2 Common (v1.33)
baseurl=https://rpm.rancher.io/rke2/stable/common/centos/9/noarch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://rpm.rancher.io/public.key
[rancher-rke2-1.33-stable]
name=Rancher RKE2 1.33 (v1.33)
baseurl=https://rpm.rancher.io/rke2/stable/1.33/centos/9/aarch64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://rpm.rancher.io/public.key
# 디렉터리 생성 확인
tree /etc/rancher/
tree /var/lib/rancher/
# rke2 명령 확인
# https://docs.rke2.io/install/configuration#running-the-binary-directly
# rke2 server : Run the RKE2 management server, which will also launch the Kubernetes control plane components such as the API server, controller-manager, and scheduler. Only Supported on Linux.
# rke2 agent : Run the RKE2 node agent. This will cause RKE2 to run as a worker node, launching the Kubernetes node services kubelet and kube-proxy. Supported on Linux and Windows.
rke2 --h
server Run management server
agent Run node agent
# RKE2 설정 : cni 플러그인(canal) 등
# https://docs.rke2.io/install/configuration
# https://docs.rke2.io/advanced
cat << EOF > /etc/rancher/rke2/config.yaml
write-kubeconfig-mode: "0644"
debug: true
cni: canal
bind-address: 192.168.10.11
advertise-address: 192.168.10.11
node-ip: 192.168.10.11
disable-cloud-controller: true
disable:
- servicelb
- rke2-coredns-autoscaler
- rke2-ingress-nginx
- rke2-snapshot-controller
- rke2-snapshot-controller-crd
- rke2-snapshot-validation-webhook
EOF
cat /etc/rancher/rke2/config.yaml
# canal cni 플러그인 helm chart values 파일 작성
# https://docs.rke2.io/networking/basic_network_options
# https://github.com/rancher/rke2-charts/blob/main-source/packages/rke2-canal/charts/values.yaml
mkdir -p /var/lib/rancher/rke2/server/manifests/
cat << EOF > /var/lib/rancher/rke2/server/manifests/rke2-canal-config.yaml
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
name: rke2-canal
namespace: kube-system
spec:
valuesContent: |-
flannel:
iface: "enp0s9"
EOF
# coredns 의 autoscaler 미설치를 위한 helm chart values 파일 작성
# https://docs.rke2.io/add-ons/helm#customizing-packaged-components-with-helmchartconfig
# https://github.com/rancher/rke2-charts/tree/main/charts/rke2-coredns/rke2-coredns/1.45.200
cat << EOF > /var/lib/rancher/rke2/server/manifests/rke2-coredns-config.yaml
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
name: rke2-coredns
namespace: kube-system
spec:
valuesContent: |-
autoscaler:
enabled: false
EOF
# 모니터링 : 신규 터미널창
watch -d pstree -a
journalctl -u rke2-server -f
# RKE2 시작 : 2분 정도 소요 -> coredns 파드까지 정상화 대략 1~2분 추가 소요
systemctl enable --now rke2-server.service
systemctl status rke2-server --no-pager
# 프로세스 확인
pstree -a | grep -v color | grep 'rke2$' -A5
pstree -a | grep -v color | grep 'containerd-shim ' -A2
# 자격증명 파일 복사
mkdir ~/.kube
ls -l /etc/rancher/rke2/rke2.yaml
cp /etc/rancher/rke2/rke2.yaml ~/.kube/config
# /etc/rancher 디렉터리 확인
tree /etc/rancher/
cat /etc/rancher/node/password
cat /etc/rancher/rke2/config.yaml
cat /etc/rancher/rke2/rke2-pss.yaml
# 바이너리 파일 확인
tree /var/lib/rancher/rke2/bin/
├── containerd
├── containerd-shim-runc-v2
├── crictl
├── ctr
├── kubectl
├── kubelet
└── runc
# PATH 안 건드리고 표준 위치로 바이너리 노출 설정 : 심볼릭 링크 방식
ln -s /var/lib/rancher/rke2/bin/containerd /usr/local/bin/containerd
ln -s /var/lib/rancher/rke2/bin/kubectl /usr/local/bin/kubectl
ln -s /var/lib/rancher/rke2/bin/crictl /usr/local/bin/crictl
ln -s /var/lib/rancher/rke2/bin/runc /usr/local/bin/runc
ln -s /var/lib/rancher/rke2/bin/ctr /usr/local/bin/ctr
ln -s /var/lib/rancher/rke2/agent/etc/crictl.yaml /etc/crictl.yaml
runc --version
containerd --version
kubectl version
# 편의성 설정
source <(kubectl completion bash)
alias k=kubectl
complete -F __start_kubectl k
echo 'source <(kubectl completion bash)' >> /etc/profile
echo 'alias k=kubectl' >> /etc/profile
echo 'complete -F __start_kubectl k' >> /etc/profile
k9s
# 확인
kubectl cluster-info -v=6
Kubernetes control plane is running at https://192.168.10.11:6443
# 노드, 파드 정보 확인
kubectl get node -owide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8s-node1 Ready control-plane,etcd 15m v1.34.3+rke2r3 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
helm list -A
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
rke2-canal kube-system 1 2026-02-09 14:30:45.002896818 +0000 UTC deployed rke2-canal-v3.31.3-build2026011900 v3.31.3
rke2-coredns kube-system 1 2026-02-09 14:30:44.989504642 +0000 UTC deployed rke2-coredns-1.45.008 1.13.1
rke2-metrics-server kube-system 1 2026-02-09 14:31:13.07011618 +0000 UTC deployed rke2-metrics-server-3.13.006 0.8.0
rke2-runtimeclasses kube-system 1 2026-02-09 14:31:17.059719859 +0000 UTC deployed rke2-runtimeclasses-0.1.000 0.1.0
kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system etcd-k8s-node1 1/1 Running 0 2m31s
kube-system helm-install-rke2-canal-8ck96 0/1 Completed 0 2m42s
kube-system helm-install-rke2-coredns-mhw4x 0/1 Completed 0 2m42s
kube-system helm-install-rke2-metrics-server-rhqcp 0/1 Completed 0 2m42s
kube-system helm-install-rke2-runtimeclasses-7m69w 0/1 Completed 0 2m42s
kube-system kube-apiserver-k8s-node1 1/1 Running 0 2m31s
kube-system kube-controller-manager-k8s-node1 1/1 Running 0 2m31s
kube-system kube-proxy-k8s-node1 1/1 Running 0 2m31s
kube-system kube-scheduler-k8s-node1 1/1 Running 0 2m31s
kube-system rke2-canal-dkw2n 2/2 Running 0 2m22s
kube-system rke2-coredns-rke2-coredns-784bcb7f4d-tpt2d 1/1 Running 0 2m22s
kube-system rke2-metrics-server-7b59bd8854-m5w2c 1/1 Running 0 114s
/var/lib/rancher/rke2 디렉터리 : addon helm chart, 인증서
# 디렉터리 확인
tree /var/lib/rancher/rke2 -L 1
├── agent
├── bin -> /var/lib/rancher/rke2/data/v1.34.3-rke2r3-5b8349de68df/bin
├── data
└── server
# server 디렉터리
tree /var/lib/rancher/rke2/server/
tree /var/lib/rancher/rke2/server/ -L 1
├── agent-token -> /var/lib/rancher/rke2/server/token
├── cred # kubeconfig 정보들
├── db # etcd snapshots, etcd member snap/wal
├── etc
├── manifests # helm chart manifests by helm controller
├── node-token -> /var/lib/rancher/rke2/server/token
├── tls # 인증서 관련 파일들
└── token
## A token that can be used to register other server or agent nodes will be created at /var/lib/rancher/rke2/server/node-token
ls -l /var/lib/rancher/rke2/server/
cat /var/lib/rancher/rke2/server/node-token
cat /var/lib/rancher/rke2/server/token
K1087d08f6b3f21e75c6835e1b959d634dfbe44970c7b1c93c61d8c510f8076822f::server:466038852cf7cdcd389872ba4ab64c04
## helm chart manifests + values 포함
cat /var/lib/rancher/rke2/server/manifests/rke2-coredns.yaml
apiVersion: helm.cattle.io/v1
kind: HelmChart
...
set:
global.clusterCIDR: 10.42.0.0/16
global.clusterCIDRv4: 10.42.0.0/16
# addon, helm controller 관련 crd 확인
kubectl get crd | grep -E 'helm|addon'
addons.k3s.cattle.io 2026-02-14T07:33:46Z
helmchartconfigs.helm.cattle.io 2026-02-14T07:33:46Z
helmcharts.helm.cattle.io 2026-02-14T07:33:46Z
kubectl get helmcharts.helm.cattle.io -n kube-system -owide
NAME REPO CHART VERSION TARGETNAMESPACE BOOTSTRAP FAILED JOB
rke2-canal true False helm-install-rke2-canal
rke2-coredns true False helm-install-rke2-coredns
rke2-metrics-server False helm-install-rke2-metrics-server
rke2-runtimeclasses False helm-install-rke2-runtimeclasses
kubectl get job -n kube-system
NAME STATUS COMPLETIONS DURATION AGE
helm-install-rke2-canal Complete 1/1 21s 118m
helm-install-rke2-coredns Complete 1/1 20s 118m
helm-install-rke2-metrics-server Complete 1/1 52s 118m
helm-install-rke2-runtimeclasses Complete 1/1 51s 118m
kubectl get helmchartconfigs -n kube-system
NAME AGE
rke2-canal 119m
rke2-coredns 119m
kubectl describe helmchartconfigs -n kube-system rke2-canal
...
Spec:
Failure Policy: reinstall
Values Content: flannel:
iface: "enp0s9"
kubectl get addons.k3s.cattle.io -n kube-system
NAME SOURCE CHECKSUM
rke2-canal /var/lib/rancher/rke2/server/manifests/rke2-canal.yaml 2de126b0695f5c424eba2b8e7c45c67a757edac6ecccce7a6141228e6c2fd852
rke2-canal-config /var/lib/rancher/rke2/server/manifests/rke2-canal-config.yaml 122823431e18d9f23621508c24bff9aff307f46b4d6d9208bbbbf23311db058e
rke2-coredns /var/lib/rancher/rke2/server/manifests/rke2-coredns.yaml 523c74e141f7722f3721ce5b3b6556241199bf3aed9b781a5cbfeebd2fe595f4
rke2-coredns-config /var/lib/rancher/rke2/server/manifests/rke2-coredns-config.yaml 9c8e2bbb7603c69c233c9343c516d3d302fd59b758e2e7084c7ab08b5bfba0e4
rke2-metrics-server /var/lib/rancher/rke2/server/manifests/rke2-metrics-server.yaml 4fe80fe31c6cc3d5f1cb7cd19f4d3181f1c810751ed995fa1ca5d9a560c436f8
rke2-runtimeclasses /var/lib/rancher/rke2/server/manifests/rke2-runtimeclasses.yaml 7915375038cf0683ea2ee558d01adb9a478d1c51ec3f0a508b9082cd4f0a7145
## 인증서 관련 파일들
cat /var/lib/rancher/rke2/server/tls/server-ca.crt | openssl x509 -text -noout # k8s ca 인증서
cat /var/lib/rancher/rke2/server/tls/serving-kube-apiserver.crt | openssl x509 -text -noout # apiserver web server 인증서
Issuer: CN=rke2-server-ca@1770533252
Validity
Not Before: Feb 8 06:47:32 2026 GMT
Not After : Feb 8 06:47:32 2027 GMT
Subject: CN=kube-apiserver
...
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Alternative Name:
DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster.local, DNS:localhost, DNS:k8s-node1, IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:1, IP Address:192.168.10.11, IP Address:192.168.10.11, IP Address:10.43.0.1
# data 디렉터리
tree /var/lib/rancher/rke2/data/
tree /var/lib/rancher/rke2/data/ -L 2
└── v1.34.3-rke2r3-5b8349de68df
├── bin # 핵심 구성요소 관련 바이너리 파일들
└── charts # helm charts by helm controller
## helm chart manifests
cat /var/lib/rancher/rke2/data/v1.34.3-rke2r3-5b8349de68df/charts/rke2-coredns.yaml
# agent 디렉터리
tree /var/lib/rancher/rke2/agent/ | more
tree /var/lib/rancher/rke2/agent/ -L 3
├── client-ca.crt # client 관련 kubeconfig 및 인증서 파일들
...
├── containerd # containerd root 디렉터리 , (설정값) root = "/var/lib/rancher/rke2/agent/containerd"
│ ├── bin
│ ├── containerd.log
│ ├── io.containerd.content.v1.content
│ │ ├── blobs
│ │ └── ingest
...
│ └── tmpmounts
├── etc # 주요 설정 파일
│ ├── containerd
│ │ └── config.toml
│ ├── crictl.yaml
│ └── kubelet.conf.d
│ └── 00-rke2-defaults.conf
├── images
│ ├── cloud-controller-manager-image.txt
│ ├── etcd-image.txt
│ ├── kube-apiserver-image.txt
│ ├── kube-controller-manager-image.txt
│ ├── kube-proxy-image.txt
│ ├── kube-scheduler-image.txt
│ └── runtime-image.txt
├── kubelet.kubeconfig # client 관련 kubeconfig 및 인증서 파일들
...
├── logs # kubelet 로그
│ └── kubelet.log
├── pod-manifests # static pod manifests
│ ├── cloud-controller-manager.yaml
│ ├── etcd.yaml
│ ├── kube-apiserver.yaml
│ ├── kube-controller-manager.yaml
│ ├── kube-proxy.yaml
│ └── kube-scheduler.yaml
...
## crictl.yaml 파일 확인 : k3s 포함된 경로 확인!
crictl ps
cat /var/lib/rancher/rke2/agent/etc/crictl.yaml
runtime-endpoint: unix:///run/k3s/containerd/containerd.sock
ln -s /var/lib/rancher/rke2/agent/etc/crictl.yaml /etc/crictl.yaml
crictl ps
crictl images
## rke2 에서 config.toml 은 직접 수정 비권장 -> 직접 수정하면 rke2/k3s 재시작 시 덮어써짐!
cat /var/lib/rancher/rke2/agent/etc/containerd/config.toml
# File generated by rke2. DO NOT EDIT. Use config.toml.tmpl instead.
version = 3
root = "/var/lib/rancher/rke2/agent/containerd"
...
[plugins.'io.containerd.cri.v1.images'.registry]
config_path = "/var/lib/rancher/rke2/agent/etc/containerd/certs.d"
## containerd registry 설정 디렉터리/파일이 현재는 없음
ls -l /var/lib/rancher/rke2/agent/etc/containerd/certs.d
ls: cannot access '/var/lib/rancher/rke2/agent/etc/containerd/certs.d': No such file or directory
## 컨테이너 이미지 명
grep -H '' /var/lib/rancher/rke2/agent/images/*
/var/lib/rancher/rke2/agent/images/etcd-image.txt:index.docker.io/rancher/hardened-etcd:v3.6.7-k3s1-build20260126
/var/lib/rancher/rke2/agent/images/kube-apiserver-image.txt:index.docker.io/rancher/hardened-kubernetes:v1.34.3-rke2r3-build20260127
/var/lib/rancher/rke2/agent/images/kube-controller-manager-image.txt:index.docker.io/rancher/hardened-kubernetes:v1.34.3-rke2r3-build20260127
/var/lib/rancher/rke2/agent/images/kube-proxy-image.txt:index.docker.io/rancher/hardened-kubernetes:v1.34.3-rke2r3-build20260127
/var/lib/rancher/rke2/agent/images/kube-scheduler-image.txt:index.docker.io/rancher/hardened-kubernetes:v1.34.3-rke2r3-build20260127
/var/lib/rancher/rke2/agent/images/runtime-image.txt:index.docker.io/rancher/rke2-runtime:v1.34.3-rke2r3
crictl images
## kubelet config : 보안 권장 설정 및 엔터프라이즈 권장 설정 반영되어 있음
cat /var/lib/rancher/rke2/agent/etc/kubelet.conf.d/00-rke2-defaults.conf
address: 192.168.10.11
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
anonymous:
enabled: false
webhook:
cacheTTL: 2m0s
enabled: true
x509:
clientCAFile: /var/lib/rancher/rke2/agent/client-ca.crt
authorization:
mode: Webhook
webhook:
cacheAuthorizedTTL: 5m0s
cacheUnauthorizedTTL: 30s
cgroupDriver: systemd
clusterDNS:
- 10.43.0.10
clusterDomain: cluster.local
containerRuntimeEndpoint: unix:///run/k3s/containerd/containerd.sock
cpuManagerReconcilePeriod: 10s
crashLoopBackOff: {}
evictionHard:
imagefs.available: 5%
nodefs.available: 5%
evictionMinimumReclaim:
imagefs.available: 10%
nodefs.available: 10%
evictionPressureTransitionPeriod: 5m0s
failSwapOn: false # 원래 쿠버네티스는 스왑(Swap) 메모리가 켜져 있으면 실행되지 않지만, RKE2는 이를 허용하도록 설정되어 있습니다.
fileCheckFrequency: 20s
healthzBindAddress: 127.0.0.1
httpCheckFrequency: 20s
imageMaximumGCAge: 0s
imageMinimumGCAge: 2m0s
kind: KubeletConfiguration
logging:
flushFrequency: 5s
format: text
options:
json:
infoBufferSize: "0"
text:
infoBufferSize: "0"
verbosity: 0
memorySwap: {}
nodeStatusReportFrequency: 5m0s
nodeStatusUpdateFrequency: 10s # 10초마다 "나 살아있어요"라고 컨트롤플레인 노드에 보고
resolvConf: /etc/resolv.conf
runtimeRequestTimeout: 2m0s
serializeImagePulls: false # 이미지 병렬 pull 허용
shutdownGracePeriod: 0s
shutdownGracePeriodCriticalPods: 0s
staticPodPath: /var/lib/rancher/rke2/agent/pod-manifests
streamingConnectionIdleTimeout: 4h0m0s
syncFrequency: 1m0s
tlsCertFile: /var/lib/rancher/rke2/agent/serving-kubelet.crt
tlsPrivateKeyFile: /var/lib/rancher/rke2/agent/serving-kubelet.key
volumeStatsAggPeriod: 1m0s
## kubelet 로그
tail -f /var/lib/rancher/rke2/agent/logs/kubelet.log'Kubernetes' 카테고리의 다른 글
| [6주차] Kubespray offline 설치 (0) | 2026.02.15 |
|---|---|
| [5주차] Kubespary HA & Upgrade (0) | 2026.02.06 |
| [4주차] Kubespary 배포 분석 (0) | 2026.02.06 |
| [3주차] Kubeadm & K8S Upgrade (0) | 2026.01.20 |
| [2주차] Ansible 기초 (0) | 2026.01.12 |