[번역] SCHEDULING VSPHERE PODS

출처 : https://frankdenneman.nl/2020/03/20/scheduling-vsphere-pods/

이전 기사 "Initial Placement of a vSphere Pod"에서는 vSphere Pod가 맞춤 VM 구성과 컨테이너 그룹의 조합임을 보여 주기 위해 vSphere Pod의 내부 구조에 대해 다루었다. 쿠버네티스와 vSphere 플랫폼 모두 워크로드의 스케줄링을 안내, 제어 또는 제한하는 다양한 리소스 관리 제어, 정책 및 기능을 포함하고 있다. 두 제어기 모두 유사한 유형의 표현을 사용하므로 vSphere 포드 관리의 맥락에서 (거짓) 통일감을 형성한다. 이 일련의 기사에서는 서로 다른 제어부 방언의 중첩과 새로운 vSphere 7 플랫폼이 개발자가 Kubernetes 네이티브 식을 사용할 수 있도록 하는 방법에 대해 살펴보고, vSphere 관리자는 친숙한 vSphere 네이티브 리소스 관리 기능을 계속 사용한다.

워크로드 배포 프로세스

두 제어부 모두 워크로드를 배포하기 위해 유사한 프로세스를 구현하며, 워크로드는 리소스 생산자(워커 노드 또는 ESXi 호스트)에서 스케줄링되어야 하며, 제어부는 리소스 소비자가 제시한 기준(파드 매니페스트/VM 구성)에 따라 리소스 생산자를 선택한다. 제어부는 사용 가능한 리소스가 충분한지, 그리고 포드 매니페스트/VM 구성에 나열된 기준을 충족하는지, 어느 자원 생산자가 충분한 자원 용량을 갖추고 있는지를 확인한다. 워크로드의 전원 켜기 프로세스를 시작하기 위한 지침이 워크로드 프로듀서에게 전송된다.

Scheduling-Process-1.png

컨테이너와 가상 머신의 배치 프로세스 간의 차이는 크기 측면이다. 가상 시스템은 가상 하드웨어에 의해 정의되며 이 구성은 게스트 OS와 해당 프로세스의 경계로 작용한다(가상 시스템의 강력한 분리 측면 확인). 컨테이너는 제어된 프로세스로서 추상적인 OS를 사용하여 자원 할당을 제어하며, 프로세스에 할당된 직접 하드웨어 구성이 없다. 이러한 차이점 때문에 하이퍼바이저에서 기본적으로 컨테이너를 실행하고자 할 때 몇 가지 흥미로운 문제가 발생할 수 있다. 하이퍼바이저는 워크로드를 스케줄링하고 활성 워크로드 간의 리소스 할당을 관리할 수 있도록 하드웨어 구성을 정의하기 위한 워크로드 구조가 필요하다. 예상 리소스 사용량에 대한 힌트가 전혀 없을 수 있는 구성의 크기를 어떻게 지정하나. 임의의 하드웨어 구성을 규정할 수 있지만, 애플리케이션이 구조적으로 필요한 것보다 더 많은 자원을 일시적으로 사용할 수 있도록 하려면 개발자의 의도를 파악하지 못하는 것이다. 개발자가 현재 워크로드 배치 방법을 변경해야 하는 새로운 리소스 관리 패러다임을 만들고 싶지 않고, 최소한의 수동 작업으로 새로운 워크로드를 수용할 수 있기를 원하는 경우 그러나 이러한 제어기들이 함께 작동하도록 하는 것은 도전을 해결하는 과정일 뿐만 아니라 사용자 경험을 풍부하게 할 수 있는 능력을 제공한다. 이 글에서는 리소스 스케줄러 동작의 차이와 Kubernetes 리소스 요청, 제한 및 QoS 정책이 vSphere 포드 싸이징에 미치는 영향에 대해 설명한다. 그것은 그것이 vSphere 포드 사이징과 최종적으로 vSphere 포드의 배치에 어떤 영향을 미칠 수 있는지 이해할 수 있는 충분한 배경 정보를 제공하기 위해 Kubernetes 구조와 Kubernetes 스케줄링을 도입하는 것으로 시작한다.

