Skip to content

Latest commit

 

History

History
70 lines (46 loc) · 8.93 KB

File metadata and controls

70 lines (46 loc) · 8.93 KB

v1.18 — Cilium 로드밸런싱 컨트롤 플레인: 뮤텍스 걸린 해시맵에서 StateDB로

메타데이터

항목 내용
프로젝트 Cilium
관련 릴리스 v1.18.0
관련 이슈/PR cilium/cilium#39893 — New load-balancing control-plane, cilium/cilium#38981 — Unexperimentalize the new load-balancing control-plane, cilium/cilium#38469
발견 출처 Cilium 1.18.0 릴리스 노트 — "서비스 로드밸런싱 컨트롤 플레인이 메모리 사용량을 줄이고 확장성을 높이기 위해 재설계됨"
검증 근거 cilium/cilium 저장소의 실제 이슈 #39893(설계 배경 서술), PR #38981(실제 코드 변경)

개요

Cilium은 커널의 eBPF를 이용해 쿠버네티스 Service를 실제 백엔드 파드로 라우팅하는 로드밸런서 역할을 한다. v1.18에서 이 로드밸런싱을 관리하는 컨트롤 플레인 내부 구조가 전면 재작성됐다 — 사용자에게 보이는 동작(Service가 백엔드로 라우팅되는 것) 자체는 그대로지만, Cilium 에이전트 내부에서 이 상태를 어떻게 표현하고 갱신하는지가 바뀌었다. 핵심은 "뮤텍스로 지키는 가변 해시맵들"에서 "StateDB라는 하나의 데이터 중심 저장소"로 옮긴 것이다.

사전 지식 — 기존 구조가 겪던 세 가지 문제

이슈 #39893은 기존(v1.18 이전) 구조의 문제를 세 가지로 짚는다.

1. 같은 데이터가 여러 형태로 중복 보관됨: 하나의 쿠버네티스 Service 정보가 slim_corev1.Service(K8s informer가 주는 원본 형태), k8s.Service(Cilium 내부 변환 형태), loadbalancer.SVC, service.svcInfo, lbmap.UpsertServiceParams(실제 BPF 맵에 쓸 형태)까지 최소 5단계의 서로 다른 자료구조로 각각 따로 보관됐다. 이러면 (a) 메모리를 그만큼 더 쓰고, (b) 한 곳을 갱신했는데 다른 곳은 아직 옛 값을 들고 있는 데이터 레이스가 발생하기 쉽다 — 특히 ServiceCacheServiceManager라는 두 컴포넌트가 서로 다른 시점에 상태를 참조할 때 이 문제가 불거졌다.

2. 쿠버네티스에 강하게 결합됨: 여러 로드밸런싱 기능이 "내부 서비스 모델"이 아니라 Resource[*slim_corev1.Service](쿠버네티스 API 서버에서 오는 원본 리소스 스트림)에 직접 걸려 있었다. 그러다 보니 "쿠버네티스가 아닌 다른 소스(예: 별도 설정 파일, 다른 오케스트레이터)로부터 로드밸런싱 설정을 받고 싶다"는 요구를 들어주기가 구조적으로 어려웠다 — 기능이 특정 데이터 소스의 API 형태에 종속돼 있었기 때문이다.

3. 가변 상태 + 뮤텍스 조합의 동시성 문제: "가변 객체를 가변 해시맵에 담고 뮤텍스로 보호"하는 전형적인 명령형(imperative) 패턴을 썼는데, 이 패턴은 잠금 순서가 조금만 꼬여도 데드락이 나기 쉽고, 락 경합이 빠른 경로(fast path, 즉 패킷 처리와 직결된 코드)의 성능에 영향을 줄 수 있다.

변경 분석 — StateDB: 데이터 중심 모델로 전환

새 설계는 StateDB(Cilium이 이미 다른 곳에서 쓰던 내부 인메모리 데이터베이스 추상화)를 로드밸런싱 상태의 단일 진입점으로 삼는다. 여러 곳에 흩어져 있던 서비스/백엔드 표현을 하나의 테이블 기반 저장소로 모으고, BPF 맵에 실제로 반영하는 로직(reconciler)은 이 테이블을 구독해서 변화를 감지하고 동기화하는 방식으로 바뀐다.

[변경 전] 같은 정보가 여러 자료구조에 복제되고, 뮤텍스로 각각 보호됨
┌──────────────────┐  ┌───────────┐  ┌──────────────┐  ┌───────────────────┐
│slim_corev1.Service│─▶│k8s.Service│─▶│loadbalancer.SVC│─▶│lbmap.UpsertParams │
└──────────────────┘  └───────────┘  └──────────────┘  └───────────────────┘
   (각 단계마다 별도 보관 + mutex, 갱신 시 레이스 가능)

