1、资源限制
默认情况下,容器可以无限制的使用节点上所有的资源(如内存、cpu)。
假设在一个节点上运行多个pod,其中一个pod的访问量突然增加,该pod将不断请求节点资源。最终该pod占用大量资源,导致其他的资源缺乏足够的资源可用,从而引发访问速度非常慢,甚至无法正常提供服务的问题。
为了避免出现这类问题,可以对pod中的容器进行资源限制,确保他们不会超出指定的资源配额。资源限制相关配置字段如下
resources.limits.cpu: 限制容器的CPU使用量。可以指定以下CPU核心(例如,0.5表示半个核心,1表示1个核心)或以millicores(例如500m表示半个核心,1000m表示1个核心)为单位的CPU限制
resources.limits.memory:限制容器的内存使用量。可以指定Ki、Mi、Gi等为单位的内存限制
resources.limits.hugepages<size>:限制容器的HugePages使用量。可以指定限制的HugePages大小(如2Mi、1Gi等)
此外,还可以为容器配置资源请求,用于指定容器所需的最小资源量,以确保这个pod被调度到能够满足其最小资源请求的节点上。资源请求相关配置字段如下
resources.requests.cpu:指定容器所需的最小CPU资源
resources.requests.memory:指定容器所需的最小内存资源
resources.requests.hugepages<size>:指定容器所需的最小hugepages资源
cat pod-nginx.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
app: pod-nginx
name: pod-nginx
spec:
containers:
- name: web
image: uhub.service.ucloud.cn/librarys/nginx:1.23
resources:
# 资源请求
requests:
memory: "64Mi"
cpu: "0.25"
# 资源限制
limits:
memory: "128Mi"
cpu: "0.5"
- 在上述配置中,resources部分定义了容器的资源请求和资源限制具体配置如下:
requests:定义容器的资源请求。这里告知调度器,这个pod需要被调度到至少满足64Mi内存和0.25核CPU的节点上
limits:定义容器的资源限制。这里表示该容器不允许超过128Mi,内存和0.5核CPU。容器如果尝试使用更多资源,容器资源将受到限制
kubectl apply -f pod-nginx.yaml
- 使用stress工具对该容器进行压力测试,以验证容器的资源限制。
进入容器中,安装stress工具
[root@k8s-master k8s]# kubectl exec -it pod-nginx -- bash
root@pod-nginx:/# apt update
root@pod-nginx:/# apt install stress -y
使用stres工具对CPU进行压力测试
stress -c 2
其中-c参数用于指定压测时生成的进程数量。这些进程在工作时会持续计算随机数的平方根,从而消耗更多的CPU。可以通过 kubectl top命令查看pod的资源利用率
需要注意的是,kubectl top命令依赖于metric-server服务,需要额外的部署。
详见: https://github.com/kubernetes-sigs/metrics-server
[root@k8s-master k8s]# kubectl top pod
NAME CPU(cores) MEMORY(bytes)
pod-nginx 498m 57Mi
可以看到,该pod的CPU使用受到限制,正常不会超出500m,内存也会限制在128Mi范围内
如果容器内存使用量超过限制值,kubelet组件会重新启动容器,并将容器的状态标记为 OOMKilled。当CPU使用量超过限制时,kubelet组件不会触发容器的重启。这是因为超出内存限制通常会导致应用程序无法正常工作,而重启容器可以简单的解决这种问题。相比之下,超出CPU限制并不会导致应用程序无法正常工作,只是降低了处理性能,这是一种可以接受的情况
资源限制主要目的是防止容器无限制的占用节点的计算资源。为了保障节点的稳定性和性能,通常不建议限制值超过节点硬件配置的80%。以确保容器在可以接受打最大资源范围内运行,有效的平衡各pod之间的资源利用,从而提高整个集群的可靠性
2、资源请求对pod调度的影响
当容器配置资源请求 后,调度器会根据该请求值选择能够满足的节点。如果没有节点能满足,则pod将无法被调度,并且处于pending状态。因此,kubernetes中存在一种资源管理机制,这个机制的作用如下:
调度决策:帮助调度器在集群中选择合适的节点,以满足pod的资源请求
均衡负载:根据资源请求来平衡节点上的资源使用,减少某些节点资源过载而其他节点资源空闲的情况
资源规划:有助于规划和优化集群的资源分配,提高整体资源利用率
例如在kubernetes机器中创建了6个pod,其中3个pod资源请求为500Mi内存和0.6cpu,另外3个pod资源请求为1Gi内存和1核CPU
在这种情况下,创建一个资源请求为1Gi内存和1核CPU的pod,调度器会将该pod分配给node1节点,这是因为node2节点总资源为3Gi内存和3.2核CPU,其中CPU无法满足pod的请求
需要了解的时候,调度器还会考虑其他因素,如节点资源利用率、污点、亲和性规则等,以做出最终的调度决策,而资源请求指示影响调度决策的因素之一
如果再创建一个pod,资源请求为2Gi内存和1核CPU,那么pod将无法被调度。因为两个node节点只能满足cpu的需求,不能满足内存需求。此时通过kubectl describe pod <pod名称>命令查看事件,将看到Insufficient memory的提示
需要注意的是,资源请求并不会直接占用节点资源,而是用于调度和分配。这样可以避免将pod调度到资源不足的节点上,以确保pod在运行时能够正常获取所需的计算资源
3、理想的资源配额是多少
容器资源请求和资源限制具体配置为多少并没有具体的答案。因为资源请求和资源限制的配置取决于应用程序的资源使用情况。不过,可以使用一些技巧来推算出合理的值
limits值不超过节点硬件配置的80%
requests值必须小于limits值,否则创建pod时会提示相关错误
requests值建议小于limis值的20%~30%。这是一个良性参考值
仅配置limits值时,则requests值默认与limits值保持一致。仅配置requests时,limits默认没有限制。
资源请求对整个集群资源利用率和性能有着重要的影响。如果配置不当,可能会引发一些问题。例如,当pod的资源请求值设置过大时,则节点只能容纳较少的pod,这会导致节点资源空闲率较高。相反,如果资源请求值设置过小,则节点能容纳更多的pod,这也可能导致节点资源利用率的增加,从而降低节点的处理性能