K3s 는 경이로운 도구다. 70MB 바이너리 한 개로 완전한 Kubernetes 가 1 분 내 돈다. 라즈베리 파이 / 노트북 / 작은 데스크탑에서도 production-grade 워크로드 운영 가능. 내 5 노드 홈랩 클러스터 (lemuel/ilwon/louise/david/solomon) 가 1 년 동안 settlement, lemuel-xr, academy, sparta-msa 등 수십 개 prod 워크로드 를 무사히 굴린 증거.

그러나 K3s 의 우아한 단순함동시에 한계 다. 이 글은 그 한계가 어디서 실제로 부딪혔고, 언제 RKE2 / Talos / vanilla K8s 로 갈아탈 신호인지 를 1 년 운영 경험 기반으로 정리한다.


TL;DR — K3s 의 8 가지 진짜 한계

# 한계 증상 대응
1 임베디드 etcd 분리 불가 etcd 만 별도 노드로 못 뺌 작으면 OK, 커지면 vanilla K8s
2 단일 바이너리 디버깅 모든 컴포넌트 로그가 journalctl -u k3s 한 곳 익숙해지면 OK
3 HA 가 민감 server 노드 1 개 죽으면 quorum 깨짐, recovery 까다로움 server 3 노드 반드시 유지
4 Backup/Restore 가 반자동 etcd snapshot 은 자동, 전체 복구는 수동 4 단계 runbook 미리 작성
5 대규모 한계 100+ 노드 또는 수천 pod 면 성능 ↓ 그쯤 가면 RKE2 또는 vanilla
6 Networking 옵션 제한 Flannel 기본, 다른 CNI 교체 신중 Cilium 으로 교체 가능, 다만 비표준
7 자체 디버깅 도구 부재 kubeadm, kubelet 별도 명령 사용 불가 작은 환경엔 OK
8 Enterprise / 보안 강화 기능 Pod Security Standards 는 OK, FIPS 등 X 금융권/공공이면 RKE2

결정 기준 한 줄: 5-15 노드 + 수백 pod 까지는 K3s 가 최적. 50+ 노드 또는 컴플라이언스 요구 시 RKE2 / vanilla 로.


0. K3s 의 기원과 약속

2019 년 Rancher 가 K3s 발표. 목표:

  • 바이너리 < 100MB
  • 메모리 < 512MB
  • ARM 지원
  • Edge / IoT / 홈랩 환경

달성 방법:

  • 모든 컴포넌트를 단일 바이너리 — api-server, scheduler, controller-manager, etcd, kubelet, kube-proxy 가 한 프로세스
  • Containerd 임베디드
  • 기본 etcd 대안: SQLite (단일 노드)
  • Flannel + Traefik + ServiceLB 내장
  • 불필요한 alpha API 제거

이 단순함이 5 노드 홈랩 에선 축복, 50 노드 production 에선 제약 이 된다.


1. 한계 ① — 임베디드 etcd 분리 불가

1.1 vanilla K8s 의 구조

[etcd cluster (3 노드 별도)]
       ↓
[kube-apiserver (3 노드)]
       ↓
[kube-scheduler] [kube-controller-manager]
       ↓
[kubelet on each worker]

etcd 가 완전히 별도 노드. control-plane 의 다른 컴포넌트와도 분리. 각 layer 별 *독립적 scale up.

1.2 K3s 의 구조

[k3s-server 노드 1] ─┐
   ├─ embedded etcd  │
   ├─ apiserver       ├─ etcd raft (3 노드 quorum)
   ├─ scheduler       │
   └─ controller-mgr ─┘

[k3s-server 노드 2] (동일 구조)
[k3s-server 노드 3] (동일 구조)

etcd 가 k3s-server 프로세스 안에 임베디드. 한 프로세스 죽으면 etcd + control-plane 다 죽음.

1.3 실전 사례 — etcd 만 격리 불가

