리소스 쿼터
여러 사용자나 팀이 정해진 수의 노드로 클러스터를 공유할 때 한 팀이 공정하게 분배된 리소스보다 많은 리소스를 사용할 수 있다는 우려가 있다.
리소스 쿼터는 관리자가 이 문제를 해결하기 위한 도구이다.
- 리소스 쿼터 활성화
- 컴퓨트 리소스 쿼터
- 스토리지 리소스 쿼터
- 오브젝트 수 쿼터
- 쿼터 범위
- 요청과 제한의 비교
- 쿼터 보기 및 설정
- 쿼터 및 클러스터 용량
- 기본적으로 우선 순위 클래스 소비 제한
- 예제
- 다음 내용
ResourceQuota
오브젝트로 정의된 리소스 쿼터는 네임스페이스별 총 리소스 사용을 제한하는
제약 조건을 제공한다. 유형별로 네임스페이스에서 만들 수 있는 오브젝트 수와
해당 프로젝트의 리소스가 사용할 수 있는 총 컴퓨트 리소스의 양을
제한할 수 있다.
리소스 쿼터는 다음과 같이 작동한다.
- 다른 팀은 다른 네임스페이스에서 작동한다. 현재 이것은 자발적이지만 ACL을 통해 이 필수 사항을 적용하기 위한 지원이 계획되어 있다.
- 관리자는 각 네임스페이스에 대해 하나의
ResourceQuota
를 생성한다. - 사용자는 네임스페이스에서 리소스(파드, 서비스 등)를 생성하고 쿼터 시스템은
사용량을 추적하여
ResourceQuota
에 정의된 하드(hard) 리소스 제한을 초과하지 않도록 한다. - 리소스를 생성하거나 업데이트할 때 쿼터 제약 조건을 위반하면 위반된 제약 조건을 설명하는
메시지와 함께 HTTP 상태 코드
403 FORBIDDEN
으로 요청이 실패한다. cpu
,memory
와 같은 컴퓨트 리소스에 대해 네임스페이스에서 쿼터가 활성화된 경우 사용자는 해당값에 대한 요청 또는 제한을 지정해야 한다. 그렇지 않으면 쿼터 시스템이 파드 생성을 거부할 수 있다. 힌트: 컴퓨트 리소스 요구 사항이 없는 파드를 기본값으로 설정하려면LimitRanger
어드미션 컨트롤러를 사용하자. 이 문제를 회피하는 방법에 대한 예제는 연습을 참고하길 바란다.
ResourceQuota
오브젝트의 이름은 유효한
DNS 서브도메인 이름이어야 한다.
네임스페이스와 쿼터를 사용하여 만들 수 있는 정책의 예는 다음과 같다.
- 용량이 32GiB RAM, 16 코어인 클러스터에서 A 팀이 20GiB 및 10 코어를 사용하고 B 팀은 10GiB 및 4 코어를 사용하게 하고 2GiB 및 2 코어를 향후 할당을 위해 보유하도록 한다.
- “testing” 네임스페이스를 1 코어 및 1GiB RAM을 사용하도록 제한한다. “production” 네임스페이스에는 원하는 양을 사용하도록 한다.
클러스터의 총 용량이 네임스페이스의 쿼터 합보다 작은 경우 리소스에 대한 경합이 있을 수 있다. 이것은 선착순으로 처리된다.
경합이나 쿼터 변경은 이미 생성된 리소스에 영향을 미치지 않는다.
리소스 쿼터 활성화
많은 쿠버네티스 배포판에 기본적으로 리소스 쿼터 지원이 활성화되어 있다.
API 서버 --enable-admission-plugins=
플래그의 인수 중 하나로
ResourceQuota
가 있는 경우 활성화된다.
해당 네임스페이스에 ResourceQuota
가 있는 경우 특정 네임스페이스에 리소스 쿼터가 적용된다.
컴퓨트 리소스 쿼터
지정된 네임스페이스에서 요청할 수 있는 총 컴퓨트 리소스 합을 제한할 수 있다.
다음과 같은 리소스 유형이 지원된다.
리소스 이름 | 설명 |
---|---|
limits.cpu |
터미널이 아닌 상태의 모든 파드에서 CPU 제한의 합은 이 값을 초과할 수 없음 |
limits.memory |
터미널이 아닌 상태의 모든 파드에서 메모리 제한의 합은 이 값을 초과할 수 없음 |
requests.cpu |
터미널이 아닌 상태의 모든 파드에서 CPU 요청의 합은 이 값을 초과할 수 없음 |
requests.memory |
터미널이 아닌 상태의 모든 파드에서 메모리 요청의 합은 이 값을 초과할 수 없음 |
확장된 리소스에 대한 리소스 쿼터
위에서 언급한 리소스 외에도 릴리스 1.10에서는 확장된 리소스에 대한 쿼터 지원이 추가되었다.
확장된 리소스에는 오버커밋(overcommit)이 허용되지 않으므로 하나의 쿼터에서
동일한 확장된 리소스에 대한 requests
와 limits
을 모두 지정하는 것은 의미가 없다. 따라서 확장된
리소스의 경우 지금은 접두사 requests.
이 있는 쿼터 항목만 허용된다.
예를 들어, 리소스 이름이 nvidia.com/gpu
이고 네임스페이스에서 요청된 총 GPU 수를 4개로 제한하려는 경우,
GPU 리소스를 다음과 같이 쿼터를 정의할 수 있다.
requests.nvidia.com/gpu: 4
자세한 내용은 쿼터 보기 및 설정을 참고하길 바란다.
스토리지 리소스 쿼터
지정된 네임스페이스에서 요청할 수 있는 총 스토리지 리소스 합을 제한할 수 있다.
또한 연관된 스토리지 클래스를 기반으로 스토리지 리소스 사용을 제한할 수 있다.
리소스 이름 | 설명 |
---|---|
requests.storage |
모든 퍼시스턴트 볼륨 클레임에서 스토리지 요청의 합은 이 값을 초과할 수 없음 |
persistentvolumeclaims |
네임스페이스에 존재할 수 있는 총 퍼시스턴트 볼륨 클레임 수 |
<storage-class-name>.storageclass.storage.k8s.io/requests.storage |
storage-class-name과 관련된 모든 퍼시스턴트 볼륨 클레임에서 스토리지 요청의 합은 이 값을 초과할 수 없음 |
<storage-class-name>.storageclass.storage.k8s.io/persistentvolumeclaims |
storage-class-name과 관련된 모든 퍼시스턴트 볼륨 클레임에서 네임스페이스에 존재할 수 있는 총 퍼시스턴트 볼륨 클레임 수 |
예를 들어, 운영자가 bronze
스토리지 클래스와 별도로 gold
스토리지 클래스를 사용하여 스토리지에 쿼터를 지정하려는 경우 운영자는 다음과 같이
쿼터를 정의할 수 있다.
gold.storageclass.storage.k8s.io/requests.storage: 500Gi
bronze.storageclass.storage.k8s.io/requests.storage: 100Gi
릴리스 1.8에서는 로컬 임시 스토리지에 대한 쿼터 지원이 알파 기능으로 추가되었다.
리소스 이름 | 설명 |
---|---|
requests.ephemeral-storage |
네임스페이스의 모든 파드에서 로컬 임시 스토리지 요청의 합은 이 값을 초과할 수 없음 |
limits.ephemeral-storage |
네임스페이스의 모든 파드에서 로컬 임시 스토리지 제한의 합은 이 값을 초과할 수 없음 |
오브젝트 수 쿼터
1.9 릴리스는 다음 구문을 사용하여 모든 표준 네임스페이스 리소스 유형에 쿼터를 지정하는 지원을 추가했다.
count/<resource>.<group>
다음은 사용자가 오브젝트 수 쿼터 아래에 배치하려는 리소스 셋의 예이다.
count/persistentvolumeclaims
count/services
count/secrets
count/configmaps
count/replicationcontrollers
count/deployments.apps
count/replicasets.apps
count/statefulsets.apps
count/jobs.batch
count/cronjobs.batch
count/deployments.extensions
1.15 릴리스는 동일한 구문을 사용하여 사용자 정의 리소스에 대한 지원을 추가했다.
예를 들어 example.com
API 그룹에서 widgets
사용자 정의 리소스에 대한 쿼터를 생성하려면 count/widgets.example.com
을 사용한다.
count/*
리소스 쿼터를 사용할 때 서버 스토리지 영역에 있다면 오브젝트는 쿼터에 대해 과금된다.
이러한 유형의 쿼터는 스토리지 리소스 고갈을 방지하는 데 유용하다. 예를 들어,
크기가 큰 서버에서 시크릿 수에 쿼터를 지정할 수 있다. 클러스터에 시크릿이 너무 많으면 실제로 서버와
컨트롤러가 시작되지 않을 수 있다! 네임스페이스에 너무 많은 작업을 생성하는
잘못 구성된 크론 잡으로 인해 서비스 거부를 유발하는 것으로부터 보호하기 위해 작업의 쿼터를 지정하도록 선택할 수 있다.
1.9 릴리스 이전에는 제한된 리소스 셋에서 일반 오브젝트 수 쿼터를 적용할 수 있었다. 또한, 특정 리소스에 대한 쿼터를 유형별로 추가로 제한할 수 있다.
다음 유형이 지원된다.
리소스 이름 | 설명 |
---|---|
configmaps |
네임스페이스에 존재할 수 있는 총 구성 맵 수 |
persistentvolumeclaims |
네임스페이스에 존재할 수 있는 총 퍼시스턴트 볼륨 클레임 수 |
pods |
네임스페이스에 존재할 수 있는 터미널이 아닌 상태의 파드의 총 수. .status.phase in (Failed, Succeeded) 가 true인 경우 파드는 터미널 상태임 |
replicationcontrollers |
네임스페이스에 존재할 수 있는 총 레플리케이션 컨트롤러 수 |
resourcequotas |
네임스페이스에 존재할 수 있는 총 리소스 쿼터 수 |
services |
네임스페이스에 존재할 수 있는 총 서비스 수 |
services.loadbalancers |
네임스페이스에 존재할 수 있는 로드 밸런서 유형의 총 서비스 수 |
services.nodeports |
네임스페이스에 존재할 수 있는 노드 포트 유형의 총 서비스 수 |
secrets |
네임스페이스에 존재할 수 있는 총 시크릿 수 |
예를 들어, pods
쿼터는 터미널이 아닌 단일 네임스페이스에서 생성된 pods
수를 계산하고 최대값을 적용한다.
사용자가 작은 파드를 많이 생성하여 클러스터의 파드 IP 공급이 고갈되는 경우를 피하기 위해
네임스페이스에 pods
쿼터를 설정할 수 있다.
쿼터 범위
각 쿼터에는 연결된 범위 셋이 있을 수 있다. 쿼터는 열거된 범위의 교차 부분과 일치하는 경우에만 리소스 사용량을 측정한다.
범위가 쿼터에 추가되면 해당 범위와 관련된 리소스를 지원하는 리소스 수가 제한된다. 허용된 셋 이외의 쿼터에 지정된 리소스는 유효성 검사 오류가 발생한다.
범위 | 설명 |
---|---|
Terminating |
.spec.activeDeadlineSeconds >= 0 에 일치하는 파드 |
NotTerminating |
.spec.activeDeadlineSeconds is nil 에 일치하는 파드 |
BestEffort |
최상의 서비스 품질을 제공하는 파드 |
NotBestEffort |
서비스 품질이 나쁜 파드 |
BestEffort
범위는 다음의 리소스(파드)를 추적하도록 쿼터를 제한한다.
Terminating
, NotTerminating
및 NotBestEffort
범위는 쿼터를 제한하여 다음의 리소스를 추적한다.
cpu
limits.cpu
limits.memory
memory
pods
requests.cpu
requests.memory
PriorityClass별 리소스 쿼터
Kubernetes 1.12
beta
- 버전 이름에는 베타(예: v2beta3)가 포함된다.
- 코드의 테스트가 완료되었다. 기능을 활성화해도 안전한 것으로 간주한다. 기본으로 활성화되어 있다.
- 자세한 내용은 변경될 수 있지만, 전체 기능에 대한 지원은 중단되지 않는다.
- 오브젝트의 스키마 및(또는) 의미(semantics)는 후속 베타 또는 안정적인 릴리즈에서 호환되지 않는 방식으로 변경될 수 있다. 이 경우, 다음 버전으로 마이그레이션하기 위한 지침을 제공할 것이다. 이를 위해서는 API 오브젝트의 삭제, 수정 또는 재생성이 필요할 수 있다. 편집 과정에서 약간의 생각이 필요할 수 있다. 이 기능을 사용하는 애플리케이션은 가동 중지 시간(downtime)이 필요할 수 있다.
- 후속 릴리즈에서 호환되지 않는 변경 가능성이 있으므로 오직 업무상 중요하지 않은 용도로만 권장한다. 만약 사용자가 독립적으로 업그레이드가 가능한 다중 클러스터를 가지고 있다면, 이 제약은 완화될 수 있다.
- 베타 기능을 사용해보고, 우리에게 피드백을 주십시오! 베타가 종료된 후에 많은 것을 변경하는 것은 타당하지 않을 수 있습니다.
특정 우선 순위로 파드를 생성할 수 있다.
쿼터 스펙의 scopeSelector
필드를 사용하여 파드의 우선 순위에 따라 파드의 시스템 리소스 사용을
제어할 수 있다.
쿼터 스펙의 scopeSelector
가 파드를 선택한 경우에만 쿼터가 일치하고 사용된다.
이 예에서는 쿼터 오브젝트를 생성하여 특정 우선 순위의 파드와 일치시킨다. 예제는 다음과 같이 작동한다.
- 클러스터의 파드는 “low(낮음)”, “medium(중간)”, “high(높음)“의 세 가지 우선 순위 클래스 중 하나를 가진다.
- 각 우선 순위마다 하나의 쿼터 오브젝트가 생성된다.
다음 YAML을 quota.yml
파일에 저장한다.
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pods-high
spec:
hard:
cpu: "1000"
memory: 200Gi
pods: "10"
scopeSelector:
matchExpressions:
- operator : In
scopeName: PriorityClass
values: ["high"]
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pods-medium
spec:
hard:
cpu: "10"
memory: 20Gi
pods: "10"
scopeSelector:
matchExpressions:
- operator : In
scopeName: PriorityClass
values: ["medium"]
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pods-low
spec:
hard:
cpu: "5"
memory: 10Gi
pods: "10"
scopeSelector:
matchExpressions:
- operator : In
scopeName: PriorityClass
values: ["low"]
kubectl create
를 사용하여 YAML을 적용한다.
kubectl create -f ./quota.yml
resourcequota/pods-high created
resourcequota/pods-medium created
resourcequota/pods-low created
kubectl describe quota
를 사용하여 Used
쿼터가 0
인지 확인하자.
kubectl describe quota
Name: pods-high
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 0 1k
memory 0 200Gi
pods 0 10
Name: pods-low
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 0 5
memory 0 10Gi
pods 0 10
Name: pods-medium
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 0 10
memory 0 20Gi
pods 0 10
우선 순위가 “high”인 파드를 생성한다. 다음 YAML을
high-priority-pod.yml
파일에 저장한다.
apiVersion: v1
kind: Pod
metadata:
name: high-priority
spec:
containers:
- name: high-priority
image: ubuntu
command: ["/bin/sh"]
args: ["-c", "while true; do echo hello; sleep 10;done"]
resources:
requests:
memory: "10Gi"
cpu: "500m"
limits:
memory: "10Gi"
cpu: "500m"
priorityClassName: high
kubectl create
로 적용하자.
kubectl create -f ./high-priority-pod.yml
“high” 우선 순위 쿼터가 적용된 pods-high
에 대한 “Used” 통계가 변경되었고
다른 두 쿼터는 변경되지 않았는지 확인한다.
kubectl describe quota
Name: pods-high
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 500m 1k
memory 10Gi 200Gi
pods 1 10
Name: pods-low
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 0 5
memory 0 10Gi
pods 0 10
Name: pods-medium
Namespace: default
Resource Used Hard
-------- ---- ----
cpu 0 10
memory 0 20Gi
pods 0 10
scopeSelector
는 operator
필드에서 다음 값을 지원한다.
In
NotIn
Exist
DoesNotExist
요청과 제한의 비교
컴퓨트 리소스를 할당할 때 각 컨테이너는 CPU 또는 메모리에 대한 요청과 제한값을 지정할 수 있다. 쿼터는 값에 대한 쿼터를 지정하도록 구성할 수 있다.
쿼터에 requests.cpu
나 requests.memory
에 지정된 값이 있으면 들어오는 모든
컨테이너가 해당 리소스에 대한 명시적인 요청을 지정해야 한다. 쿼터에 limits.cpu
나
limits.memory
에 지정된 값이 있으면 들어오는 모든 컨테이너가 해당 리소스에 대한 명시적인 제한을 지정해야 한다.
쿼터 보기 및 설정
Kubectl은 쿼터 생성, 업데이트 및 보기를 지원한다.
kubectl create namespace myspace
cat <<EOF > compute-resources.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-resources
spec:
hard:
requests.cpu: "1"
requests.memory: 1Gi
limits.cpu: "2"
limits.memory: 2Gi
requests.nvidia.com/gpu: 4
EOF
kubectl create -f ./compute-resources.yaml --namespace=myspace
cat <<EOF > object-counts.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: object-counts
spec:
hard:
configmaps: "10"
persistentvolumeclaims: "4"
pods: "4"
replicationcontrollers: "20"
secrets: "10"
services: "10"
services.loadbalancers: "2"
EOF
kubectl create -f ./object-counts.yaml --namespace=myspace
kubectl get quota --namespace=myspace
NAME AGE
compute-resources 30s
object-counts 32s
kubectl describe quota compute-resources --namespace=myspace
Name: compute-resources
Namespace: myspace
Resource Used Hard
-------- ---- ----
limits.cpu 0 2
limits.memory 0 2Gi
requests.cpu 0 1
requests.memory 0 1Gi
requests.nvidia.com/gpu 0 4
kubectl describe quota object-counts --namespace=myspace
Name: object-counts
Namespace: myspace
Resource Used Hard
-------- ---- ----
configmaps 0 10
persistentvolumeclaims 0 4
pods 0 4
replicationcontrollers 0 20
secrets 1 10
services 0 10
services.loadbalancers 0 2
Kubectl은 count/<resource>.<group>
구문을 사용하여 모든 표준 네임스페이스 리소스에 대한
오브젝트 수 쿼터를 지원한다.
kubectl create namespace myspace
kubectl create quota test --hard=count/deployments.extensions=2,count/replicasets.extensions=4,count/pods=3,count/secrets=4 --namespace=myspace
kubectl run nginx --image=nginx --replicas=2 --namespace=myspace
kubectl describe quota --namespace=myspace
Name: test
Namespace: myspace
Resource Used Hard
-------- ---- ----
count/deployments.extensions 1 2
count/pods 2 3
count/replicasets.extensions 1 4
count/secrets 1 4
쿼터 및 클러스터 용량
ResourceQuotas
는 클러스터 용량과 무관하다. 그것들은 절대 단위로 표현된다.
따라서 클러스터에 노드를 추가해도 각 네임스페이스에 더 많은 리소스를
사용할 수 있는 기능이 자동으로 부여되지는 않는다.
가끔 다음과 같은 보다 복잡한 정책이 필요할 수 있다.
- 여러 팀으로 전체 클러스터 리소스를 비례적으로 나눈다.
- 각 테넌트가 필요에 따라 리소스 사용량을 늘릴 수 있지만, 실수로 리소스가 고갈되는 것을 막기 위한 충분한 제한이 있다.
- 하나의 네임스페이스에서 요구를 감지하고 노드를 추가하며 쿼터를 늘린다.
이러한 정책은 쿼터 사용을 감시하고 다른 신호에 따라 각 네임스페이스의 쿼터 하드 제한을
조정하는 “컨트롤러”를 작성하여 ResourceQuotas
를 구성 요소로
사용하여 구현할 수 있다.
리소스 쿼터는 통합된 클러스터 리소스를 분할하지만 노드에 대한 제한은 없다. 여러 네임스페이스의 파드가 동일한 노드에서 실행될 수 있다.
기본적으로 우선 순위 클래스 소비 제한
파드가 특정 우선 순위, 예를 들어 일치하는 쿼터 오브젝트가 존재하는 경우에만 “cluster-services”가 네임스페이스에 허용되어야 힌다.
이 메커니즘을 통해 운영자는 특정 우선 순위가 높은 클래스의 사용을 제한된 수의 네임스페이스로 제한할 수 있으며 모든 네임스페이스가 기본적으로 이러한 우선 순위 클래스를 사용할 수 있는 것은 아니다.
이를 적용하려면 kube-apiserver 플래그 --admission-control-config-file
을 사용하여 다음 구성 파일의 경로를 전달해야 한다.
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: "ResourceQuota"
configuration:
apiVersion: apiserver.config.k8s.io/v1
kind: ResourceQuotaConfiguration
limitedResources:
- resource: pods
matchScopes:
- scopeName: PriorityClass
operator: In
values: ["cluster-services"]
# Deprecated in v1.17 in favor of apiserver.config.k8s.io/v1
apiVersion: apiserver.k8s.io/v1alpha1
kind: AdmissionConfiguration
plugins:
- name: "ResourceQuota"
configuration:
# Deprecated in v1.17 in favor of apiserver.config.k8s.io/v1, ResourceQuotaConfiguration
apiVersion: resourcequota.admission.k8s.io/v1beta1
kind: Configuration
limitedResources:
- resource: pods
matchScopes:
- scopeName: PriorityClass
operator: In
values: ["cluster-services"]
이제 “cluster-services” 파드는 scopeSelector
와 일치하는 쿼터 오브젝트가 있는 네임스페이스에서만 허용된다.
예를 들면 다음과 같다.
scopeSelector:
matchExpressions:
- scopeName: PriorityClass
operator: In
values: ["cluster-services"]
자세한 내용은 LimitedResources와 우선 순위 클래스에 대한 쿼터 지원 디자인 문서를 참고하길 바란다.
예제
리소스 쿼터를 사용하는 방법에 대한 자세한 예를 참고하길 바란다.
다음 내용
자세한 내용은 리소스쿼터 디자인 문서를 참고하길 바란다.
피드백
이 페이지가 도움이 되었나요?
피드백 감사합니다. 쿠버네티스 사용 방법에 대해서 구체적이고 답변 가능한 질문이 있다면, 다음 링크에서 질문하십시오. Stack Overflow. 원한다면 GitHub 리포지터리에 이슈를 열어서 문제 리포트 또는 개선 제안이 가능합니다..