Kubelet 资源驱逐 (Eviction) 通信流程
Kubelet 资源驱逐 (Eviction) 通信流程
目标
这篇文档只回答一个核心问题:kubelet 如何在节点资源不足时决定并执行 Pod 驱逐?
重点放在 EvictionManager 的监控机制、驱逐决策逻辑以及驱逐执行流程。
一句话摘要
kubelet 的 EvictionManager 定期监控节点资源使用,当资源超过阈值时,根据 QoS 和优先级选择 Pod 进行驱逐,以保护节点稳定性。
1. 流程总览
从通信视角看,这条链路可以拆成 3 个阶段:
- 资源监控阶段:EvictionManager 定期采集节点资源使用情况。
- 决策判断阶段:根据阈值和策略决定是否需要驱逐以及驱逐哪些 Pod。
- 执行驱逐阶段:通过 API Server 删除选中的 Pod。
架构总览图
flowchart TB
subgraph 资源采集["资源采集层"]
direction TB
CAD[cAdvisor<br/>容器资源监控]
SYS[系统信息<br/>节点资源]
SIG[信号采集器<br/>Memory/Disk/PID]
end
subgraph EvictionManager["EvictionManager"]
direction TB
MON[Monitor<br/>资源监控循环]
THRESH[ThresholdManager<br/>阈值管理]
RANK[Ranking<br/>Pod 排序]
EVICT[Evictor<br/>驱逐执行]
end
subgraph 决策依据["决策依据"]
direction LR
QOS[Pod QoS<br/>Guaranteed/Burstable/BestEffort]
PRI[Priority<br/>Pod 优先级]
USAGE[资源使用<br/>实际使用量]
end
subgraph 驱逐执行["驱逐执行"]
direction TB
API[kube-apiserver]
KL[Kubelet]
STATUS[节点状态更新]
end
CAD --> SIG
SYS --> SIG
SIG --> MON
MON --> THRESH
THRESH --> RANK
QOS --> RANK
PRI --> RANK
USAGE --> RANK
RANK --> EVICT
EVICT --> API
EVICT --> STATUS
API --> KL
资源信号层次图
flowchart TB
subgraph 软驱逐["软驱逐 (Soft Eviction)"]
direction TB
S1[memory.available < 1.5Gi<br/>等待 graceful period]
S2[nodefs.available < 10%<br/>等待 graceful period]
S3[imagefs.available < 15%<br/>等待 graceful period]
end
subgraph 硬驱逐["硬驱逐 (Hard Eviction)"]
direction TB
H1[memory.available < 200Mi<br/>立即驱逐]
H2[nodefs.available < 5%<br/>立即驱逐]
H3[imagefs.available < 5%<br/>立即驱逐]
H4[pid.available < 1000<br/>立即驱逐]
end
subgraph 节点条件["Node Conditions"]
direction TB
NC1[MemoryPressure]
NC2[DiskPressure]
NC3[PIDPressure]
end
S1 --> NC1
S2 --> NC2
S3 --> NC2
H1 --> NC1
H2 --> NC2
H3 --> NC2
H4 --> NC3
这张图想表达什么
- 驱逐是基于资源信号触发的,不是主动预测。
- 软驱逐有等待期,硬驱逐立即执行。
- 驱逐决策考虑 QoS、优先级和资源使用。
2. 分阶段通信流程
阶段一:资源监控
这个阶段的本质是:EvictionManager 定期采集节点资源使用情况。
步骤 1.1:启动监控循环
kubelet 启动时,EvictionManager 开始一个定期监控循环(默认每 10 秒)。
通信方向:EvictionManager 内部循环
步骤 1.2:采集资源信号
监控循环会采集以下资源信号:
memory.available:可用内存nodefs.available:节点文件系统可用空间nodefs.inodesFree:节点文件系统可用 inodeimagefs.available:镜像文件系统可用空间imagefs.inodesFree:镜像文件系统可用 inodepid.available:可用 PID 数
通信方向:EvictionManager → cAdvisor/系统接口
步骤 1.3:计算资源使用
EvictionManager 计算每个资源信号的使用量和可用量。
通信方向:EvictionManager 内部计算
步骤 1.4:更新节点条件
如果资源使用超过阈值,EvictionManager 会更新 Node 的 Conditions(MemoryPressure、DiskPressure、PIDPressure)。
通信方向:kubelet → API Server(PATCH Node status)
阶段二:决策判断
这个阶段的本质是:根据阈值和策略决定是否需要驱逐以及驱逐哪些 Pod。
步骤 2.1:检查阈值
EvictionManager 检查每个资源信号是否超过配置的阈值。
通信方向:ThresholdManager 内部检查
步骤 2.2:区分软硬驱逐
- 软驱逐:超过阈值后等待
evictionSoftGracePeriod,如果持续超过则触发驱逐。 - 硬驱逐:超过阈值立即触发驱逐。
通信方向:ThresholdManager 内部判断
步骤 2.3:确定驱逐资源
确定哪个资源信号触发了驱逐,决定驱逐策略。
通信方向:EvictionManager 内部决策
步骤 2.4:Pod 排序
根据以下规则对 Pod 进行排序:
- QoS 优先级:BestEffort > Burstable > Guaranteed
- Pod Priority:低优先级优先驱逐
- 资源使用:使用量高的优先驱逐(针对特定资源)
通信方向:Ranking 内部排序
步骤 2.5:选择驱逐目标
选择排序后的第一个 Pod 作为驱逐目标。
通信方向:EvictionManager 内部选择
阶段三:执行驱逐
这个阶段的本质是:通过 API Server 删除选中的 Pod,并更新状态。
步骤 3.1:记录驱逐事件
EvictionManager 记录驱逐事件,包含驱逐原因和资源使用情况。
通信方向:EventRecorder → API Server
步骤 3.2:删除 Pod
EvictionManager 通过 API Server 删除选中的 Pod。
通信方向:EvictionManager → API Server(DELETE Pod)
步骤 3.3:等待 Pod 终止
kubelet 的 podWorkers 处理 Pod 删除,优雅终止容器。
通信方向:kubelet 内部处理
步骤 3.4:更新驱逐统计
EvictionManager 更新驱逐统计信息,用于监控和告警。
通信方向:EvictionManager 内部统计
3. 详细流程图
3.1 驱逐决策流程图
flowchart TD
subgraph 监控["资源监控"]
A1[采集资源信号] --> A2[计算可用量]
A2 --> A3[更新 Node Conditions]
end
subgraph 阈值检查["阈值检查"]
A3 --> B1{检查硬驱逐阈值}
B1 -->|超过| C1[立即驱逐]
B1 -->|未超过| B2{检查软驱逐阈值}
B2 -->|超过| B3{持续超过 grace period?}
B3 -->|是| C1
B3 -->|否| B4[继续监控]
B2 -->|未超过| B4
end
subgraph 排序["Pod 排序"]
C1 --> D1[获取所有 Pod]
D1 --> D2[按 QoS 分类]
D2 --> D3[按 Priority 排序]
D3 --> D4[按资源使用排序]
D4 --> D5[选择第一个 Pod]
end
subgraph 执行["驱逐执行"]
D5 --> E1[记录 Event]
E1 --> E2[DELETE Pod]
E2 --> E3[等待终止]
E3 --> E4[更新统计]
end
3.2 Pod QoS 排序流程图
flowchart LR
subgraph QoS分类["QoS 分类"]
direction TB
G[Guaranteed<br/>CPU/内存都设置 limits]
B[Burstable<br/>至少设置一个资源]
BE[BestEffort<br/>未设置任何资源]
end
subgraph 驱逐顺序["驱逐优先级 (高到低)"]
direction TB
P1[1. BestEffort Pod]
P2[2. Burstable Pod<br/>低 Priority]
P3[3. Burstable Pod<br/>高 Priority]
P4[4. Guaranteed Pod<br/>低 Priority]
P5[5. Guaranteed Pod<br/>高 Priority]
end
BE --> P1
B --> P2
B --> P3
G --> P4
G --> P5
3.3 资源信号处理流程图
flowchart TB
subgraph 内存["memory.available"]
M1[计算: node.status.capacity.memory<br/>- node.status.memory.workingSet]
M2[阈值: memory.available < 200Mi]
M3[排名: 按内存使用排序]
end
subgraph 磁盘["nodefs.available"]
D1[计算: df -h /var/lib/kubelet]
D2[阈值: nodefs.available < 10%]
D3[排名: 按磁盘使用排序<br/>+ 日志量]
end
subgraph 镜像["imagefs.available"]
I1[计算: df -h /var/lib/containerd]
I2[阈值: imagefs.available < 15%]
I3[排名: 优先驱逐使用镜像多的 Pod]
end
subgraph PID["pid.available"]
P1[计算: /proc/sys/kernel/pid_max<br/>- 当前 PID 数]
P2[阈值: pid.available < 1000]
P3[排名: 按 PID 使用排序]
end
M1 --> M2 --> M3
D1 --> D2 --> D3
I1 --> I2 --> I3
P1 --> P2 --> P3
4. 关键数据结构
4.1 驱逐阈值配置
1 | # kubelet 配置 |
4.2 Pod QoS 分类规则
| QoS 等级 | 条件 | 驱逐优先级 |
|---|---|---|
| Guaranteed | CPU/内存 requests == limits | 最低 (最后驱逐) |
| Burstable | 至少设置一个资源 (CPU 或内存) | 中等 |
| BestEffort | 未设置任何资源 | 最高 (最先驱逐) |
4.3 节点条件映射
| 资源信号 | Node Condition | 含义 |
|---|---|---|
| memory.available < threshold | MemoryPressure | 内存压力 |
| nodefs.available < threshold | DiskPressure | 磁盘压力 |
| imagefs.available < threshold | DiskPressure | 镜像磁盘压力 |
| pid.available < threshold | PIDPressure | PID 压力 |
5. 详细时序图
5.1 硬驱逐时序图
sequenceDiagram
autonumber
participant MON as EvictionManager
participant SIG as 信号采集器
participant RANK as PodRanking
participant API as kube-apiserver
participant KL as Kubelet
participant NODE as Node Status
loop 每 10 秒
MON->>SIG: 采集资源信号
SIG-->>MON: 返回资源使用
MON->>MON: 检查硬驱逐阈值
alt memory.available < 200Mi
MON->>MON: 触发硬驱逐
MON->>RANK: 获取所有 Pod
RANK-->>MON: Pod 列表
MON->>MON: 按 QoS 排序
MON->>MON: 按 Priority 排序
MON->>MON: 按内存使用排序
MON->>MON: 选择第一个 Pod
MON->>API: DELETE /api/v1/namespaces/<ns>/pods/<pod>
API-->>MON: 200 OK
MON->>API: POST Event (Evicted)
API-->>MON: 201 Created
MON->>NODE: 更新 MemoryPressure=True
else 资源正常
MON->>MON: 继续监控
end
end
5.2 软驱逐时序图
sequenceDiagram
autonumber
participant MON as EvictionManager
participant THRESH as ThresholdManager
participant TIMER as GracePeriodTimer
participant API as kube-apiserver
participant NODE as Node Status
loop 每 10 秒
MON->>THRESH: 检查软驱逐阈值
alt memory.available < 1.5Gi
THRESH->>TIMER: 启动/继续计时器
alt 持续超过 grace period (1m30s)
TIMER-->>THRESH: grace period 已过
THRESH-->>MON: 触发软驱逐
MON->>MON: Pod 排序
MON->>MON: 选择 Pod
MON->>API: DELETE Pod
API-->>MON: 200 OK
MON->>NODE: 更新 MemoryPressure=True
else 未超过 grace period
TIMER-->>THRESH: 继续等待
MON->>NODE: 更新 MemoryPressure=True
end
else memory.available >= 1.5Gi
THRESH->>TIMER: 重置计时器
MON->>NODE: 更新 MemoryPressure=False
end
end
5.3 驱逐与节点条件更新时序图
sequenceDiagram
autonumber
participant MON as EvictionManager
participant STATUS as StatusManager
participant API as kube-apiserver
participant CTRL as Controllers
participant SCHED as Scheduler
Note over MON: 资源压力检测
MON->>STATUS: 设置 MemoryPressure=True
STATUS->>API: PATCH Node status
API-->>CTRL: watch Node UPDATE
CTRL->>CTRL: NodeLifecycleController 处理
Note over CTRL: 可能添加 NoSchedule taint
API-->>SCHED: watch Node UPDATE
SCHED->>SCHED: 更新调度器缓存
Note over MON: 执行驱逐
MON->>API: DELETE Pod
loop 被驱逐的 Pod
API-->>CTRL: watch Pod DELETE
CTRL->>CTRL: 重建 Pod (如 Deployment)
CTRL->>API: 创建新 Pod
API-->>SCHED: watch Pod ADDED
SCHED->>SCHED: 调度到其他节点
end
Note over MON: 资源恢复
MON->>STATUS: 设置 MemoryPressure=False
STATUS->>API: PATCH Node status
6. 故障排查指南
6.1 常见问题与诊断方法
问题 1:Pod 被意外驱逐
症状:Pod 突然被删除,事件显示 Evicted
排查流程图:
flowchart TD
A[Pod 被驱逐] --> B{检查驱逐事件}
B --> B1[kubectl describe pod]
B1 --> B2[查看 Reason: Evicted]
A --> C{检查节点资源}
C --> C1[kubectl describe node]
C1 --> C2[检查 Conditions]
C2 --> C3{哪个 Condition 为 True?}
C3 -->|MemoryPressure| D1[内存不足]
C3 -->|DiskPressure| D2[磁盘不足]
C3 -->|PIDPressure| D3[PID 不足]
D1 --> E1[增加节点内存]
D1 --> E2[减少 Pod 内存使用]
D1 --> E3[调整驱逐阈值]
D2 --> E4[清理磁盘空间]
D2 --> E5[清理未使用镜像]
D2 --> E6[调整日志保留]
D3 --> E7[检查进程泄漏]
D3 --> E8[调整 PID 限制]
诊断命令:
1 | # 检查 Pod 驱逐事件 |
问题 2:节点持续处于压力状态
症状:Node Conditions 持续显示 MemoryPressure/DiskPressure
排查流程图:
flowchart TD
A[持续压力状态] --> B{检查资源使用}
B --> B1[内存使用高]
B1 --> C1[检查 Pod 内存使用]
C1 --> C1a[kubectl top pods]
C1 --> C1b[检查内存泄漏]
B --> B2[磁盘使用高]
B2 --> C2[检查磁盘占用]
C2 --> C2a[du -sh /var/lib/*]
C2 --> C2b[检查日志大小]
C2 --> C2c[检查镜像大小]
B --> B3[PID 使用高]
B3 --> C3[检查进程数]
C3 --> C3a[ps aux | wc -l]
C3 --> C3b[检查僵尸进程]
A --> D{检查驱逐阈值}
D --> D1[检查 evictionHard]
D --> D2[检查 evictionSoft]
D --> D3[考虑调整阈值]
诊断命令:
1 | # 检查 Pod 资源使用 |
问题 3:驱逐后 Pod 未重建
症状:Pod 被驱逐后,Deployment/ReplicaSet 未创建新 Pod
排查流程图:
flowchart TD
A[Pod 未重建] --> B{检查控制器}
B --> B1[检查 Deployment]
B1 --> B1a[kubectl get deployment]
B1 --> B1b[检查 replicas]
B --> B2[检查 ReplicaSet]
B2 --> B2a[kubectl get rs]
B2 --> B2b[检查控制器事件]
A --> C{检查调度}
C --> C1[检查新 Pod 状态]
C1 --> C1a[Pending? 检查调度失败原因]
C1 --> C1b[Running? 正常]
A --> D{检查节点 taint}
D --> D1[检查节点 taint]
D1 --> D2{有 NoSchedule taint?}
D2 -->|是| D3[Pod 缺少 toleration]
D2 -->|否| D4[检查其他原因]
诊断命令:
1 | # 检查控制器状态 |
6.2 关键日志关键词
| 场景 | 日志关键词 | 含义 |
|---|---|---|
| 驱逐触发 | eviction manager: attempting to reclaim |
开始回收资源 |
| Pod 排序 | ranking active pods |
Pod 排序 |
| 驱逐执行 | evicting pod |
驱逐 Pod |
| 节点条件 | Update condition |
更新节点条件 |
| 阈值检查 | thresholds met |
阈值超过 |
| 资源监控 | memory available |
内存可用 |
6.3 配置参数参考
| 参数 | 默认值 | 说明 |
|---|---|---|
--eviction-hard |
memory.available<100Mi | 硬驱逐阈值 |
--eviction-soft |
无 | 软驱逐阈值 |
--eviction-soft-grace-period |
无 | 软驱逐等待期 |
--eviction-minimum-reclaim |
无 | 最小回收量 |
--eviction-pressure-transition-period |
5m | 压力状态转换等待 |
--eviction-max-pod-grace-period-seconds |
-1 | 最大优雅终止时间 |
6.4 一键诊断命令
1 | # 驱逐问题诊断脚本 |
7. 最佳实践
7.1 资源配置建议
1 | # Pod 资源配置示例 |
7.2 驱逐阈值调优建议
| 场景 | 建议配置 |
|---|---|
| 生产环境 | 软驱逐 + 硬驱逐,留足够缓冲 |
| 开发环境 | 只配置硬驱逐 |
| 内存敏感 | 提高 memory.available 阈值 |
| 磁盘敏感 | 提高磁盘阈值,配置独立 imagefs |
8. 版本差异说明
1.27 → 1.28 变化
| 变化点 | 说明 |
|---|---|
| 驱逐指标改进 | 更详细的驱逐统计指标 |
| 资源监控优化 | 减少监控开销 |
1.28 → 1.29 变化
| 变化点 | 说明 |
|---|---|
| 驱逐优先级细化 | 更精细的优先级排序 |
| 优雅终止改进 | 更好的驱逐时优雅终止处理 |
9. 代码入口(精简版)
如果读者想从流程跳回实现,可从下面几个入口开始:
- EvictionManager 主结构:
pkg/kubelet/eviction/eviction_manager.go - 阈值通知器:
pkg/kubelet/eviction/threshold_notifier_linux.go - Pod 排序:
pkg/kubelet/eviction/helpers.go - 资源信号采集:
pkg/kubelet/eviction/helpers.go - QoS 分类:
pkg/kubelet/qos/policy.go
10. 面试题与详细解答
问题 1:kubelet 驱逐(Eviction)的软驱逐和硬驱逐有什么区别?生产环境如何配置?
回答要点:
软驱逐 vs 硬驱逐对比:
| 特性 | 硬驱逐(Hard) | 软驱逐(Soft) |
|---|---|---|
| 触发时机 | 立即触发 | 等待 grace period |
| 宽限期 | 无 | evictionSoftGracePeriod |
| 适用场景 | 紧急资源不足 | 可恢复的压力状态 |
| 风险 | 可能丢失数据 | 可能错过最佳驱逐时机 |
| 优雅终止 | 无 | 有(maxPodGracePeriodSeconds) |
工作原理:
1 | 硬驱逐: |
生产环境推荐配置:
1 | # kubelet 配置 |
配置建议:
- 同时配置软硬驱逐:软驱逐作为预警,硬驱逐作为最后防线
- 阈值留有余量:软阈值比硬阈值高 2-3 倍
- grace period 合理:给应用足够时间恢复或优雅终止
- 考虑业务特点:内存敏感型应用提高内存阈值
问题 2:Pod QoS(Guaranteed/Burstable/BestEffort)如何影响驱逐顺序?
回答要点:
QoS 分类规则:
| QoS 等级 | 条件 | 示例 |
|---|---|---|
| Guaranteed | 所有容器都设置了 limits(CPU 和内存),且 limits == requests | limits={cpu:1,mem:1Gi}, requests={cpu:1,mem:1Gi} |
| Burstable | 至少一个容器设置了 requests 或 limits | limits={mem:1Gi}, requests={mem:512Mi} |
| BestEffort | 没有设置任何 requests 和 limits | 无资源配置 |
驱逐排序规则:
1 | // 驱逐优先级排序(pkg/kubelet/eviction/helpers.go) |
驱逐顺序(从高到低):
1 | 1. BestEffort Pod(最先驱逐) |
实际影响:
1 | # Guaranteed Pod - 最安全 |
最佳实践:
- 关键应用使用 Guaranteed:确保资源不被抢占
- 普通应用使用 Burstable:设置合理 requests
- 避免 BestEffort:除非可以接受随时被驱逐
- 配合 PriorityClass:进一步控制驱逐顺序
问题 3:kubelet 驱逐与 API Server 驱逐(如 Descheduling)有什么区别?
回答要点:
两种驱逐对比:
| 特性 | kubelet 驱逐 | API Server 驱逐 |
|---|---|---|
| 触发者 | kubelet | 控制器或用户 |
| 触发条件 | 节点资源不足 | 策略决策 |
| 目标 | 保护节点稳定性 | 优化集群资源 |
| 范围 | 单节点 | 整个集群 |
| Pod 状态 | Failed (Evicted) | 正常终止 |
kubelet 驱逐流程:
1 | 节点资源监控 → 超过阈值 → Pod 排序 → DELETE Pod → 更新 Node Condition |
API Server 驱逐类型:
手动驱逐:
1
2kubectl delete pod <pod-name>
kubectl drain <node-name> # 驱逐节点上所有 PodDescheduler 驱逐:
- 低使用率 Pod
- 反亲和性违反
- 节点资源不平衡
PodDisruptionBudget (PDB) 保护:
1
2
3
4
5
6
7
8
9apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: my-app-pdb
spec:
minAvailable: 2 # 至少保持 2 个 Pod 运行
selector:
matchLabels:
app: my-app
关键区别:
PDB 保护:
- API Server 驱逐受 PDB 限制
- kubelet 驱逐不受 PDB 限制
优雅终止:
- API Server 驱逐:遵循 terminationGracePeriodSeconds
- kubelet 硬驱逐:可能立即终止
重建行为:
- 两者都会触发 Controller 重建 Pod
- kubelet 驱逐的 Pod 会标记
DisruptionTargetcondition
驱逐事件记录:
1 | # kubelet 驱逐 |
问题 4:节点出现 MemoryPressure/DiskPressure Condition 后,调度器会有什么行为?
回答要点:
Node Condition 对调度的影响:
1 | Node Condition 更新 → API Server → Scheduler watch → 更新调度缓存 |
默认行为:
MemoryPressure:
- 默认无自动 taint
- Scheduler 正常调度(除非有自定义 predicate)
DiskPressure:
- 默认无自动 taint
- Scheduler 正常调度
Taint Manager 行为(如果启用):
1 | # kube-controller-manager 配置 |
NoSchedule Taint 影响:
1 | # 节点 taint |
调度器 Predicate 检查:
1 | // pkg/scheduler/framework/plugins/noderesources/fit.go |
实际影响:
| Condition | 对调度的影响 |
|---|---|
| MemoryPressure | BestEffort Pod 不会被调度 |
| DiskPressure | 所有 Pod 不会被调度(如果配置了 predicate) |
| PIDPressure | 通常不影响调度 |
最佳实践:
- 配置 taint:自动为压力节点添加 NoSchedule taint
- 关键 Pod 添加 toleration:允许调度到压力节点
- 监控 Condition:及时告警处理
1 | # 关键 Pod 的 toleration |
问题 5:如何配置 kubelet 的资源预留(Resource Reservation)?与驱逐阈值如何配合?
回答要点:
资源预留类型:
1 | # kubelet 配置 |
资源关系图:
1 | 节点总资源 (Capacity) |
计算公式:
1 | Allocatable = Capacity - systemReserved - kubeReserved - evictionThreshold |
与驱逐阈值的配合:
1 | # 示例配置(16Gi 内存节点) |
enforceNodeAllocatable 作用:
1 | enforceNodeAllocatable: |
cgroup 配置(启用 enforce 时):
1 | /sys/fs/cgroup/kubepods/ # Pod cgroup (限制在 Allocatable 内) |
最佳实践:
- 预留足够资源:避免系统组件和 K8s 争抢资源
- 驱逐阈值与预留配合:确保驱逐触发前有缓冲空间
- 启用 enforce:强制执行资源限制
- 监控实际使用:根据实际情况调整预留值
推荐配置(生产环境):
1 | # 小型节点(4C8G) |
问题 6:Pod 被驱逐后如何恢复?如何避免频繁驱逐导致的业务抖动?
回答要点:
Pod 被驱逐后的恢复流程:
1 | Pod 被驱逐 → Controller 检测 → 创建新 Pod → Scheduler 调度 → 新节点启动 |
恢复机制:
Deployment/ReplicaSet:
- 自动创建新 Pod 替换被驱逐的 Pod
- 维持期望副本数
StatefulSet:
- Pod 有稳定标识,会被重建
- 可能需要 PVC 恢复数据
DaemonSet:
- 节点恢复后自动重建 Pod
避免频繁驱逐的策略:
合理配置资源:
1
2
3
4
5resources:
requests:
memory: "1Gi" # 保证调度时预留足够资源
limits:
memory: "2Gi" # 限制最大使用使用 Guaranteed QoS:
1
2
3
4
5
6
7resources:
requests:
memory: "1Gi"
cpu: "500m"
limits:
memory: "1Gi" # limits == requests
cpu: "500m"配置 PriorityClass:
1
2
3
4
5
6
7apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false
preemptionPolicy: PreemptLowerPriority设置 PodDisruptionBudget:
1
2
3
4
5
6
7
8
9apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: my-app-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: my-app添加节点容忍度:
1
2
3
4
5tolerations:
- key: node.kubernetes.io/memory-pressure
operator: Exists
effect: NoExecute
tolerationSeconds: 300 # 5 分钟后再驱逐
监控和告警:
1 | # Prometheus 告警规则 |
故障排查:
1 | # 查看驱逐事件 |
问题 7:PID 驱逐是什么?什么情况下会触发?如何排查 PID 资源耗尽问题?
回答要点:
PID 驱逐概念:
PID 驱逐是 kubelet 在系统 PID 资源不足时触发的驱逐行为。每个进程都需要一个唯一的 PID,当 PID 耗尽时,系统无法创建新进程。
触发条件:
1 | evictionHard: |
PID 资源限制:
1 | # 查看系统 PID 上限 |
常见 PID 耗尽原因:
- 进程泄漏:应用创建子进程后未正确回收
- 僵尸进程:父进程未 wait 子进程
- 并发过高:短时间创建大量进程
- 容器配置不当:未限制容器进程数
排查步骤:
1 | # 1. 检查节点 PID 状态 |
解决方案:
配置 PID 驱逐阈值:
1
2
3
4
5
6evictionHard:
pid.available: "1000"
evictionSoft:
pid.available: "2000"
evictionSoftGracePeriod:
pid.available: "1m"限制容器进程数:
1
2
3
4
5
6
7
8
9# Pod spec
spec:
containers:
- name: app
resources:
limits:
hugepages-2Mi: 512Mi
# Kubernetes 1.20+ 支持
# 通过 cgroup 限制进程数使用 PidLimit feature gate:
1
2
3
4# kubelet 配置
featureGates:
SupportPodPidsLimit: true
SupportNodePidsLimit: true调整系统 PID 上限:
1
2
3
4
5
6# 临时调整
echo 65536 > /proc/sys/kernel/pid_max
# 永久调整
echo "kernel.pid_max = 65536" >> /etc/sysctl.conf
sysctl -p
最佳实践:
- 监控 PID 使用:设置告警监控 PID 使用率
- 应用设计:避免无限创建子进程
- 容器限制:使用 cgroup 限制容器进程数
- 定期清理:清理僵尸进程和无用进程