내 환경에서 lemuel 의 CPU 부하 가 control-plane 컴포넌트에 영향 줘서 cordon 한 적 있음. vanilla K8s 면 etcd 만 분리해 디스크 성능 좋은 노드 에 배치 가능. K3s 에선 불가.

1.4 우회 방법

  • --disable-apiserver --disable-controller-manager --disable-scheduler 옵션으로 일부 컴포넌트만 동작 가능. 그러나 권장 패턴 아님 (rancher 공식 문서에 mention 적음)
  • 외부 etcd cluster 와 연동 도 가능 (--datastore-endpoint), 그러나 K3s 의 단순함 장점 상실

1.5 진짜 영향

대부분 5-15 노드 환경에선 체감 무. 50+ 노드 가면 etcd I/O 가 진짜 병목 이 됨. 그 시점 → RKE2 또는 vanilla 로 갈아타는 자연스러운 신호.


2. 한계 ② — 단일 바이너리의 디버깅 비용

2.1 단일 로그의 양면성

장점: journalctl -u k3s 한 줄로 모든 로그 봄. 셋업 단순.

단점: 문제가 발생했을 때모든 컴포넌트 로그가 한 곳에 섞임:

May 28 14:23:01 lemuel k3s[12345]: time="..." level=info msg="api-server: ..."
May 28 14:23:01 lemuel k3s[12345]: time="..." level=error msg="etcd: leader changed"
May 28 14:23:02 lemuel k3s[12345]: time="..." level=warning msg="scheduler: pod ..."
May 28 14:23:02 lemuel k3s[12345]: time="..." level=info msg="kubelet: pulling image ..."
May 28 14:23:03 lemuel k3s[12345]: time="..." level=info msg="controller-manager: ..."

어느 컴포넌트의 어느 phase 인지 파악 어려움. vanilla K8s 면 각 컴포넌트 별 별도 로그 파일 + 각자 로그 레벨 조정 가능.

2.2 실전 사례 — 5 월 lemuel cluster-reset 사고

내 환경에서 etcd quorum 깨짐 으로 cluster-reset 한 적 있음. 진단 시:

  • journalctl -u k3s | head -1000 으로 수천 줄 로그 sift
  • 어느 라인이 etcd, 어느 라인이 apiserver 분별 어려움
  • 결국 4 단계 복구 — token sync (file + env 둘 다), server/ wipe, 옛 etcd member 강제 제거, restart

이 모든 정보가 vanilla K8s 였으면 etcd member list + apiserver audit log 별도로 훨씬 명확.

2.3 우회 방법

  • --log-level debug상세 로그 활성
  • journalctl -u k3s --since "1 hour ago" | grep -E "etcd|apiserver" 같은 grep 패턴 익히기
  • Prometheus 메트릭 적극 활용 (api-server, etcd 별 메트릭은 별도 노출)

2.4 진짜 영향

5 노드 환경엔 익숙해지면 OK. 50+ 노드 + 다중 팀 운영 가면 컴포넌트별 분리 로그 가 필수.


3. 한계 ③ — HA 가 민감

3.1 K3s 의 etcd HA 룰

  • server 노드 = etcd 멤버 (분리 불가, 위에서 본 1번 한계)
  • HA 는 3 노드 이상 (raft quorum)
  • 짝수 노드 비추 — 5 노드, 7 노드 가능
  • server 노드 *반드시 홀수*

3.2 실제로 까다로운 부분

시나리오: 3 server 노드 중 1 개 디스크 죽음 → 2 노드 남음 → quorum 유지. 그러나:

  • 그 노드를 완전히 재가입 시키는 절차가 까다로움
  • 옛 etcd member 가 cluster 안에 남아있음 → 새 노드 가입 시 충돌