컨테이너의 계산 리소스 관리

쿠버네티스에서 컨테이너가 사용할 수 있는 리소스 양(한계)과 워커 노드가 컨테이너에 할당해야 하는 리소스 수(요청)를 지정할 수 있다. 이는 vSphere VM Reservations 및 Limits과 유사하다. vSphere와 마찬가지로 Kubernetes는 컨테이너의 요청(예약)을 기반으로 워커 노드(작업량을 실행하는 호스트를 가르키는 Kubernetes 용어)를 선택한다. vSphere에서는 예약, 공유 및 제한을 할당할 원자 단위가 가상 머신이고, 쿠버네티스서는 컨테이너다. 직설적으로 들리지만, 약간의 함정이 있다.

컨테이너는 쿠버네티스 워커 노드에 직접 배치되는 것이 아니라 포드라고 하는 더 높은 수준의 구조로 캡슐화되어 있다. 간단히 말해서, 포드가 존재하는 이유는 포드가 용기에서 단일 프로세스를 실행할 것으로 예상되기 때문이다. 여러 프로세스에서 앱이 존재하는 경우, 컨테이너 그룹이 존재해야 하며, 프로세스 그룹을 독립적으로 관리하려는 것이 아니라 앱 자체로 관리해야 하며, 따라서 포드가 존재해야 한다. 뭐가 문제야? 포드를 배포하더라도 포드가 아니라 컨테이너별로 리소스 할당 설정을 지정해야 한다. 그러나 포드는 스케줄링을 위한 원자 단위이기 때문에, 포드 내부의 모든 컨테이너의 요청이 합산되고, 그 결과는 작업자 노드 선택에 사용된다. 포드가 배치되면 작업자 노드 리소스 스케줄러는 각 컨테이너 요청과 제한을 개별적으로 처리해야 한다. 그러나 그것은 미래의 글를 위한 주제다. 포드 메니페스트를 좀 더 자세히 살펴자.

Pod-manifest-resources.png

컨테이너 크기 대 VM 크기 생각

포드 매니페스트에는 CPU와 메모리 모두에 대한 요청과 제한이 각각 장착된 두 개의 컨테이너가 나열되어 있다. CPU는 몇 가지 다른 방법으로 표현될 수 있다. 1은 Intel 프로세서의 하이퍼스레드와 동일한 CPU 1과 동일하다. 만약 그것이 사치스럽게 외딴 것처럼 보인다면, 당신은 실제로 밀리큐나 십진법을 사용하여 더 작은 단위의 표현을 사용할 수 있다. 0.5는 하이퍼스레드의 반이나 500millicpu를 의미한다. 숙련된 vSphere 관리자의 경우, 이제 64코어를 요구하는 사용자를 다루는 대신, 우리는 여기서 원자를 분할하려고 시도하고 있다. 메모리를 사용하면 메모리 요구 사항을 접미사 64MiB(2^26바이트)를 사용하여 일반 정수(126754378954) 또는 고정 포인트 정수로 표현할 수 있다. Kubernetes.io 문서는 고정점 정수가 존재하는 것을 도와줄 수 있다. 이 예에서 포드 요청은 메모리의 128 Mi, CPU 리소스의 500m이다.

쿠버네티스 스케줄링

컨테이너의 초기 배치 과정에서 스케줄러는 먼저 "호환성"을 점검할 필요가 있다. Kubernetes 스케줄러는 tains와 tolerations, 포드 선호도와 반선호도, 노드 선호도를 고려한 후, 노드 용량을 검토하여 포드 요청을 만족시킬 수 있는지(128Mi 및 500m CPU) 파악한다. 더 정확히 말하면, 그것은 "노드 할당 가능"을 검사한다. 이것은 포드가 소비할 수 있는 자원의 수이다. 쿠버네티스는 자원의 부족을 감수하지 않고 시스템 데몬과 그 자체가 실행될 수 있도록 노드의 자원을 비축하고 있다. 노드 할당 가능 자원은 할당 및 할당되지 않은 두 부분으로 나뉜다. 할당된 리소스의 총합은 워커 노드에 있는 모든 활성 컨테이너의 모든 요청 구성의 합이다. 결과적으로, Kubernetes는 포드 매니페스트에 명시된 요청과 클러스터의 각 작업자 노드가 나열한 할당되지 않은 리소스와 일치한다. 할당되지 않은 리소스가 가장 많은 노드를 선택하여 포드를 실행한다. 명확히 하기 위해 쿠버네티스의 초기 배치에서는 실제 자원 사용량을 고려하지 않는다.

