kubelet驱逐源码分析

本文详细分析了kubelet的内存驱逐过程,包括关键调用链路、初始化模块、evictionManager的工作原理。重点讲解了如何通过cadvisor获取节点和Pod的资源统计,如何判断驱逐条件,并根据阈值驱逐Pod。同时,指出了官方文档关于memory.available的误解,建议合理设置阈值以避免OOM。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

k8s版本信息:v1.17.4

1. 关键调用链路

2. initializeRuntimeDependentModules

省略kubelet->run->updateRuntimeUp,直接从initializeRuntimeDependentModules开发分析。

initializeRuntimeDependentModules的核心逻辑就是启动evictionManager和其他相关的组件。该函数只在kubelet运行时启动一次。

这里关注的核心函数:

(1)启动cadvisor

(2)启动containerManager

(3)启动evictionManager

因为evictionManager需要的数据是来源于,cadvisor的,所以必须等cadvisor启动完后在启动evictionManager

// initializeRuntimeDependentModules will initialize internal modules that require the container runtime to be up.
func (kl *Kubelet) initializeRuntimeDependentModules() {
  // 1. 启动cadvisor
  if err := kl.cadvisor.Start(); err != nil {
    // Fail kubelet and rely on the babysitter to retry starting kubelet.
    // TODO(random-liu): Add backoff logic in the babysitter
    klog.Fatalf("Failed to start cAdvisor %v", err)
  }
​
  // trigger on-demand stats collection once so that we have capacity information for ephemeral storage.
  // ignore any errors, since if stats collection is not successful, the container manager will fail to start below.
  kl.StatsProvider.GetCgroupStats("/", true)
  // Start container manager.
  node, err := kl.getNodeAnyWay()
  if err != nil {
    // Fail kubelet and rely on the babysitter to retry starting kubelet.
    klog.Fatalf("Kubelet failed to get node info: %v", err)
  }
  
  // 2.启动containerManager
  // containerManager must start after cAdvisor because it needs filesystem capacity information
  if err := kl.containerManager.Start(node, kl.GetActivePods, kl.sourcesReady, kl.statusManager, kl.runtimeService); err != nil {
    // Fail kubelet and rely on the babysitter to retry starting kubelet.
    klog.Fatalf("Failed to start ContainerManager %v", err)
  }
  
  // 3.启动evictionManager
  // eviction manager must start after cadvisor because it needs to know if the container runtime has a dedicated imagefs
  kl.evictionManager.Start(kl.StatsProvider, kl.GetActivePods, kl.podResourcesAreReclaimed, evictionMonitoringPeriod)
​
  ...
}

3. evictionManager.Start

核心逻辑如下 (1)是否利用kernel memcg notification机制。默认是否,可以通过--kernel-memcg-notification参数开启

kubelet 定期通过 cadvisor 接口采集节点内存使用数据,当节点短时间内内存使用率突增,此时 kubelet 无法感知到也不会有 MemoryPressure 相关事件,但依然会调用 OOMKiller 停止容器。可以通过为 kubelet 配置 --kernel-memcg-notification 参数启用 memcg api,当触发 memory 使用率阈值时 memcg 会主动进行通知;

memcg 主动通知的功能是 cgroup 中已有的,kubelet 会在 /sys/fs/cgroup/memory/cgroup.event_control 文件中写入 memory.available 的阈值,而阈值与 inactive_file 文件的大小有关系,kubelet 也会定期更新阈值,当 memcg 使用率达到配置的阈值后会主动通知 kubelet,kubelet 通过 epoll 机制来接收通知。

这个暂时先了解一下,不做深入。

(2)循环调用synchronize,waitForPodsCleanup来驱逐清理pod。循环间隔是10s,monitoringInterval默认10s

