共计 4372 个字符,预计需要花费 11 分钟才能阅读完成。
前言
为了避免容器调度到资源有余的节点上,能够为容器指定资源起码要求量。
为了避免容器无节制的应用 CPU、内存 等资源,能够为容器指定资源最大容许使用量。
更新历史
- 20200714 – 初稿 – 左程立
- 原文地址 – https://blog.zuolinux.com/2020/07/14/container-resources-request-limit.html
资源申请和资源束缚
能够为容器指定资源申请量和资源束缚量。
资源个别指 CPU、内存。
资源申请量,指容器要求节点调配的最小容量,如果该节点可用容量小于容器要求的申请量,容器将被调度到其余适合节点。
资源束缚量,指容器要求节点限度其应用的最大容量,如果容器内存使用量超过内容束缚量,容器将被杀掉,如果指定了重启策略,容器杀掉后将被重启。
波及的参数
束缚量
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>
示例
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 个超线程 。
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 如何调度
调度程序确保所调度的 Pod 的资源申请量小于节点的容量。
即,调度程序将查找到资源可用量短缺的,可用量大于申请量的节点来搁置 Pod。
带资源束缚的 Pod 如何运行
内存资源束缚
如果容器超过其内存最大限度,则可能会被终止。如果容器可重新启动,kubelet 将重新启动容器。
如果一个容器内存使用量超过其内存申请值,那么当节点内存不足时,容器所处的 Pod 可能被逐出。
CPU 资源束缚
每个容器可能被容许也可能不被容许应用超过其 CPU 束缚的解决工夫。然而,容器不会因为 CPU 使用率过高而被杀死。
spec.containers[].resources.limits.cpu 先被转换为 millicore 值,再乘以 100。其后果就是每 100 毫秒内容器能够应用的 CPU 工夫总量。在此期间(100ms),容器所应用的 CPU 工夫不会超过它被调配的工夫。
默认的配额(quota)周期为 100 毫秒。CPU 配额的最小精度为 1 毫秒。
如何获知集群资源应用状况,须要通过 metrics-server 来获取。
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