當多個團隊或使用者共用同一個 Kubernetes 叢集時,資源競爭是很常見的。為了避免某個團隊的資源使用影響到其他團隊,我們可以使用資源配額來進行限制。在 Kubernetes 中,可以透過命名空間 (namespace) 來分隔不同的團隊,並使用 ResourceQuota
和 LimitRange
來管理資源。
ResourceQuota
是 Kubernetes 提供的機制,用來限制特定 namespace 中可以使用的資源總量。透過 Resource Quotas,可以限制該 namespace 中可創建的 Pod、Service、PersistentVolumeClaim(PVC)等資源數量,以及這些資源的總 CPU 和記憶體用量。如果資源申請超過了配額限制,新的申請會被拒絕。
以下是一個 Resource Quota 的範例配置:
apiVersion: v1
kind: ResourceQuota
metadata:
name: my-quota
spec:
hard:
pods: "10" # 限制該 namespace 中最多可以創建 10 個 Pod
requests.cpu: "4" # 限制 CPU 的總請求數為 4 核心
requests.memory: "8Gi" # 限制記憶體的總請求數為 8 GiB
limits.cpu: "8" # 限制 CPU 的總限制數為 8 核心
limits.memory: "16Gi" # 限制記憶體的總限制數為 16 GiB
LimitRange
用來控制 namespace 中容器和 Pod 的資源使用範圍,可以設定最小(min)和最大(max)資源請求和限制,並提供默認的資源配置值。
以下是一個 Limit Range 的範例配置:
apiVersion: v1
kind: LimitRange
metadata:
name: my-limit-range
spec:
limits:
- type: Container
max:
cpu: "2" # 每個容器最多使用 2 核心 CPU
memory: "1Gi" # 每個容器最多使用 1 GiB 記憶體
min:
cpu: "100m" # 每個容器至少使用 100m CPU
memory: "128Mi" # 每個容器至少使用 128 MiB 記憶體
default:
cpu: "500m" # 容器默認使用 500m CPU
memory: "256Mi" # 容器默認使用 256 MiB 記憶體
defaultRequest:
cpu: "250m" # 容器默認的資源請求值為 250m CPU
memory: "128Mi" # 容器默認的資源請求值為 128 MiB 記憶體
透過這些策略,我們可以有效地避免資源的過度使用,確保每個團隊都能獲得公平的資源分配。
建立一個名字空間,以便將本練習所建立的資源與叢集的其餘資源相隔離。
kubectl create ns manage-resources-ns
組態檔案:resource-quota-compute.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: my-resource-quota
namespace: manage-resources-ns
spec:
hard:
requests.cpu: "1"
requests.memory: 1Gi
limits.cpu: "2"
limits.memory: 2Gi
kubectl -n manage-resources-ns describe resourcequotas my-resource-quota
---
Name: my-resource-quota
Namespace: manage-resources-ns
Resource Used Hard
-------- ---- ----
limits.cpu 0 2
limits.memory 0 2Gi
requests.cpu 0 1
requests.memory 0 1Gi
組態檔案:compute-resources-pod-1.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod1
namespace: manage-resources-ns
spec:
containers:
- name: c1
image: nginx
resources:
limits:
memory: "800Mi"
cpu: "800m"
requests:
memory: "600Mi"
cpu: "400m"
kubectl apply -f compute-resources-pod-1.yaml
kubectl -n manage-resources-ns describe resourcequotas my-resource-quota
---
Name: my-resource-quota
Namespace: manage-resources-ns
Resource Used Hard
-------- ---- ----
limits.cpu 800m 2
limits.memory 800Mi 2Gi
requests.cpu 400m 1
requests.memory 600Mi 1Gi
組態檔案:compute-resources-pod-2.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod2
namespace: manage-resources-ns
spec:
containers:
- name: c1
image: nginx
resources:
limits:
memory: "1Gi"
cpu: "800m"
requests:
memory: "700Mi"
cpu: "400m"
request.memory
600Mi + 700Mi > 1G,會超過請求上限
kubectl apply -f compute-resources-pod-2.yaml
---
Error from server (Forbidden): error when creating "compute-resources-pod-2.yaml": pods "pod2" is forbidden: exceeded quota: my-resource-quota, requested: requests.memory=700Mi, used: requests.memory=600Mi, limited: requests.memory=1Gi
可以看到,超出上限的請求,叢集回報 403 (Forbidden) 錯誤,並且給與錯誤訊息。
組態檔案:resource-quota-count.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: my-resource-quota
namespace: manage-resources-ns
spec:
hard:
configmaps: "10"
persistentvolumeclaims: "4"
replicationcontrollers: "20"
secrets: "10"
services: "10"
services.loadbalancers: "2"
kubectl apply -f resource-quota-count.yaml
kubectl -n manage-resources-ns describe resourcequotas my-resource-quota
---
Name: my-resource-quota
Namespace: manage-resources-ns
Resource Used Hard
-------- ---- ----
configmaps 1 10
persistentvolumeclaims 0 4
replicationcontrollers 0 20
secrets 0 10
services 0 10
services.loadbalancers 0 2
組態檔案:limit-range.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: mem-limit-range
namespace: manage-resources-ns
spec:
limits:
- default:
memory: 1Gi
cpu: 1
defaultRequest:
memory: 500Mi
cpu: 0.5
max:
memory: 2Gi
cpu: 2
min:
memory: 128Mi
cpu: 0.1
type: Container
default:當 Pod 或容器沒有指定資源限制時,帶入該值。
defaultRequest:當 Pod 或容器沒有指定資源請求時,帶入該值。
max:Pod 或容器可以請求或限制的資源最大值為該值。
min:Pod 或容器必須請求或限制的資源最小值為該值。
type:指定這些限制適用於容器級別。
查看 LimitRange
kubectl -n manage-resources-ns describe limitranges my-limit-range
結果如下
Name: my-limit-range
Namespace: manage-resources-ns
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Container memory 128Mi 2Gi 500Mi 1Gi -
Container cpu 100m 2 500m 1 -
組態檔案: limit-range-pod-1.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod1
namespace: manage-resources-ns
spec:
containers:
- name: c1
image: nginx
kubectl -n manage-resources-ns get pod pod1 -o jsonpath='{range .spec.containers[*]}{.name}{"\n"}{.resources}{"\n\n"}{end}'
結果如下
Limits:
cpu: 1
memory: 1Gi
Requests:
cpu: 500m
memory: 500Mi
可以看到,建立沒有請求和限制的 Pod,其請求和限制會自動帶入 limit-range 裡的 default, defaultRequest。
組態檔案: limit-range-pod-2.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod2
namespace: manage-resources-ns
spec:
containers:
- name: c1
image: nginx
resources:
requests:
memory: 100Mi
Error from server (Forbidden): error when creating "`limit-range-pod-2.yaml": pods "pod2" is forbidden: minimum memory usage per Container is 128Mi, but request is 100Mi
可以看到,建立低於 LimitRanges 請求的資源時,叢集回報 403 (Forbidden) 錯誤,並且給與錯誤訊息。
kubectl delete namespace manage-resources-ns
Kubernetes 的 ResourceQuota
和 LimitRange
是非常有效的資源管理工具,能夠確保多個團隊,在同一叢集中公平地使用資源。透過這些配額和限制,每個團隊都能擁有足夠的資源去完成他們的工作,同時也避免了資源的浪費和搶奪。
最後我們再快速複習一遍: