持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情
k8s可以对pod中的每个容器设置cpu和内存的request和limit值,本文总结这些设置是如何对容器进程的实际运行产生影响的。
1. Pod 的服务质量
QoS(Quality of Service),服务质量等级,是作用在 Pod 上的一个配置,当 Kubernetes 创建一个 Pod 时,它就会给这个 Pod 分配一个 QoS 等级,可以是以下等级之一:
- Guaranteed:Pod 里的每个容器(包括普通容器和初始容器,下同)都必须有内存/CPU 限制和请求,而且限制和请求值相等。
- Burstable:Pod 里至少有一个容器有内存或者 CPU 请求或限制,且不满足 Guarantee 等级的要求,即内存/CPU 的值设置的不同。
- BestEffort:容器必须没有任何内存或者 CPU 的限制或请求。 QoS 类决定 Pod 的调度和驱逐策略,同时影响系统对其容器进程的OOM kill优先级。
Kubernetes 通过给 pod 设置 QoS 级别,当资源不足时先kill优先级低的 pod,在实际使用过程中,通过oom_score分数值来实现,oom_score分数值越高,越容易被 OOM killer 杀死。
oom_score 主要有两部分组成,一部分是系统打分,主要是根据该task的内存使用情况,另外一部分是用户打分,也就是 oom_score_adj。
对于Guaranteed级别的 Pod,oom_score_adj 参数设置成了-998,对于Burstable级别的 Pod,oom_score_adj 参数设置成了999,对于Best-Effort级别的 Pod,oom_score_adj 参数设置成了1000。
2. pod 容器资源设置对cgroup的影响
cpu
cpu 的 request 体现在 cgroup 中的 cpu.shares,
其值为 1024 * cpu.request,比如 cpu.request=2,则 cpu.shares=2048,在发生cpu资源争用时,按cpu.shares的比例分配cpu资源。
如果 cpu.request 没有设置,则cpu.shares = 2。
cpu的limit 等于 cgroup 中的 cpu.cfs_quota_us/cpu.cfs_period_us, 为cpu的使用上限。
memory
memory 的 request 只影响 pod 的调度,不影响 cgroup,即不影响进程的实际运行。
memory 的 limit 的值等于 cgroup 中的 memory.limit_in_bytes,为memory的使用上限。
3. cgroup中的内存限制及OOM
failcnt
memory使用达到上限,即memory.usage_in_bytes(约为memory.stat中rss和cacahe之和) = memory.limit_in_bytes,则申请内存时memory.failcnt计数加一,此时内核会尝试进行系统级别的内存回收。
OOM killer
cadvisor容器监控指标中的container_memory_working_set_bytes表示进程当前使用的内存集,等于total usage - inactive file,它表示不可被驱逐的内存。
// The amount of working set memory, this includes recently accessed memory,
// dirty memory, and kernel memory. Working set is <= "usage".
// Units: Bytes.
WorkingSet uint64 `json:"working_set"`
当该值达到内存上限时,cgroup调用OOM killer杀死容器(而非pod级的驱逐)。
总结
- pod通过设置cpu和内存的request和limit的值的组合,设定pod的QoS等级,给出不同的oom_score_adj参数,从而影响容器进程在系统内存承压时OOM kill的优先级
- cpu的reqest和limit通过cgroup对容器进程产生影响
- memory的limit通过cgroup对容器进程产生影响,request无实际影响