Kubernetes-Initial-Placement.png

다이어그램에 표시된 대로 워크로드를 스케줄링해야 한다. Kubernetes 제어면은 개별 워커 노드를 검토하고, 포드에 맞출 수 있는 노드를 필터링한 다음, 구성된 우선순위 지정 기능에 따라 노드를 선택한다. 가장 많이 사용되는 기능은 요청된 리소스가 적은 워커 노드를 선호하는 "LastRequestedPriority" 옵션이다. 노드 B는 예약된 리소스의 양이 가장 적기 때문에 스케줄러는 이 노드가 워크로드를 실행하기에 가장 적합한 후보라고 간주한다.

vSphere 스케줄링

DRS는 보다 광범위한 리소스 스케줄링 모델을 가지고 있다. 쿠버네티스가 사용하는 방법은 vSphere 승인 제어 모델과 more or less in-line이다. 쿠버넷 스케줄링에는 방금 위의 단락에서 설명한 것보다 더 많은 뉘앙스와 특징이 포함되어 있다. 노드가 메모리 압력을 보고하는지 확인하여 노드 선택 목록(CheckNodeMemoryPressure)에서 제외할 수 있으며 우선순위 기능은 베타에 있지만 예약 및 예약되지 않은 메모리를 전체적으로 살펴보면 약간 거친 것으로 간주할 수 있다. vSphere에는 연속성과 리소스 가용성을 보장하기 위해 모두 함께 작동하는 세 가지 승인 제어 기능이 있다. DRS 리소스 스케줄링은 워크로드의 리소스 사용 권한과 호스트 리소스 가용성을 일치시킨다. 워크로드의 예약, 공유, 제한 및 실제 리소스 사용량을 사용하여 적절한 호스트를 결정한다. 이제 여러분은 배치해야 할 작업 부하가 아직 자원을 사용하지 않는다고 주장할 수도 있는데, 이 작업은 어떻게 이루어지는가?

DRS는 초기 배치 중에 구성된 크기를 리소스 사용 권한으로 간주하며, 이 경우 리소스 사용 권한은 최악의 시나리오가 된다. 따라서 4개의 vCPU와 16GB의 하드웨어 구성을 가진 VM은 4개의 vCPU 및 16GB의 전원을 켜기 전에 VM을 실행하기 위한 일부 오버헤드(VM 오버헤드)를 추가로 사용할 수 있는 리소스 사용 권한을 가지고 있다. 그러나 예약이 8GB로 설정되어 있으면 리소스 사용 권한이 vCPU 4개, VM 오버헤드 8GB 이상의 최소 리소스 사용 권한으로 전환된다. 호스트에는 최소 8GB(+VM 오버헤드)의 예약되지 않은 리소스를 고려할 수 있어야 한다.

이것이 쿠버네티스와 어떻게 다른가? 글쎄, 이 부분은 그렇지 않아. 핵심은 작업량의 미래 상태를 고려하는 것이다.

DRS는 다른 호스트에서 실행되는 다른 모든 활성 워크로드의 실제 리소스 사용량(및 사용 권한)을 이해한다. 따라서 각 호스트에서 수행할 워크로드의 능력(및 가능성)을 정확하게 파악한다. 사용 권한은 작업 부하가 소비할 권리가 있는 자원의 수를 나타낸다. 따라서 작업 부하 압력에 대한 예측의 한 형태로서 기능하기도 한다. 붐비는 호스트에 새 워크로드를 배치하시겠습니까, 아니면 덜 바쁜 호스트에 배치하시겠습니까?

