IT기술/쿠버네티스 (k8s)

Rancher와 RKE2 완벽 가이드: 차세대 쿠버네티스 플랫폼 구축과 자동화

후스파 2025. 7. 14. 07:12
반응형

Rancher는 여러 쿠버네티스 클러스터를 효율적으로 관리할 수 있는 오픈소스 플랫폼으로, 다양한 환경에서 쿠버네티스를 쉽게 배포하고 운영할 수 있게 해줍니다. RKE2(Rancher Kubernetes Engine 2)는 Rancher에서 개발한 보안에 중점을 둔 쿠버네티스 배포판으로, 미국 정부의 보안 규정을 준수하도록 설계되었습니다. RKE2는 기존 RKE보다 강화된 보안 기능과 containerd 런타임을 사용하여 더 안정적이고 효율적인 쿠버네티스 환경을 제공합니다.
RKE2는 2025년 7월 RKE의 지원 종료(EOL)가 예정됨에 따라 더욱 중요해지고 있으며, 기존 RKE 사용자들은 RKE2로의 마이그레이션을 고려해야 합니다. RKE2는 containerd를 채택하여 더 강력한 보안과 효율적인 환경을 제공하며, CIS 쿠버네티스 벤치마크를 기본적으로 통과할 수 있도록 설계되었습니다.


RKE2 클러스터 구축 기본 과정

사전 준비 사항

RKE2 클러스터를 구축하기 전에 다음과 같은 사전 작업이 필요합니다:

# 스왑 메모리 비활성화 (모든 노드)
sudo swapoff -a
sudo sed -i '/swap/s/^/#/' /etc/fstab

# 방화벽 및 SELinux 설정
sudo systemctl disable --now firewalld  # CentOS/RHEL
sudo ufw disable  # Ubuntu
sudo setenforce 0

# 시간 동기화
sudo timedatectl set-ntp true
sudo systemctl enable --now chronyd

# 필수 패키지 설치
sudo apt update && sudo apt install -y curl wget  # Ubuntu
sudo dnf update && sudo dnf install -y curl wget  # CentOS/RHEL

호스트 파일 설정: 모든 노드의 /etc/hosts 파일에 클러스터 노드 정보를 추가합니다:

sudo tee -a /etc/hosts > ~/.bashrc
source ~/.bashrc

# 클러스터 상태 확인
kubectl get nodes
kubectl get pods -A

워커 노드 설치

# 마스터 노드에서 토큰 확인
sudo cat /var/lib/rancher/rke2/server/node-token

# 워커 노드에서 RKE2 에이전트 설치
curl -sfL https://get.rke2.io | sudo INSTALL_RKE2_TYPE="agent" sh -

# 설정 디렉토리 생성
sudo mkdir -p /etc/rancher/rke2

# 설정 파일 생성
sudo tee /etc/rancher/rke2/config.yaml 
node-label:
  - "node-type=worker"
EOF

# RKE2 에이전트 서비스 활성화 및 시작
sudo systemctl enable rke2-agent.service
sudo systemctl start rke2-agent.service

# 서비스 상태 확인
sudo systemctl status rke2-agent

Rancher와 RKE2 연동 방법

Rancher 설치

Docker를 이용한 Rancher 설치 (단일 노드):

# Docker 설치 (Ubuntu)
sudo apt update
sudo apt install -y docker.io
sudo systemctl enable --now docker
sudo usermod -aG docker $USER

# Rancher 컨테이너 실행
sudo docker run -d --restart=unless-stopped \
  -p 80:80 -p 443:443 \
  --privileged \
  -v rancher-data:/var/lib/rancher \
  rancher/rancher:latest

# 초기 비밀번호 확인
sudo docker logs container-id 2>&1 | grep "Bootstrap Password:"

Helm을 이용한 HA Rancher 설치:

# Helm 설치
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

# cert-manager 설치
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.3/cert-manager.yaml

