爲了防止容器調度到資源不足的節點上,能夠爲容器指定資源最少要求量。html
爲了防止容器無節制的使用 CPU、內存 等資源,能夠爲容器指定資源最大容許使用量。node
能夠爲容器指定資源請求量和資源約束量。mysql
資源通常指 CPU、內存。linux
資源請求量,指容器要求節點分配的最小容量,若是該節點可用容量小於容器要求的請求量,容器將被調度到其餘合適節點。git
資源約束量,指容器要求節點限制其使用的最大容量,若是容器內存使用量超過內容約束量,容器將被殺掉,若是指定了重啓策略,容器殺掉後將被重啓。github
涉及的參數sql
約束量 spec.containers[].resources.limits.cpu spec.containers[].resources.limits.memory spec.containers[].resources.limits.hugepages-<size> 請求量 spec.containers[].resources.requests.cpu spec.containers[].resources.requests.memory spec.containers[].resources.requests.hugepages-<size>
示例docker
apiVersion: v1 kind: Pod metadata: name: frontend spec: containers: - name: app image: images.my-company.example/app:v4 env: - name: MYSQL_ROOT_PASSWORD value: "password" resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m" - name: log-aggregator image: images.my-company.example/log-aggregator:v6 resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m"
K8S 中的一個 cpu 等於雲平臺上的 1 個 vCPU/核或裸機 Intel 處理器上的 1 個超線程。api
spec.containers[].resources.requests.cpu 爲 0.5 的容器確定可以得到請求 1 CPU 的容器的一半 CPU 資源。表達式 0.1 等價於表達式 100m, 能夠看做 「100 millicpu」。具備小數點(如 0.1)的請求由 API 轉換爲 100m;最大精度是 1m。微信
優先考慮使用 100m 的形式。
內存可使用E、P、T、G、M、K。也可使用對應的 2 的冪數:Ei、Pi、Ti、Gi、Mi、Ki。
Pod 的請求量等於內部全部容器的請求量之和。
Pod 的約束量等於內部全部容器的約束量之和。
調度程序確保所調度的 Pod 的資源請求量小於節點的容量。
即,調度程序將查找到資源可用量充足的,可用量大於請求量的節點來放置 Pod。
若是容器超過其內存最大限制,則可能會被終止。若是容器可從新啓動,kubelet 將從新啓動容器。
若是一個容器內存使用量超過其內存請求值,那麼當節點內存不足時,容器所處的 Pod 可能被逐出。
每一個容器可能被容許也可能不被容許使用超過其 CPU 約束的處理時間。 可是,容器不會因爲 CPU 使用率太高而被殺死。
spec.containers[].resources.limits.cpu 先被轉換爲 millicore 值,再乘以 100。其結果就是每 100 毫秒內容器可使用的 CPU 時間總量。在此期間(100ms),容器所使用的 CPU 時間不會超過它被分配的時間。
默認的配額(quota)週期爲 100 毫秒。 CPU配額的最小精度爲 1 毫秒。
如何獲知集羣資源使用狀況,須要經過 metrics-server 來獲取。
查看是否已安裝 metrics-server,如下說明沒安裝
# kubectl top node Error from server (NotFound): the server could not find the requested resource (get services http:heapster:) # kubectl get pods,svc,deployments -n kube-system | grep metrics-server #
開始安裝 metrics-server
git clone https://github.com/kubernetes-incubator/metrics-server cd metrics-server/ git checkout release-0.3
修改 metrics-server/deploy/1.8+/metrics-server-deployment.yaml
containers: - name: metrics-server #image: k8s.gcr.io/metrics-server/metrics-server:v0.3.6 image: registry.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6 imagePullPolicy: IfNotPresent args: - --cert-dir=/tmp - --secure-port=4443 - --metric-resolution=30s - --kubelet-preferred-address-types=InternalIP,Hostname,InternalDNS,ExternalDNS,ExternalIP - --kubelet-insecure-tls
參數說明
--metric-resolution=30s:從 kubelet 採集數據的週期; --kubelet-preferred-address-types:優先使用 InternalIP 來訪問 kubelet,這樣能夠避免節點名稱沒有 DNS 解析記錄時,經過節點名稱調用節點 kubelet API 失敗的狀況(未配置時默認的狀況); --kubelet-insecure-tls:kubelet 的10250端口使用的是https協議,鏈接須要驗證tls證書。--kubelet-insecure-tls不驗證客戶端證書
安裝
kubectl apply -f deploy/1.8+/
再次查看,須要多等一下子,確保採集到數據。
[root@master01 ~]# kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes" {"kind":"NodeMetricsList","apiVersion":"metrics.k8s.io/v1beta1","metadata":{"selfLink":"/apis/metrics.k8s.io/v1beta1/nodes"},"items":[]} [root@master01 1.8+]# kubectl top nodes NAME CPU(cores) CPU% MEMORY(bytes) MEMORY% master01 163m 4% 2093Mi 56% master02 147m 3% 1638Mi 44% master03 151m 3% 1609Mi 43% work01 141m 3% 1084Mi 29% work02 150m 3% 1097Mi 29% work03 138m 3% 1471Mi 39% [root@master01 1.8+]# kubectl top pod NAME CPU(cores) MEMORY(bytes) mysql-0 15m 202Mi mysql-1 14m 191Mi mysql-2 13m 182Mi nfs-client-provisioner-7db698bbc9-8ph55 2m 8Mi
已經能夠看到資源使用狀況。
建立一個測試用命名空間
# kubectl create namespace mem-example namespace/mem-example created
建立一個最大限額 100M,但最少須要 250M 的容器
# cat memory-request-limit-2.yaml apiVersion: v1 kind: Pod metadata: name: memory-demo-2 namespace: mem-example spec: containers: - name: memory-demo-2-ctr image: polinux/stress resources: requests: memory: "50Mi" limits: memory: "100Mi" command: ["stress"] args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1"]
# kubectl apply -f memory-request-limit-2.yaml pod/memory-demo-2 created
查看發現建立失敗
# kubectl get pod -n mem-example NAME READY STATUS RESTARTS AGE memory-demo-2 0/1 CrashLoopBackOff 3 88s
查看緣由
# kubectl get pod -n mem-example -o go-template='{{range.status.containerStatuses}}{{"Container Name: "}}{{.name}}{{"\r\nLastState: "}}{{.lastState}}{{end}}' memory-demo-2 Container Name: memory-demo-2-ctr LastState: map[terminated:map[containerID:docker://aaf41e exitCode:1 reason:OOMKilled ]]
其中有 reason:OOMKilled,說明超過了內存最大限額,致使了 OOM 而後被殺掉。
經過 resources.requests 和 resources.limits,能夠對資源進行最少容量要求和最大容量限制,確保容器能夠運行在資源充足的節點上,同時也不會因爲自身佔用了過多資源而影響節點上其餘容器。
微信公衆號:zuolinux_com