K8s apiserver OOM 故障分析
apiserver作为K8s集群的“大脑”,负责接收所有客户端请求(kubectl命令、UI操作、Pod调度等),并与etcd交互完成数据读写。一旦apiserver发生OOM(内存溢出),会直接导致服务崩溃,所有集群操作无法响应,属于P0级故障。本文结合生产中真实的apiserver OOM案例,拆解排查思路、核心命令,以及可落地的修复和优化步骤,帮运维人员快速恢复服务、规避隐患。
一、真实故障案例
某政企K8s集群(2主4从),日常运行约300个Pod、50个服务,某天突然出现kubectl命令执行无响应,集群控制台报错“503 Service Unavailable”,登录主节点查看,发现apiserver容器已退出,日志中频繁出现“Out Of Memory: Kill process xxx (kube-apiserver)”。排查后确认,由于近期集群扩容,Pod和服务数量翻倍,且存在大量频繁的资源查询、更新请求,apiserver默认内存配置不足,导致内存溢出,服务崩溃。故障影响:集群管理中断,无法进行Pod启停、资源调整,持续约30分钟。
二、排查命令(快速定位OOM原因)
1. 确认apiserver运行状态
# 查看apiserver容器状态(K8s默认以静态Pod运行在kube-system命名空间)
kubectl get pods -n kube-system | grep kube-apiserver
# 若状态为CrashLoopBackOff或Error,查看容器日志
kubectl logs -n kube-system kube-apiserver-[节点名] --tail=100
# 查看apiserver容器退出原因
kubectl describe pod kube-apiserver-[节点名] -n kube-system | grep -A 10 "Exit Code"2. 排查apiserver内存使用情况
# 查看apiserver容器当前内存占用(若容器未崩溃)
kubectl top pod kube-apiserver-[节点名] -n kube-system
# 登录主节点,查看系统内存使用情况
free -h
top # 查看kube-apiserver进程(进程名:kube-apiserver)的内存占用
# 查看apiserver进程的内存限制和请求配置
cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep -A 10 "resources"3. 定位OOM触发原因
# 查看apiserver日志,筛选OOM相关信息
kubectl logs -n kube-system kube-apiserver-[节点名] | grep -i "out of memory"
# 查看近期apiserver请求量,判断是否存在请求过载
kubectl logs -n kube-system kube-apiserver-[节点名] | grep "requests per second"
# 查看apiserver缓存配置(缓存不足会导致频繁查询etcd,增加内存消耗)
cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep -E "cache|etcd"4. 排查是否存在异常请求或资源泄露
# 查看apiserver的请求类型和频率(需安装metrics-server)
kubectl get --raw /metrics | grep -E "apiserver_request_total|apiserver_request_duration_seconds"
# 查看是否有大量异常的Pod创建、删除请求
kubectl get events -n kube-system --sort-by='.lastTimestamp' | grep -E "create|delete|pod" | tail -50三、修复步骤(先恢复服务,再优化根治)
第一步:紧急恢复apiserver服务(优先止损)
重启apiserver静态Pod(K8s会自动重启静态Pod,若未自动重启,手动删除Pod触发重启)
# 删除apiserver Pod,K8s会自动重建
kubectl delete pod kube-apiserver-[节点名] -n kube-system
# 查看重启后的状态,确认启动成功
kubectl get pods -n kube-system | grep kube-apiserver
# 查看日志,确认无OOM报错
kubectl logs -n kube-system kube-apiserver-[节点名] --tail=50临时调整apiserver内存限制(快速缓解内存压力)
# 编辑apiserver静态Pod配置文件
vim /etc/kubernetes/manifests/kube-apiserver.yaml
# 找到resources字段,增加内存请求和限制(根据节点内存调整,示例:节点内存16G,配置8G内存)
resources:
requests:
cpu: 100m
memory: 4Gi # 临时增加请求内存
limits:
cpu: 2000m
memory: 8Gi # 临时增加内存限制
# 保存文件后,K8s会自动重建apiserver Pod,应用新配置
kubectl get pods -n kube-system | grep kube-apiserver验证服务恢复
# 执行kubectl命令,验证apiserver正常响应
kubectl get nodes
kubectl get pods -n kube-system
# 查看apiserver内存占用,确认在限制范围内
kubectl top pod kube-apiserver-[节点名] -n kube-system第二步:根治优化,避免OOM再次发生
优化apiserver内存配置(核心优化)
根据集群规模(Pod数量、服务数量、请求量)调整内存配置,建议参考:
- 小规模集群(<500个Pod):内存限制4-8Gi
- 中规模集群(500-2000个Pod):内存限制8-16Gi
- 大规模集群(>2000个Pod):内存限制16-32Gi
# 编辑apiserver配置文件,设置合理的内存配置
vim /etc/kubernetes/manifests/kube-apiserver.yaml
# 调整resources字段(示例:中规模集群配置)
resources:
requests:
cpu: 500m
memory: 8Gi
limits:
cpu: 4000m
memory: 16Gi优化apiserver缓存配置(减少内存消耗)
# 编辑apiserver配置文件,添加缓存相关参数
vim /etc/kubernetes/manifests/kube-apiserver.yaml
# 在command字段中添加以下参数
- --kubelet-cache-timeout=10m # 延长kubelet缓存超时时间,减少查询
- --cache-duration=5m # 延长资源缓存 duration,减少etcd查询
- --etcd-compaction-interval=5m # 缩短etcd压缩间隔,减少数据量
# 保存后,K8s自动重建apiserver限制apiserver请求频率(避免请求过载)
# 编辑apiserver配置文件,添加请求限流参数
vim /etc/kubernetes/manifests/kube-apiserver.yaml
# 在command字段中添加
- --max-requests-inflight=1000 # 最大并发请求数(根据集群规模调整)
- --max-mutating-requests-inflight=500 # 最大并发修改请求数
# 保存后重建apiserver清理无用资源,减少apiserver负担
# 删除未使用的Namespace、Pod、Service
kubectl get namespaces --no-headers | grep -v "kube-" | grep -v "default" | awk '{print $1}' | xargs kubectl delete namespace
kubectl get pods --all-namespaces --no-headers | grep "Completed" | awk '{print $2 " -n " $1}' | xargs kubectl delete pod
# 清理过期的ConfigMap、Secret
kubectl get configmaps --all-namespaces --no-headers | grep -v "kube-" | awk '{print $2 " -n " $1}' | xargs kubectl delete configmap
kubectl get secrets --all-namespaces --no-headers | grep -v "kube-" | awk '{print $2 " -n " $1}' | xargs kubectl delete secret监控apiserver内存和请求量(提前预警)
通过Prometheus+Grafana监控apiserver的内存使用率、请求量、响应时间,设置阈值告警:
- 内存使用率超过85%触发告警
- 并发请求数超过max-requests-inflight的80%触发告警
- 响应时间超过1s触发告警
第三步:验证优化效果
# 查看apiserver内存占用,确认稳定在合理范围
kubectl top pod kube-apiserver-[节点名] -n kube-system
# 查看apiserver请求量和响应时间
kubectl get --raw /metrics | grep -E "apiserver_request_total|apiserver_request_duration_seconds_sum"
# 模拟高并发请求,验证是否会出现OOM
kubectl run -it --rm load-test --image=busybox -- sh -c "for i in {1..1000}; do kubectl get pods & done"四、注意事项
- 调整apiserver内存配置时,需结合主节点内存大小,避免内存分配过多导致节点内存不足。
- 限流参数需根据集群实际请求量调整,避免设置过低导致正常请求被拒绝。
- 定期清理无用资源,避免资源堆积导致apiserver内存消耗过高。