이 예에서는 각각 100GB의 메모리 용량을 가진 세 개의 호스트가 있다. 호스트 A에는 60GB의 메모리가 예약된 활성 워크로드가 있다. 40GB의 메모리는 예약되지 않았다. 호스트 B와 호스트 C는 40GB의 메모리를 예약한 워크로드가 활성 상태임. 60GB의 메모리는 예약되지 않았다. 35GB의 예약된 새로운 작업 부하가 들어온다. 쿠버네티스 스케줄러는 두 호스트 모두 똑같이 좋다고 생각했을 것이다. 그러나 DRS는 활성 용도에 대해 알고 있다. 호스트 B는 활성 리소스 소비량이 70GB인 반면 호스트 C는 45GB의 활성 사용량을 가지고 있다. 호스트 B 리소스 사용량이 용량에 가까워짐에 따라 DRS는 호스트 C를 초기 배치를 위한 대상 호스트로 선택한다.

vSphere-Initial-Placement.png

VM 구성품이든 vSphere 포드 내의 컨테이너든 다른 활성 리소스 소비자의 활성 리소스 사용을 고려하면 의도를 더 만족시킬 수 있는 플랫폼을 생성한다. 포드가 버스트 가능한 서비스 품질 클래스로 구성된 경우(한계는 요청을 초과함), 개발자는 워크로드가 가용할 경우 더 많은 리소스를 소비할 수 있어야 한다는 의도를 선언한다. 활성 호스트 리소스 사용으로 강화된 초기 배치를 통해 그러한 기능을 가질 확률은 매우 높아진다.

vSphere 포드의 계산 리소스 관리

vSphere 포드가 컨테이너와 VM 구성의 조합인 것을 보고 두 제어면은 vSphere 포드의 여러 구성 요소와 상호 작용한다. 그러나 다른 구성의 몇몇 특성은 예를 들어 크기 조정과 같은 다른 구성의 행동에 영향을 미친다. VM은 하드웨어 구성에 의해 정의된 구성이다. 본질적으로 VM은 가상화된 하드웨어로, 스케줄러는 VM의 경계를 파악하여 적절히 배치하고 스케줄링해야 한다. 이 구성은 게스트 OS가 살고 있는 세계의 경계로 작용한다. 게스트 OS는 VM의 경계를 넘어서는 것을 볼 수 없으며, 따라서 VM이 살고 있는 세계에 맞게 작동하고 최적화된다. 그것은 "외부 공간"에 대한 개념이 없다.

컨테이너는 이것의 반대다. 컨테이너는 그 정의와는 달리 견고하거나 단단한 구조가 아니다. 그것은 리소스 사용(제어 그룹)을 분리하거나 "연결"하기 위해 기능이 포함하는 프로세스 그룹이다. 이를 윈도우즈 시스템의 프로세스 또는 응용 프로그램과 비교하십시오. 응용 프로그램을 시작하거나 구성할 때 특정 응용 프로그램이 사용할 수 있는 CPU 또는 메모리 수를 정의하지 않는다. 이것이 Galactus(Google Chrome으로 더 잘 알려져 있음)처럼 행동하지 않기를 바라며, 당신의 모든 자원을 소모하지 않기를 바란다. 이는 윈도우즈의 프로세스가 호스트에 포함된 모든 리소스(즉, 랩톱 또는 가상 시스템)를 볼 수 있음을 의미한다. 리눅스 컨테이너도 마찬가지다. 컨테이너는 해당 호스트에서 사용할 수 있는 모든 리소스를 볼 수 있다. 제한 설정은 이 경계 이상으로 사용하도록 제한한다. 즉, 제한이 설정되어 있지 않다면 컨테이너는 워커 노드가 제공할 수 있는 만큼의 양을 소비할 수 있어야 한다. 즉, VM-싸이징 용어로 컨테이너의 크기는 워커 노드와 동일하다. 이 컨테이너를 vSphere 포드 내에서 실행하려면 vSphere 포드의 크기가 ESXi 호스트 크기여야 한다. 비록 우리 모두가 몬스터-VM을 좋아하지만, 이렇게 해서는 안 된다. 특히 대부분의 컨테이너 자원 관리 식이 원자 분열과 접하고 있으며, 데이터 센터에 행성 크기의 컨테이너 실체를 도입하려는 의도가 아닌 경우라면 말이다.

