最近接手了一个K8s集群管理的工作,遇到个特别有意思的情况。同事在部署一个Deployment时,系统报错"0/4 nodes available: 3 Insufficient memory"。但当我打开Rancher Dashboard一看,明明每个节点都还有好几G的空闲内存啊!这就像你去银行取钱,ATM机显示余额充足,但柜台却说账户没钱一样让人困惑。
经过一番折腾,我发现这其实是Kubernetes资源管理机制中的一个经典认知误区。Rancher Dashboard显示的是节点的实际物理内存使用情况,就像你用free -h命令看到的那样。而Kubernetes调度器关注的却是另一种"货币"——你在Pod中通过resources.requests声明的"预留内存"。这两者可能相差甚远,就像你的信用卡额度和钱包里的现金不是一回事。
想象你经营一家咖啡店。Requests就像顾客提前预约时承诺的最低座位需求,而Limits是他们可能使用的最大座位数。即使店里还有很多空位(实际内存使用低),但如果所有预约座位(requests总和)已经占满,新顾客(Pod)也会被拒之门外。
在K8s中,每个Pod的资源配置通常这样写:
yaml复制resources:
limits:
memory: 2Gi
requests:
memory: 1Gi
这意味着:
Rancher 2.6的Dashboard默认显示的是节点的实际内存用量,这容易给人造成误导。就像只看咖啡店实时监控,发现还有很多空座,却忽略了这些座位可能都已被预约。要查看真实的"预约情况",我们需要更底层的工具。
运行这个魔法命令可以看清真相:
bash复制kubectl describe node | grep -E '((Name|Roles):\s{6,})|(\s+(memory|cpu)\s+[0-9]+\w{0,2}.+%\))'
输出类似这样:
code复制Name: node-1
Roles: worker
cpu 4870m (62%) 3000m (38%) 7870m (100%)
memory 11300Mi (98%) 200Mi (2%) 11500Mi (100%)
关键数字是那个98%——它表示所有Pod的requests内存总和已经占用了节点98%的"预约额度",尽管实际用量可能很低。
这里有个小学数学问题:11500Mi的2%是230Mi,远小于我们要部署的1G(1024Mi)需求。这就是报错的根本原因——不是物理内存不足,而是"预约额度"不够了。
有些Pod就像餐厅里占着座位却不点餐的顾客。找出它们:
bash复制kubectl get pods --all-namespaces -o jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name}: {.spec.containers[*].resources.requests.memory}{"\n"}{end}'
然后可以考虑:
如果是长期需求,给集群加节点最省心:
bash复制# 如果是云环境,通常通过控制台操作
# 本地环境可能需要手动添加节点
kubectl get nodes # 确认新节点已加入
有时候我们的requests设置过于保守。比如这个Deployment:
yaml复制resources:
requests:
memory: 1Gi
如果实际监控发现它只用500M,可以适当调低requests值。但要注意:这相当于降低了服务质量保证,可能影响稳定性。
要避免这种问题再现,需要更好的监控:
bash复制kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
然后就可以查看实际用量:
bash复制kubectl top pods
kubectl top nodes
VPA能自动调整requests值,就像智能餐厅管理系统:
bash复制# 安装VPA
kubectl apply -f https://github.com/kubernetes/autoscaler/releases/download/vertical-pod-autoscaler-0.11.0/vertical-pod-autoscaler.yaml
# 为Deployment创建VPA配置
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: my-app-vpa
spec:
targetRef:
apiVersion: "apps/v1"
kind: Deployment
name: my-app
updatePolicy:
updateMode: "Auto"
管理K8s集群就像经营城市的基础设施——不能只看表面数据。我现在的做法是:
记住,在K8s的世界里,"内存不足"可能不是真的没内存,而是你的"资源信用卡"刷爆了。下次遇到这种情况,别急着加内存条,先用kubectl describe node看看requests的使用情况。