oomkilled 问题分析和解决方案

3,133 阅读3分钟

问题描述:

​ 目前K8s 集群容器经常有oomkilled问题出现进而影响容器服务正常工作

问题的定义和归纳:

​ oomkilled 触发类型按类别分应该有两大类,一类是属于k8s级别的,一类是属于系统级别的,具体我这边归纳又有以下几种:

  1. 第一种 容器耗用的内存达到Resource定义的limit上限,k8s会进入oomkilled动作
  2. 第二种 当QOS类型为Burstable,容器调度算法是根据request定义的内存来估算资源。按(request)最小资源分配过多容器到一个主机节点,容器内存增长触发宿主机oomkilled (举例: 宿主16G内存,pod request: 1G,Limit 2G. 分配了15个pod到宿主机,这15个容器如果使用内存超过1G以上则共享剩余1G内存,而这1G内是跟宿主机共享的,会导致触发系统级的oomkilled)

细化分类问题原因

根据我们业务环境引起第二种系统oomkilled由以下几种原因导致

1. 系统没设置预留内存,这块待优化kubelet 预留系统资源,使pod和系统一些服务对资源需求有一个界限,避免抢占导致系统级的oomkilled
2.  容器服务未声明内存申请多少,导致分配过多服务在一节点上,服务动态耗用内存触发oomkilled。这块有几种问题:
 - 中间件未声明内存申请
 - 部分服务走的旧的jenkins job部署,未走新的ansible playbook 更新逻辑
 - 手动部署的完全没走线上逻辑
 - 旧的服务一直没更新过
3.   容器按request分配调度,n* request * 1G < n * limit * 2G,request 和limit 不全等约束导致pod资源抢占进而触发系统oomkilled.

解决方案:

​ 根据上面的问题定义,第1种比较好解决,第一种是属于声明配置容器内存过小而导致的。只要有监控并且研发了解业务本身的运算逻辑和资源耗用,一般可以修改一下声明内存大小就可以解决。

​ 第二种问题本质上是声明分配资源未明确和资源抢占问题,上面三种都是需要解决。但只能逐步推进,根据线上最多问题,优先解决 ”细化分类问题原因 3 和 2“

关于QOS

QOS类型决定pod服务的高保障性和oom的优先级,但是鉴于Guaranteed是强分配资源,所以不太适用我们的环境,因为我们当前宿主每台是4核,16G,如果强制分配资源,cpu资源太少,cpu最小资源约束会影响每台宿主可以承裁的容器数量。所以Burstable模式是比较合适的,但是为了减少因为 ”细化分类问题原因3" 的问题,内存的限制可以把request 和 limit设置相等。

QoS(Quality of Service) 简介
QoS(Quality of Service),大部分译为 “服务质量等级”,又译作 “服务质量保证”,是作用在 Pod 上的一个配置,当 Kubernetes 创建一个 Pod 时,它就会给这个 Pod 分配一个 QoS 等级,可以是以下等级之一:

Guaranteed:Pod 里的每个容器都必须有内存/CPU 限制和请求,而且值必须相等。如果一个容器只指明limit而未设定request,则request的值等于limit值。
Burstable:Pod 里至少有一个容器有内存或者 CPU 请求且不满足 Guarantee 等级的要求,即内存/CPU 的值设置的不同。
BestEffort:容器必须没有任何内存或者 CPU 的限制或请求。
该配置不是通过一个配置项来配置的,而是通过配置 CPU/MEM的 limits 与 requests 值的大小来确认服务质量等级。

为系统守护进程预留计算资源:

kubernetes.io/zh/docs/tas…