为啥内存使用量大于我在 Kubernetes 的节点中设置的?
Posted
技术标签:
【中文标题】为啥内存使用量大于我在 Kubernetes 的节点中设置的?【英文标题】:Why memory usage is greater than what I set in Kubernetes's node?为什么内存使用量大于我在 Kubernetes 的节点中设置的? 【发布时间】:2020-01-03 10:32:06 【问题描述】:我只为 1 个 pod 分配了 650MB/30% 内存的资源(对于其他内置 pod,限制内存仅为 69%)
但是,在处理 pod 的过程中,pod 的使用率在 650MB 以内,但 node 的总体使用率是 94%。
为什么会发生,因为它应该有 69% 的上限?是不是因为其他内置的 pod 没有设置限制?如果内存使用率 > 100%,如何防止这种情况发生,因为有时我的 pod 会出错?
我的分配设置(kubectl describe nodes
):
Kubernetes Node 和 Pod 空闲时的内存使用情况:kubectl top nodes
kubectl top pods
Kubernetes Node 和 Pod 运行任务时的内存使用情况:kubectl top nodes
kubectl top pods
进一步测试的行为:
1. 准备命名空间test-ns下的deployment、pods和service
2. 由于只有 kube-system 和 test-ns 有 pod,因此为它们每个分配 1000Mi(来自kubectl describe nodes
),目标是小于 2GB
3. 假设 kube-system 和 test-ns 使用的内存小于 2GB 小于 100%,为什么内存使用率可以达到 106%?
在 .yaml 文件中:
apiVersion: v1
kind: LimitRange
metadata:
name: default-mem-limit
namespace: test-ns
spec:
limits:
- default:
memory: 1000Mi
type: Container
---
apiVersion: v1
kind: LimitRange
metadata:
name: default-mem-limit
namespace: kube-system
spec:
limits:
- default:
memory: 1000Mi
type: Container
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: devops-deployment
namespace: test-ns
labels:
app: devops-pdf
spec:
selector:
matchLabels:
app: devops-pdf
replicas: 2
template:
metadata:
labels:
app: devops-pdf
spec:
containers:
- name: devops-pdf
image: dev.azurecr.io/devops-pdf:latest
imagePullPolicy: Always
ports:
- containerPort: 3000
resources:
requests:
cpu: 600m
memory: 500Mi
limits:
cpu: 600m
memory: 500Mi
imagePullSecrets:
- name: regcred
---
apiVersion: v1
kind: Service
metadata:
name: devops-pdf
namespace: test-ns
spec:
type: LoadBalancer
ports:
- port: 8007
selector:
app: devops-pdf
【问题讨论】:
内存 94% 到底是什么意思?有多种不同类型的内存,Linux 机器的理想状态是接近 100% 的 RAM 消耗。 我刚刚使用kubectl top nodes
获取“CUP 和内存的运行时使用情况”进行监控。因此,我的案例是以 100% 的内存使用率运行 Puppeteer 代码,page.evaluate() 出现错误,无法打印 PDF。
如果不知道它究竟在报告什么 - 你无法讨论它。一般来说 - 约 100% 的消费并不意味着任何坏、好或中性。
【参考方案1】:
这种影响很可能是由于在该节点上运行的 4 个 Pod没有指定的内存限制,显示为 0 (0%)
。当然 0 并不意味着它甚至不能使用一个字节的内存,因为不使用内存就无法启动任何程序;相反,它意味着没有限制,它可以尽可能多地使用。不在 pod 中运行的程序(ssh、cron、...)也包括在总使用量中,但不受 kubernetes 的限制(由 cgroups)。
现在 kubernetes 以一种巧妙的方式设置内核 oom 调整值,以支持在其内存 request 下的容器,使其更有可能杀死在其内存之间的容器中的进程 request 和 limit,并使其最有可能杀死没有内存limits 的容器中的进程。然而,从长远来看,这仅显示为正常工作,有时内核可以杀死您最喜欢的容器中表现良好的您最喜欢的进程(使用少于其内存request)。见https://kubernetes.io/docs/tasks/administer-cluster/out-of-resource/#node-oom-behavior
在这种特殊情况下,没有内存限制的 pod 来自 aks 系统本身,因此不能在 pod 模板中设置它们的内存限制,因为有一个协调器可以恢复它(最终)。为了纠正这种情况,我建议您在 kube-system 命名空间中创建一个 LimitRange 对象,该对象将为所有没有限制的 pod 分配内存限制(在创建时):
apiVersion: v1
kind: LimitRange
metadata:
name: default-mem-limit
namespace: kube-system
spec:
limits:
- default:
memory: 150Mi
type: Container
(您需要删除已经存在的没有内存限制的 Pods 才能生效;它们将被重新创建)
这并不能完全消除问题,因为您最终可能会得到一个过度使用的节点;然而,内存使用将是有意义的,并且 oom 事件将更可预测。
【讨论】:
谢谢!这几乎是我需要的情况。但是,我在创建带有限制的 pod 时确实设置了限制(您可以从第一张图片中看到)。我尝试使用 1000Mi 在 .yaml 文件中运行您的 LimitRange 脚本,但它导致 2 个 pod 仅运行 kubectl top nodes 来查看内存使用了 2GB RAM 的 74%。 1000MB + 2*100MB 应该小于 60%,(1)为什么会是 74%? (2) 当我将请求和限制设置为 500Mi 时,为什么 2 个 pod 只运行 这个问题实际上是重复的,因为 similar question 已经讨论过了,但这里的 Janos's 答案实际上对我来说是完整的和解释性的。 嗨 Janos 和 mebius99,添加了“进一步测试的行为”部分进行解释,因为我 确实为 pod 设置了请求/资源限制(未设置为 0) 请进一步告知,谢谢。 在创建LimitRange后是否删除了没有内存限制的pod? 嗨@JanosLenart,是的,我在kubectl delete deployment devops-deployment
创建LimitRange 之前删除了pod。以上是关于为啥内存使用量大于我在 Kubernetes 的节点中设置的?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 OpenJDK Docker 容器会忽略 Kubernetes 中的内存限制?
为啥任务管理器显示的内存大于我的简单 hello world java 应用程序的最大堆内存?