一、Kubernetes服务质量QoS是什么

在Kubernetes集群里跑应用的时候,你有没有遇到过这种情况:某个Pod突然把CPU吃满了,导致其他Pod饿得嗷嗷叫?或者某个Pod内存泄漏,把整个节点拖垮了?这时候就需要QoS(Quality of Service)机制来救场了。

简单来说,QoS就是Kubernetes给Pod划分的三六九等。就像飞机有头等舱、商务舱和经济舱一样,Kubernetes把Pod也分为三个等级:

  1. Guaranteed(保证型):VIP级别,资源管够
  2. Burstable(突发型):普通会员,饿不死但也吃不饱
  3. BestEffort(尽力型):站票选手,自求多福

二、QoS的三种等级详解

2.1 Guaranteed级别

这种Pod是亲儿子待遇,资源有绝对保障。要达成这个级别需要满足两个条件:

  1. 必须同时设置CPU和内存的limits
  2. requests必须等于limits(不能少也不能多)

来看个YAML示例(技术栈:Kubernetes v1.22):

apiVersion: v1
kind: Pod
metadata:
  name: guaranteed-pod
spec:
  containers:
  - name: nginx
    image: nginx
    resources:
      limits:
        cpu: "1"
        memory: "1Gi"
      requests:
        cpu: "1"
        memory: "1Gi"

这个配置里,CPU和内存的requests和limits完全一致,所以这个Pod会被标记为Guaranteed级别。当资源紧张时,系统会优先保证这类Pod的资源供给。

2.2 Burstable级别

这类Pod就像普通打工人,基本工资(requests)有保障,但奖金(超出requests的部分)要看公司效益。满足以下任一条件就是Burstable:

  1. 只设置了requests没设置limits
  2. requests和limits不相等
  3. 只设置了部分资源的requests/limits

示例配置:

apiVersion: v1
kind: Pod
metadata:
  name: burstable-pod
spec:
  containers:
  - name: nginx
    image: nginx
    resources:
      limits:
        memory: "2Gi"
      requests:
        cpu: "0.5"
        memory: "1Gi"

这个例子里,内存有requests和limits但不相等,CPU只设置了requests,所以是典型的Burstable Pod。

2.3 BestEffort级别

这类Pod就像临时工,啥保障都没有。判断标准很简单:啥资源限制都没设置。

示例配置:

apiVersion: v1
kind: Pod
metadata:
  name: best-effort-pod
spec:
  containers:
  - name: nginx
    image: nginx

这种Pod在资源紧张时最先被干掉,适合那些无关紧要的后台任务。

三、资源限制的实战技巧

3.1 CPU限制的坑

CPU限制和其他资源不太一样,它是个软限制。比如下面这个配置:

resources:
  limits:
    cpu: "1"
  requests:
    cpu: "0.5"

这里的"1"表示1个CPU核心,实际使用时:

  1. 如果节点有空闲CPU,Pod可以突破limits限制
  2. 当其他Pod也需要CPU时,才会被限制在1核以内
  3. CPU是以时间片方式分配的,不是硬性上限

3.2 内存限制的血泪教训

内存限制可是硬限制,超过就OOM(Out Of Memory)被杀。看这个例子:

resources:
  limits:
    memory: "512Mi"
  requests:
    memory: "256Mi"

如果这个容器内存使用超过512MiB,Kubernetes会毫不留情地干掉它。所以设置内存limits时一定要留够余量。

3.3 如何合理设置资源限制

根据经验,建议这样设置:

  1. 生产环境核心服务:用Guaranteed级别
  2. 普通服务:Burstable,requests设为日常使用量的120%
  3. 测试/开发环境:BestEffort或者低配Burstable

监控工具建议:

  • 用Metrics Server收集资源使用数据
  • 用Prometheus做长期监控
  • 用Grafana做可视化

四、QoS的底层实现原理

4.1 Linux内核的cgroups机制

Kubernetes的QoS实际上是靠Linux的cgroups实现的。每个Pod都会被分配到对应的cgroup中:

  1. /kubepods.slice:所有Pod的父cgroup
  2. /kubepods/burstable.slice:Burstable Pods
  3. /kubepods/besteffort.slice:BestEffort Pods

4.2 OOM评分机制

当节点内存不足时,内核会根据OOM分数决定杀哪个进程。分数计算规则:

  1. Guaranteed Pod:-998分(几乎不会被杀)
  2. Burstable Pod:min(max(2, 1000 - (1000 * memoryRequest)/memoryAvailable)), 999)
  3. BestEffort Pod:1000分(最先被杀)

4.3 CPU调度优先级

CFS调度器会给不同QoS的Pod不同的权重:

  1. Guaranteed:1024
  2. Burstable:2-1024之间动态调整
  3. BestEffort:2

五、常见问题解决方案

5.1 Pod频繁OOM被杀

症状:Pod经常重启,日志显示OOMKilled

解决方案:

  1. 检查内存limits是否设置过小
  2. 使用kubectl top pod查看实际使用量
  3. 适当提高limits值
  4. 优化应用内存使用

5.2 CPU节流影响性能

症状:应用性能下降,监控显示CPU throttling

解决方案:

  1. 检查CPU limits是否设置过低
  2. 考虑使用Guaranteed级别
  3. 优化应用CPU使用效率
  4. 增加节点资源

5.3 节点资源耗尽

症状:新Pod无法调度,节点状态显示MemoryPressure/DiskPressure

解决方案:

  1. 使用ResourceQuota限制命名空间资源
  2. 设置合理的requests/limits
  3. 增加集群节点
  4. 驱逐低优先级Pod

六、最佳实践总结

  1. 重要服务一定要用Guaranteed级别
  2. 内存limits要留足安全余量(建议20%)
  3. 使用HPA(Horizontal Pod Autoscaler)自动扩缩容
  4. 定期检查资源使用情况并调整限制
  5. 测试环境模拟压力测试,找出合适的资源限制值

记住,资源限制不是一劳永逸的,随着业务发展要不断调整。就像给小孩买衣服,不能总按去年的尺码来。