k8s deploy 7주차 RKE2 & Cluster API

dev_suha·2026년 2월 22일

RKE2 소개

Rancher Labs(현재 SUSE)에서 만든 보안 강화형 Kubernetes 배포판

아키텍처

출처 : https://docs.rke2.io/architecture

RKE2 Server Node

  • Control Plane
  • RKE Supervisor
    • Kubernetes 구성요소 자동 관리
    • static pod 생성/관리
  • kubelet
    • static pod 실행
  • Static Pods
    • etcd
    • api-server
    • scheduler
    • controller-manager

Agent Node

  • Worker
  • RKE Supervisor
    • kubelet / containerd 관리
  • kubelet + containerd
    • 실제 컨테이너 실행

RKE2 구성요소

  • k3s
  • k8s
  • etcd
  • runc
  • containerd/cri
  • CNI
  • CoreDNS
  • Ingress NGINX Controller or Traefik
  • Metrics Server
  • Helm
구분RKE2K3skubeadm
목적EnterpriseLightweightVanilla Kubernetes
보안매우 강함기본직접 설정
설치 난이도쉬움매우 쉬움어려움
Production매우 적합Edge/IoT가능
기본 구성많음최소화없음

RKE2 실습

실습 환경 배포

  • Vagrantfile
    # 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

설치 (Rocky Linux 9 기준)

설치 스크립트

curl -sfL https://get.rke2.io --output install.sh
chmod +x install.sh
INSTALL_RKE2_CHANNEL=v1.33 ./install.sh

주요 환경변수

변수설명
INSTALL_RKE2_VERSION특정 버전 지정
INSTALL_RKE2_TYPEserver / agent
INSTALL_RKE2_CHANNELstable / latest / v1.xx
INSTALL_RKE2_METHODrpm / tar

설치 확인

rke2 --version
dnf repolist

기본 설정

/etc/rancher/rke2/config.yaml

HelmChartConfig (Addon 커스터마이징)

Canal NIC 지정

apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
  name: rke2-canal
  namespace: kube-system
spec:
  valuesContent: |-
    flannel:
      iface: "enp0s9"

CoreDNS autoscaler 비활성화

apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
  name: rke2-coredns
  namespace: kube-system
spec:
  valuesContent: |-
    autoscaler:
      enabled: false

RKE2 시작

systemctl enable --now rke2-server
journalctl -u rke2-server -f

kubeconfig 설정

mkdir ~/.kube
cp /etc/rancher/rke2/rke2.yaml ~/.kube/config

주요 디렉토리 구조

/var/lib/rancher/rke2

agent
server
data
bin -> versioned bin

server 디렉토리

경로설명
credkubeconfig
dbetcd 데이터
manifestshelm addon
tls인증서
tokennode join token

agent 디렉토리

경로설명
containerdruntime 데이터
etc/containerdconfig.toml
pod-manifestsstatic pod
logskubelet 로그

Static Pod (Control Plane)

경로:

/var/lib/rancher/rke2/agent/pod-manifests

포함:

  • etcd
  • kube-apiserver
  • kube-controller-manager
  • kube-scheduler
  • kube-proxy

특징 (보안 강화)

  • anonymous-auth=false
  • etcd encryption at rest
  • TLS cipher suite 제한
  • admission control 적용
  • mTLS health check

인증서

확인

rke2 certificate check --output table

기본 정책

  • 유효기간: 365일
  • 만료 120일 전 자동 갱신

수동 회전

systemctl stop rke2-server
rke2 certificate rotate
systemctl start rke2-server

Worker 노드 추가

서버 노드에서 token 확인

cat /var/lib/rancher/rke2/server/node-token

Agent 설치

curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE=agent sh -

agent config

server: https://192.168.10.11:9345
token: <NODE_TOKEN>

시작

systemctl enable --now rke2-agent

Worker 삭제

서버

kubectl drain <node> --ignore-daemonsets --delete-emptydir-data
kubectl delete node <node>

워커

systemctl stop rke2-agent
rke2-uninstall.sh

샘플 앱 배포

Deployment + NodePort Service
image: traefik/whoami

확인:

kubectl get deploy,pod,svc

수동 업그레이드

원칙

  1. Server 먼저
  2. Agent 나중

Server 업그레이드

curl -sfL https://get.rke2.io | INSTALL_RKE2_CHANNEL=v1.34 sh -
systemctl restart rke2-server

Agent 업그레이드

curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE=agent INSTALL_RKE2_CHANNEL=v1.34 sh -
systemctl restart rke2-agent

확인

kubectl get node -owide

자동 업그레이드 (System Upgrade Controller)

설치

kubectl apply -f https://github.com/rancher/system-upgrade-controller/releases/latest/download/crd.yaml -f https://github.com/rancher/system-upgrade-controller/releases/latest/download/system-upgrade-controller.yaml

Plan 구조

Server Plan

kind: Plan
spec:
  concurrency: 1
  cordon: true
  nodeSelector:
    control-plane
  upgrade:
    image: rancher/rke2-upgrade
  channel: stable

Agent Plan

prepare:
  - server-plan
  • 서버 업그레이드 완료 후 실행

확인

kubectl -n system-upgrade get plans
kubectl -n system-upgrade get jobs

Cluster API


Cluster API란?

Cluster API (CAPI) 는 Kubernetes 스타일의 선언적 API(CRD) 를 사용해 여러 Kubernetes 클러스터의 생성 · 확장 · 업그레이드 · 삭제 를 자동화하는 프로젝트

  • Kubernetes SIG Cluster Lifecycle 프로젝트
  • Kubernetes 방식으로 Kubernetes를 관리
  • K8S as a Service 구현의 핵심 기술

기본 구조

Management Cluster

  • Cluster API 컨트롤러가 실행되는 클러스터
  • 다른 클러스터를 생성/관리

Workload Cluster

  • 실제 사용자 워크로드가 실행되는 클러스터
  • Cluster API가 프로비저닝

Core 리소스 구조

Cluster (최상위 리소스)

클러스터 전체 정의

Cluster
 ├─ infrastructureRef
 └─ controlPlaneRef
  • 네트워크 CIDR 등 공통 속성 정의
  • 실제 구현은 Provider가 담당

Machine (노드 정의)

Machine = Kubernetes Node를 호스팅하는 인프라

Machine
 ├─ infrastructureRef
 └─ bootstrap.configRef
  • VM/Instance 생성
  • Node 등록
  • 삭제 시 인프라도 제거

Machine 계층 구조

graph TD
    MD[MachineDeployment]
    MS[MachineSet]
    M[Machine]
    Infra[Infrastructure Resource]
    VM[Actual VM]

    MD --> MS
    MS --> M
    M --> Infra
    Infra --> VM

MachineDeployment

  • Deployment와 동일 개념
  • Machine 롤링 업데이트 수행

MachineSet

  • ReplicaSet 역할
  • 원하는 Machine 수 유지

MachineHealthCheck

  • Node 상태 감시
  • 문제 발생 시 Machine 교체

Provider 구조

Cluster API = 인터페이스 + 구현체

CNI 구조와 동일 개념.

구분CNICluster API
표준 인터페이스CNICluster API Core
구현체Calico, FlannelInfrastructure Provider

Infrastructure Provider

실제 인프라 생성 담당

예:

  • AWS (CAPA)
  • Azure (CAPZ)
  • vSphere
  • Metal3
  • OpenStack 등

역할:

  • VM 생성
  • VPC / LB / Network 구성
  • Cloud API 호출

Control Plane Provider

Control Plane 구성 방식 정의

종류

  • Self-provisioned (kubeadm)
  • Pod-based
  • Managed (EKS / AKS / GKE)
  • RKE2
  • Talos
  • K3s 등

Bootstrap Provider

Machine → Node 변환 담당

역할:

  • 인증서 생성
  • Control Plane 초기화
  • Node Join 수행

대표:

  • kubeadm
  • RKE2
  • Talos 등

Machine Immutability

기본 원칙:

Machine은 immutable (불변)
  • 수정 대신 교체
  • 변경 = 새 Machine 생성

In-place Update (v1.12)

  • 일부 조건에서 Machine 교체 없이 업데이트 가능
  • 사용자 경험은 동일
  • 내부적으로 최적 전략 선택

Chained Upgrades (v1.12)

여러 버전 업그레이드 자동 수행

예:

v1.33 → v1.34 → v1.35

사용자는:

v1.35 지정만 하면 됨

ownerReferences (자동 정리)

리소스 간 부모-자식 관계 정의.

Deployment 삭제
 → ReplicaSet 삭제
   → Pod 삭제

Cluster API도 동일 방식 사용.

➡️ Cluster 삭제 시 하위 인프라 자동 정리


Cluster API가 필요한 이유

kubeadm 한계

  • 초기 설치만 도움
  • 장기 운영 자동화 없음

