压力驱逐机制

kubelet 监控节点的CPU、内存、磁盘工具和文件系统的inode等资源。
这些资源中的一个或者多个达到压力水位,kubelet会主动使节点上的一个或多个Pod失效,以收回资源。驱逐的方式是将Pod的 PodPhase 设置为 Failed,来终止 Pod。

节点压力驱逐时,kubelet 会考虑是:
软驱逐条件(有宽限期 viction-max-pod-grace-period),
还是硬驱逐 (宽限期为 0)

如Pod是由控制器管理,Pod终止后,Pod控制器会创建新的Pod来替代被驱逐的Pod。
驱逐的条件:

驱逐信号 描述
memory.available memory.available := node.status.capacity[memory] - node.stats.memory.workingSet
nodefs.available nodefs.available := node.stats.fs.available
nodefs.inodesFree nodefs.inodesFree := node.stats.fs.inodesFree
imagefs.available imagefs.available := node.stats.runtime.imagefs.available
imagefs.inodesFree imagefs.inodesFree := node.stats.runtime.imagefs.inodesFree

关于可用内存 memory.available

我们可以参考如下脚本来加深认识

  1. #!/bin/bash
  2. #!/usr/bin/env bash
  3. # This script reproduces what the kubelet does
  4. # to calculate memory.available relative to root cgroup.
  5. # current memory usage
  6. memory_capacity_in_kb=$(cat /proc/meminfo | grep MemTotal | awk '{print $2}')
  7. memory_capacity_in_bytes=$((memory_capacity_in_kb * 1024))
  8. memory_usage_in_bytes=$(cat /sys/fs/cgroup/memory/memory.usage_in_bytes)
  9. memory_total_inactive_file=$(cat /sys/fs/cgroup/memory/memory.stat | grep total_inactive_file | awk '{print $2}')
  10. memory_working_set=${memory_usage_in_bytes}
  11. if [ "$memory_working_set" -lt "$memory_total_inactive_file" ];
  12. then
  13. memory_working_set=0
  14. else
  15. memory_working_set=$((memory_usage_in_bytes - memory_total_inactive_file))
  16. fi
  17. memory_available_in_bytes=$((memory_capacity_in_bytes - memory_working_set))
  18. memory_available_in_kb=$((memory_available_in_bytes / 1024))
  19. memory_available_in_mb=$((memory_available_in_kb / 1024))
  20. echo "memory.capacity_in_bytes $memory_capacity_in_bytes"
  21. echo "memory.usage_in_bytes $memory_usage_in_bytes"
  22. echo "memory.total_inactive_file $memory_total_inactive_file"
  23. echo "memory.working_set $memory_working_set"
  24. echo "memory.available_in_bytes $memory_available_in_bytes"
  25. echo "memory.available_in_kb $memory_available_in_kb"
  26. echo "memory.available_in_mb $memory_available_in_mb"

可以看到 memory.available 的值来自 cgroupfs, 而不是像 free 这样的工具呈现的数值。
node.status.capacity[memory] 是节点内存总量,参照 /proc/meminfo 中的 MemTotal
node.stats.memory.workingSet 是已工作负载占用内存,计算方式为:
memory_usage_in_bytes - memory_total_inactive_file
即:使用中的内存,减去可释放的缓存(未激活的匿名缓存页),这应该是一个很合理的可用内存算法。

nodefs是—root-dir目录所在分区,imagefs是docker安装目录所在的分区