복구 4 단계:

  1. 옛 member 강제 제거: etcdctl member remove <ID>
  2. 새 노드에서 server/ wipe: rm -rf /var/lib/rancher/k3s/server/db
  3. token 동기화 (file + env 둘 다 — 흔히 빠뜨림)
  4. k3s 재시작

내가 4 시간 디버깅 한 후 정리한 runbook. K3s 공식 문서엔 단편적으로만 적힘.

3.3 우회 방법

  • server 노드 *최소 3 + worker 분리*. server 1 개 죽어도 quorum 안 깨짐
  • etcd snapshot 자동화 (--etcd-snapshot-schedule-cron)
  • runbook 미리 작성. 한 번 겪고 나면 영원히 기억

4. 한계 ④ — Backup / Restore 의 반자동

4.1 K3s 의 backup 기능

  • etcd snapshot 자동: --etcd-snapshot-schedule-cron "0 */6 * * *" (6시간마다)
  • retention: --etcd-snapshot-retention 24
  • S3 upload 도 가능: --etcd-s3 + --etcd-s3-endpoint

여기까진 훌륭함. 문제는 복구.

4.2 복구 절차 — 반자동

# 새 클러스터 셋업
k3s server \
  --cluster-reset \
  --cluster-reset-restore-path=/var/lib/rancher/k3s/server/db/snapshots/<snapshot>

# 그 다음 *수동으로*:
# - 다른 server 노드들 *재가입* (위 한계 3 의 4 단계)
# - PV (특히 local-path) *수동 복원*
# - Secret/ConfigMap 검증
# - ArgoCD 의 Application 들 *재배포*

vanilla K8s 의 Velero 같은 full backup/restore 도구는 K3s 에도 사용 가능 하지만 기본 도구 부재. 별도 설치 필요.

4.3 진짜 영향

소규모엔 수동 복구 OK. 그러나 시간 압박 있는 production 사고4 단계 매뉴얼 따라가기스트레스.


5. 한계 ⑤ — 대규모 한계

5.1 K3s 의 실용적 상한

공식 문서엔 명시 안 함. 커뮤니티 경험 + 내 실험:

  • 10 노드 이하: 완벽. 단일 server 도 가능
  • 10-30 노드: 3 server + N worker. 잘 동작
  • 30-100 노드: 동작은 함. 그러나 etcd I/O 압박, apiserver 응답 시간 ↑
  • 100+ 노드: 공식적으로 RKE2 권장. K3s 의 단순함이 더 이상 장점 아님

5.2 실측 사례

내 5 노드 환경에서 144 pod 운영 중. kubectl 응답 < 100ms. 문제 없음.

지인의 40 노드 K3s 환경에서 2,000+ pod. kubectl get pods -A 가 5 초. 이 시점에 RKE2 마이그레이션 진행 중.

5.3 한계가 오는가

  • embedded etcd 의 I/O 한계 — vanilla 처럼 etcd 분리 못 함
  • Flannel 의 VXLAN overhead — 노드 많아지면 broadcast 비용
  • 모든 control-plane 컴포넌트가 *같은 메모리/CPU 풀 공유 → 압박 시 모두 영향

6. 한계 ⑥ — Networking 옵션 제한

6.1 K3s 의 기본 CNI

  • Flannel (VXLAN 모드 기본)
  • 단순, 가벼움, 대부분의 홈랩에 충분

6.2 교체 가능 하지만 신중

다른 CNI 사용하려면:

k3s server --flannel-backend=none --disable-network-policy
# 그 다음 별도 설치:
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml

가능은 함. 그러나:

  • K3s 의 기본 가정 이 Flannel 기반. Service IP, kube-proxy 등 설정 유의
  • RKE2 는 Cilium / Calico / Canal 공식 지원. K3s 는 비공식

6.3 실전 함정

내 환경에서 노드 재부팅 후 ufw 활성화 → VXLAN (UDP 8472) 차단 → Flannel 통신 죽음pod-to-pod 통신 모두 실패. 해결: sudo ufw disable.