쿠버네티스 QoS 클래스 및 vSphere 포드 사이징의 영향

Kubernetes의 매우 흥미로운 행동은 포드 매니페스트에서 한계와 요청 정의의 조합으로 인한 QoS 클래스의 암묵적 정의다. 본 문서의 도입에서 보듯이, 포드 매니페스트에는 각 용기의 정의와 한계를 포함하고 있다. 그러나 이러한 규격은 전적으로 선택사항이다. 사용된 조합을 바탕으로 쿠버네티스는 자동으로 포드 내부의 용기에 QoS 클래스를 할당한다. 그리고 QoS 클래스에 근거하여 매립이 일어난다. 쿠버네티스의 방언에 정통한 개발자는 이러한 행동을 이해하고 그에 따라 포드 표기를 구성한다. 개발자의 의도를 더 잘 이해하기 위해 세 개의 QoS 클래스를 살펴보자.

Kubernetes-QoS-Classes-Overview.png

BestEffort 클래스, Burstable 클래스, Guaranteed 클래스 세 가지가 있다. 포드 매니페스트에 있는 모든 용기에 요청과 제한이 설정되어 있지 않으면 BestEffort 클래스가 해당 포드에 할당된다. 즉, 그 포드의 모든 컨테이너는 원하는 만큼 자원을 할당할 수 있지만, 자원 압력이 발생할 경우 퇴출되는 첫 번째 컨테이너이기도 하다. 포드 매니페스트에 있는 모든 컨테이너가 메모리와 CPU 요청을 모두 포함하고 있고 요청이 한도와 같다면, Kubernetes는 Guaranteed된 QoS 클래스를 포드에 할당한다. Guaranteed된 포드는 자원 경합이 발생할 경우 마지막으로 타격을 받을 수 있는 후보들이다. CPU와 메모리 요청 및 제한의 다른 모든 생각할 수 있는 조합은 쿠버네티스가 Burstable 클래스를 할당하도록 보장한다. 자원 할당과 매립의 예상 동작을 방해하지 않는 것이 중요하며, 그 결과, 포드 매니페스트에 사용된 요청과 한계는 다양한 조합의 예상 회수 동작을 유지하면서 vSphere 포드 사이징의 지침으로 사용된다.

컨테이너에 제한이 설정되어 있지 않은 경우 vSphere 포드의 크기를 조정할 때 vSphere에서 이 문제를 어떻게 해석해야 하는가?

호스트 크기의 vSphere 포드를 방지하기 위해 기본 컨테이너 크기가 도입된다. 콘테이너 단위인 것이다. 정확히 말해서, 요청/제한 설정이 없고 하나의 컨테이너가 있는 가장 단순한 포드가 생성되면 vSphere Pod는 1개의 vCPU와 512MB를 얻게 된다. 실제로는 0.5개의 코어를 얻지만, 하나의 컨테이너만 있으면 vCPU를 최대 1개까지 둘 것이다.

왜 포드가 단위가 아니지? 단순히 확장성 때문에, 안에 있는 BestEffort 컨테이너의 수에 따라 포드의 크기가 커진다. 요청 또는 한도가 설정된 경우 이 메트릭이 컨테이너 크기를 결정하는 데 사용되는 것보다 큰 기본 크기. 포드 매니페스트에 여러 개의 컨테이너가 포함된 경우, 각 컨테이너의 가장 큰 메트릭이 방정식에 추가되고 합계의 제품이 vSphere 포드 크기로 사용된다. 예를 들어, 포드는 컨테이너의 기본 크기보다 큰 요청과 제한이 있는 두 개의 컨테이너를 포함한다. CPU 한도가 CPU 요청 크기를 초과하여 vSphere는 두 CPU 한도의 합계를 사용하며 포드 라이프사이클, 포드 구성 및 vSpherelet 상호 작용을 담당하는 구성 요소에 약간의 패딩을 추가한다. 메모리도 비슷한 계산이 나온다.

