在 Kubernetes 集群中,资源管理是确保系统稳定性和公平性的核心。如果不对 Pod 的资源使用进行限制,单个行为异常或配置错误的 Pod 可能会消耗掉节点上的所有内存,导致节点不稳定,甚至引发其他关键系统组件的 OOM(Out Of Memory)终止。
解决这个问题的“两把斧”就是资源的 requests(请求)和 limits(限制)。
1. Request 与 Limit 的区别
Request (请求)
- 目的: 确保性保障。requests 定义了 Pod 成功调度到节点上所需的最低资源量。
- 作用: Kube-scheduler 只会将 Pod 放置到具有足够可用资源满足其 requests 的节点上。它影响了 Pod 的服务质量(QoS Class)。
Limit (限制)
- 目的: 设定硬性上限。limits 定义了 Pod 在运行时可以使用的最大资源量。
- 作用: 对于内存资源,如果容器试图使用的内存超过了其 limit,Kubernetes 会立即终止该容器(发出 OOMKill 信号)。
2. 内存限制实操:防止节点 OOM
相比于 CPU 资源,内存(Memory)是不可压缩资源。一旦内存耗尽,系统稳定性将面临严重挑战。因此,对内存设置严格的 limits 至关重要。
我们通过一个示例 Deployment YAML 来演示如何为容器设置严格的内存限制。
示例 YAML 配置
以下配置定义了一个 Pod,它保证至少有 64 MiB 内存,但其内存使用量绝不能超过 128 MiB。
apiVersion: apps/v1
kind: Deployment
metadata:
name: memory-constrained-app
spec:
replicas: 1
selector:
matchLabels:
app: high-stability-worker
template:
metadata:
labels:
app: high-stability-worker
spec:
containers:
- name: worker-container
image: busybox:latest
command: ["sh", "-c", "echo 'Worker running'; sleep 3600"]
resources:
# Request: 调度保障。确保节点至少有 64 MiB 内存可用。
requests:
memory: "64Mi"
# Limit: 运行时硬限制。如果超过 128 MiB,容器将被 OOMKill。
limits:
memory: "128Mi"
3. 如何应用与验证
应用配置:
kubectl apply -f memory-constrained-app.yaml
验证配置是否生效:
使用 kubectl describe pod 可以清晰地看到资源限制已经被 Kubelet 认可并设置。
kubectl describe pod memory-constrained-app-xxxxxx
在输出的 Containers 部分,您会看到如下信息:
... (部分输出省略)
Containers:
worker-container:
Image: busybox:latest
... (省略)
Limits:
memory: 128Mi
Requests:
memory: 64Mi
... (部分输出省略)
观察 OOMKill 行为:
如果您的容器是一个会消耗大量内存的进程,并且实际使用量超过了 128Mi,Kubelet 会立即终止该容器。您可以通过查看 Pod 的事件(Events)和状态(Status)来确认是否发生了 OOMKilled:
kubectl get pod memory-constrained-app-xxxxxx
# 观察到 Restarts 计数增加,并且状态可能显示 OOMKilled
kubectl describe pod memory-constrained-app-xxxxxx
# 在 Events 中会看到类似信息:
# Warning OOMKilled ... Container worker-container failed to allocate memory.
总结与建议
通过为所有关键工作负载设置 limits.memory,您可以在容器级别强制执行内存隔离。这是确保节点稳定性的最有效手段。推荐的实践是将 requests.memory 设置为一个略低于或等于 limits.memory 的值,以保证 Pod 获得更高的 QoS 等级(Guaranteed 或 Burstable),进一步提升其稳定性。
汤不热吧