# Rancher Helm 저장소 추가
helm repo add rancher-stable https://releases.rancher.com/server-charts/stable
helm repo update

# Rancher 설치
helm install rancher rancher-stable/rancher \
  --namespace cattle-system \
  --create-namespace \
  --set hostname=rancher.example.com \
  --set bootstrapPassword=admin123

RKE2 클러스터 Rancher에 등록

  1. 클러스터 추가: Rancher UI에서 "☰ > Cluster Management" → "Import Existing" 클릭
  2. 클러스터 유형 선택: "Generic" 선택
  3. 클러스터 설정:
    • 클러스터 이름 입력
    • 필요에 따라 라벨 및 어노테이션 추가
  4. 등록 명령어 생성: Rancher가 생성한 등록 명령어 복사
  5. 노드에 명령어 실행: 마스터 노드에서 등록 명령어 실행
# Rancher 등록 명령어 예시
curl --insecure -sfL https://rancher.example.com/v3/import/xyz.yaml | kubectl apply -f -

고가용성(HA) 클러스터 구성

로드 밸런서 설정

HAProxy와 Keepalived를 사용한 HA 구성:

# HAProxy 설치
sudo apt install -y haproxy keepalived

# HAProxy 설정
sudo tee /etc/haproxy/haproxy.cfg 
node-name: master-02  # 각 노드마다 다르게
tls-san:
  - "192.168.1.100"
  - "192.168.1.10"
  - "192.168.1.11"
  - "192.168.1.12"
  - "rancher.example.com"

Rancher와 RKE2 관리 자동화 방법

Ansible을 활용한 자동화

# Ansible 설치
pip3 install ansible

# 인벤토리 파일 생성
cat > inventory.ini  5.0"
    }
  }
}

provider "aws" {
  region = var.aws_region
}

# VPC 생성
resource "aws_vpc" "rke2_vpc" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name = "rke2-vpc"
  }
}

# 서브넷 생성
resource "aws_subnet" "rke2_subnet" {
  vpc_id                  = aws_vpc.rke2_vpc.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = data.aws_availability_zones.available.names[0]
  map_public_ip_on_launch = true

  tags = {
    Name = "rke2-subnet"
  }
}

