쿠버네티스는 좋지만, 컨트롤 플레인 한 대를 위해 서버 3대를 쓰기엔 비용이 부담입니다. 단일 노드만으로도 K8s API와 매니페스트를 그대로 쓸 수 있다면 가장 좋겠죠. k3s가 그런 도구입니다.

k3s 단일 노드 아키텍처


k3s가 적합한 경우

상황 k3s 풀 K8s
사이드 프로젝트 / 스테이징 과함
프로덕션, 노드 1~3대 과함
노드 10대 이상, HA 필요
엣지·IoT 디바이스
메모리 1GB 서버

k3s는 풀 K8s와 API 호환입니다. kubectl 명령, Deployment YAML 등이 그대로 동작합니다. 차이는 etcd 대신 SQLite를 쓰고, 불필요한 컨트롤러를 제거해 가볍게 만든 점입니다.


1단계 — 사전 준비

일본 서버 1대(Ubuntu 22.04 LTS, 메모리 2GB 이상 권장)를 준비합니다. swap이 켜져 있으면 비활성화해야 합니다.

# swap 비활성화 (k8s 권장)
sudo swapoff -a
sudo sed -i '/ swap / s/^/#/' /etc/fstab

# 커널 모듈 적재
sudo modprobe overlay
sudo modprobe br_netfilter

# sysctl 설정
cat <<EOF | sudo tee /etc/sysctl.d/99-k3s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF
sudo sysctl --system

2단계 — k3s 설치

공식 설치 스크립트는 한 줄입니다.

curl -sfL https://get.k3s.io | sh -

설치가 끝나면 자동으로 systemd 서비스가 등록되고 클러스터가 동작합니다.

sudo systemctl status k3s
sudo k3s kubectl get nodes
# NAME       STATUS   ROLES                  AGE   VERSION
# server1    Ready    control-plane,master   30s   v1.30.x+k3s1

kubectl을 root 없이 사용하려면 kubeconfig를 사용자 홈으로 복사합니다.

mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $(id -u):$(id -g) ~/.kube/config
chmod 600 ~/.kube/config

kubectl get pods -A

3단계 — 기본 컴포넌트

k3s는 다음을 기본으로 포함합니다.

  • Traefik — Ingress 컨트롤러 (L7 라우팅, 자동 HTTPS)
  • CoreDNS — 클러스터 내부 DNS
  • ServiceLB(Klipper)Service: LoadBalancer 타입 자동 처리
  • Local Path ProvisionerPersistentVolumeClaim을 호스트 디렉토리에 매핑
  • Metrics Serverkubectl top 동작

별도 설치 없이 첫 배포부터 외부 접근, HTTPS, 영구 볼륨이 모두 가능합니다.


4단계 — 첫 배포 (Nginx 예시)

# nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 2
  selector:
    matchLabels: { app: nginx }
  template:
    metadata:
      labels: { app: nginx }
    spec:
      containers:
        - name: nginx
          image: nginx:1.27
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector: { app: nginx }
  ports:
    - port: 80
      targetPort: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  ingressClassName: traefik
  rules:
    - host: app.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: nginx
                port:
                  number: 80
  tls:
    - hosts: [app.example.com]
      secretName: nginx-tls
kubectl apply -f nginx.yaml
kubectl get ingress

도메인의 A 레코드를 일본 서버 IP로 향하게 하면 https://app.example.com으로 접근 가능합니다.


5단계 — Let’s Encrypt 자동 인증서 (cert-manager)

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

# cert-manager 설치
helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager --create-namespace \
  --set crds.enabled=true

ClusterIssuer 등록:

# letsencrypt.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: admin@example.com
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
      - http01:
          ingress:
            ingressClassName: traefik
kubectl apply -f letsencrypt.yaml

이후 Ingress의 tls: 섹션과 cert-manager.io/cluster-issuer 어노테이션만 추가하면 인증서가 자동 발급·갱신됩니다.


6단계 — 모니터링과 로그

가벼운 환경에서는 Prometheus 풀스택보다 간단한 도구가 적합합니다.

# 컨테이너 단위 리소스 확인
kubectl top pods -A
kubectl top nodes

# 특정 파드 로그
kubectl logs -f deploy/nginx

# 컨테이너 안으로 진입
kubectl exec -it deploy/nginx -- /bin/sh

운영 모니터링이 필요하다면 k9s라는 TUI 도구가 매우 유용합니다.

curl -sS https://webinstall.dev/k9s | bash
k9s

7단계 — 백업

k3s의 상태는 SQLite 파일 하나에 저장됩니다.

# k3s 정지
sudo systemctl stop k3s

# 백업
sudo cp /var/lib/rancher/k3s/server/db/state.db /backup/k3s-$(date +%F).db

# 시작
sudo systemctl start k3s

자동화된 백업이 필요하면 cron으로 매일 새벽 실행되도록 설정합니다.


운영 시 주의점

  • 단일 노드의 한계 — 노드가 죽으면 모든 서비스가 죽습니다. 진짜 HA가 필요하면 노드 3대 + embedded etcd 모드로 구성하세요.
  • 로컬 볼륨의 종속성 — Local Path Provisioner는 호스트 디렉토리를 사용하므로, 노드를 옮기면 데이터도 함께 이동시켜야 합니다.
  • 메모리 모니터링 — k3s 자체는 가볍지만 그 위에서 도는 워크로드(Java, MySQL 등)가 메모리를 잡아먹습니다. 1GB VPS는 권장하지 않습니다.
  • 포트 충돌 — k3s는 6443(API), 10250(kubelet) 포트를 사용합니다. 외부에서 직접 접근할 일이 없다면 방화벽으로 막아두세요.

마무리

k3s는 “쿠버네티스 학습 비용은 그대로 가져가되, 운영 비용은 한 대 분량으로” 줄이고 싶을 때 가장 합리적인 선택입니다. TCP-80.NET의 일본 VPS 4GB 플랜이면 k3s + 웹 + DB + 캐시까지 모두 운영 가능합니다.

설치 중 막히는 부분이 있으면 @tcp80net으로 문의해 주세요. 한국어로 도와드립니다.