컨트롤러-런타임 캐시의 실제 작동 방식, 그리고 당신의 컨트롤러가 API 서버를 충돌시키지 않는 이유
Kubernetes 컨트롤러는 일반적으로 Go 언어와 kubebuilder 및 controller-runtime을 사용하여 작성되며, 분산 워크로드에 대한 효율적인 개발을 제공합니다. 그러나 부하가 증가함에 따라 프로덕션 문제를 피하기 위해 controller-runtime의 내부 작동 방식을 이해하는 것이 중요합니다. 핵심 개념은 reconciler 내의 r.Get() 및 r.List()가 API 서버를 직접 쿼리하는 것이 아니라 로컬 메모리 내 캐시에 액세스한다는 것입니다. 이 캐시는 리스트 작업으로 초기화된 후 워치를 통해 유지 관리됩니다.이러한 설계는 로컬 읽기를 매우 빠르게 만들어 컨트롤 플레인에 부담을 주지 않습니다. 그러나 단점은 로컬 캐시가 상당한 메모리를 소비할 수 있으며 오래된 데이터를 반환할 수 있다는 것입니다. 반대로 쓰기는 항상 캐시를 우회하여 API 서버로 직접 전송됩니다. 이 로컬 캐시의 크기와 인덱싱 전략은 메모리 사용량에 직접적인 영향을 미칩니다. 비효율적인 List() 작업은 수많은 객체에 대한 느린 선형 스캔으로 이어질 수 있습니다.재조정 루프는 원하는 상태와 실제 상태를 지속적으로 비교하여 일치시킵니다. 이벤트가 큐에 쌓이면 현재 상태를 읽고 필요한 작업을 결정하며 잠재적으로 새 이벤트를 생성하는 재조정 함수가 트리거됩니다. 캐시의 주요 목적은 이러한 재조정 루프에 대한 객체 상태의 빠르고 최신 보기를 제공하는 것입니다. client-go에서 유래한 이 워치 기반 모델은 업데이트를 위한 단일의 장기 실행 연결을 유지하여 지속적인 API 폴링을 방지합니다.controller-runtime은 Reflector, DeltaFIFO 및 Indexer와 같은 하위 수준 client-go 구성 요소의 복잡성을 추상화합니다. Manager는 공유 캐시, 컨트롤러 및 기타 서비스를 오케스트레이션합니다. Informer는 특정 GVK를 모니터링하고 로컬 저장소(Indexer)를 유지하며 구독자에게 이벤트를 전달합니다. ResourceEventHandlers는 이러한 이벤트를 처리하여 저장소를 업데이트하고, 이는 컨트롤러의 보기에 반영됩니다. workqueue는 작업자가 처리할 객체 키를 관리하고, Predicates는 큐에 넣기 전에 이벤트를 필터링합니다.Reflector는 API 서버와 직접 상호 작용하는 유일한 구성 요소로, 초기 리스트를 수행한 후 워치를 설정합니다. resourceVersion을 활용하여 워치를 재개하고 누락된 이벤트가 없는지 확인합니다. 워치 연결이 끊어지거나 API 서버가 오래된 resourceVersion을 나타내는 경우 다시 리스트를 수행합니다. DeltaFIFO는 변경 사항에 대한 순서가 지정된 버퍼 역할을 하며 객체 키별로 델타를 그룹화합니다. 마지막 Pop() 호출 이후 객체에 대한 누적된 모든 변경 사항을 제공하여 순서가 지정되고 일괄 처리된 처리를 보장합니다. 그러나 연속적인 "Added" 또는 "Updated" 이벤트를 축소하지 않으므로 빠르게 변경되는 객체에 대해 여러 번의 처리 라운드가 발생할 수 있습니다.
r.Get()및r.List()가 API 서버를 직접 쿼리하는 것이 아니라 로컬 메모리 내 캐시에 액세스한다는 것입니다. 이 캐시는 리스트 작업으로 초기화된 후 워치를 통해 유지 관리됩니다.이러한 설계는 로컬 읽기를 매우 빠르게 만들어 컨트롤 플레인에 부담을 주지 않습니다. 그러나 단점은 로컬 캐시가 상당한 메모리를 소비할 수 있으며 오래된 데이터를 반환할 수 있다는 것입니다. 반대로 쓰기는 항상 캐시를 우회하여 API 서버로 직접 전송됩니다. 이 로컬 캐시의 크기와 인덱싱 전략은 메모리 사용량에 직접적인 영향을 미칩니다. 비효율적인List()작업은 수많은 객체에 대한 느린 선형 스캔으로 이어질 수 있습니다.재조정 루프는 원하는 상태와 실제 상태를 지속적으로 비교하여 일치시킵니다. 이벤트가 큐에 쌓이면 현재 상태를 읽고 필요한 작업을 결정하며 잠재적으로 새 이벤트를 생성하는 재조정 함수가 트리거됩니다. 캐시의 주요 목적은 이러한 재조정 루프에 대한 객체 상태의 빠르고 최신 보기를 제공하는 것입니다. client-go에서 유래한 이 워치 기반 모델은 업데이트를 위한 단일의 장기 실행 연결을 유지하여 지속적인 API 폴링을 방지합니다.controller-runtime은 Reflector, DeltaFIFO 및 Indexer와 같은 하위 수준 client-go 구성 요소의 복잡성을 추상화합니다. Manager는 공유 캐시, 컨트롤러 및 기타 서비스를 오케스트레이션합니다. Informer는 특정 GVK를 모니터링하고 로컬 저장소(Indexer)를 유지하며 구독자에게 이벤트를 전달합니다. ResourceEventHandlers는 이러한 이벤트를 처리하여 저장소를 업데이트하고, 이는 컨트롤러의 보기에 반영됩니다. workqueue는 작업자가 처리할 객체 키를 관리하고, Predicates는 큐에 넣기 전에 이벤트를 필터링합니다.Reflector는 API 서버와 직접 상호 작용하는 유일한 구성 요소로, 초기 리스트를 수행한 후 워치를 설정합니다.resourceVersion을 활용하여 워치를 재개하고 누락된 이벤트가 없는지 확인합니다. 워치 연결이 끊어지거나 API 서버가 오래된resourceVersion을 나타내는 경우 다시 리스트를 수행합니다. DeltaFIFO는 변경 사항에 대한 순서가 지정된 버퍼 역할을 하며 객체 키별로 델타를 그룹화합니다. 마지막Pop()호출 이후 객체에 대한 누적된 모든 변경 사항을 제공하여 순서가 지정되고 일괄 처리된 처리를 보장합니다. 그러나 연속적인 "Added" 또는 "Updated" 이벤트를 축소하지 않으므로 빠르게 변경되는 객체에 대해 여러 번의 처리 라운드가 발생할 수 있습니다.