Files
project-infra/docs/standards/infra/k3s-specific.md
T

11 KiB

K3s-specific 기준

목적

이 문서는 일반 Kubernetes 표준과 분리해서, K3s 운영에서만 발생하는 특수성을 고정한다.

목표:

  • K3s packaged component (coredns, traefik, local-storage, metrics-server, servicelb)를 일반 manifest처럼 관리하는 실수를 막는다
  • /var/lib/rancher/k3s/server/manifests를 source-of-truth로 쓰는 실수를 막는다
  • 멀티 server HA 환경에서 critical configuration value mismatch join 실패를 예방한다
  • embedded registry mirror(Spegel)의 네트워크·버전 게이트를 정확히 이해한다
  • 1000+ 서비스 prod 스케일에서 K3s의 어떤 기능을 켜고 어떤 기능을 외부로 뺄지 기준을 박는다

공식 의미 (근거 URL 포함)

  • K3s packaged component: coredns, traefik, local-storage, metrics-server (매니페스트 파일 기반) + servicelb(매니페스트 없이 --disable만 가능).
  • AddOn auto-deploy: /var/lib/rancher/k3s/server/manifests 하위 파일은 server 시작 시 + 파일 변경 시 자동 apply. packaged component는 K3s가 재기록하므로 직접 수정 금지.
  • multi-server 유저 AddOn은 서버 간 자동 동기화되지 않는다.
  • K3s 설정: /etc/rancher/k3s/config.yaml + /etc/rancher/k3s/config.yaml.d/*.yaml drop-in.
  • critical 값 (cluster-cidr / service-cidr / cluster-dns / cluster-domain / disable 세트 / CNI / embedded-registry 활성화)이 서버 간 불일치면 critical configuration value mismatch join 실패.
  • packaged Helm component(traefik 등) 커스터마이징은 HelmChartConfig (apiVersion helm.cattle.io/v1).
  • K3s 기본 local storage는 Rancher Local Path Provisioner (local-path StorageClass, node-local, not replicated).
  • embedded registry mirror (Spegel): 기본 비활성. 활성화 시 노드 간 TCP 5001 (p2p gossip) + TCP 6443 (registry + supervisor)이 reachable해야 한다. 출처: https://docs.k3s.io/installation/registry-mirror — "all nodes must be able to reach each other via their internal IP addresses, on TCP ports 5001 and 6443".
  • K3s 이미지 import: /var/lib/rancher/k3s/agent/images/*.tar{,.zst,.gz}.
  • K3s는 기본적으로 network policy enforcer (kube-router 기반)를 포함한다. 외부 CNI(Cilium 등) 사용 시 --disable-network-policy + --flannel-backend=none 조합 필요.

기본 규칙

1. K3s 전용 규칙은 별도 문서로 유지

일반 Kubernetes 표준 문서에 K3s 특수성을 흩뿌리지 않는다. 분리 범주:

  • packaged component
  • AddOn auto-deploy
  • config.yaml / config.yaml.d
  • local-path provisioner
  • embedded registry mirror
  • critical server flags
  • Helm component customization

2. packaged component는 “편의 기능”, 직접 수정 절대 금지

관리 대상:

  • coredns
  • traefik
  • local-storage
  • metrics-server
  • servicelb (manifest 없음, flag로만 제어)

금지:

  • /var/lib/rancher/k3s/server/manifests/traefik.yaml 직접 edit
  • packaged manifest를 Git SoT로 관리
  • 재시작 후 overwrite되는 파일에 운영 커스터마이징 저장

3. packaged component 유지/비활성은 cluster bootstrap 때 박는다

1000-서비스 prod 스케일에서 현재 기준:

component prod 기본 이유
traefik disable ingress-nginx / Envoy Gateway로 교체. Traefik은 dev만.
servicelb disable MetalLB L2/BGP 또는 외부 LB. klipper는 노드 80/443 점유.
local-storage disable Longhorn / Ceph RBD / CSI. node-local은 DR 불가.
metrics-server keep HPA + kubectl top 전제. 대체 pipeline 준비되면 교체 가능.
coredns keep 교체는 특수 케이스. node-local dns cache는 별도로 추가.
network policy 상황별 Cilium 도입 시 disable. 기본 kube-router 유지도 가능.

4. server critical config는 Git에서 단일 파일로 관리

/etc/rancher/k3s/config.yaml이 Git의 inventory repo (Ansible / Fleet / CI)에서 push된다. 서버별 ad-hoc 수정 금지. critical 값 mismatch는 join 실패로 직결된다.

일치해야 하는 값:

  • cluster-cidr, service-cidr, cluster-dns, cluster-domain
  • disable 세트
  • flannel-backend / disable-network-policy
  • embedded-registry 활성화 여부
  • datastore-endpoint (etcd / external DB)

5. CLI argument보다 config file 우선

재현성 / diff / multi-node 동기화를 위해 server/agent 플래그는 모두 config.yaml로. /etc/rancher/k3s/config.yaml.d/*.yaml drop-in은 역할별 파일 분리(예: 10-networking.yaml, 20-audit.yaml)에 사용.

6. /var/lib/rancher/k3s/server/manifests는 apply sink, SoT 아님

  • 운영 SoT = Git (+ Kustomize / ArgoCD / Flux)
  • 이 디렉터리는 bootstrap addon에만 한정 (예: k3s-addons-disabled.yaml placeholder)
  • 서버별로 다른 파일을 두고 "알아서 맞겠지"는 금지
  • .skip 파일은 임시 비활성화 용. 장기 disable은 --disable 플래그로.

7. multi-server user AddOn은 Git push, 로컬 scp 금지

K3s는 user AddOn을 서버 간 동기화하지 않는다. 멀티 server 환경에서 AddOn을 쓰려면:

  • GitOps 컨트롤러(ArgoCD/Flux)가 apply
  • 또는 Ansible/Fleet이 단일 server 노드에만 drop
  • 또는 완전히 포기하고 kubectl apply로만 관리 (권장)

8. packaged Helm component 커스터마이징은 HelmChartConfig

traefik 유지가 불가피할 때:

apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
  name: traefik
  namespace: kube-system
spec:
  valuesContent: |-
    <override values>
  • metadata.name / namespace는 대응 HelmChart와 반드시 일치
  • 민감 값은 valuesSecrets로 Secret 참조 (valuesContent에 하드코딩 금지)
  • HelmChartConfig 자체는 Git 관리

9. local-path provisioner는 dev/test 한정

Rancher Local Path Provisioner = node-local hostPath. 특성:

  • ReadWriteOnce only
  • 노드 장애 시 데이터 접근 불가
  • 백업/DR 불가 (StorageClass 레벨 스냅샷 없음)
  • binding mode = WaitForFirstConsumer (Pod가 뜰 때 PV 생성)

기준:

  • dev/test StatefulSet의 PVC 기본값으로만 허용
  • prod의 DB / Vault / MinIO / Kafka / etcd backup target에 절대 사용 금지
  • prod storage는 Longhorn (K3s 권장) / Ceph RBD / 외부 CSI 중 택1

10. metrics-server는 유지 기본값

HPA v2 metrics, kubectl top, VPA, kube-state-metrics 연동 모두가 전제. disable 시 Prometheus Adapter 등 대체 pipeline을 먼저 준비한 뒤에만 꺼야 한다.

11. traefik / servicelb는 포트 점유 + 노드 노출 전략을 같이 본다

  • servicelb (klipper) = 모든 노드가 80/443 HostPort로 열림. prod에서는 거의 항상 disable + MetalLB 또는 외부 LB.
  • traefik 유지 시 IngressClass / Middleware / EntryPoint 세 레이어가 전부 K3s 관리. prod에서는 disable + ingress-nginx DaemonSet 또는 Envoy Gateway Deployment.

12. network policy controller 충돌

  • 기본: K3s 내장 kube-router 기반 enforcer
  • Cilium / Calico 도입 시: --flannel-backend=none + --disable-network-policy + --disable=servicelb
  • 도입 계획은 클러스터 bootstrap 결정 사항 (리빌드 없이 swap 불가에 가까움)

13. embedded registry mirror (Spegel): 명시적 opt-in + 네트워크 요구사항

  • 기본 비활성
  • 활성화 방법: /etc/rancher/k3s/config.yamlembedded-registry: true + registries.yaml에 mirror 설정
  • 네트워크 요구사항 (공식): 모든 노드가 서로 **TCP 5001 (p2p gossip) + TCP 6443 (local registry + supervisor)**에 도달 가능해야 한다. firewall / security group에서 해당 포트 오픈 필수.
  • 활성화 대상:
    • airgap / 반-airgap 환경
    • 이미지 pull bottleneck이 심한 대규모 배포
    • external registry 의존을 낮춰야 하는 환경
  • 클러스터 범위 기능이므로 모든 server/agent에 동일 적용

14. 이미지 import / airgap 전략

  • 평상시: registry pull (internal mirror 선호)
  • airgap: /var/lib/rancher/k3s/agent/images/*.tar{,.zst,.gz} 사용, import 절차를 runbook에 명시
  • 이미지 import는 agent startup 때만 로드됨 → 런타임 교체는 re-push 필요

15. K3s version gating을 항상 확인

다음 기능은 버전에 따라 동작/옵션이 바뀌므로, 업그레이드 전 CHANGELOG 확인 필수:

  • embedded registry mirror (Spegel)
  • image pre-import
  • HelmChartConfig schema
  • disable-helm-controller 동작
  • etcd snapshot / S3 backup 옵션

16. K3s-specific 예외는 component 문서보다 먼저 확정

이 문서에서 박고 내려가야 하는 결정:

  • traefik 유지/비활성
  • servicelb 유지/비활성
  • local-storage 유지 범위 (env별)
  • metrics-server 유지
  • network policy controller 선택
  • embedded registry mirror 사용 여부

그 다음에 keycloak / vault / minio / ingress / storage 문서로 내려간다.

17. kubectl apply --server-side 기본 사용

K3s도 SSA 지원. ArgoCD / Flux / CI 모두 --server-side --field-manager=<id> 기본. last-applied-configuration annotation 2MB 한계 회피 + multi-controller ownership 명시.

18. etcd snapshot은 K3s 고유 메커니즘 사용

  • embedded etcd면 k3s etcd-snapshot CLI 또는 --etcd-snapshot-* config
  • S3 업로드 설정은 /etc/rancher/k3s/config.yaml에 선언
  • 외부 datastore(PostgreSQL/MySQL) 사용 시 backup은 해당 DB 레이어에서 따로

현재 스택 기본 권장안 (prod)

  • traefik: disable, ingress-nginx + cert-manager로 교체
  • servicelb: disable, MetalLB (L2 또는 BGP)로 교체
  • local-storage: disable (prod), dev/staging 만 유지. Longhorn으로 교체
  • metrics-server: keep (HPA 전제)
  • network policy: 현 단계 kube-router 유지, Cilium 도입은 별 RFC
  • embedded registry mirror: off (현재 airgap 아님), 옵션으로 남김
  • etcd snapshot: S3 업로드 활성, 6시간 주기, 72시간 retention
  • HelmChartConfig: traefik 유지 경로를 쓰지 않으므로 현재 미사용
  • apply 방식: kubectl apply --server-side --field-manager=argocd

프로젝트 기준 요약

  • K3s 전용 규칙은 별도 문서
  • packaged component 직접 수정 금지 (HelmChartConfig / disable만)
  • manifests/는 SoT 아님
  • critical config는 Git 단일 파일, 서버 간 동일
  • local-path는 dev/test만
  • embedded registry mirror는 TCP 5001 + 6443 reachability가 전제
  • prod에서 traefik/servicelb/local-storage 전부 disable이 기본
  • Server-Side Apply가 GitOps 기본