클러스터 관리자를 위한 동적 리소스 할당(DRA) 모범 사례
클러스터 관리자를 위한 동적 리소스 할당(DRA) 모범 사례 (Good practices for Dynamic Resource Allocation as a Cluster Admin)
이 페이지는 DRA(Dynamic Resource Allocation, 동적 리소스 할당)를 활용하는 쿠버네티스 클러스터를 구성할 때의 모범 사례를 설명해요. 이 지침은 클러스터 관리자를 위한 것이에요.
출처: 문서
본문
DRA 관련 API에 대한 권한 분리하기
DRA는 여러 다른 API를 통해 오케스트레이션돼요. 사용자의 페르소나(persona)에 따라 올바른 API에 대한 접근을 제어하려면 권한 부여 도구(예: RBAC 또는 다른 솔루션)를 사용하세요.
일반적으로 DeviceClass와 ResourceSlice는 관리자와 DRA 드라이버로 제한해야 해요. 클레임이 있는 파드를 배포할 클러스터 운영자는 ResourceClaim과 ResourceClaimTemplate API에 대한 접근이 필요하며, 이 두 API는 모두 네임스페이스 스코프예요.
DRA 드라이버 배포와 유지보수
DRA 드라이버는 클러스터의 각 노드에서 실행되어 그 노드의 하드웨어 및 쿠버네티스 네이티브 DRA 구성 요소와 인터페이스하는 서드파티 애플리케이션이에요. 설치 절차는 선택한 드라이버에 따라 다르지만, 아마도 DaemonSet으로 클러스터의 모든 노드 또는 (노드 셀렉터 같은 메커니즘으로) 일부 선택된 노드에 배포될 거예요.
가능하면 매끄러운 업그레이드가 있는 드라이버 사용하기
DRA 드라이버는 kubeletplugin 패키지 인터페이스를 구현해요. 드라이버가 이 인터페이스의 속성을 구현해 두 버전의 같은 DRA 드라이버가 잠시 공존하도록 하면 매끄러운 업그레이드를 지원할 수 있어요. 이는 kubelet 1.33 이상 버전에서만 사용할 수 있으며, 더 오래된 쿠버네티스 버전을 실행하는 attached 노드가 있는 이기종 클러스터에서는 드라이버가 지원하지 않을 수 있어요. 확실히 하려면 드라이버의 문서를 확인하세요.
자신의 상황에 매끄러운 업그레이드가 가능하다면, 드라이버가 업데이트될 때 스케줄링 지연을 최소화하기 위해 그것을 사용하는 것을 고려해 보세요.
매끄러운 업그레이드를 사용할 수 없다면, 업그레이드를 위한 드라이버 다운타임 동안 다음을 관찰할 수 있어요.
- 파드가 의존하는 클레임이 사용 준비가 이미 되지 않았다면 파드가 시작할 수 없어요.
- 마지막 파드가 클레임을 사용한 후의 정리는 드라이버가 다시 사용 가능해질 때까지 지연돼요. 파드는 종료된 것으로 표시되지 않아요. 이는 파드가 사용한 리소스를 다른 파드가 재사용하지 못하게 해요.
- 실행 중인 파드는 계속 실행돼요.
DRA 드라이버가 liveness 프로브를 노출하는지 확인하고 활용하기
DRA 드라이버는 DRA 드라이버 모범 사례의 일부로 상태 검사를 위한 gRPC 소켓을 구현할 가능성이 높아요. 이 grpc 소켓을 활용하는 가장 쉬운 방법은 DRA 드라이버를 배포하는 DaemonSet의 liveness 프로브로 구성하는 것이에요. 드라이버의 문서나 배포 도구가 이미 이 기능을 포함할 수 있지만, 구성을 별도로 만들거나 DRA 드라이버를 쿠버네티스 파드로 실행하지 않는 경우, 오케스트레이션 도구가 이 grpc 소켓에 대한 실패한 상태 검사 시 DRA 드라이버를 재시작하도록 해야 해요. 이렇게 하면 DRA 드라이버의 우발적인 다운타임을 최소화하고 자가 치유 기회를 더 많이 주어, 스케줄링 지연이나 문제 해결 시간을 줄일 수 있어요.
노드를 드레인할 때 DRA 드라이버를 가능한 한 늦게 드레인하기
DRA 드라이버는 파드에 할당된 장치를 준비 해제(unprepare)할 책임이 있어요. 클레임이 있는 파드가 삭제되기 전에 DRA 드라이버를 드레인하면 정리를 완료할 수 없어요. 노드에 대한 사용자 지정 드레인 로직을 구현한다면, DRA 드라이버 자체를 종료하기 전에 할당되거나 예약된 ResourceClaim 또는 ResourceClaimTemplate이 없는지 확인하는 것을 고려하세요.
더 높은 부하를 위해 구성 요소 모니터링 및 조정, 특히 대규모 환경에서
제어 플레인 구성 요소인 kube-scheduler와 kube-controller-manager 구성 요소가 오케스트레이션하는 내부 ResourceClaim 컨트롤러는 DRA API에 저장된 메타데이터를 기반으로 클레임이 있는 파드를 스케줄링하는 동안 무거운 작업을 해요. DRA가 아닌 스케줄링된 파드와 비교해, DRA 클레임을 사용하는 파드의 경우 이러한 구성 요소가 필요로 하는 API 서버 호출 수, 메모리, CPU 사용량이 증가해요. 또한 DRA 드라이버와 kubelet 같은 노드 로컬 구성 요소는 파드 샌드박스 생성 시 하드웨어 요청을 할당하기 위해 DRA API를 활용해요. 특히 노드가 많고, 및/또는 DRA 정의 리소스 클레임을 많이 활용하는 워크로드를 많이 배포하는 대규모 환경에서, 클러스터 관리자는 관련 구성 요소를 구성할 때 증가된 부하를 예상해야 해요.
미조정 구성 요소의 영향은 직접적이거나 눈덩이처럼 커져 파드 수명주기 동안 다른 증상을 유발할 수 있어요. kube-scheduler 구성 요소의 QPS와 burst 구성이 너무 낮으면, 스케줄러는 파드에 적합한 노드를 빠르게 식별할 수 있지만 파드를 그 노드에 바인딩하는 데 더 오래 걸릴 수 있어요. DRA에서는 파드 스케줄링 중에 kube-controller-manager 내의 client-go 구성의 QPS와 Burst 파라미터가 중요해요.
클러스터를 조정하는 특정 값은 노드/파드 수, 파드 생성 속도, 변화(churn) 등 다양한 요인에 따라 달라지며, 이는 비-DRA 환경에서도 마찬가지예요. 자세한 내용은 쿠버네티스 확장성 임계값에 대한 SIG 확장성 README를 참고하세요. 100개 노드가 있는 DRA 활성 클러스터에 대해 이루어진 확장성 테스트에서, 720개 장기 실행 파드(90% 포화)와 80개 변화 파드(10% 변화, 10회), 작업 생성 QPS 10을 포함하는 테스트에서 kube-controller-manager QPS는 낮게는 75, Burst는 150으로 설정해 비-DRA 배포와 동등한 메트릭 목표를 충족할 수 있었어요. 이 하한에서는 클라이언트 측 rate limiter가 API 서버를 폭발적인 burst에서 보호할 만큼 충분히 트리거되면서도 파드 시작 SLO에 영향을 주지 않을 만큼 충분히 높은 것이 관찰됐어요. 이것이 좋은 시작점이지만, 다음 메트릭을 모니터링해 배포에서 DRA 성능에 가장 큰 영향을 주는 다른 구성 요소를 어떻게 조정할지 더 잘 파악할 수 있어요. 쿠버네티스의 모든 안정 메트릭에 대한 자세한 내용은 쿠버네티스 메트릭 참조를 참고하세요.
kube-controller-manager 메트릭
다음 메트릭은 kube-controller-manager 구성 요소가 관리하는 내부 ResourceClaim 컨트롤러를 자세히 들여다봐요.
- Workqueue Add Rate:
sum(rate(workqueue_adds_total{name="resource_claim"}[5m]))을 모니터링해 ResourceClaim 컨트롤러에 항목이 얼마나 빨리 추가되는지 측정해요. - Workqueue Depth:
sum(workqueue_depth{endpoint="kube-controller-manager",name="resource_claim"})을 추적해 ResourceClaim 컨트롤러의 백로그를 식별해요. - Workqueue Work Duration:
histogram_quantile(0.99, sum(rate(workqueue_work_duration_seconds_bucket{name="resource_claim"}[5m])) by (le))을 관찰해 ResourceClaim 컨트롤러가 작업을 처리하는 속도를 이해해요.
낮은 Workqueue Add Rate, 높은 Workqueue Depth, 및/또는 높은 Workqueue Work Duration을 겪고 있다면, 이는 컨트롤러가 최적으로 수행하지 못하고 있음을 시사해요. QPS, burst, CPU/메모리 구성 같은 파라미터를 조정하는 것을 고려하세요.
높은 Workqueue Add Rate, 높은 Workqueue Depth, 하지만 합리적인 Workqueue Work Duration을 겪고 있다면, 이는 컨트롤러가 작업을 처리하고 있지만 동시성(concurrency)이 부족할 수 있음을 나타내요. 동시성은 컨트롤러에 하드코딩되어 있으므로, 클러스터 관리자로서 파드 생성 QPS를 줄여 리소스 클레임 워크큐에 대한 추가율이 더 관리하기 쉽게 함으로써 조정할 수 있어요.
kube-scheduler 메트릭
다음 스케줄러 메트릭은 DRA를 사용하는 파드뿐 아니라 스케줄링된 모든 파드에 걸친 성능을 집계하는 상위 수준 메트릭이에요. ResourceClaimTemplate을 많이 사용하는 배포에서 엔드 투 엔드 메트릭은 궁극적으로 ResourceClaimTemplate에서 ResourceClaim을 만드는 kube-controller-manager의 성능에 영향을 받는다는 점을 주목하는 것이 중요해요.
- Scheduler End-to-End Duration:
histogram_quantile(0.99, sum(increase(scheduler_pod_scheduling_sli_duration_seconds_bucket[5m])) by (le))을 모니터링해요. - Scheduler Algorithm Latency:
histogram_quantile(0.99, sum(increase(scheduler_scheduling_algorithm_duration_seconds_bucket[5m])) by (le))을 추적해요.
kubelet 메트릭
노드에 바인딩된 파드가 ResourceClaim을 충족해야 할 때, kubelet은 DRA 드라이버의 NodePrepareResources와 NodeUnprepareResources 메서드를 호출해요. 다음 메트릭으로 kubelet의 관점에서 이 동작을 관찰할 수 있어요.
- Kubelet NodePrepareResources:
histogram_quantile(0.99, sum(rate(dra_operations_duration_seconds_bucket{operation_name="PrepareResources"}[5m])) by (le))을 모니터링해요. - Kubelet NodeUnprepareResources:
histogram_quantile(0.99, sum(rate(dra_operations_duration_seconds_bucket{operation_name="UnprepareResources"}[5m])) by (le))을 추적해요.
DRA kubeletplugin 작업
DRA 드라이버는 기반 gRPC 작업 NodePrepareResources와 NodeUnprepareResources에 대한 자체 메트릭을 표면화하는 kubeletplugin 패키지 인터페이스를 구현해요. 다음 메트릭으로 내부 kubeletplugin의 관점에서 이 동작을 관찰할 수 있어요.
- DRA kubeletplugin gRPC NodePrepareResources 작업:
histogram_quantile(0.99, sum(rate(dra_grpc_operations_duration_seconds_bucket{method_name=~".*NodePrepareResources"}[5m])) by (le))을 관찰해요. - DRA kubeletplugin gRPC NodeUnprepareResources 작업:
histogram_quantile(0.99, sum(rate(dra_grpc_operations_duration_seconds_bucket{method_name=~".*NodeUnprepareResources"}[5m])) by (le))을 관찰해요.
더 알아보기 (Learn more)
- DRA에 대해 더 배워 보세요.
- 쿠버네티스 메트릭 참조를 읽어 보세요.