이건 K3s 의 한계라기보단 Flannel + Linux firewall 의 함정. 그러나 K3s 가 기본 Flannel 이라 대다수 사용자가 이 함정에 빠짐.

6.4 대안

  • RKE2 — Cilium 기본 옵션 가능
  • vanilla K8s — CNI 완전 자유 선택

대규모 / 보안 강화 / multi-cluster 환경이면 Cilium 의 eBPF훨씬 강력. K3s 에서도 가능은 함공식 path 아님.


7. 한계 ⑦ — 자체 디버깅 도구 부재

7.1 vanilla K8s 의 디버깅 도구

  • kubeadm — cluster bootstrap, upgrade, reset
  • kubelet 직접 명령
  • etcdctl — etcd 직접 조작
  • 각 컴포넌트 별 별도 binary

7.2 K3s 에서는

  • 모두 k3s 바이너리 안에 포함
  • etcdctl 직접 사용은 bundled etcd 의 socket path 알아야:
    ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
      --cacert=/var/lib/rancher/k3s/server/tls/etcd/server-ca.crt \
      --cert=/var/lib/rancher/k3s/server/tls/etcd/server-client.crt \
      --key=/var/lib/rancher/k3s/server/tls/etcd/server-client.key \
      member list
    
  • kubeadm 명령 사용 불가
  • K3s 의 자체 명령: k3s check-config, k3s server, k3s agent, k3s ctr (containerd 직접)

7.3 진짜 영향

대부분의 K8s 책 / 강의 / 블로그가 vanilla 기준. K3s 로 따라하면 명령이 다름 또는 경로가 다름. 학습 곡선 살짝 ↑.


8. 한계 ⑧ — Enterprise / 보안 강화

8.1 부재 또는 까다로움 한 기능

기능 K3s RKE2 vanilla
Pod Security Standards
OPA (Open Policy Agent) ⚠️ (별도 설치)
FIPS 140-2 인증 ✅ (배포본에 따라)
CIS Hardening ⚠️ (수동) ✅ (기본 활성) ⚠️ (수동)
감사 로깅 (audit) ✅ (설정 복잡)
Encryption at rest (etcd) ✅ (설정)
Custom scheduler plugin ⚠️ ⚠️

8.2 RKE2 가 *production-grade 인 이유*

Rancher 가 K3s 다음으로 만든 RKE2:

  • K3s 의 단순함 + vanilla K8s 의 standardness
  • FIPS 140-2, CIS hardened
  • 컴포넌트 분리 — etcd, apiserver 등이 별도 컨테이너
  • 공식 미국 정부 (US DoD) 사용 인증

내가 금융권 또는 공공기관 K8s 컨설팅 한다면 K3s 가 아닌 RKE2. 내 홈랩 엔 K3s 가 압도적으로 좋음.


9. 대안 비교 — K3s vs RKE2 vs Talos vs vanilla

항목 K3s RKE2 Talos vanilla (kubeadm)
바이너리 크기 70MB 230MB OS 자체 컴포넌트별 분리
메모리 (idle) 512MB 1GB 1GB 2GB
설치 시간 30 초 2 분 5 분 (OS 부팅) 30 분
학습 곡선 낮음 보통 보통 (API only) 가파름
Production 수준 중소규모 대규모/엔터프라이즈 클라우드/엔터프라이즈 모든 규모
보안 강화 보통 강함 (CIS, FIPS) 강함 (immutable OS) 직접 설정
컴포넌트 분리 ❌ (단일 바이너리)
ARM 지원 ⚠️
홈랩 적합 ⭐⭐⭐ ⭐⭐ ⭐⭐
엔터프라이즈 적합 ⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐

Talos 의 매력

Sidero Labs 의 immutable OS for Kubernetes. SSH 없음, API 만으로 관리. 가장 모던:

  • 공격 표면 최소
  • upgrade 가 OS 재부팅 = 새 버전
  • 학습 곡선: talosctl 새로 배워야