Cluster API가 해결하는 문제

  • 멀티 클러스터 관리
  • 클러스터 수명주기 자동화
  • 인프라별 일관된 관리
  • 선언형 운영

Cluster API 실습

Cluster API 실습 정리 (kind + Docker 기반) — 실습 코드 포함 버전 (Notion용)


목표

kind Kubernetes = Management Cluster
Docker daemon = Workload Cluster 인프라
  • WSL2 + Docker 환경
  • Cluster API Quick Start 실습
  • CAPD (Docker Provider) 사용
  • Kubernetes를 Kubernetes로 배포

전체 구조

Management Cluster (kind)
 ├─ Core Provider (CAPI)
 ├─ Bootstrap Provider (kubeadm)
 ├─ ControlPlane Provider (kubeadm)
 └─ Infrastructure Provider (CAPD)

↓ reconcile

Workload Cluster (Docker Containers)
 ├─ Control Plane Nodes
 ├─ Worker Nodes
 └─ HAProxy LoadBalancer

Management Cluster 생성

kind 클러스터 생성

kind 설정 파일 (docker.sock mount 필수)

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: capi-test
nodes:
  - role: control-plane
    extraMounts:
      - hostPath: /var/run/docker.sock
        containerPath: /var/run/docker.sock

클러스터 생성

kind create cluster --config kind.yaml

clusterctl 설치

curl -L https://github.com/kubernetes-sigs/cluster-api/releases/latest/download/clusterctl-linux-amd64 -o clusterctl
chmod +x clusterctl
sudo mv clusterctl /usr/local/bin/

확인:

clusterctl version

Cluster API 초기화

clusterctl init --infrastructure docker

설치되는 Provider:

타입Provider
Corecluster-api
Bootstrapkubeadm
Control Planekubeadm
Infrastructuredocker (CAPD)

설치 확인

kubectl get pods -A

cert-manager 확인

kubectl get pods -n cert-manager
kubectl get certificates -A

역할:

Webhook TLS 인증서 자동 관리

Workload Cluster 생성

클러스터 YAML 생성

clusterctl generate cluster capi-quickstart --flavor development > cluster.yaml

생성된 YAML 적용

kubectl apply -f cluster.yaml

생성 확인

kubectl get cluster
kubectl get machines
kubectl get kubeadmcontrolplanes
kubectl get machinedeployments

ClusterClass 구조 (핵심 코드)

ClusterClass = 설계도.

apiVersion: cluster.x-k8s.io/v1beta2
kind: Cluster
metadata:
  name: capi-quickstart
spec:
  topology:
    class: quick-start
    version: v1.29.0
    controlPlane:
      replicas: 3
    workers:
      machineDeployments:
        - class: default-worker
          name: md-0
          replicas: 3

리소스 생성 흐름

Cluster
 → KubeadmControlPlane
 → MachineDeployment
 → Machine
 → DockerMachine
 → Docker Container(Node)

kubeconfig 가져오기

Workload cluster 접근:

clusterctl get kubeconfig capi-quickstart > workload.kubeconfig

테스트:

kubectl --kubeconfig workload.kubeconfig get nodes

CNI 설치 (Node Ready 필수)

초기 상태:

Node = NotReady (정상)

Calico 설치

kubectl --kubeconfig workload.kubeconfig apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.0/manifests/calico.yaml

확인:

kubectl --kubeconfig workload.kubeconfig get nodes

리소스 관계 확인 (실습 필수)

kubectl get cluster
kubectl get machines
kubectl get dockerclusters
kubectl get dockermachines

Machine 계층 구조

MachineDeployment
   ↓
MachineSet
   ↓
Machine
   ↓
DockerMachine
   ↓
Docker Container

kubeadm 내부 확인

ConfigMap 확인:

kubectl --kubeconfig workload.kubeconfig -n kube-system get cm kubeadm-config -o yaml

확인 포인트:

  • controlPlaneEndpoint (HAProxy)
  • podSubnet
  • serviceSubnet

인증서 및 Secret 확인

Management Cluster:

kubectl get secrets | grep capi-quickstart

Bootstrap 흐름:

cloud-init → kubeadm init/join → Node 등록

Docker 기반 노드 확인

실제 노드는 Docker 컨테이너:

docker ps | grep capi-quickstart

최종 상태

Management Cluster (kind)
        ↓
Cluster API Controllers
        ↓
Workload Cluster (Docker)
  - Control Plane
  - Worker
  - HAProxy

0개의 댓글