Day 21 - 常見問題與建議 (2)
本日共賞
- 超出資源限制 (Exceeding CPU/Memory Limit)
- 資源配額
希望你知道
超出資源限制
k8s 可以讓管理者限制配置到 Pod 或 Container 的資源 (CPU, Memory),而使用者 (或開發者) 不會特別知道這些限制。一般來說都會等到發現部署失敗後才會察覺到有資源的限制。
底下為 error-limit-resource.yaml 內容
# error-limit-resource.yaml
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: err-limit-nginx
spec:
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
resources:
requests:
memory: 100Gi <=== 請分配 100G 的記憶體給我!
這裡指定需要分配 100G 的 memory,透過 kubectl 部署,應該能理解正常來說都不會成功吧!
一般人的機器應該不會超過 100G 的記憶體吧,有神機請自行調高後再測試
$ kubectl apply -f error-limit-resource.yaml
deployment "err-limit-nginx" configured
接著觀察 Pod
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
err-limit-nginx-b4548b69d-ll665 0/1 Pending 0 1m
這時候發現 Pod 並沒有運作,接著再觀察 pods/err-limit-nginx-b4548b69d-ll665
內的 Event
記得將 err-limit-nginx-b4548b69d-ll665 改成正確的名稱
$ kubectl describe pods/err-limit-nginx-b4548b69d-ll665
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 46s (x8 over 1m) default-scheduler No nodes are available that match all of the predicates: Insufficient memory (1).
...
這裡就會顯示 Insufficient memory
,很清楚的說明 Pod 無法成功建立的原因是因為記憶體不足。
也有可能是因為 CPU 不足,都會顯示在 Event 內
如果想查看預設的資源限制可以使用
$ kubectl get limitrange [namespace]
如果是查詢 default 內的資源限制則 [namespace]
可不填
$ kubectl get limitrange
No resources found.
minikube 預設沒有任何資源限制,但若是使用雲端方案 (GCP, AWS, …) 等等,就會發現預設是有資源限制的。
建議方案
針對超出資源限制的問題,建議以下方式處理
- 請系統管理者修改資源限制
- 降低部署物件所需要的資源
- 擴充硬體設備 (一般開發者較無法達成)
資源配額
與資源限制很類似,k8s 允許管理者指定資源配額 (Resource Quotas)。例如 Pod 在某個命名空間的最大運行數、最多能有幾個 Secret 物件或是 Memory, CPU 最多能使用多少等等。
更多說明請參考 官方網站
也正是因為如此,在部署物件到 k8s 的時候,可能就會面臨資源配額不足的問題。接著我們來實際模擬一下,首先建立 quotas.yaml 模擬資源配額如下
# quotas.yaml
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: resource-quota
spec:
hard:
pods: 1 <=== 只准運行一個 Pod
這裡我們指定只能運行一個 Pod,並部署到 k8s 預設命名空間 default 內
$ kubectl apply -f quotas.yaml
resourcequota "resource-quota" created
建議測試前先將 default 內運行的 Deployment 與 Pod 刪除
接著編輯 quotas-deploy.yaml
# quotas-deploy.yaml
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: quotas-nginx
spec:
replicas: 2 <=== 指定運行兩個 Pod,很明顯違反最多只能運行一個 Pod 的規範
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
並部署到 k8s
$ kubectl apply -f quotas-deploy.yaml
deployment "quotas-nginx" created
接著查看 Deployment 與 Pod 狀態
$ kubectl get deploy
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
quotas-nginx 2 1 1 1 1m
$ kubectl get po
NAME READY STATUS RESTARTS AGE
quotas-nginx-75f4785b7-98762 1/1 Running 0 1m
雖然我們指定運行兩個 Pod (DESIRED: 2),但是只有一個 Pod 正確運行。於是再查看 Deployment 內容
$ kubectl describe deployment/quotas-nginx
...
NewReplicaSet: quotas-nginx-75f4785b7 (1/2 replicas created) <=== 只建立 1 個
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 3m deployment-controller Scaled up replica set quotas-nginx-75f4785b7 to 2
...
這裡發現 (1/2 replicas created)
,的確只有一個 Pod 被建立,繼續追蹤 NewReplicaSet: quotas-nginx-75f4785b7
$ kubectl describe replicaset/quotas-nginx-75f4785b7 <=== 記得換名字喔
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 6m replicaset-controller Created pod: quotas-nginx-75f4785b7-98762
Warning FailedCreate 1m (x17 over 6m) replicaset-controller Error creating: pods "quotas-nginx-75f4785b7-" is forbidden: exceeded quota: resource-quota, requested: pods=1, used: pods=1, limited: pods=1
終於在 replicaset 中的 Event 發現 exceeded quota
。就像我們預設的情況一樣,我們給環境射了一個最多只能運行一個 Pod 的限制,所以當你想要運行兩個 Pod 的時候就會違反了規則。
建議方案
遇到這種情況,可以考慮使用下面方式處理
- 請系統管理者修改資源配額
- 刪除已部署且不必要的資源
本文與部署檔案同步發表於 https://jlptf.github.io/ironman2018-day21/