Resource-Allocation-Setting-Impact-vSphere-Pod-Size.png

쿠버네티스가 설치된 vSphere의 vSphere 포드 내부에 컨테이너의 초기 배치

개발자가 파드 매니페스트를 쿠버네티스 제어면에 밀어넣을 때, 적절한 작업자 노드를 찾기 위해 Kube-Scheduler가 필요하다. 쿠버네티스 방언에서는 포드의 자원 할당 요건을 충족하는 워커 노드를 피저블(feasible) 노드라고 한다.

피저블 노드를 결정하기 위해, Kube-Scheduler는 포드 매니페스트에 나열된 요청을 충족시키는 데 필요한 할당되지 않은 리소스가 충분하지 않은 노드를 필터링할 것이다. Kube-Scheduler에 의해 수행된 프로세스의 두 번째 단계는 선호도나 라벨과 같은 추가 요건에 기초하여 목록의 실현 가능한 각 노드를 채점하는 것이다. 순위가 지정된 목록은 Pacific Scheduler Extension으로 전송되고, 이 목록은 vSphere API 서버로 전송되며, vSphere DRS 서비스로 전달된다.

DRS는 어떤 호스트가 리소스 요구 사항에 가장 잘 부합하는지 결정하고 vSphere 포드가 가장 높은 행복도 점수를 받을 수 있도록(vSphere 포드가 부여하는 리소스 가져오기) 가장 적합한 후보인지 판단한다. vSphere Pod LifeCycle Controller는 선택한 호스트의 Spearlet이 포드를 생성하고 Photon Linux 커널을 vSphere 포드에 주입(inject)하도록 보장한다. 스피어릿이 컨테이너를 시작한다. (vSphere Pod의 생성 프로세스에 대한 자세한 다이어그램은 Initial Placement of a vSphere Pod를 참조)

vSphere-with-Kubernetes-Initial-Placement.png

그러나 개발자가 지정한 제한이 생성된 것 보다 호스트 기능을 초과하는 경우 vSphere 포드가 배포되지 않는다는 점에 유의한다.

리소스 회수

vSphere는 vSphere 포드 사이징 외에도 포드 매니페스트에 나열된 리소스 요청을 사용하여 요청된 리소스를 사용할 수 있는지 확인하기 위해 vSphere 리소스 할당 설정을 적용한다. 설정된 예약과 vSphere 포드의 크기 사이에는 차이가 있을 수 있다. VM 동작과 유사하게 이러한 리소스는 리소스 경합이 없는 한 사용할 수 있다. 리소스 경합이 발생하면 리소스 재확보가 시작된다. vSphere 포드의 경우 vSphere의 광범위한 통합 기술이 사용되지만, 포드의 제거에 관해서는 vSphere가 쿠버네티스가이 더러운 작업을 하도록 허용한다. 심각하게도, 내부 쿠버네티스 이벤트 관리와 자원 사용에 대한 보다 세밀한 관점 때문이다.

네임스페이스

쿠버네티스는 멤버 포드를 안내하고 제어하기 위해 보다 높은 수준의 구조를 이용할 수 있는데, 이 구조를 네임스페이스라고 한다. vSphere 7 with Kubernetes는 vSphere 수준의 유사한 구성인 슈퍼바이저 네임스페이스를 제공한다. vSphere 리소스 풀은 감독자 네임스페이스의 계산 리소스를 관리하는 데 사용된다. 네임스페이스는 기본 요청 또는 컨테이너의 제한을 정의하여 vSphere 포드 크기와 회수 동작에 영향을 미치는 선택적 제한 범위로 구성할 수 있다. 슈퍼바이저 네임스페이스는 광범위한 주제여서 네임스페이스에 대한 더 많은 정보가 이 시리즈의 다음 글에 나타날 것이다.