First Korean l10n Work For Release 1.18
* Update to Outdated files in the dev-1.18-ko.1 branch (#19886) * Translate reference/glossary/service-catalog.md in Korean (#20055) * Translate storage/dynamic-provisioning.md in Korean (#19952) * Translate extend-kubernetes/extend-cluster.md in Korean (#20031) * Translate storage/persistent-volumes.md in Korean (#19906) * Translate partners/_index.html in Korean (#19967) * Translate extend-kubernetes/operator.md in Korean (#20037) * Translate assign-pods-nodes to Korean (#20035) * Translate scheduling/kube-scheduler.md in Korean (#19879) * Translate concepts/containers/overview in Korean (#19885) * Translate policy/pod-security-policy.md in Korean (#19922) * Translate policy/limit-range.md in Korean (#19912) * Translate policy/resource-quotas.md in Korean (#19931) * Translate extend-kubernetes/api-extension/custom-resources.md in Korean (#20093) * Translate reference/glossary/managed-service.md in Korean (#20150) Co-authored-by: Jerry Park <jaehwa@gmail.com> Co-authored-by: heechang lee <bluefriday86@gmail.com> Co-authored-by: Yuk, Yongsu <ysyukr@gmail.com> Co-authored-by: Seokho Son <shsongist@gmail.com> Co-authored-by: coolguyhong <podolsmith@naver.com> Co-authored-by: santachopa <santachopa@naver.com> Co-authored-by: Jesang Myung <jesang.myung@gmail.com> Co-authored-by: June Yi <june.yi@samsung.com>
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "정책"
|
||||
weight: 90
|
||||
---
|
||||
@@ -0,0 +1,388 @@
|
||||
---
|
||||
title: 리밋 레인지(Limit Range)
|
||||
content_template: templates/concept
|
||||
weight: 10
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
|
||||
기본적으로 컨테이너는 쿠버네티스 클러스터에서 무제한 [컴퓨팅 리소스](/docs/user-guide/compute-resources)로 실행된다.
|
||||
리소스 쿼터을 사용하면 클러스터 관리자는 네임스페이스별로 리소스 사용과 생성을 제한할 수 있다.
|
||||
네임스페이스 내에서 파드나 컨테이너는 네임스페이스의 리소스 쿼터에 정의된 만큼의 CPU와 메모리를 사용할 수 있다. 하나의 파드 또는 컨테이너가 사용 가능한 모든 리소스를 독점할 수 있다는 우려가 있다. 리밋레인지는 네임스페이스에서 리소스 할당(파드 또는 컨테이너)을 제한하는 정책이다.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture body %}}
|
||||
|
||||
_리밋레인지_ 는 다음과 같은 제약 조건을 제공한다.
|
||||
|
||||
- 네임스페이스에서 파드 또는 컨테이너별 최소 및 최대 컴퓨팅 리소스 사용량을 지정한다.
|
||||
- 네임스페이스에서 스토리지클래스별 최소 및 최대 스토리지 요청을 지정한다.
|
||||
- 네임스페이스에서 리소스에 대한 요청과 제한 사이의 비율을 지정한다.
|
||||
- 네임스페이스에서 컴퓨팅 리소스에 대한 기본 요청/제한을 설정하고 런타임에 있는 컨테이너에 자동으로 설정한다.
|
||||
|
||||
## 리밋레인지 활성화
|
||||
|
||||
많은 쿠버네티스 배포판에 리밋레인지 지원이 기본적으로 활성화되어 있다. apiserver `--enable-admission-plugins=` 플래그의 인수 중 하나로 `LimitRanger` 어드미션 컨트롤러가 있는 경우 활성화된다.
|
||||
|
||||
해당 네임스페이스에 리밋레인지 오브젝트가 있는 경우 특정 네임스페이스에 리밋레인지가 지정된다.
|
||||
|
||||
리밋레인지 오브젝트의 이름은 유효한 [DNS 서브도메인 이름](/ko/docs/concepts/overview/working-with-objects/names/#dns-서브도메인-이름)이어야한다.
|
||||
|
||||
### 범위 제한의 개요
|
||||
|
||||
- 관리자는 하나의 네임스페이스에 하나의 `LimitRange`를 만든다.
|
||||
- 사용자는 네임스페이스에서 파드, 컨테이너 및 퍼시스턴트볼륨클레임과 같은 리소스를 생성한다.
|
||||
- `LimitRanger` 어드미션 컨트롤러는 컴퓨팅 리소스 요청 사항을 설정하지 않은 모든 파드와 컨테이너에 대한 기본값과 제한을 지정하고 네임스페이스의 리밋레인지에 정의된 리소스의 최소, 최대 및 비율을 초과하지 않도록 사용량을 추적한다.
|
||||
- 리밋레인지 제약 조건을 위반하는 리소스(파드, 컨테이너, 퍼시스턴트볼륨클레임)를 생성하거나 업데이트하는 경우 HTTP 상태 코드 `403 FORBIDDEN` 및 위반된 제약 조건을 설명하는 메시지와 함께 API 서버에 대한 요청이 실패한다.
|
||||
- `cpu`, `memory`와 같은 컴퓨팅 리소스의 네임스페이스에서 리밋레인지가 활성화된 경우 사용자는 해당 값에 대한 요청 또는 제한을 지정해야 한다. 그렇지 않으면 시스템에서 파드 생성이 거부될 수 있다.
|
||||
- 리밋레인지 유효성 검사는 파드 실행 단계가 아닌 파드 어드미션 단계에서만 발생한다.
|
||||
|
||||
범위 제한을 사용하여 생성할 수 있는 정책의 예는 다음과 같다.
|
||||
|
||||
- 용량이 8GiB RAM과 16 코어인 2 노드 클러스터에서 네임스페이스의 파드를 제한하여 CPU의 최대 제한이 500m인 CPU 100m를 요청하고 메모리의 최대 제한이 600M인 메모리 200Mi를 요청하라.
|
||||
- 스펙에 CPU 및 메모리 요청없이 시작된 컨테이너에 대해 기본 CPU 제한 및 요청을 150m로, 메모리 기본 요청을 300Mi로 정의하라.
|
||||
|
||||
네임스페이스의 총 제한이 파드/컨테이너의 제한 합보다 작은 경우 리소스에 대한 경합이 있을 수 있다.
|
||||
이 경우 컨테이너 또는 파드가 생성되지 않는다.
|
||||
|
||||
경합이나 리밋레인지 변경은 이미 생성된 리소스에 영향을 미치지 않는다.
|
||||
|
||||
## 컨테이너 컴퓨팅 리소스 제한
|
||||
|
||||
다음 절에서는 컨테이너 레벨에서 작동하는 리밋레인지 생성에 대해 설명한다.
|
||||
4개의 컨테이너가 있는 파드가 먼저 생성된다. 파드 내의 각 컨테이너에는 특정 `spec.resource` 구성이 있다.
|
||||
파드 내의 각 컨테이너는 `LimitRanger` 어드미션 컨트롤러에 의해 다르게 처리된다.
|
||||
|
||||
다음 kubectl 명령을 사용하여 네임스페이스 `limitrange-demo`를 생성한다.
|
||||
|
||||
```shell
|
||||
kubectl create namespace limitrange-demo
|
||||
```
|
||||
|
||||
kubectl 명령에서 네임스페이스 대상인 `limitrange-demo`를 빠트리지 않으려면 다음 명령으로 컨텍스트를 변경한다.
|
||||
|
||||
```shell
|
||||
kubectl config set-context --current --namespace=limitrange-demo
|
||||
```
|
||||
|
||||
다음은 리밋레인지 오브젝트의 구성 파일이다.
|
||||
{{< codenew file="admin/resource/limit-mem-cpu-container.yaml" >}}
|
||||
|
||||
이 오브젝트는 컨테이너에 적용할 최소 및 최대 CPU/메모리 제한, 기본 CPU/메모리 요청과 CPU/메모리 리소스에 대한 기본 제한을 정의한다.
|
||||
|
||||
다음 kubectl 명령을 사용하여 `limit-mem-cpu-per-container` 리밋레인지를 생성한다.
|
||||
|
||||
```shell
|
||||
kubectl create -f https://k8s.io/examples/admin/resource/limit-mem-cpu-container.yaml
|
||||
```
|
||||
|
||||
```shell
|
||||
kubectl describe limitrange/limit-mem-cpu-per-container
|
||||
```
|
||||
|
||||
```shell
|
||||
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
|
||||
---- -------- --- --- --------------- ------------- -----------------------
|
||||
Container cpu 100m 800m 110m 700m -
|
||||
Container memory 99Mi 1Gi 111Mi 900Mi -
|
||||
```
|
||||
다음은 4개의 컨테이너가 포함된 파드의 구성 파일로 리밋레인지 기능을 보여준다.
|
||||
{{< codenew file="admin/resource/limit-range-pod-1.yaml" >}}
|
||||
|
||||
`busybox1` 파드를 생성한다.
|
||||
|
||||
```shell
|
||||
kubectl apply -f https://k8s.io/examples/admin/resource/limit-range-pod-1.yaml
|
||||
```
|
||||
|
||||
### 유효한 CPU/메모리 요청과 제한이 있는 컨테이너 스펙
|
||||
|
||||
`busybox-cnt01`의 리소스 구성을 보자.
|
||||
|
||||
```shell
|
||||
kubectl get po/busybox1 -o json | jq ".spec.containers[0].resources"
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"limits": {
|
||||
"cpu": "500m",
|
||||
"memory": "200Mi"
|
||||
},
|
||||
"requests": {
|
||||
"cpu": "100m",
|
||||
"memory": "100Mi"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- `busybox` 파드 내의 `busybox-cnt01` 컨테이너는 `requests.cpu=100m`와 `requests.memory=100Mi`로 정의됐다.
|
||||
- `100m <= 500m <= 800m`, 컨테이너 CPU 제한(500m)은 승인된 CPU 리밋레인지 내에 있다.
|
||||
- `99Mi <= 200Mi <= 1Gi`, 컨테이너 메모리 제한(200Mi)은 승인된 메모리 리밋레인지 내에 있다.
|
||||
- CPU/메모리에 대한 요청/제한 비율 검증이 없으므로 컨테이너가 유효하며 생성되었다.
|
||||
|
||||
|
||||
### 유효한 CPU/메모리 요청은 있지만 제한이 없는 컨테이너 스펙
|
||||
|
||||
`busybox-cnt02`의 리소스 구성을 보자.
|
||||
|
||||
```shell
|
||||
kubectl get po/busybox1 -o json | jq ".spec.containers[1].resources"
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"limits": {
|
||||
"cpu": "700m",
|
||||
"memory": "900Mi"
|
||||
},
|
||||
"requests": {
|
||||
"cpu": "100m",
|
||||
"memory": "100Mi"
|
||||
}
|
||||
}
|
||||
```
|
||||
- `busybox1` 파드 내의 `busybox-cnt02` 컨테이너는 `requests.cpu=100m`와 `requests.memory=100Mi`를 정의했지만 CPU와 메모리에 대한 제한은 없다.
|
||||
- 컨테이너에 제한 섹션이 없다. `limit-mem-cpu-per-container` 리밋레인지 오브젝트에 정의된 기본 제한은 `limits.cpu=700mi` 및 `limits.memory=900Mi`로 이 컨테이너에 설정된다.
|
||||
- `100m <= 700m <= 800m`, 컨테이너 CPU 제한(700m)이 승인된 CPU 제한 범위 내에 있다.
|
||||
- `99Mi <= 900Mi <= 1Gi`, 컨테이너 메모리 제한(900Mi)이 승인된 메모리 제한 범위 내에 있다.
|
||||
- 요청/제한 비율이 설정되지 않았으므로 컨테이너가 유효하며 생성되었다.
|
||||
|
||||
### 유효한 CPU/메모리 제한은 있지만 요청은 없는 컨테이너 스펙
|
||||
|
||||
`busybox-cnt03`의 리소스 구성을 보자.
|
||||
|
||||
```shell
|
||||
kubectl get po/busybox1 -o json | jq ".spec.containers[2].resources"
|
||||
```
|
||||
```json
|
||||
{
|
||||
"limits": {
|
||||
"cpu": "500m",
|
||||
"memory": "200Mi"
|
||||
},
|
||||
"requests": {
|
||||
"cpu": "500m",
|
||||
"memory": "200Mi"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- `busybox1` 파드 내의 `busybox-cnt03` 컨테이너는 `limits.cpu=500m`와 `limits.memory=200Mi`를 정의했지만 CPU와 메모리에 대한 요청은 없다.
|
||||
- 컨테이너에 요청 섹션이 정의되지 않았다. `limit-mem-cpu-per-container` 리밋레인지에 정의된 기본 요청은 제한 섹션을 채우는 데 사용되지 않지만 컨테이너에 의해 정의된 제한은 `limits.cpu=500m` 및 `limits.memory=200Mi`로 설정된다.
|
||||
- `100m <= 500m <= 800m`, 컨테이너 CPU 제한(500m)은 승인된 CPU 제한 범위 내에 있다.
|
||||
- `99Mi <= 200Mi <= 1Gi`, 컨테이너 메모리 제한(200Mi)은 승인된 메모리 제한 범위 내에 있다.
|
||||
- 요청/제한 비율이 설정되지 않았으므로 컨테이너가 유효하며 생성되었다.
|
||||
|
||||
### CPU/메모리 요청/제한이 없는 컨테이너 스펙
|
||||
|
||||
`busybox-cnt04`의 리소스 구성을 보자.
|
||||
|
||||
```shell
|
||||
kubectl get po/busybox1 -o json | jq ".spec.containers[3].resources"
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"limits": {
|
||||
"cpu": "700m",
|
||||
"memory": "900Mi"
|
||||
},
|
||||
"requests": {
|
||||
"cpu": "110m",
|
||||
"memory": "111Mi"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- `busybox1`의 `busybox-cnt04` 컨테이너는 제한이나 요청을 정의하지 않았다.
|
||||
- 컨테이너는 제한 섹션을 정의하지 않으며 `limit-mem-cpu-per-container` 리밋레인지에 정의된 기본 제한은 `limit.cpu=700m` 및 `limits.memory=900Mi`로 설정된다.
|
||||
- 컨테이너는 요청 섹션을 정의하지 않으며 `limit-mem-cpu-per-container` 리밋레인지에 정의된 defaultRequest는 `requests.cpu=110m` 및 `requests.memory=111Mi`로 설정된다.
|
||||
- `100m <= 700m <= 800m`, 컨테이너 CPU 제한(700m)은 승인된 CPU 제한 범위 내에 있다.
|
||||
- `99Mi <= 900Mi <= 1Gi`, 컨테이너 메모리 제한(900Mi)은 승인된 메모리 제한 범위 내에 있다.
|
||||
- 요청/제한 비율이 설정되지 않았으므로 컨테이너가 유효하며 생성되었다.
|
||||
|
||||
`busybox` 파드에 정의된 모든 컨테이너는 리밋레인지 유효성 검사를 통과했으므로 이 파드는 유효하며 네임스페이스에서 생성된다.
|
||||
|
||||
## 파드 컴퓨팅 리소스 제한
|
||||
|
||||
다음 절에서는 파드 레벨에서 리소스를 제한하는 방법에 대해 설명한다.
|
||||
|
||||
{{< codenew file="admin/resource/limit-mem-cpu-pod.yaml" >}}
|
||||
|
||||
`busybox1` 파드를 삭제하지 않고 `limitrange-demo` 네임스페이스에 `limit-mem-cpu-pod` 리밋레인지를 생성한다.
|
||||
|
||||
```shell
|
||||
kubectl apply -f https://k8s.io/examples/admin/resource/limit-mem-cpu-pod.yaml
|
||||
```
|
||||
리밋레인지가 생성되고 파드별로 CPU가 2 코어로, 메모리가 2Gi로 제한된다.
|
||||
|
||||
```shell
|
||||
limitrange/limit-mem-cpu-per-pod created
|
||||
```
|
||||
|
||||
다음 kubectl 명령을 사용하여 `limit-mem-cpu-per-pod` 리밋레인지 오브젝트의 정보를 나타낸다.
|
||||
|
||||
```shell
|
||||
kubectl describe limitrange/limit-mem-cpu-per-pod
|
||||
```
|
||||
|
||||
```shell
|
||||
Name: limit-mem-cpu-per-pod
|
||||
Namespace: limitrange-demo
|
||||
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
|
||||
---- -------- --- --- --------------- ------------- -----------------------
|
||||
Pod cpu - 2 - - -
|
||||
Pod memory - 2Gi - - -
|
||||
```
|
||||
|
||||
이제 `busybox2` 파드를 생성한다.
|
||||
|
||||
{{< codenew file="admin/resource/limit-range-pod-2.yaml" >}}
|
||||
|
||||
```shell
|
||||
kubectl apply -f https://k8s.io/examples/admin/resource/limit-range-pod-2.yaml
|
||||
```
|
||||
|
||||
`busybox2` 파드 정의는 `busybox1`과 동일하지만 이제 파드 리소스가 제한되어 있으므로 오류가 보고된다.
|
||||
|
||||
```shell
|
||||
Error from server (Forbidden): error when creating "limit-range-pod-2.yaml": pods "busybox2" is forbidden: [maximum cpu usage per Pod is 2, but limit is 2400m., maximum memory usage per Pod is 2Gi, but limit is 2306867200.]
|
||||
```
|
||||
|
||||
```shell
|
||||
kubectl get po/busybox1 -o json | jq ".spec.containers[].resources.limits.memory"
|
||||
"200Mi"
|
||||
"900Mi"
|
||||
"200Mi"
|
||||
"900Mi"
|
||||
```
|
||||
|
||||
해당 컨테이너의 총 메모리 제한이 리밋레인지에 정의된 제한보다 크므로 `busybox2` 파드는 클러스터에서 허용되지 않는다.
|
||||
`busyRange1`은 리밋레인지를 생성하기 전에 클러스터에서 생성되고 허용되므로 제거되지 않는다.
|
||||
|
||||
## 스토리지 리소스 제한
|
||||
|
||||
리밋레인지를 사용하여 네임스페이스에서 각 퍼시스턴트볼륨클레임이 요청할 수 있는 [스토리지 리소스](/ko/docs/concepts/storage/persistent-volumes/)의 최소 및 최대 크기를 지정할 수 있다.
|
||||
|
||||
{{< codenew file="admin/resource/storagelimits.yaml" >}}
|
||||
|
||||
`kubectl create`를 사용하여 YAML을 적용한다.
|
||||
|
||||
```shell
|
||||
kubectl create -f https://k8s.io/examples/admin/resource/storagelimits.yaml
|
||||
```
|
||||
|
||||
```shell
|
||||
limitrange/storagelimits created
|
||||
```
|
||||
|
||||
생성된 오브젝트의 정보를 나타낸다.
|
||||
|
||||
```shell
|
||||
kubectl describe limits/storagelimits
|
||||
```
|
||||
|
||||
출력은 다음과 같다.
|
||||
|
||||
```shell
|
||||
Name: storagelimits
|
||||
Namespace: limitrange-demo
|
||||
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
|
||||
---- -------- --- --- --------------- ------------- -----------------------
|
||||
PersistentVolumeClaim storage 1Gi 2Gi - - -
|
||||
```
|
||||
|
||||
{{< codenew file="admin/resource/pvc-limit-lower.yaml" >}}
|
||||
|
||||
```shell
|
||||
kubectl create -f https://k8s.io/examples/admin/resource/pvc-limit-lower.yaml
|
||||
```
|
||||
|
||||
`requests.storage`가 리밋레인지의 Min 값보다 낮은 PVC를 만드는 동안 서버에서 발생하는 오류는 다음과 같다.
|
||||
|
||||
```shell
|
||||
Error from server (Forbidden): error when creating "pvc-limit-lower.yaml": persistentvolumeclaims "pvc-limit-lower" is forbidden: minimum storage usage per PersistentVolumeClaim is 1Gi, but request is 500Mi.
|
||||
```
|
||||
|
||||
`requests.storage`가 리밋레인지의 Max 값보다 큰 경우에도 동일한 동작이 나타난다.
|
||||
|
||||
{{< codenew file="admin/resource/pvc-limit-greater.yaml" >}}
|
||||
|
||||
```shell
|
||||
kubectl create -f https://k8s.io/examples/admin/resource/pvc-limit-greater.yaml
|
||||
```
|
||||
|
||||
```shell
|
||||
Error from server (Forbidden): error when creating "pvc-limit-greater.yaml": persistentvolumeclaims "pvc-limit-greater" is forbidden: maximum storage usage per PersistentVolumeClaim is 2Gi, but request is 5Gi.
|
||||
```
|
||||
|
||||
## 제한/요청 비율
|
||||
|
||||
`LimitRangeSpec`에 `LimitRangeItem.maxLimitRequestRatio`가 지정되어 있으면 명명된 리소스는 제한을 요청으로 나눈 값이 열거된 값보다 작거나 같은 0이 아닌 값을 요청과 제한 모두 가져야 한다.
|
||||
|
||||
다음의 리밋레인지는 메모리 제한이 네임스페이스의 모든 파드에 대한 메모리 요청 양의 최대 두 배가 되도록 한다.
|
||||
|
||||
{{< codenew file="admin/resource/limit-memory-ratio-pod.yaml" >}}
|
||||
|
||||
```shell
|
||||
kubectl apply -f https://k8s.io/examples/admin/resource/limit-memory-ratio-pod.yaml
|
||||
```
|
||||
|
||||
다음의 kubectl 명령으로 `limit-memory-ratio-pod` 리밋레인지의 정보를 나타낸다.
|
||||
|
||||
```shell
|
||||
kubectl describe limitrange/limit-memory-ratio-pod
|
||||
```
|
||||
|
||||
```shell
|
||||
Name: limit-memory-ratio-pod
|
||||
Namespace: limitrange-demo
|
||||
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
|
||||
---- -------- --- --- --------------- ------------- -----------------------
|
||||
Pod memory - - - - 2
|
||||
```
|
||||
|
||||
|
||||
`requests.memory=100Mi` 및 `limits.memory=300Mi`로 파드를 생성한다.
|
||||
|
||||
{{< codenew file="admin/resource/limit-range-pod-3.yaml" >}}
|
||||
|
||||
```shell
|
||||
kubectl apply -f https://k8s.io/examples/admin/resource/limit-range-pod-3.yaml
|
||||
```
|
||||
|
||||
위 예에서 제한/요청 비율(`3`)이 `limit-memory-ratio-pod` 리밋레인지에 지정된 제한 비율(`2`)보다 커서 파드 생성에 실패했다.
|
||||
|
||||
```
|
||||
Error from server (Forbidden): error when creating "limit-range-pod-3.yaml": pods "busybox3" is forbidden: memory max limit to request ratio per Pod is 2, but provided ratio is 3.000000.
|
||||
```
|
||||
|
||||
## 정리
|
||||
|
||||
모든 리소스를 해제하려면 `limitrange-demo` 네임스페이스를 삭제한다.
|
||||
|
||||
```shell
|
||||
kubectl delete ns limitrange-demo
|
||||
```
|
||||
다음 명령을 사용하여 컨텍스트를 `default` 네임스페이스로 변경한다.
|
||||
|
||||
```shell
|
||||
kubectl config set-context --current --namespace=default
|
||||
```
|
||||
|
||||
## 예제
|
||||
|
||||
- [네임스페이스별 컴퓨팅 리소스를 제한하는 방법에 대한 튜토리얼](/docs/tasks/administer-cluster/manage-resources/cpu-constraint-namespace/)을 참고하길 바란다.
|
||||
- [스토리지 사용을 제한하는 방법](/docs/tasks/administer-cluster/limit-storage-consumption/#limitrange-to-limit-requests-for-storage)을 확인하라.
|
||||
- [네임스페이스별 쿼터에 대한 자세한 예](/docs/tasks/administer-cluster/quota-memory-cpu-namespace/)를 참고하길 바란다.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture whatsnext %}}
|
||||
|
||||
보다 자세한 내용은 [LimitRanger 설계 문서](https://git.k8s.io/community/contributors/design-proposals/resource-management/admission_control_limit_range.md)를 참고하길 바란다.
|
||||
|
||||
{{% /capture %}}
|
||||
@@ -0,0 +1,635 @@
|
||||
---
|
||||
title: 파드 시큐리티 폴리시
|
||||
content_template: templates/concept
|
||||
weight: 20
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
|
||||
{{< feature-state state="beta" >}}
|
||||
|
||||
파드 시큐리티 폴리시를 사용하면 파드 생성 및 업데이트에 대한 세분화된 권한을
|
||||
부여할 수 있다.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture body %}}
|
||||
|
||||
## 파드 시큐리티 폴리시란?
|
||||
|
||||
_Pod Security Policy_ 는 파드 명세의 보안 관련 측면을 제어하는 클러스터-레벨의
|
||||
리소스이다. [파드시큐리티폴리시](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podsecuritypolicy-v1beta1-policy) 오브젝트는
|
||||
관련 필드에 대한 기본값뿐만 아니라 시스템에 적용하기 위해 파드가 실행해야만 하는
|
||||
조건 셋을 정의한다. 관리자는
|
||||
다음을 제어할 수 있다.
|
||||
|
||||
| 제어 측면 | 필드 이름 |
|
||||
| ----------------------------------------------------| ------------------------------------------- |
|
||||
| 특권을 가진(privileged) 컨테이너의 실행 | [`privileged`](#privileged) |
|
||||
| 호스트 네임스페이스의 사용 | [`hostPID`, `hostIPC`](#host-namespaces) |
|
||||
| 호스트 네트워킹과 포트의 사용 | [`hostNetwork`, `hostPorts`](#host-namespaces) |
|
||||
| 볼륨 유형의 사용 | [`volumes`](#volumes-and-file-systems) |
|
||||
| 호스트 파일시스템의 사용 | [`allowedHostPaths`](#volumes-and-file-systems) |
|
||||
| FlexVolume 드라이버의 화이트리스트 | [`allowedFlexVolumes`](#flexvolume-drivers) |
|
||||
| 파드 볼륨을 소유한 FSGroup 할당 | [`fsGroup`](#volumes-and-file-systems) |
|
||||
| 읽기 전용 루트 파일시스템 사용 필요 | [`readOnlyRootFilesystem`](#volumes-and-file-systems) |
|
||||
| 컨테이너의 사용자 및 그룹 ID | [`runAsUser`, `runAsGroup`, `supplementalGroups`](#users-and-groups) |
|
||||
| 루트 특권으로의 에스컬레이션 제한 | [`allowPrivilegeEscalation`, `defaultAllowPrivilegeEscalation`](#privilege-escalation) |
|
||||
| 리눅스 기능 | [`defaultAddCapabilities`, `requiredDropCapabilities`, `allowedCapabilities`](#capabilities) |
|
||||
| 컨테이너의 SELinux 컨텍스트 | [`seLinux`](#selinux) |
|
||||
| 컨테이너에 허용된 Proc 마운트 유형 | [`allowedProcMountTypes`](#allowedprocmounttypes) |
|
||||
| 컨테이너가 사용하는 AppArmor 프로파일 | [어노테이션](#apparmor) |
|
||||
| 컨테이너가 사용하는 seccomp 프로파일 | [어노테이션](#seccomp) |
|
||||
| 컨테이너가 사용하는 sysctl 프로파일 | [`forbiddenSysctls`,`allowedUnsafeSysctls`](#sysctl) |
|
||||
|
||||
|
||||
## 파드 시큐리티 폴리시 활성화
|
||||
|
||||
파드 시큐리티 폴리시 제어는 선택 사항(하지만 권장함)인
|
||||
[어드미션
|
||||
컨트롤러](/docs/reference/access-authn-authz/admission-controllers/#podsecuritypolicy)로
|
||||
구현된다. [어드미션 컨트롤러 활성화](/docs/reference/access-authn-authz/admission-controllers/#how-do-i-turn-on-an-admission-control-plug-in)하면
|
||||
파드시큐리티폴리시가 적용되지만,
|
||||
정책을 승인하지 않고 활성화하면 클러스터에
|
||||
**파드가 생성되지 않는다.**
|
||||
|
||||
파드 시큐리티 폴리시 API(`policy/v1beta1/podsecuritypolicy`)는
|
||||
어드미션 컨트롤러와 독립적으로 활성화되므로 기존 클러스터의 경우
|
||||
어드미션 컨트롤러를 활성화하기 전에 정책을 추가하고 권한을
|
||||
부여하는 것이 좋다.
|
||||
|
||||
## 정책 승인
|
||||
|
||||
파드시큐리티폴리시 리소스가 생성되면 아무 것도 수행하지 않는다. 이를 사용하려면
|
||||
요청 사용자 또는 대상 파드의
|
||||
[서비스 어카운트](/docs/tasks/configure-pod-container/configure-service-account/)는
|
||||
정책에서 `use` 동사를 허용하여 정책을 사용할 권한이 있어야 한다.
|
||||
|
||||
대부분의 쿠버네티스 파드는 사용자가 직접 만들지 않는다. 대신 일반적으로
|
||||
컨트롤러 관리자를 통해
|
||||
[디플로이먼트](/ko/docs/concepts/workloads/controllers/deployment/),
|
||||
[레플리카셋](/ko/docs/concepts/workloads/controllers/replicaset/), 또는 기타
|
||||
템플릿 컨트롤러의 일부로 간접적으로 생성된다. 컨트롤러에 정책에 대한 접근 권한을 부여하면
|
||||
해당 컨트롤러에 의해 생성된 *모든* 파드에 대한 접근 권한이 부여되므로 정책을 승인하는
|
||||
기본 방법은 파드의 서비스 어카운트에 대한 접근 권한을
|
||||
부여하는 것이다([예](#다른-파드를-실행) 참고).
|
||||
|
||||
### RBAC을 통한 방법
|
||||
|
||||
[RBAC](/docs/reference/access-authn-authz/rbac/)은 표준 쿠버네티스 권한 부여 모드이며,
|
||||
정책 사용 권한을 부여하는 데 쉽게 사용할 수 있다.
|
||||
|
||||
먼저, `Role` 또는 `ClusterRole`은 원하는 정책을 `use` 하려면 접근 권한을 부여해야 한다.
|
||||
접근 권한을 부여하는 규칙은 다음과 같다.
|
||||
|
||||
```yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: <role name>
|
||||
rules:
|
||||
- apiGroups: ['policy']
|
||||
resources: ['podsecuritypolicies']
|
||||
verbs: ['use']
|
||||
resourceNames:
|
||||
- <list of policies to authorize>
|
||||
```
|
||||
|
||||
그런 다음 `(Cluster)Role`이 승인된 사용자에게 바인딩된다.
|
||||
|
||||
```yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: <binding name>
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: <role name>
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
subjects:
|
||||
# Authorize specific service accounts:
|
||||
- kind: ServiceAccount
|
||||
name: <authorized service account name>
|
||||
namespace: <authorized pod namespace>
|
||||
# Authorize specific users (not recommended):
|
||||
- kind: User
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
name: <authorized user name>
|
||||
```
|
||||
|
||||
`RoleBinding`(`ClusterRoleBinding` 아님)을 사용하는 경우, 바인딩과 동일한 네임스페이스에서
|
||||
실행되는 파드에 대해서만 사용 권한을 부여한다. 네임스페이스에서 실행되는 모든 파드에 접근 권한을
|
||||
부여하기 위해 시스템 그룹과 쌍을 이룰 수 있다.
|
||||
```yaml
|
||||
# Authorize all service accounts in a namespace:
|
||||
- kind: Group
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
name: system:serviceaccounts
|
||||
# Or equivalently, all authenticated users in a namespace:
|
||||
- kind: Group
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
name: system:authenticated
|
||||
```
|
||||
|
||||
RBAC 바인딩에 대한 자세한 예는,
|
||||
[역할 바인딩 예제](/docs/reference/access-authn-authz/rbac#role-binding-examples)를 참고하길 바란다.
|
||||
파드시큐리티폴리시 인증에 대한 전체 예제는
|
||||
[아래](#예제)를 참고하길 바란다.
|
||||
|
||||
|
||||
### 문제 해결
|
||||
|
||||
- [컨트롤러 관리자](/docs/admin/kube-controller-manager/)는
|
||||
[보안 API 포트](/docs/reference/access-authn-authz/controlling-access/)에 대해 실행해야 하며,
|
||||
슈퍼유저 권한이 없어야 한다. 그렇지 않으면 요청이 인증 및 권한 부여 모듈을 우회하고,
|
||||
모든 파드시큐리티폴리시 오브젝트가 허용되며
|
||||
사용자는 특권있는 컨테이너를 만들 수 있다. 컨트롤러 관리자 권한 구성에 대한 자세한
|
||||
내용은 [컨트롤러 역할](/docs/reference/access-authn-authz/rbac/#controller-roles)을
|
||||
참고하길 바란다.
|
||||
|
||||
## 정책 순서
|
||||
|
||||
파드 생성 및 업데이트를 제한할 뿐만 아니라 파드 시큐리티 폴리시를 사용하여
|
||||
제어하는 많은 필드에 기본값을 제공할 수도 있다. 여러 정책을
|
||||
사용할 수 있는 경우 파드 시큐리티 폴리시 컨트롤러는
|
||||
다음 기준에 따라 정책을 선택한다.
|
||||
|
||||
1. 기본 설정을 변경하거나 파드를 변경하지 않고 파드를 있는 그대로 허용하는 파드시큐리티폴리시가
|
||||
선호된다. 이러한 비-변이(non-mutating) 파드시큐리티폴리시의
|
||||
순서는 중요하지 않다.
|
||||
2. 파드를 기본값으로 설정하거나 변경해야 하는 경우, 파드를 허용할 첫 번째 파드시큐리티폴리시
|
||||
(이름순)가 선택된다.
|
||||
|
||||
{{< note >}}
|
||||
업데이트 작업 중(파드 스펙에 대한 변경이 허용되지 않는 동안) 비-변이 파드시큐리티폴리시만
|
||||
파드의 유효성을 검사하는 데 사용된다.
|
||||
{{< /note >}}
|
||||
|
||||
## 예제
|
||||
|
||||
_이 예에서는 파드시큐리티폴리시 어드미션 컨트롤러가 활성화된 클러스터가 실행 중이고
|
||||
클러스터 관리자 권한이 있다고 가정한다._
|
||||
|
||||
### 설정
|
||||
|
||||
이 예제와 같이 네임스페이스와 서비스 어카운트를 설정한다.
|
||||
이 서비스 어카운트를 사용하여 관리자가 아닌 사용자를 조정한다.
|
||||
|
||||
```shell
|
||||
kubectl create namespace psp-example
|
||||
kubectl create serviceaccount -n psp-example fake-user
|
||||
kubectl create rolebinding -n psp-example fake-editor --clusterrole=edit --serviceaccount=psp-example:fake-user
|
||||
```
|
||||
|
||||
어떤 사용자로 활동하고 있는지 명확하게 하고 입력 내용을 저장하려면 2개의 별칭(alias)을
|
||||
만든다.
|
||||
|
||||
```shell
|
||||
alias kubectl-admin='kubectl -n psp-example'
|
||||
alias kubectl-user='kubectl --as=system:serviceaccount:psp-example:fake-user -n psp-example'
|
||||
```
|
||||
|
||||
### 정책과 파드 생성
|
||||
|
||||
파일에서 예제 파드시큐리티폴리시 오브젝트를 정의한다. 이는 특권있는 파드를
|
||||
만들지 못하게 하는 정책이다.
|
||||
파드시큐리티폴리시 오브젝트의 이름은 유효한
|
||||
[DNS 서브도메인 이름](/ko/docs/concepts/overview/working-with-objects/names#dns-서브도메인-이름)이어야 한다.
|
||||
|
||||
{{< codenew file="policy/example-psp.yaml" >}}
|
||||
|
||||
그리고 kubectl로 생성한다.
|
||||
|
||||
```shell
|
||||
kubectl-admin create -f example-psp.yaml
|
||||
```
|
||||
|
||||
이제 권한이 없는 사용자로서 간단한 파드를 생성해보자.
|
||||
|
||||
```shell
|
||||
kubectl-user create -f- <<EOF
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: pause
|
||||
spec:
|
||||
containers:
|
||||
- name: pause
|
||||
image: k8s.gcr.io/pause
|
||||
EOF
|
||||
Error from server (Forbidden): error when creating "STDIN": pods "pause" is forbidden: unable to validate against any pod security policy: []
|
||||
```
|
||||
|
||||
**무슨 일이 일어났나?** 파드시큐리티폴리시가 생성되었지만, 파드의 서비스 어카운트나 `fake-user`는
|
||||
새 정책을 사용할 권한이 없다.
|
||||
|
||||
```shell
|
||||
kubectl-user auth can-i use podsecuritypolicy/example
|
||||
no
|
||||
```
|
||||
|
||||
예제 정책에서 `fake-user`에게 `use` 동사를 부여하는 rolebinding을
|
||||
생성한다.
|
||||
|
||||
{{< note >}}
|
||||
이 방법은 권장하지 않는다! 선호하는 방법은 [다음 절](#다른-파드를-실행)을
|
||||
참고하길 바란다.
|
||||
{{< /note >}}
|
||||
|
||||
```shell
|
||||
kubectl-admin create role psp:unprivileged \
|
||||
--verb=use \
|
||||
--resource=podsecuritypolicy \
|
||||
--resource-name=example
|
||||
role "psp:unprivileged" created
|
||||
|
||||
kubectl-admin create rolebinding fake-user:psp:unprivileged \
|
||||
--role=psp:unprivileged \
|
||||
--serviceaccount=psp-example:fake-user
|
||||
rolebinding "fake-user:psp:unprivileged" created
|
||||
|
||||
kubectl-user auth can-i use podsecuritypolicy/example
|
||||
yes
|
||||
```
|
||||
|
||||
이제 파드 생성을 다시 시도하자.
|
||||
|
||||
```shell
|
||||
kubectl-user create -f- <<EOF
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: pause
|
||||
spec:
|
||||
containers:
|
||||
- name: pause
|
||||
image: k8s.gcr.io/pause
|
||||
EOF
|
||||
pod "pause" created
|
||||
```
|
||||
|
||||
예상대로 작동한다! 그러나 특권있는 파드를 만들려는 시도는 여전히
|
||||
거부되어야 한다.
|
||||
|
||||
```shell
|
||||
kubectl-user create -f- <<EOF
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: privileged
|
||||
spec:
|
||||
containers:
|
||||
- name: pause
|
||||
image: k8s.gcr.io/pause
|
||||
securityContext:
|
||||
privileged: true
|
||||
EOF
|
||||
Error from server (Forbidden): error when creating "STDIN": pods "privileged" is forbidden: unable to validate against any pod security policy: [spec.containers[0].securityContext.privileged: Invalid value: true: Privileged containers are not allowed]
|
||||
```
|
||||
|
||||
계속 진행하기 전에 파드를 삭제하자.
|
||||
|
||||
```shell
|
||||
kubectl-user delete pod pause
|
||||
```
|
||||
|
||||
### 다른 파드를 실행
|
||||
|
||||
약간 다르게 다시 시도해보자.
|
||||
|
||||
```shell
|
||||
kubectl-user run pause --image=k8s.gcr.io/pause
|
||||
deployment "pause" created
|
||||
|
||||
kubectl-user get pods
|
||||
No resources found.
|
||||
|
||||
kubectl-user get events | head -n 2
|
||||
LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT TYPE REASON SOURCE MESSAGE
|
||||
1m 2m 15 pause-7774d79b5 ReplicaSet Warning FailedCreate replicaset-controller Error creating: pods "pause-7774d79b5-" is forbidden: no providers available to validate pod request
|
||||
```
|
||||
|
||||
**무슨 일이 일어났나?** 우리는 이미 `fake-user`에 대해 `psp:unprivileged` 역할을 바인딩했는데,
|
||||
`Error creating: pods "pause-7774d79b5-" is
|
||||
forbidden: no providers available to validate pod request` 오류가
|
||||
발생하는 이유는 무엇인가? 그 답은 소스인 `replicaset-controller`에 있다. Fake-user가
|
||||
디플로이먼트를 성공적으로 생성했지만(레플리카셋을 성공적으로 생성했음), 레플리카셋이
|
||||
파드를 생성했을 때 podsecuritypolicy 예제를
|
||||
사용할 권한이 없었다.
|
||||
|
||||
이 문제를 해결하려면 `psp:unprivileged` 역할을 파드의 서비스 어카운트에 대신
|
||||
바인딩한다. 이 경우(지정하지 않았으므로) 서비스 어카운트는
|
||||
`default`이다.
|
||||
|
||||
```shell
|
||||
kubectl-admin create rolebinding default:psp:unprivileged \
|
||||
--role=psp:unprivileged \
|
||||
--serviceaccount=psp-example:default
|
||||
rolebinding "default:psp:unprivileged" created
|
||||
```
|
||||
|
||||
이제 다시 한번 해본다면 replicaset-controller가
|
||||
파드를 성공적으로 생성할 것이다.
|
||||
|
||||
```shell
|
||||
kubectl-user get pods --watch
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
pause-7774d79b5-qrgcb 0/1 Pending 0 1s
|
||||
pause-7774d79b5-qrgcb 0/1 Pending 0 1s
|
||||
pause-7774d79b5-qrgcb 0/1 ContainerCreating 0 1s
|
||||
pause-7774d79b5-qrgcb 1/1 Running 0 2s
|
||||
```
|
||||
|
||||
### 정리
|
||||
|
||||
네임스페이스를 삭제하여 대부분의 예제 리소스를 정리한다.
|
||||
|
||||
```shell
|
||||
kubectl-admin delete ns psp-example
|
||||
namespace "psp-example" deleted
|
||||
```
|
||||
|
||||
`PodSecurityPolicy` 리소스는 네임스페이스에 포함되지 않으므로 별도로
|
||||
정리해야 한다.
|
||||
|
||||
```shell
|
||||
kubectl-admin delete psp example
|
||||
podsecuritypolicy "example" deleted
|
||||
```
|
||||
|
||||
### 정책 예제
|
||||
|
||||
다음은 파드 시큐리티 폴리시 어드미션 컨트롤러를 사용하지 않는 것과 동일하게 만들 수 있는
|
||||
최소한의 제한 정책이다.
|
||||
|
||||
{{< codenew file="policy/privileged-psp.yaml" >}}
|
||||
|
||||
다음은 권한이 없는 사용자로서의 실행을 필요로 하고, 루트로의 에스컬레이션(escalation) 가능성을 차단하고,
|
||||
여러 보안 메커니즘을 사용을 필요로 하는 제한적
|
||||
정책의 예제이다.
|
||||
|
||||
{{< codenew file="policy/restricted-psp.yaml" >}}
|
||||
|
||||
## 정책 레퍼런스
|
||||
|
||||
### 특권을 가진
|
||||
|
||||
**Privileged** - 파드의 컨테이너가 특권 모드를 사용할 수 있는지 여부를 결정한다.
|
||||
기본적으로 컨테이너는 호스트의 모든 장치에 접근할 수 없지만
|
||||
"특권을 가진" 컨테이너는 호스트의 모든 장치에 접근할 수 있다. 이것은
|
||||
컨테이너가 호스트에서 실행되는 프로세스와 거의 동일한 접근을 허용한다.
|
||||
이것은 네트워크 스택 조작 및 장치 접근과 같은
|
||||
리눅스 기능을 사용하려는 컨테이너에 유용하다.
|
||||
|
||||
### 호스트 네임스페이스
|
||||
|
||||
**HostPID** - 파드 컨테이너가 호스트 프로세스 ID 네임스페이스를 공유할 수 있는지 여부를
|
||||
제어한다. ptrace와 함께 사용하면 컨테이너 외부로 권한을 에스컬레이션하는 데 사용할 수
|
||||
있다(ptrace는 기본적으로 금지되어 있음).
|
||||
|
||||
**HostIPC** - 파드 컨테이너가 호스트 IPC 네임스페이스를 공유할 수 있는지 여부를
|
||||
제어한다.
|
||||
|
||||
**HostNetwork** - 파드가 노드 네트워크 네임스페이스를 사용할 수 있는지 여부를 제어한다.
|
||||
이렇게 하면 파드에 루프백 장치에 접근 권한을 주고, 서비스는 로컬호스트(localhost)를 리스닝할 수 있으며,
|
||||
동일한 노드에 있는 다른 파드의 네트워크 활동을 스누핑(snoop)하는 데
|
||||
사용할 수 있다.
|
||||
|
||||
**HostPorts** - 호스트 네트워크 네임스페이스에 허용되는 포트 범위의 화이트리스트(whitelist)를
|
||||
제공한다. `min`과 `max`를 포함하여 `HostPortRange`의 목록으로 정의된다.
|
||||
기본값은 허용하는 호스트 포트 없음(no allowed host ports)이다.
|
||||
|
||||
### 볼륨 및 파일시스템
|
||||
|
||||
**Volumes** - 허용되는 볼륨 유형의 화이트리스트를 제공한다. 허용 가능한 값은
|
||||
볼륨을 생성할 때 정의된 볼륨 소스에 따른다. 볼륨 유형의 전체 목록은
|
||||
[볼륨 유형들](/ko/docs/concepts/storage/volumes/#볼륨-유형들)에서 참고한다.
|
||||
또한 `*`를 사용하여 모든 볼륨 유형을
|
||||
허용할 수 있다.
|
||||
|
||||
새 PSP에 허용되는 볼륨의 **최소 권장 셋** 은 다음과 같다.
|
||||
|
||||
- 컨피그맵
|
||||
- 다운워드API
|
||||
- emptyDir
|
||||
- 퍼시스턴트볼륨클레임
|
||||
- 시크릿
|
||||
- 프로젝티드(projected)
|
||||
|
||||
{{< warning >}}
|
||||
파드시큐리티폴리시는 `PersistentVolumeClaim`이 참조할 수 있는 `PersistentVolume`
|
||||
오브젝트의 유형을 제한하지 않으며 hostPath 유형
|
||||
`PersistentVolumes`은 읽기-전용 접근 모드를 지원하지 않는다. 신뢰할 수 있는 사용자만
|
||||
`PersistentVolume` 오브젝트를 생성할 수 있는 권한을 부여 받아야 한다.
|
||||
{{< /warning >}}
|
||||
|
||||
**FSGroup** - 일부 볼륨에 적용되는 보충 그룹(supplemental group)을 제어한다.
|
||||
|
||||
- *MustRunAs* - 하나 이상의 `range`를 지정해야 한다. 첫 번째 범위의 최솟값을
|
||||
기본값으로 사용한다. 모든 범위에 대해 검증한다.
|
||||
- *MayRunAs* - 하나 이상의 `range`를 지정해야 한다. 기본값을 제공하지 않고
|
||||
`FSGroups`을 설정하지 않은 상태로 둘 수 있다. `FSGroups`이 설정된 경우 모든 범위에 대해
|
||||
유효성을 검사한다.
|
||||
- *RunAsAny* - 기본값은 제공되지 않는다. 어떠한 `fsGroup` ID의 지정도 허용한다.
|
||||
|
||||
**AllowedHostPaths** - hostPath 볼륨에서 사용할 수 있는 호스트 경로의 화이트리스트를
|
||||
지정한다. 빈 목록은 사용되는 호스트 경로에 제한이 없음을 의미한다.
|
||||
이는 단일 `pathPrefix` 필드가 있는 오브젝트 목록으로 정의되며, hostPath 볼륨은
|
||||
허용된 접두사로 시작하는 경로를 마운트할 수 있으며 `readOnly` 필드는
|
||||
읽기-전용으로 마운트 되어야 함을 나타낸다.
|
||||
예를 들면 다음과 같습니다.
|
||||
|
||||
```yaml
|
||||
allowedHostPaths:
|
||||
# 이 정책은 "/foo", "/foo/", "/foo/bar" 등을 허용하지만,
|
||||
# "/fool", "/etc/foo" 등은 허용하지 않는다.
|
||||
# "/foo/../" 는 절대 유효하지 않다.
|
||||
- pathPrefix: "/foo"
|
||||
readOnly: true # 읽기 전용 마운트만 허용
|
||||
```
|
||||
|
||||
{{< warning >}}호스트 파일시스템에 제한없는 접근을 부여하며, 컨테이너가 특권을 에스컬레이션
|
||||
(다른 컨테이너들에 있는 데이터를 읽고, 시스템 서비스의 자격 증명을 어뷰징(abusing)하는 등)할
|
||||
수 있도록 만드는 다양한 방법이 있다. 예를 들면, Kubelet과 같다.
|
||||
|
||||
쓰기 가능한 hostPath 디렉토리 볼륨을 사용하면, 컨테이너가 `pathPrefix` 외부의
|
||||
호스트 파일시스템에 대한 통행을 허용하는 방식으로 컨테이너의 파일시스템 쓰기(write)를 허용한다.
|
||||
쿠버네티스 1.11 이상 버전에서 사용 가능한 `readOnly: true`는 지정된 `pathPrefix`에 대한
|
||||
접근을 효과적으로 제한하기 위해 **모든** `allowedHostPaths`에서 사용해야 한다.
|
||||
{{< /warning >}}
|
||||
|
||||
**ReadOnlyRootFilesystem** - 컨테이너는 읽기-전용 루트 파일시스템(즉, 쓰기 가능한 레이어 없음)으로
|
||||
실행해야 한다.
|
||||
|
||||
### FlexVolume 드라이버
|
||||
|
||||
flexvolume에서 사용할 수 있는 FlexVolume 드라이버의 화이트리스트를 지정한다.
|
||||
빈 목록 또는 nil은 드라이버에 제한이 없음을 의미한다.
|
||||
[`volumes`](#볼륨-및-파일시스템) 필드에 `flexVolume` 볼륨 유형이 포함되어
|
||||
있는지 확인한다. 그렇지 않으면 FlexVolume 드라이버가 허용되지 않는다.
|
||||
|
||||
예를 들면 다음과 같다.
|
||||
|
||||
```yaml
|
||||
apiVersion: policy/v1beta1
|
||||
kind: PodSecurityPolicy
|
||||
metadata:
|
||||
name: allow-flex-volumes
|
||||
spec:
|
||||
# ... 다른 스펙 필드
|
||||
volumes:
|
||||
- flexVolume
|
||||
allowedFlexVolumes:
|
||||
- driver: example/lvm
|
||||
- driver: example/cifs
|
||||
```
|
||||
|
||||
### 사용자 및 그룹
|
||||
|
||||
**RunAsUser** - 컨테이너를 실행할 사용자 ID를 제어힌다.
|
||||
|
||||
- *MustRunAs* - 하나 이상의 `range`를 지정해야 한다. 첫 번째 범위의 최솟값을
|
||||
기본값으로 사용한다. 모든 범위에 대해 검증한다.
|
||||
- *MustRunAsNonRoot* - 파드가 0이 아닌 `runAsUser`로 제출되거나
|
||||
이미지에 `USER` 지시문이 정의되어 있어야 한다(숫자 UID 사용). `runAsNonRoot` 또는
|
||||
`runAsUser` 설정을 지정하지 않은 파드는 `runAsNonRoot=true`를 설정하도록
|
||||
변경되므로 컨테이너에 0이 아닌 숫자가 정의된 `USER` 지시문이
|
||||
필요하다. 기본값은 제공되지 않는다.
|
||||
이 전략에서는 `allowPrivilegeEscalation=false`를 설정하는 것이 좋다.
|
||||
- *RunAsAny* - 기본값은 제공되지 않는다. 어떠한 `runAsUser`의 지정도 허용한다.
|
||||
|
||||
**RunAsGroup** - 컨테이너가 실행될 기본 그룹 ID를 제어한다.
|
||||
|
||||
- *MustRunAs* - 하나 이상의 `range`를 지정해야 한다. 첫 번째 범위의 최솟값을
|
||||
기본값으로 사용한다. 모든 범위에 대해 검증한다.
|
||||
- *MayRunAs* - `RunAsGroup`을 지정할 필요가 없다. 그러나 `RunAsGroup`을 지정하면
|
||||
정의된 범위에 속해야 한다.
|
||||
- *RunAsAny* - 기본값은 제공되지 않는다. 어떠한 `runAsGroup`의 지정도 허용한다.
|
||||
|
||||
|
||||
**SupplementalGroups** - 컨테이너가 추가할 그룹 ID를 제어한다.
|
||||
|
||||
- *MustRunAs* - 하나 이상의 `range`를 지정해야 한다. 첫 번째 범위의 최솟값을
|
||||
기본값으로 사용한다. 모든 범위에 대해 검증한다.
|
||||
- *MayRunAs* - 하나 이상의 `range`를 지정해야 한다. `supplementalGroups`에
|
||||
기본값을 제공하지 않고 설정하지 않은 상태로 둘 수 있다.
|
||||
`supplementalGroups`가 설정된 경우 모든 범위에 대해 유효성을 검증한다.
|
||||
- *RunAsAny* - 기본값은 제공되지 않는다. 어떠한 `supplementalGroups`의 지정도
|
||||
허용한다.
|
||||
|
||||
### 권한 에스컬레이션
|
||||
|
||||
이 옵션은 `allowPrivilegeEscalation` 컨테이너 옵션을 제어한다. 이 bool은
|
||||
컨테이너 프로세스에서
|
||||
[`no_new_privs`](https://www.kernel.org/doc/Documentation/prctl/no_new_privs.txt)
|
||||
플래그가 설정되는지 여부를 직접 제어한다. 이 플래그는 `setuid` 바이너리가
|
||||
유효 사용자 ID를 변경하지 못하게 하고 파일에 추가 기능을 활성화하지 못하게
|
||||
한다(예: `ping` 도구 사용을 못하게 함). `MustRunAsNonRoot`를 효과적으로
|
||||
강제하려면 이 동작이 필요하다.
|
||||
|
||||
**AllowPrivilegeEscalation** - 사용자가 컨테이너의 보안 컨텍스트를
|
||||
`allowPrivilegeEscalation=true`로 설정할 수 있는지 여부를 게이트한다.
|
||||
이 기본값은 setuid 바이너리를 중단하지 않도록 허용한다. 이를 `false`로 설정하면
|
||||
컨테이너의 하위 프로세스가 상위 프로세스보다 더 많은 권한을 얻을 수 없다.
|
||||
|
||||
**DefaultAllowPrivilegeEscalation** - `allowPrivilegeEscalation` 옵션의
|
||||
기본값을 설정한다. 이것이 없는 기본 동작은 setuid 바이너리를 중단하지 않도록
|
||||
권한 에스컬레이션을 허용하는 것이다. 해당 동작이 필요하지 않은 경우 이 필드를 사용하여
|
||||
기본적으로 허용하지 않도록 설정할 수 있지만 파드는 여전히 `allowPrivilegeEscalation`을
|
||||
명시적으로 요청할 수 있다.
|
||||
|
||||
### 기능
|
||||
|
||||
리눅스 기능은 전통적으로 슈퍼유저와 관련된 권한을 보다 세밀하게 분류한다.
|
||||
이러한 기능 중 일부는 권한 에스컬레이션 또는 컨테이너 분류에 사용될 수 있으며
|
||||
파드시큐리티폴리시에 의해 제한될 수 있다. 리눅스 기능에 대한 자세한 내용은
|
||||
[기능(7)](http://man7.org/linux/man-pages/man7/capabilities.7.html)을
|
||||
참고하길 바란다.
|
||||
|
||||
다음 필드는 대문자로 표기된 기능 이름 목록을
|
||||
`CAP_` 접두사 없이 가져온다.
|
||||
|
||||
**AllowedCapabilities** - 컨테이너에 추가될 수 있는 기능의 화이트리스트를
|
||||
제공한다. 기본적인 기능 셋은 암시적으로 허용된다. 비어있는 셋은
|
||||
기본 셋을 넘어서는 추가 기능이 추가되지 않는 것을
|
||||
의미한다. `*`는 모든 기능을 허용하는 데 사용할 수 있다.
|
||||
|
||||
**RequiredDropCapabilities** - 컨테이너에서 삭제해야 하는 기능이다.
|
||||
이러한 기능은 기본 셋에서 제거되며 추가해서는 안된다.
|
||||
`RequiredDropCapabilities`에 나열된 기능은 `AllowedCapabilities` 또는
|
||||
`DefaultAddCapabilities`에 포함되지 않아야 한다.
|
||||
|
||||
**DefaultAddCapabilities** - 런타임 기본값 외에 기본적으로 컨테이너에 추가되는 기능이다.
|
||||
도커 런타임을 사용할 때 기본 기능 목록은
|
||||
[도커 문서](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities)를
|
||||
참고하길 바란다.
|
||||
|
||||
### SELinux
|
||||
|
||||
- *MustRunAs* - `seLinuxOptions`을 구성해야 한다.
|
||||
`seLinuxOptions`을 기본값으로 사용한다. `seLinuxOptions`에 대해 유효성을 검사한다.
|
||||
- *RunAsAny* - 기본값은 제공되지 않는다. 어떠한 `seLinuxOptions`의 지정도
|
||||
허용한다.
|
||||
|
||||
### AllowedProcMountTypes
|
||||
|
||||
`allowedProcMountTypes`는 허용된 ProcMountTypes의 화이트리스트이다.
|
||||
비어 있거나 nil은 `DefaultProcMountType`만 사용할 수 있음을 나타낸다.
|
||||
|
||||
`DefaultProcMount`는 /proc의 읽기 전용 및 마스킹(masking)된 경로에 컨테이너 런타임
|
||||
기본값을 사용한다. 대부분의 컨테이너 런타임은 특수 장치나 정보가 실수로 보안에
|
||||
노출되지 않도록 /proc의 특정 경로를 마스킹한다. 이것은 문자열
|
||||
`Default`로 표시된다.
|
||||
|
||||
유일하게 다른 ProcMountType은 `UnmaskedProcMount`로, 컨테이너 런타임의
|
||||
기본 마스킹 동작을 무시하고 새로 작성된 /proc 컨테이너가 수정없이
|
||||
그대로 유지되도록 한다. 이 문자열은
|
||||
`Unmasked`로 표시된다.
|
||||
|
||||
### AppArmor
|
||||
|
||||
파드시큐리티폴리시의 어노테이션을 통해 제어된다. [AppArmor
|
||||
문서](/docs/tutorials/clusters/apparmor/#podsecuritypolicy-annotations)를 참고하길 바란다.
|
||||
|
||||
### Seccomp
|
||||
|
||||
파드에서 seccomp 프로파일의 사용은 파드시큐리티폴리시의 어노테이션을 통해
|
||||
제어할 수 있다. Seccomp는 쿠버네티스의 알파 기능이다.
|
||||
|
||||
**seccomp.security.alpha.kubernetes.io/defaultProfileName** - 컨테이너에
|
||||
적용할 기본 seccomp 프로파일을 지정하는 어노테이션이다. 가능한 값은
|
||||
다음과 같다.
|
||||
|
||||
- `unconfined` - 대안이 제공되지 않으면 Seccomp가 컨테이너 프로세스에 적용되지
|
||||
않는다(쿠버네티스의 기본값임).
|
||||
- `runtime/default` - 기본 컨테이너 런타임 프로파일이 사용된다.
|
||||
- `docker/default` - 도커 기본 seccomp 프로파일이 사용된다. 쿠버네티스 1.11 부터 사용 중단(deprecated)
|
||||
되었다. 대신 `runtime/default` 사용을 권장한다.
|
||||
- `localhost/<path>` - `<seccomp_root>/<path>`에 있는 노드에서 파일을 프로파일로
|
||||
지정한다. 여기서 `<seccomp_root>`는 Kubelet의 `--seccomp-profile-root` 플래그를
|
||||
통해 정의된다.
|
||||
|
||||
**seccomp.security.alpha.kubernetes.io/allowedProfileNames** - 파드 seccomp
|
||||
어노테이션에 허용되는 값을 지정하는 어노테이션. 쉼표로 구분된
|
||||
허용된 값의 목록으로 지정된다. 가능한 값은 위에 나열된 값과
|
||||
모든 프로파일을 허용하는 `*` 이다.
|
||||
이 주석이 없으면 기본값을 변경할 수 없다.
|
||||
|
||||
### Sysctl
|
||||
|
||||
기본적으로 모든 안전한 sysctls가 허용된다.
|
||||
|
||||
- `forbiddenSysctls` - 특정 sysctls를 제외한다. 목록에서 안전한 것과 안전하지 않은 sysctls의 조합을 금지할 수 있다. 모든 sysctls 설정을 금지하려면 자체적으로 `*`를 사용한다.
|
||||
- `allowedUnsafeSysctls` - `forbiddenSysctls`에 나열되지 않는 한 기본 목록에서 허용하지 않은 특정 sysctls를 허용한다.
|
||||
|
||||
[Sysctl 문서](
|
||||
/docs/concepts/cluster-administration/sysctl-cluster/#podsecuritypolicy)를 참고하길 바란다.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture whatsnext %}}
|
||||
|
||||
API 세부 정보는 [파드 시큐리티 폴리시 레퍼런스](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podsecuritypolicy-v1beta1-policy) 참조
|
||||
|
||||
{{% /capture %}}
|
||||
@@ -0,0 +1,600 @@
|
||||
---
|
||||
title: 리소스 쿼터
|
||||
content_template: templates/concept
|
||||
weight: 10
|
||||
---
|
||||
|
||||
{{% capture overview %}}
|
||||
|
||||
여러 사용자나 팀이 정해진 수의 노드로 클러스터를 공유할 때
|
||||
한 팀이 공정하게 분배된 리소스보다 많은 리소스를 사용할 수 있다는 우려가 있다.
|
||||
|
||||
리소스 쿼터는 관리자가 이 문제를 해결하기 위한 도구이다.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
|
||||
{{% capture body %}}
|
||||
|
||||
`ResourceQuota` 오브젝트로 정의된 리소스 쿼터는 네임스페이스별 총 리소스 사용을 제한하는
|
||||
제약 조건을 제공한다. 유형별로 네임스페이스에서 만들 수 있는 오브젝트 수와
|
||||
해당 프로젝트의 리소스가 사용할 수 있는 총 컴퓨트 리소스의 양을
|
||||
제한할 수 있다.
|
||||
|
||||
리소스 쿼터는 다음과 같이 작동한다.
|
||||
|
||||
- 다른 팀은 다른 네임스페이스에서 작동한다. 현재 이것은 자발적이지만 ACL을 통해 이 필수 사항을
|
||||
적용하기 위한 지원이 계획되어 있다.
|
||||
- 관리자는 각 네임스페이스에 대해 하나의 `ResourceQuota`를 생성한다.
|
||||
- 사용자는 네임스페이스에서 리소스(파드, 서비스 등)를 생성하고 쿼터 시스템은
|
||||
사용량을 추적하여 `ResourceQuota`에 정의된 하드(hard) 리소스 제한을 초과하지 않도록 한다.
|
||||
- 리소스를 생성하거나 업데이트할 때 쿼터 제약 조건을 위반하면 위반된 제약 조건을 설명하는
|
||||
메시지와 함께 HTTP 상태 코드 `403 FORBIDDEN`으로 요청이 실패한다.
|
||||
- `cpu`, `memory`와 같은 컴퓨트 리소스에 대해 네임스페이스에서 쿼터가 활성화된 경우
|
||||
사용자는 해당값에 대한 요청 또는 제한을 지정해야 한다. 그렇지 않으면 쿼터 시스템이
|
||||
파드 생성을 거부할 수 있다. 힌트: 컴퓨트 리소스 요구 사항이 없는 파드를 기본값으로 설정하려면 `LimitRanger` 어드미션 컨트롤러를 사용하자.
|
||||
이 문제를 회피하는 방법에 대한 예제는 [연습](/docs/tasks/administer-cluster/quota-memory-cpu-namespace/)을 참고하길 바란다.
|
||||
|
||||
`ResourceQuota` 오브젝트의 이름은 유효한
|
||||
[DNS 서브도메인 이름](/ko/docs/concepts/overview/working-with-objects/names#dns-서브도메인-이름)이어야 한다.
|
||||
|
||||
네임스페이스와 쿼터를 사용하여 만들 수 있는 정책의 예는 다음과 같다.
|
||||
|
||||
- 용량이 32GiB RAM, 16 코어인 클러스터에서 A 팀이 20GiB 및 10 코어를 사용하고
|
||||
B 팀은 10GiB 및 4 코어를 사용하게 하고 2GiB 및 2 코어를 향후 할당을 위해 보유하도록 한다.
|
||||
- "testing" 네임스페이스를 1 코어 및 1GiB RAM을 사용하도록 제한한다.
|
||||
"production" 네임스페이스에는 원하는 양을 사용하도록 한다.
|
||||
|
||||
클러스터의 총 용량이 네임스페이스의 쿼터 합보다 작은 경우 리소스에 대한 경합이 있을 수 있다.
|
||||
이것은 선착순으로 처리된다.
|
||||
|
||||
경합이나 쿼터 변경은 이미 생성된 리소스에 영향을 미치지 않는다.
|
||||
|
||||
## 리소스 쿼터 활성화
|
||||
|
||||
많은 쿠버네티스 배포판에 기본적으로 리소스 쿼터 지원이 활성화되어 있다.
|
||||
API 서버 `--enable-admission-plugins=` 플래그의 인수 중 하나로
|
||||
`ResourceQuota`가 있는 경우 활성화된다.
|
||||
|
||||
해당 네임스페이스에 `ResourceQuota`가 있는 경우 특정 네임스페이스에 리소스 쿼터가 적용된다.
|
||||
|
||||
## 컴퓨트 리소스 쿼터
|
||||
|
||||
지정된 네임스페이스에서 요청할 수 있는 총 [컴퓨트 리소스](/docs/user-guide/compute-resources) 합을 제한할 수 있다.
|
||||
|
||||
다음과 같은 리소스 유형이 지원된다.
|
||||
|
||||
| 리소스 이름 | 설명 |
|
||||
| --------------------- | ----------------------------------------------------------- |
|
||||
| `limits.cpu` | 터미널이 아닌 상태의 모든 파드에서 CPU 제한의 합은 이 값을 초과할 수 없음 |
|
||||
| `limits.memory` | 터미널이 아닌 상태의 모든 파드에서 메모리 제한의 합은 이 값을 초과할 수 없음 |
|
||||
| `requests.cpu` | 터미널이 아닌 상태의 모든 파드에서 CPU 요청의 합은 이 값을 초과할 수 없음 |
|
||||
| `requests.memory` | 터미널이 아닌 상태의 모든 파드에서 메모리 요청의 합은 이 값을 초과할 수 없음 |
|
||||
|
||||
### 확장된 리소스에 대한 리소스 쿼터
|
||||
|
||||
위에서 언급한 리소스 외에도 릴리스 1.10에서는
|
||||
[확장된 리소스](/docs/concepts/configuration/manage-compute-resources-container/#extended-resources)에 대한 쿼터 지원이 추가되었다.
|
||||
|
||||
확장된 리소스에는 오버커밋(overcommit)이 허용되지 않으므로 하나의 쿼터에서
|
||||
동일한 확장된 리소스에 대한 `requests`와 `limits`을 모두 지정하는 것은 의미가 없다. 따라서 확장된
|
||||
리소스의 경우 지금은 접두사 `requests.`이 있는 쿼터 항목만 허용된다.
|
||||
|
||||
예를 들어, 리소스 이름이 `nvidia.com/gpu`이고 네임스페이스에서 요청된 총 GPU 수를 4개로 제한하려는 경우,
|
||||
GPU 리소스를 다음과 같이 쿼터를 정의할 수 있다.
|
||||
|
||||
* `requests.nvidia.com/gpu: 4`
|
||||
|
||||
자세한 내용은 [쿼터 보기 및 설정](#쿼터-보기-및-설정)을 참고하길 바란다.
|
||||
|
||||
|
||||
## 스토리지 리소스 쿼터
|
||||
|
||||
지정된 네임스페이스에서 요청할 수 있는 총 [스토리지 리소스](/ko/docs/concepts/storage/persistent-volumes/) 합을 제한할 수 있다.
|
||||
|
||||
또한 연관된 스토리지 클래스를 기반으로 스토리지 리소스 사용을 제한할 수 있다.
|
||||
|
||||
| 리소스 이름 | 설명 |
|
||||
| --------------------- | ----------------------------------------------------------- |
|
||||
| `requests.storage` | 모든 퍼시스턴트 볼륨 클레임에서 스토리지 요청의 합은 이 값을 초과할 수 없음 |
|
||||
| `persistentvolumeclaims` | 네임스페이스에 존재할 수 있는 총 [퍼시스턴트 볼륨 클레임](/ko/docs/concepts/storage/persistent-volumes/#퍼시스턴트볼륨클레임) 수 |
|
||||
| `<storage-class-name>.storageclass.storage.k8s.io/requests.storage` | storage-class-name과 관련된 모든 퍼시스턴트 볼륨 클레임에서 스토리지 요청의 합은 이 값을 초과할 수 없음 |
|
||||
| `<storage-class-name>.storageclass.storage.k8s.io/persistentvolumeclaims` | storage-class-name과 관련된 모든 퍼시스턴트 볼륨 클레임에서 네임스페이스에 존재할 수 있는 총 [퍼시스턴트 볼륨 클레임](/ko/docs/concepts/storage/persistent-volumes/#퍼시스턴트볼륨클레임) 수 |
|
||||
|
||||
예를 들어, 운영자가 `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` | 네임스페이스에 존재할 수 있는 총 [퍼시스턴트 볼륨 클레임](/ko/docs/concepts/storage/persistent-volumes/#퍼시스턴트볼륨클레임) 수 |
|
||||
| `pods` | 네임스페이스에 존재할 수 있는 터미널이 아닌 상태의 파드의 총 수. `.status.phase in (Failed, Succeeded)`가 true인 경우 파드는 터미널 상태임 |
|
||||
| `replicationcontrollers` | 네임스페이스에 존재할 수 있는 총 레플리케이션 컨트롤러 수 |
|
||||
| `resourcequotas` | 네임스페이스에 존재할 수 있는 총 [리소스 쿼터](/docs/reference/access-authn-authz/admission-controllers/#resourcequota) 수 |
|
||||
| `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별 리소스 쿼터
|
||||
|
||||
{{< feature-state for_k8s_version="1.12" state="beta" >}}
|
||||
|
||||
특정 [우선 순위](/docs/concepts/configuration/pod-priority-preemption/#pod-priority)로 파드를 생성할 수 있다.
|
||||
쿼터 스펙의 `scopeSelector` 필드를 사용하여 파드의 우선 순위에 따라 파드의 시스템 리소스 사용을
|
||||
제어할 수 있다.
|
||||
|
||||
쿼터 스펙의 `scopeSelector`가 파드를 선택한 경우에만 쿼터가 일치하고 사용된다.
|
||||
|
||||
이 예에서는 쿼터 오브젝트를 생성하여 특정 우선 순위의 파드와 일치시킨다.
|
||||
예제는 다음과 같이 작동한다.
|
||||
|
||||
- 클러스터의 파드는 "low(낮음)", "medium(중간)", "high(높음)"의 세 가지 우선 순위 클래스 중 하나를 가진다.
|
||||
- 각 우선 순위마다 하나의 쿼터 오브젝트가 생성된다.
|
||||
|
||||
다음 YAML을 `quota.yml` 파일에 저장한다.
|
||||
|
||||
```yaml
|
||||
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을 적용한다.
|
||||
|
||||
```shell
|
||||
kubectl create -f ./quota.yml
|
||||
```
|
||||
|
||||
```shell
|
||||
resourcequota/pods-high created
|
||||
resourcequota/pods-medium created
|
||||
resourcequota/pods-low created
|
||||
```
|
||||
|
||||
`kubectl describe quota`를 사용하여 `Used` 쿼터가 `0`인지 확인하자.
|
||||
|
||||
```shell
|
||||
kubectl describe quota
|
||||
```
|
||||
|
||||
```shell
|
||||
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` 파일에 저장한다.
|
||||
|
||||
```yaml
|
||||
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`로 적용하자.
|
||||
|
||||
```shell
|
||||
kubectl create -f ./high-priority-pod.yml
|
||||
```
|
||||
|
||||
"high" 우선 순위 쿼터가 적용된 `pods-high`에 대한 "Used" 통계가 변경되었고
|
||||
다른 두 쿼터는 변경되지 않았는지 확인한다.
|
||||
|
||||
```shell
|
||||
kubectl describe quota
|
||||
```
|
||||
|
||||
```shell
|
||||
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`
|
||||
|
||||
## 요청과 제한의 비교 {#requests-vs-limits}
|
||||
|
||||
컴퓨트 리소스를 할당할 때 각 컨테이너는 CPU 또는 메모리에 대한 요청과 제한값을 지정할 수 있다.
|
||||
쿼터는 값에 대한 쿼터를 지정하도록 구성할 수 있다.
|
||||
|
||||
쿼터에 `requests.cpu`나 `requests.memory`에 지정된 값이 있으면 들어오는 모든
|
||||
컨테이너가 해당 리소스에 대한 명시적인 요청을 지정해야 한다. 쿼터에 `limits.cpu`나
|
||||
`limits.memory`에 지정된 값이 있으면 들어오는 모든 컨테이너가 해당 리소스에 대한 명시적인 제한을 지정해야 한다.
|
||||
|
||||
## 쿼터 보기 및 설정
|
||||
|
||||
Kubectl은 쿼터 생성, 업데이트 및 보기를 지원한다.
|
||||
|
||||
```shell
|
||||
kubectl create namespace myspace
|
||||
```
|
||||
|
||||
```shell
|
||||
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
|
||||
```
|
||||
|
||||
```shell
|
||||
kubectl create -f ./compute-resources.yaml --namespace=myspace
|
||||
```
|
||||
|
||||
```shell
|
||||
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
|
||||
```
|
||||
|
||||
```shell
|
||||
kubectl create -f ./object-counts.yaml --namespace=myspace
|
||||
```
|
||||
|
||||
```shell
|
||||
kubectl get quota --namespace=myspace
|
||||
```
|
||||
|
||||
```shell
|
||||
NAME AGE
|
||||
compute-resources 30s
|
||||
object-counts 32s
|
||||
```
|
||||
|
||||
```shell
|
||||
kubectl describe quota compute-resources --namespace=myspace
|
||||
```
|
||||
|
||||
```shell
|
||||
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
|
||||
```
|
||||
|
||||
```shell
|
||||
kubectl describe quota object-counts --namespace=myspace
|
||||
```
|
||||
|
||||
```shell
|
||||
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>` 구문을 사용하여 모든 표준 네임스페이스 리소스에 대한
|
||||
오브젝트 수 쿼터를 지원한다.
|
||||
|
||||
```shell
|
||||
kubectl create namespace myspace
|
||||
```
|
||||
|
||||
```shell
|
||||
kubectl create quota test --hard=count/deployments.extensions=2,count/replicasets.extensions=4,count/pods=3,count/secrets=4 --namespace=myspace
|
||||
```
|
||||
|
||||
```shell
|
||||
kubectl run nginx --image=nginx --replicas=2 --namespace=myspace
|
||||
```
|
||||
|
||||
```shell
|
||||
kubectl describe quota --namespace=myspace
|
||||
```
|
||||
|
||||
```shell
|
||||
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`을 사용하여 다음 구성 파일의 경로를 전달해야 한다.
|
||||
|
||||
{{< tabs name="example1" >}}
|
||||
{{% tab name="apiserver.config.k8s.io/v1" %}}
|
||||
```yaml
|
||||
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"]
|
||||
```
|
||||
{{% /tab %}}
|
||||
{{% tab name="apiserver.k8s.io/v1alpha1" %}}
|
||||
```yaml
|
||||
# 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"]
|
||||
```
|
||||
{{% /tab %}}
|
||||
{{< /tabs >}}
|
||||
|
||||
이제 "cluster-services" 파드는 `scopeSelector`와 일치하는 쿼터 오브젝트가 있는 네임스페이스에서만 허용된다.
|
||||
예를 들면 다음과 같다.
|
||||
```yaml
|
||||
scopeSelector:
|
||||
matchExpressions:
|
||||
- scopeName: PriorityClass
|
||||
operator: In
|
||||
values: ["cluster-services"]
|
||||
```
|
||||
|
||||
자세한 내용은 [LimitedResources](https://github.com/kubernetes/kubernetes/pull/36765)와 [우선 순위 클래스에 대한 쿼터 지원 디자인 문서](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/scheduling/pod-priority-resourcequota.md)를 참고하길 바란다.
|
||||
|
||||
## 예제
|
||||
|
||||
[리소스 쿼터를 사용하는 방법에 대한 자세한 예](/docs/tasks/administer-cluster/quota-api-object/)를 참고하길 바란다.
|
||||
|
||||
{{% /capture %}}
|
||||
|
||||
{{% capture whatsnext %}}
|
||||
|
||||
자세한 내용은 [리소스쿼터 디자인 문서](https://git.k8s.io/community/contributors/design-proposals/resource-management/admission_control_resource_quota.md)를 참고하길 바란다.
|
||||
|
||||
{{% /capture %}}
|
||||
Reference in New Issue
Block a user