StarRocks Resource Group으로 멀티테넌트 환경 CPU 격리
토스에서 StarRocks를 실시간 OLAP 엔진으로 도입하여 다양한 워크로드(Workload)를 통합 관리하면서, 워크로드 격리의 필요성을 느낌
Resource Group을 활용하여 서비스 쿼리, 배치 작업, 모니터링 쿼리 등 워크로드별 CPU 우선순위(CPU Priority)를 설정하고, 격리 전략을 수립함
토스 쇼핑 사례를 통해 cpu_weight에서 exclusive_cpu_cores로의 점진적 적용 과정을 설명하며, 실시간 서비스 응답 시간(Response Time) 개선을 확인
Docker 환경에서 cpuset, bind_cpus, borrowing 간의 의존 관계를 이해하고, 운영 환경에 맞는 설정을 적용하는 것이 중요함을 강조
StarRocks Resource Group의 핵심 원리
StarRocks Resource Group은 BE(Backend)와 CN(Compute Node)의 컴퓨팅 리소스를 논리적으로 분할하여, 멀티테넌트 환경(Multi-tenant Environment)에서 워크로드 격리를 제공한다. 핵심은 cpu_weight와 exclusive_cpu_cores 설정을 통해 CPU 사용량과 우선순위를 제어하는 것이다.
cpu_weight: CPU 경합 시 설정된 비율대로 CPU 자원 분배. Linux CFS(Completely Fair Scheduler) 기반 자체 스케줄러가 weight에 따라 CPU 시간을 할당
exclusive_cpu_cores: 특정 리소스 그룹에 물리 CPU 코어(Physical CPU Core)를 전용으로 할당. pthread_setaffinity_np를 사용하여 스레드를 코어에 바인딩하고, 전용 ThreadPool을 생성
Classifier: 쿼리 속성(user, query_type 등)을 기반으로 쿼리를 리소스 그룹에 매칭. db 기반 Classifier는 영향 범위가 넓으므로 주의 필요
토스 쇼핑 사례: cpu_weight에서 exclusive_cpu_cores 적용
토스 쇼핑은 StarRocks 클러스터에서 실시간 서비스 쿼리(Real-time Service Query)와 헤비 배치성 워크로드(Heavy Batch Workload)를 함께 운영하며, 성능 문제를 겪었다. 초기에는 cpu_weight 설정을 통해 서비스 쿼리에 높은 우선순위를 부여했지만, 배치 작업의 부하로 인해 서비스 응답 시간이 불안정했다.
1단계: cpu_weight 조정을 통해 서비스 쿼리에 더 높은 weight를 부여하여, 배치 쿼리보다 우선순위를 높임
2단계: exclusive_cpu_cores 적용을 통해 서비스 쿼리에 전용 코어를 할당하여, 배치 작업의 영향을 완전히 차단
결과: exclusive_cpu_cores 적용 후, 서비스 응답 시간의 안정성을 확보. 레이턴시(Latency) 개선 및 SLA 준수 가능
결론적으로, cpu_weight는 일반적인 상황에서 유용하지만, 하드 격리가 필요한 경우 exclusive_cpu_cores가 효과적이다.
Docker 환경에서의 Resource Group 설정 주의점
Docker 환경에서 StarRocks를 운영할 때, Resource Group의 기능을 제대로 활용하기 위해서는 Docker 컨테이너의 CPU 설정에 주의해야 한다. 특히, exclusive_cpu_cores, bind_cpus, cpu_borrowing 간의 의존 관계를 이해하는 것이 중요하다.
--cpuset-cpus 설정: Docker 컨테이너에 CPU 코어(CPU Core)를 명시적으로 할당해야 bind_cpus가 정상적으로 동작
bind_cpus: 스레드를 물리 코어에 바인딩하여, CPU 사용량(CPU Usage)을 제어하고 borrowing 활성화
borrowing: exclusive_cpu_cores로 할당된 코어가 유휴 상태일 때, 다른 리소스 그룹이 해당 코어를 사용할 수 있도록 함
Docker --cpuset-cpus 설정을 통해 bind_cpus를 활성화하지 않으면, borrowing 기능이 제대로 동작하지 않아 CPU 자원 낭비(CPU Resource Waste)가 발생할 수 있다.
Classifier 설계 및 운영 팁
Classifier는 쿼리를 리소스 그룹에 매칭하는 규칙으로, 쿼리 속성(Query Attribute)을 기반으로 한다. 안정적인 운영을 위해서는 user 또는 db 기반으로 Classifier를 설계하는 것이 권장된다.
user 기반: 서비스 쿼리는 user='shopping_service' AND query_type IN ('SELECT')와 같이 서비스 계정 기준으로 묶음
db 기반: dw_common 조회는 db='dw_common'과 같이 데이터베이스(Database) 기준으로 묶음
주의사항: db 기반 Classifier는 영향 범위가 넓으므로, 영향 범위(Impact Range)를 인지하고 사용
팁: 여러 조건을 조합하여 weight를 높여, 의도한 그룹(Intended Group)에 안정적으로 매칭되도록 설계
Classifier 설계는 워크로드 격리의 핵심이며, 운영 환경에 맞는 유연한 설계를 통해 성능(Performance)과 안정성(Stability)을 확보해야 한다.
모니터링 및 쿼리 이력 활용
Resource Group이 의도대로 동작하는지 확인하기 위해서는 쿼리 이력 모니터링이 필수적이다. StarRocks의 AuditLoader 플러그인을 활용하여 쿼리 실행 로그를 수집하고, resourceGroup, pendingTimeMs, queryTime, cpuCostNs 등의 필드를 통해 리소스 그룹의 동작을 추적할 수 있다.
pendingTimeMs: 큐 대기 시간(Queue Wait Time)을 확인하여, 병목 지점(Bottleneck)을 파악
state = 'ERR': big_query 제한 등에 의해 킬된 쿼리를 확인하여, 문제 발생 원인(Problem Cause)을 분석
외부 플랫폼 이중 적재: 쿼리 이력을 Kafka로 수집하여 외부 플랫폼에 이중 적재하고, Grafana 대시보드를 구성하여 클러스터 장애(Cluster Failure) 상황에서도 모니터링 가능
쿼리 이력 모니터링을 통해 Resource Group 설정의 효과를 검증하고, 지속적인 개선을 수행해야 한다.