# 보안 그룹
resource "aws_security_group" "rke2_sg" {
  name_prefix = "rke2-sg"
  vpc_id      = aws_vpc.rke2_vpc.id

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 6443
    to_port     = 6443
    protocol    = "tcp"
    cidr_blocks = ["10.0.0.0/16"]
  }

  ingress {
    from_port   = 9345
    to_port     = 9345
    protocol    = "tcp"
    cidr_blocks = ["10.0.0.0/16"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

# 마스터 노드
resource "aws_instance" "rke2_master" {
  count                  = 3
  ami                    = data.aws_ami.ubuntu.id
  instance_type          = "t3.medium"
  key_name              = var.key_name
  subnet_id             = aws_subnet.rke2_subnet.id
  vpc_security_group_ids = [aws_security_group.rke2_sg.id]

  user_data = templatefile("${path.module}/scripts/master-userdata.sh", {
    node_name = "master-${count.index + 1}"
  })

  tags = {
    Name = "rke2-master-${count.index + 1}"
    Type = "master"
  }
}

# 워커 노드
resource "aws_instance" "rke2_worker" {
  count                  = 2
  ami                    = data.aws_ami.ubuntu.id
  instance_type          = "t3.medium"
  key_name              = var.key_name
  subnet_id             = aws_subnet.rke2_subnet.id
  vpc_security_group_ids = [aws_security_group.rke2_sg.id]

  user_data = templatefile("${path.module}/scripts/worker-userdata.sh", {
    master_ip = aws_instance.rke2_master[0].private_ip
  })

  tags = {
    Name = "rke2-worker-${count.index + 1}"
    Type = "worker"
  }

  depends_on = [aws_instance.rke2_master]
}

Fleet을 활용한 GitOps 자동화

Git 저장소 구조:

fleet-config/
├── clusters/
│   ├── production/
│   │   └── fleet.yaml
│   └── staging/
│       └── fleet.yaml
├── apps/
│   ├── nginx/
│   │   ├── deployment.yaml
│   │   ├── service.yaml
│   │   └── fleet.yaml
│   └── monitoring/
│       ├── prometheus/
│       └── grafana/
└── fleet.yaml

Fleet 설정 파일:

# fleet.yaml (루트)
defaultNamespace: fleet-system

# apps/nginx/fleet.yaml
defaultNamespace: nginx-system

targetCustomizations:
- name: production
  clusterSelector:
    matchLabels:
      env: production
  helm:
    values:
      replicaCount: 3
      resources:
        requests:
          memory: "256Mi"
          cpu: "250m"

- name: staging
  clusterSelector:
    matchLabels:
      env: staging
  helm:
    values:
      replicaCount: 1
      resources:
        requests:
          memory: "128Mi"
          cpu: "100m"

모니터링 및 관리 자동화

Rancher 모니터링 시스템 구축

# Rancher UI에서 모니터링 활성화 또는 CLI로 설치
helm repo add rancher-charts https://charts.rancher.io
helm repo update

# Monitoring 설치
helm install rancher-monitoring rancher-charts/rancher-monitoring \
  --namespace cattle-monitoring-system \
  --create-namespace \
  --set prometheus.prometheusSpec.retention=30d \
  --set grafana.persistence.enabled=true \
  --set grafana.persistence.size=10Gi

API를 활용한 자동화

# API 토큰 생성 (Rancher UI에서)
# User & Authentication > API & Keys

# 클러스터 정보 조회
curl -s -k -H "Authorization: Bearer " \
  https://rancher.example.com/v3/clusters | jq '.data[].name'

# 프로젝트 생성
curl -s -k -X POST \
  -H "Authorization: Bearer " \
  -H "Content-Type: application/json" \
  -d '{
    "type": "project",
    "name": "production",
    "clusterId": "c-xxxxx"
  }' \
  https://rancher.example.com/v3/projects

자동화 스크립트 예시:

#!/usr/bin/env python3
import requests
import json

class RancherAPI:
    def __init__(self, url, token):
        self.url = url
        self.token = token
        self.headers = {
            'Authorization': f'Bearer {token}',
            'Content-Type': 'application/json'
        }

    def get_clusters(self):
        response = requests.get(f'{self.url}/v3/clusters', 
                              headers=self.headers, verify=False)
        return response.json()

    def create_project(self, cluster_id, project_name):
        data = {
            'type': 'project',
            'name': project_name,
            'clusterId': cluster_id
        }
        response = requests.post(f'{self.url}/v3/projects',
                               headers=self.headers, 
                               data=json.dumps(data), verify=False)
        return response.json()

# 사용 예시
rancher = RancherAPI('https://rancher.example.com', 'token-xxxxx')
clusters = rancher.get_clusters()
for cluster in clusters['data']:
    print(f"Cluster: {cluster['name']}, State: {cluster['state']}")

RKE2 클러스터 백업 및 복구 자동화

백업 자동화

# /etc/rancher/rke2/config.yaml에 백업 설정 추가
etcd-snapshot-schedule-cron: "0 */6 * * *"  # 6시간마다
etcd-snapshot-retention: 10
etcd-snapshot-dir: /opt/rke2/etcd-snapshots
etcd-s3: true
etcd-s3-bucket: rke2-backups
etcd-s3-region: ap-northeast-2
etcd-s3-access-key: AKIAIOSFODNN7EXAMPLE
etcd-s3-secret-key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

백업 스크립트:

#!/bin/bash
# backup-rke2.sh

BACKUP_NAME="manual-backup-$(date +%Y%m%d-%H%M%S)"
S3_BUCKET="rke2-backups"
BACKUP_DIR="/var/lib/rancher/rke2/server/db/snapshots"

# etcd 스냅샷 생성
echo "Creating etcd snapshot: $BACKUP_NAME"
rke2 etcd-snapshot save --name $BACKUP_NAME

# S3에 업로드
echo "Uploading to S3..."
aws s3 cp $BACKUP_DIR/$BACKUP_NAME.zip s3://$S3_BUCKET/

# 로컬 정리 (7일 이상 된 백업 삭제)
find $BACKUP_DIR -name "*.zip" -mtime +7 -delete

echo "Backup completed: $BACKUP_NAME"

복구 자동화

#!/bin/bash
# restore-rke2.sh

SNAPSHOT_NAME=$1
S3_BUCKET="rke2-backups"

if [ -z "$SNAPSHOT_NAME" ]; then
    echo "Usage: $0 "
    exit 1
fi

# S3에서 스냅샷 다운로드
echo "Downloading snapshot from S3..."
aws s3 cp s3://$S3_BUCKET/$SNAPSHOT_NAME /tmp/

# RKE2 중지
echo "Stopping RKE2 server..."
systemctl stop rke2-server

# 스냅샷에서 복구
echo "Restoring from snapshot..."
rke2 server --cluster-reset --cluster-reset-restore-path=/tmp/$SNAPSHOT_NAME

# RKE2 재시작
echo "Starting RKE2 server..."
systemctl start rke2-server

echo "Restore completed from: $SNAPSHOT_NAME"

자동 복구 모니터링:

#!/bin/bash
# health-check.sh

HEALTH_CHECK_URL="https://192.168.1.100:6443/healthz"
MAX_RETRIES=3
RETRY_COUNT=0

while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
    if curl -k -f $HEALTH_CHECK_URL > /dev/null 2>&1; then
        echo "Cluster is healthy"
        exit 0
    else
        echo "Health check failed, attempt $((RETRY_COUNT + 1))"
        RETRY_COUNT=$((RETRY_COUNT + 1))
        sleep 30
    fi
done

echo "Cluster health check failed after $MAX_RETRIES attempts"
echo "Initiating automatic recovery..."

# 최신 백업에서 복구
LATEST_BACKUP=$(aws s3 ls s3://rke2-backups/ | sort | tail -n 1 | awk '{print $4}')
./restore-rke2.sh $LATEST_BACKUP

마무리

Rancher와 RKE2의 연동 및 관리 자동화는 현대적인 쿠버네티스 환경에서 효율성과 안정성을 크게 향상시킵니다. 이 글에서는 RKE2 클러스터 구축부터 Rancher와의 연동, 그리고 Ansible, Terraform, Fleet 등의 도구를 활용한 다양한 자동화 방법을 살펴보았습니다.
특히 2025년 7월 RKE의 지원 종료가 예정되어 있어, RKE2로의 마이그레이션은 많은 기업에게 중요한 과제가 될 것입니다. RKE2는 containerd를 채택하여 더 강력한 보안과 효율적인 환경을 제공하며, CIS 쿠버네티스 벤치마크를 기본적으로 통과할 수 있도록 설계되어 있어 보안에 민감한 환경에서 특히 유용합니다.
핵심 포인트:

  • RKE1 EOL 2025년 7월 31일로 인한 필수 마이그레이션
  • Containerd 기반 아키텍처로 보안과 성능 향상
  • Rancher 통합 관리로 다중 클러스터 운영 효율화
  • Ansible/Terraform 자동화로 인프라 코드화
  • Fleet GitOps로 선언적 애플리케이션 배포
  • 자동 백업/복구 시스템으로 재해 복구 보장

자동화는 단순히 시간을 절약하는 것을 넘어, 인적 오류를 줄이고 일관된 환경을 유지하는 데 큰 도움이 됩니다. 최신 트렌드와 모범 사례를 지속적으로 학습하고 적용하여 더욱 효율적이고 안정적인 쿠버네티스 환경을 구축하시기 바랍니다.

반응형