Skip to content

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运行状态

bash
# 查看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内存使用情况

bash
# 查看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触发原因

bash
# 查看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. 排查是否存在异常请求或资源泄露

bash
# 查看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触发重启)

bash
# 删除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内存限制(快速缓解内存压力)

bash
# 编辑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

验证服务恢复

bash
# 执行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
bash
# 编辑apiserver配置文件,设置合理的内存配置
vim /etc/kubernetes/manifests/kube-apiserver.yaml

# 调整resources字段(示例:中规模集群配置)
resources:
  requests:
    cpu: 500m
    memory: 8Gi
  limits:
    cpu: 4000m
    memory: 16Gi

优化apiserver缓存配置(减少内存消耗)

bash
# 编辑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请求频率(避免请求过载)

bash
# 编辑apiserver配置文件,添加请求限流参数
vim /etc/kubernetes/manifests/kube-apiserver.yaml

# 在command字段中添加
- --max-requests-inflight=1000  # 最大并发请求数(根据集群规模调整)
- --max-mutating-requests-inflight=500  # 最大并发修改请求数

# 保存后重建apiserver

清理无用资源,减少apiserver负担

bash
# 删除未使用的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触发告警

第三步:验证优化效果

bash
# 查看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内存消耗过高。