
여러 사용자나 팀이 정해진 수의 노드로 클러스터를 공유할 때 한 팀이 공정하게 분배된 리소스보다 많은 리소스를 사용할 수 있다는 우려가 있다. 리소스 쿼터는 관리자가 이 문제를 해결하기 위한 도구이다.
ResourceQuota 오브젝트로 정의된 리소스 쿼터는 네임스페이스별 총 리소스 사용을 제한하는 제약 조건을 제공한다. 유형별로 네임스페이스에서 만들 수 있는 오브젝트 수와 해당 네임스페이스의 리소스가 사용할 수 있는 총 컴퓨트 리소스의 양을 제한할 수 있다.
403 FORBIDDEN으로 요청이 실패한다.cpu, memory와 같은 컴퓨트 리소스에 대해 네임스페이스에서 쿼터가 활성화된 경우 사용자는 해당값에 대한 요청 또는 제한을 지정해야 한다. 그렇지 않으면 쿼터 시스템이 파드 생성을 거부할 수 있다.네임스페이스와 쿼터를 사용하여 만들 수 있는 정책의 예는 다음과 같다.
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-a-quota
namespace: team-a
spec:
hard:
requests.cpu: "10"
requests.memory: 20Gi
limits.cpu: "16"
limits.memory: 32Gi
pods: "100"
services: "10"
secrets: "20"
이 리소스 쿼터는 team-a 네임스페이스에서 CPU 요청을 최대 10 코어, 메모리 요청을 최대 20Gi, CPU 제한을 최대 16 코어, 메모리 제한을 최대 32Gi로 제한한다. 또한, 최대 100개의 파드, 10개의 서비스, 20개의 secerts을 생성할 수 있다.
apiVersion: v1
kind: ResourceQuota
metadata:
name: testing-quota
namespace: testing
spec:
hard:
requests.cpu: "1"
requests.memory: 1Gi
limits.cpu: "2"
limits.memory: 2Gi
pods: "10"
services: "5"
secrets: "10"
testing 네임스페이스용 리소스 쿼터는 CPU 요청을 최대 1 코어, 메모리 요청을 최대 1Gi, CPU 제한을 최대 2 코어, 메모리 제한을 최대 2Gi로 제한한다. 이는 testing 환경의 리소스 사용을 제한하기 위한 것으로, 최대 10개의 파드, 5개의 서비스, 10개의 secerts을 생성할 수 있다.
지정된 네임스페이스에서 요청할 수 있는 총 컴퓨트 리소스 합을 제한할 수 있다.
다음과 같은 리소스 유형이 지원된다.
| 리소스 이름 | 설명 |
|---|---|
| limits.cpu | 터미널이 아닌 상태의 모든 파드에서 CPU 제한의 합은 이 값을 초과할 수 없음. |
| limits.memory | 터미널이 아닌 상태의 모든 파드에서 메모리 제한의 합은 이 값을 초과할 수 없음. |
| requests.cpu | 터미널이 아닌 상태의 모든 파드에서 CPU 요청의 합은 이 값을 초과할 수 없음. |
| requests.memory | 터미널이 아닌 상태의 모든 파드에서 메모리 요청의 합은 이 값을 초과할 수 없음. |
| hugepages- | 터미널 상태가 아닌 모든 파드에 걸쳐서, 지정된 사이즈의 휴즈 페이지 요청은 이 값을 초과하지 못함. |
| cpu | requests.cpu 와 같음. |
| memory | requests.memory 와 같음. |
쿠버네티스에서 리소스 쿼터를 설정할 때 "터미널이 아닌 상태의 모든 파드에서 CPU 제한의 합"이라는 제한을 사용하면, 실행 중이거나 실행을 기다리고 있는 파드의 CPU 사용량에 대한 총량을 제한할 수 있다.
지정된 네임스페이스에서 요청할 수 있는 총 스토리지 리소스 합을 제한할 수 있다.
또한 연관된 스토리지 클래스를 기반으로 스토리지 리소스 사용을 제한할 수 있다.
| 리소스 이름 | 설명 |
|---|---|
| requests.storage | 모든 퍼시스턴트 볼륨 클레임에서 스토리지 요청의 합은 이 값을 초과할 수 없음 |
| persistentvolumeclaims | 네임스페이스에 존재할 수 있는 총 퍼시스턴스 볼륨 클레임 수 |
| .storageclass.storage.k8s.io/requests.storage | storage-class-name과 관련된 모든 퍼시스턴트 볼륨 클레임에서 스토리지 요청의 합은 이 값을 초과할 수 없음 |
| .storageclass.storage.k8s.io/persistentvolumeclaims | 과 관련된 모든 퍼시스턴트 볼륨 클레임에서 네임스페이스에 존재할 수 있는 총 퍼시스턴스 볼륨 클레임 수 |
예를 들어, 운영자가 bronze 스토리지 클래스와 별도로 gold 스토리지 클래스를 사용하여 스토리지에 쿼터를 지정하려는 경우
운영자는 다음과 같이 쿼터를 정의할 수 있다.
gold.storageclass.storage.k8s.io/requests.storage: 500Gibronze.storageclass.storage.k8s.io/requests.storage: 100Gi릴리스 1.8에서는 로컬 임시 스토리지에 대한 쿼터 지원이 알파 기능으로 추가되었다.
| 리소스 이름 | 설명 |
|---|---|
| requests.ephemeral-storage | 네임스페이스의 모든 파드에서 로컬 임시 스토리지 요청의 합은 이 값을 초과할 수 없음. |
| limits.ephemeral-storage | 네임스페이스의 모든 파드에서 로컬 임시 스토리지 제한의 합은 이 값을 초과할 수 없음. |
| ephemeral-storage | requests.ephemeral-storage 와 같음. |
apiVersion: v1
kind: ResourceQuota
metadata:
name: storage-and-ephemeral-quota
namespace: example-namespace
spec:
hard:
# 전체 네임스페이스의 퍼시스턴트 볼륨 클레임(PVC) 요청 스토리지 합계 제한
requests.storage: "500Gi"
# 네임스페이스에서 허용되는 총 PVC 수
persistentvolumeclaims: "10"
# gold 스토리지 클래스에 대한 스토리지 요청 합계 제한
gold.storageclass.storage.k8s.io/requests.storage: "300Gi"
# gold 스토리지 클래스에 대한 PVC 수 제한
gold.storageclass.storage.k8s.io/persistentvolumeclaims: "5"
# bronze 스토리지 클래스에 대한 스토리지 요청 합계 제한
bronze.storageclass.storage.k8s.io/requests.storage: "200Gi"
# bronze 스토리지 클래스에 대한 PVC 수 제한
bronze.storageclass.storage.k8s.io/persistentvolumeclaims: "5"
# 네임스페이스의 모든 파드에서 로컬 임시 스토리지 요청 합계 제한
requests.ephemeral-storage: "100Gi"
# 네임스페이스의 모든 파드에서 로컬 임시 스토리지 제한 합계 제한
limits.ephemeral-storage: "200Gi"
이 파일은 example-namespace 네임스페이스 내에서 스토리지 사용에 대한 다양한 제한을 설정한다.
여기에는 전체 스토리지 요청, 스토리지 클래스별 스토리지 요청, 전체 및 스토리지 클래스별 퍼시스턴트 볼륨 클레임(PVC) 수, 그리고 임시 스토리지에 대한 요청 및 제한이 포함된다.
다음 구문을 사용하여 모든 표준 네임스페이스 처리된(namespaced) 리소스 유형에 대한 특정 리소스 전체 수에 대하여 쿼터를 지정할 수 있다.
count/<resource>.<group>count/<resource>다음은 사용자가 오브젝트 수 쿼터 아래에 배치하려는 리소스 셋의 예이다.
count/persistentvolumeclaimscount/servicescount/secretscount/configmapscount/replicationcontrollerscount/deployments.appscount/replicasets.appscount/statefulsets.appscount/jobs.batchcount/cronjobs.batch사용자 정의 리소스를 위해 동일한 구문을 사용할 수 있다.
예를 들어 example.com API 그룹에서 widgets 사용자 정의 리소스에 대한 쿼터를 생성하려면 count/widgets.example.com을 사용한다.
count/* 리소스 쿼터를 사용할 때 서버 스토리지 영역에 있다면 오브젝트는 쿼터에 대해 과금된다.
이러한 유형의 쿼터는 스토리지 리소스 고갈을 방지하는 데 유용하다.
예를 들어, 크기가 큰 서버에서 시크릿 수에 쿼터를 지정할 수 있다. 클러스터에 시크릿이 너무 많으면 실제로 서버와 컨트롤러가 시작되지 않을 수 있다.
잘못 구성된 크론 잡으로부터의 보호를 위해 잡의 쿼터를 설정할 수 있다.
네임스페이스 내에서 너무 많은 잡을 생성하는 크론 잡은 서비스 거부를 유발할 수 있다.
또한 제한된 리소스 셋에 대해서 일반 오브젝트 수(generic object count) 쿼터를 적용하는 것도 가능하다. 다음 유형이 지원된다.
| 리소스 이름 | 설명 |
|---|---|
| configmaps | 네임스페이스에 존재할 수 있는 총 컨피그맵 수 |
| persistentvolumeclaims | 네임스페이스에 존재할 수 있는 총 퍼시스턴스 볼륨 클레임 수 |
| pods | 네임스페이스에 존재할 수 있는 터미널이 아닌 상태의 파드의 총 수. .status.phase in (Failed, Succeeded)가 true인 경우 파드는 터미널 상태임 |
| replicationcontrollers | 네임스페이스에 존재할 수 있는 총 레플리케이션컨트롤러 수 |
| resourcequotas | 네임스페이스에 존재할 수 있는 총 리소스쿼터 수 |
| services | 네임스페이스에 존재할 수 있는 총 서비스 수 |
| services.loadbalancers | 네임스페이스에 존재할 수 있는 LoadBalancer 유형의 총 서비스 수 |
| services.nodeports | 네임스페이스에 존재할 수 있는 NodePort 유형의 총 서비스 수 |
| secrets | 네임스페이스에 존재할 수 있는 총 시크릿 수 |
예를 들어, pods 쿼터는 터미널이 아닌 단일 네임스페이스에서 생성된 pods 수를 계산하고 최댓값을 적용한다.
사용자가 작은 파드를 많이 생성하여 클러스터의 파드 IP 공급이 고갈되는 경우를 피하기 위해 네임스페이스에 pods 쿼터를 설정할 수 있다.
apiVersion: v1
kind: ResourceQuota
metadata:
name: object-counts-quota
namespace: example-namespace
spec:
hard:
# 코어 그룹 리소스
count/persistentvolumeclaims: "10"
count/services: "10"
count/secrets: "20"
count/configmaps: "10"
count/replicationcontrollers: "5"
count/pods: "50"
# 서비스 유형별 쿼터
count/services.loadbalancers: "2"
count/services.nodeports: "4"
# 코어가 아닌 그룹 리소스
count/deployments.apps: "10"
count/replicasets.apps: "20"
count/statefulsets.apps: "10"
count/jobs.batch: "15"
count/cronjobs.batch: "10"
# 사용자 정의 리소스 (예시)
count/widgets.example.com: "25"
위의 예시에서는 다음과 같은 리소스 쿼터를 설정한다:
widgets라는 사용자 정의 리소스에 대한 오브젝트 수 제한.네임스페이스 내에서 리소스 쿼터를 설정함으로써, 관리자는 리소스 고갈로부터 시스템을 보호할 수 있다.
기능 상태: Kubernetes v1.17 [stable]
특정 우선 순위로 파드를 생성할 수 있다. 쿼터 스펙의 scopeSelector 필드를 사용하여 파드의 우선 순위에 따라 파드의 시스템 리소스 사용을 제어할 수 있다.
쿼터 스펙의 scopeSelector가 파드를 선택한 경우에만 쿼터가 일치하고 사용된다.
scopeSelector 필드를 사용하여 우선 순위 클래스의 쿼터 범위를 지정하면, 쿼터 오브젝트는 다음의 리소스만 추적하도록 제한된다.
podscpumemoryephemeral-storagelimits.cpulimits.memorylimits.ephemeral-storagerequests.cpurequests.memoryrequests.ephemeral-storage이 예에서는 쿼터 오브젝트를 생성하여 특정 우선 순위의 파드와 일치시킨다. 예제는 다음과 같이 작동한다.
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-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