kl.evictionManager.Start(kl.StatsProvider, kl.GetActivePods, kl.podResourcesAreReclaimed, evictionMonitoringPeriod)
​
// Start starts the control loop to observe and response to low compute resources.
func (m *managerImpl) Start(diskInfoProvider DiskInfoProvider, podFunc ActivePodsFunc, podCleanedUpFunc PodCleanedUpFunc, monitoringInterval time.Duration) {
  
  thresholdHandler := func(message string) {
    klog.Infof(message)
    m.synchronize(diskInfoProvider, podFunc)
  }
  // 1.是否利用kernel memcg notification机制。默认是否,可以通过--kernel-memcg-notification参数开启
  if m.config.KernelMemcgNotification {
    for _, threshold := range m.config.Thresholds {
      if threshold.Signal == evictionapi.SignalMemoryAvailable || threshold.Signal =
<think>好的,我需要详细描述一下Kuberneteskubelet驱逐机制。首先,我应该回忆一下kubelet的基本职责,它负责管理节点上的Pod生命周期,包括启动、停止和监控容器。驱逐机制是kubelet在资源不足时保护节点稳定的重要功能。 接下来,我需要明确驱逐机制触发的原因。通常是节点上的资源压力,比如CPU、内存不足,或者磁盘空间不够。Kubernetes会根据这些资源的使用情况来决定是否驱逐Pod。 然后,我需要考虑驱逐信号的类型。kubelet监控的资源包括内存、磁盘(可能分为节点文件系统和镜像文件系统)、以及进程数(如PID)。当这些资源达到设定的阈值时,就会触发驱逐。 接下来是驱逐策略。这里可能分为硬驱逐和软驱逐。硬驱逐有明确的阈值,一旦达到立即触发驱逐。软驱逐则允许设置一个宽限期,超过阈值一段时间后才触发,这样可以避免短暂的高负载导致不必要的驱逐。 资源阈值方面,需要提到默认值和用户自定义的可能性。比如内存的默认eviction-hard可能设置为100Mi,用户可以通过配置调整这些值。 然后,驱逐的优先级和顺序。kubelet驱逐时会根据Pod的QoS等级,优先驱逐BestEffort,然后是Burstable,最后是Guaranteed。同时,会考虑资源使用量,优先驱逐使用量大的Pod。 驱逐过程的具体步骤也需要描述。包括监控资源、触发条件、选择Pod、发送终止信号、等待宽限期、强制终止等步骤。 此外,用户如何配置驱逐参数也很重要。比如通过kubelet的启动参数设置eviction-hard、eviction-soft等,以及调整监控间隔和宽限期。 最后,可能需要提到驱逐的局限性,比如无法完全避免服务中断,需要合理配置阈值和结合集群层面的策略(如HPA、Cluster Autoscaler)来优化资源管理。 在整理这些点时,要确保符合用户给的格式要求,比如行内数学表达式用$...$,独立公式用$$...$$,但这个问题中可能不太需要数学公式,不过要注意LaTeX的正确使用。同时用中文回答,结构清晰,分步骤说明。</think>Kuberneteskubelet驱逐机制是节点级别的资源保护机制,用于在节点资源不足时主动终止Pod以释放资源,确保节点稳定性。以下是其核心机制的分步解析: --- ### **1. 驱逐触发条件** kubelet持续监控节点资源使用情况,当以下资源达到阈值时触发驱逐: - **内存不足**(MemoryPressure) - **磁盘不足**(DiskPressure):包括节点文件系统(`nodefs`)和容器镜像存储(`imagefs`) - **进程数过多**(PIDPressure) --- ### **2. 驱逐信号(Eviction Signals)** kubelet通过以下指标判断资源状态: - **内存**:`memory.available`(可用内存) - **磁盘**: - `nodefs.available`(节点文件系统剩余空间) - `nodefs.inodesFree`(节点文件系统inode剩余数) - `imagefs.available`(容器镜像存储剩余空间) - **进程数**:`processes`(当前运行进程数) --- ### **3. 驱逐阈值类型** #### **(1) 硬驱逐(Hard Eviction)** - **定义**:直接触发驱逐的绝对阈值。 - **示例配置**: ```bash --eviction-hard=memory.available<500Mi,nodefs.available<10% ``` - **行为**:一旦达到阈值,立即驱逐Pod。 #### **(2) 软驱逐(Soft Eviction)** - **定义**:允许资源在阈值以上波动一定时间后再触发驱逐。 - **参数**: - `eviction-soft`:阈值(如`memory.available<1Gi`) - `eviction-soft-grace-period`:宽限期(如`memory.available=1m30s`) - `eviction-max-pod-grace-period`:最大允许的Pod终止宽限期。 - **行为**:资源持续超过阈值超过宽限期后触发驱逐。 --- ### **4. 驱逐优先级策略** kubelet按以下顺序选择被驱逐的Pod: 1. **QoS等级**: - 优先驱逐`BestEffort`(无资源请求/限制) - 其次`Burstable`(资源请求<限制) - 最后`Guaranteed`(资源请求=限制) 2. **资源使用量**: - 优先驱逐占用紧缺资源最多的Pod。 3. **Pod优先级**(若启用`PodPriority`): - 低优先级的Pod先被驱逐。 --- ### **5. 驱逐过程** 1. **监控资源**:kubelet通过cAdvisor获取实时资源使用数据。 2. **触发条件检查**:周期性检查是否达到硬/软驱逐阈值。 3. **选择目标Pod**:根据优先级策略选择待驱逐的Pod。 4. **优雅终止**: - 向Pod发送`SIGTERM`信号。 - 等待`terminationGracePeriodSeconds`(默认30秒)。 - 超时后强制终止(`SIGKILL`)。 5. **资源释放**:清理Pod占用的资源(如存储卷、网络资源)。 --- ### **6. 配置参数示例** 通过kubelet启动参数配置: ```bash --eviction-hard=memory.available<100Mi,nodefs.available<10% --eviction-soft=imagefs.available<15% --eviction-soft-grace-period=imagefs.available=2m --eviction-pressure-transition-period=5m # 脱离压力状态的等待时间 ``` --- ### **7. 驱逐的局限性** - **资源竞争**:无法完全避免短时间内的资源竞争。 - **全局视角缺失**:节点级别的驱逐无法感知集群整体资源状态,需结合调度器(Scheduler)和集群自动扩缩(Cluster Autoscaler)使用。 --- ### **8. 最佳实践** 1. **合理设置资源请求/限制**:避免Pod因未设置限制被优先驱逐。 2. **监控与告警**:通过Prometheus监控`kubelet_evictions`指标。 3. **动态调整阈值**:根据节点规格和工作负载特征调整驱逐阈值。 通过以上机制,kubelet能够在资源紧张时主动释放资源,保障节点核心组件(如kubelet、容器运行时)的稳定性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值