내 환경에서 Talos 도 시도해봄. 결론: 고정 인프라 (servers) 엔 좋지만 변화 잦은 홈랩 엔 K3s 의 유연성 이 더 편함.


10. K3s 가 여전히 옳은 경우

홈랩 / 학습 환경1-30 노드 규모Edge / IoT (라즈베리 파이)소규모 production — 스타트업, 작은 SaaS ✅ 빠른 prototypeCI/CD 의 임시 K8s cluster

내 환경 (5 노드, 144 pod, settlement/lemuel-xr/academy/sparta-msa 등 prod) 은 K3s 가 압도적 최적. vanilla K8s 였으면 운영 부담 10 배.


11. K3s 를 떠나야 할 신호

⚠️ 다음 신호 하나라도 보이면 RKE2 / vanilla 검토:

  1. 노드 수 50+ 또는 3 년 안에 100 노드 예상
  2. 컴플라이언스 — 금융권, 공공기관, 의료 (FIPS, CIS hardened 요구)
  3. 다중 팀 운영 — 한 cluster 에 10+ namespace, 5+ team
  4. 고급 networking 요구 — service mesh + multi-cluster + dual-stack 동시
  5. etcd 의 독립 scale up 필요 — 데이터 많은 환경
  6. 컴포넌트 별 별도 모니터링 필수 — debugging 시간이 비즈니스 손실
  7. 다양한 CNI 실험 필요 — Cilium 의 eBPF 기능 풀 활용 등
  8. 장기 (5+ 년) production — K3s 의 라이프사이클이 자주 변함

내 환경엔 아직 어느 신호도 안 보임. K3s 유지.


12. 내 클러스터의 미래

현재:

  • K3s v1.35.4
  • 5 노드 (lemuel/ilwon/louise/david/solomon)
  • 144 pod, 10+ namespace (prod 다수)

다음 3-6 개월:

  • issachar (R730xd) 합류 — 6 노드
  • 새 맥미니 합류 — 7 노드
  • K3s 유지

12-24 개월 후 가능한 경로:

  • 그대로 K3s — 노드 10 개 이내 유지
  • RKE2 마이그레이션 — 컴플라이언스 또는 enterprise 기능 필요 시
  • Talos고정 자원 부분 만 (예: storage 노드)
  • vanilla K8s 서브 클러스터 — 학습 / 포트폴리오용

선택 변수: 내 운영 부담 + 클러스터 규모 + 비즈니스 요구.


결론 — K3s 의 한계는 *결함이 아닌 *설계 결정**

K3s 의 한계는 “못 한다” 가 아니라 “안 한다” — 설계상 단순함을 위해 *명시적으로 포기한 것*.

K3s 는 *5-30 노드의 가장 좋은 K8s. 그 위로 가면 RKE2 / Talos / vanilla 가 답.*

내 1 년 운영 경험으로:

  • 5 노드 + 144 pod + production 워크로드 다수 — K3s 가 놀랍게 잘 굴림
  • ⚠️ 5 월 cluster-reset 사고 — embedded etcd 의 반자동 복구4 시간 디버깅 의 원인
  • ⚠️ 노드 재부팅 시 ufw — Flannel + 기본 firewall 의 함정. 한 번 겪으면 영원히 기억
  • settlement / lemuel-xr / academy / sparta-msa 안정 운영

K3s 를 *완벽하게 운영하는 사람* = K3s 의 한계를 정확히 아는 사람. 그 한계에 부딪힐 시점이 오면 *주저 없이 RKE2 / vanilla 로 갈아탈* 판단도 함께.

오늘 시점 (2026 년 5 월) 내 결론: 5-15 노드면 K3s, 50+ 노드 또는 컴플라이언스면 RKE2, immutable + API-only 가 매력적이면 Talos.


참고