[변경 후] StateDB 테이블 하나가 단일 진실 소스, BPF reconciler가 구독해서 동기화
┌───────────────────┐  구독(락 없이)  ┌───────────────┐  반영  ┌──────────┐
│ StateDB 테이블      │ ─────────────▶ │ BPF Reconciler │ ─────▶ │ BPF 맵    │
│ (services/backends) │                └───────────────┘        └──────────┘
└───────────────────┘
   ▲ 여러 소스(K8s 외에도)가 이 테이블에 직접 쓸 수 있음

PR #38981("Unexperimentalize the new load-balancing control-plane")을 보면, 실제로 LBMaps 래퍼와 BPF reconciler를 맵 처리·리컨실리에이션·리다이렉트 정책 전용의 별도 패키지들로 나누고, 쿠버네티스 리소스에서 BPF 맵까지의 처리량을 재는 벤치마크도 같이 추가됐다 — 재설계가 추상적 정리에 그치지 않고 실측 가능한 성능 목표를 갖고 진행됐음을 보여준다.

설계 결정 및 트레이드오프

왜 뮤텍스 기반 명령형 모델을 버리고 StateDB(데이터 중심 모델)를 택했는가: 이슈는 StateDB의 API가 "생산자(producer)에 영향을 주거나 락을 걸지 않고도 데이터를 소비할 수 있는 유연한 방법"을 제공한다고 설명한다. 기존 모델에서는 "이 상태를 누가 언제 바꿀 수 있는가"를 뮤텍스로 직접 조율해야 했는데, 이는 컴포넌트가 늘어날수록 락 순서 관리가 기하급수적으로 복잡해진다. 테이블 기반 모델로 옮기면 각 컴포넌트가 "테이블에 쓴다"/"테이블을 구독해서 읽는다"는 단순한 계약만 지키면 되고, 락 관리는 StateDB 내부로 위임된다 — 개별 기능 구현자가 동시성 버그를 직접 신경 쓸 필요가 줄어드는 대신, StateDB 자체의 일관성 보장에 전체 시스템이 의존하게 된다.

왜 쿠버네티스 리소스 타입 대신 내부 서비스 모델에 기능을 붙이도록 바꿨는가: 기존처럼 Resource[*slim_corev1.Service]에 직접 기능을 거는 방식은 구현이 빠르지만, 그 기능은 영원히 "쿠버네티스가 유일한 소스"라는 가정에 묶인다. StateDB 테이블을 중간에 두면, 그 테이블에 값을 채우는 게 K8s informer든 다른 무엇이든 상관없이 하위의 리컨실리에이션 로직은 그대로 재사용된다 — 당장 이번 릴리스에서 K8s 외의 소스를 실제로 붙인 건 아니지만("확장성을 개선"이라는 표현이 릴리스 노트에 등장하는 것도 이 때문), 구조적으로 그 문을 열어둔 선택이다.

왜 데이터 중복 제거를 "성능"이 아니라 "메모리+정확성" 문제로 접근했는가: 릴리스 노트가 명시한 목표는 메모리 사용량 감소와 향후 확장성이지, 처리 속도 자체는 아니다. 사실 데이터를 여러 형태로 미리 변환해서 각 소비자가 자기 형태로 바로 읽게 해두는 건 흔히 "읽기 성능"을 위한 선택이기도 하다 — 여기서는 그 이점을 포기하고 단일 표현으로 합친 것인데, 이는 중복 표현들 사이의 불일치(데이터 레이스)로 인한 정확성 문제가 약간의 변환 비용보다 훨씬 비싸다고 판단했다는 뜻이다.

더 살펴볼 점

  • StateDB로의 전환이 실제로 대규모 클러스터(서비스/백엔드 수가 많은 환경)에서 에이전트 메모리 사용량을 얼마나 줄였는지 실측치가 있을까?
  • "K8s 외의 로드밸런싱 설정 소스"를 실제로 지원하는 첫 기능은 무엇이 될까?
  • 이 재설계가 진행되는 동안 기존 기능(BGP, Gateway API, kube-proxy replacement 등)과의 상호작용에서 회귀가 있었을까?

참고 자료

참고 외 별도 확인 링크

  • Cilium 1.18 — Isovalent 공식 블로그벤더(Isovalent) 블로그라 홍보성 서술이 섞일 수 있어 본문 근거로는 쓰지 않고, 기능 목록 확인용 보조 자료로만 참고했다.