Kubernetes NodeSwap:原理、k3s 配置与验证
NodeSwap 允许 Kubernetes 工作负载在受控范围内使用节点的 swap。它在 Kubernetes v1.34 进入稳定阶段,但 kubelet 默认仍使用 NoSwap,需要显式配置才能让符合条件的容器使用 swap。
本文基于东风微鸣的 Homelab 实践整理。环境信息和命令输出均来自原作者;文末“官方资料核对”单独说明实验经验的适用边界。
适用条件与收益
原文建议在满足以下条件时启用 NodeSwap:
- Kubernetes v1.34 及以上版本。
- 节点系统盘使用本地 SSD 或 NVMe 高速存储。
- 节点使用 cgroup v2。
kubelet 的核心配置如下:
failSwapOn: false
memorySwap:
swapBehavior: LimitedSwap作者将启用 swap 的收益归纳为:
- 降低内存成本:符合条件的工作负载可以在内存压力下换出空闲匿名页,提高 Pod 密度。
- 缓冲内存尖峰:为工作负载提供额外的缓冲,减少因内存压力触发 OOM 的机会。
- 配置改动少:本次实验的宿主机已启用 swap,swap 文件、分区和
/etc/fstab均未改动,主要调整 kubelet 的swapBehavior。 - 可以观测:通过
node.status.nodeInfo.swap.capacity和kubectl top nodes --show-swap查看容量与使用量。
这些收益有明确边界:
- 只有符合条件的 Burstable Pod 中、内存 request 小于 limit 的容器能使用 swap;Guaranteed 工作负载不会因此获得 swap 额度。
- 调度器不感知 swap,容量规划仍以节点物理内存为准,不能将 swap 计入可调度内存。
- 匿名页换出会产生磁盘 I/O。原文不建议在系统盘不具备本地 SSD 或 NVMe 性能条件时启用。
原文将社区的常见建议概括为:用 swap 缓冲内存尖峰,容量规划仍按物理 RAM 计算。
实验环境与前置检查
作者使用的 Homelab 环境如下:
| 项目 | 配置 |
|---|---|
| 节点 | 4 台 N100 小主机 |
| 集群 | k3s v1.36.5+k3s1 |
| cgroup | v2 |
| 宿主机 swap | /swap.img,实验前已通过 swapon 启用 |
开始前,逐项确认:
- 检查 cgroup 版本:
stat -fc %T /sys/fs/cgroup应返回cgroup2fs。 - 检查宿主机 swap:
swapon --show应有输出。作者的环境使用/swap.img;尚未启用 swap 的节点需要先完成宿主机配置。 - 确认 k3s 对应的 Kubernetes 版本为 v1.34 或更高,包含稳定版 NodeSwap。
前置条件不满足时,仅修改 kubelet 配置无法完成启用。
两个 kubelet 配置项的区别
memorySwap.swapBehavior 的默认值是 NoSwap。在此模式下,即使宿主机启用了 swap,并设置了 failSwapOn: false,容器 cgroup 的 memory.swap.max 仍为 0。
| 配置项 | 控制内容 |
|---|---|
failSwapOn: false | 允许 kubelet 在宿主机已启用 swap 时启动 |
memorySwap.swapBehavior: LimitedSwap | 允许符合条件的容器使用受限的 swap 额度 |
两项配置分别控制启动与容器用量
仅设置
failSwapOn: false不会给容器分配 swap。作者的宿主机 swap、分区和/etc/fstab已配置好,本次需要补上的是 kubelet 的LimitedSwap策略。
LimitedSwap 的适用范围与额度
LimitedSwap 会按 Pod QoS、容器内存配置以及是否为关键 Pod 限制 swap 的使用范围:
- Pod 必须属于 Burstable QoS。
- 容器的 memory request 与 limit 必须不相等。
- Guaranteed 和 BestEffort Pod 不能使用 swap。
- 关键 Pod(
IsCriticalPod)不能使用 swap,与 QoS 类别无关。
| Pod QoS | request vs limit | 能否用 swap |
|---|---|---|
| Burstable | request != limit | 可以,使用 LimitedSwap |
| Burstable | request == limit | 不可以,使用 NoSwap |
| Guaranteed | request == limit | 不可以,使用 NoSwap |
| BestEffort | 都没设 | 不可以,使用 NoSwap |
| 任意 | IsCriticalPod | 不可以,使用 NoSwap |
容器可使用的 swap 额度按以下公式计算:
containerSwapLimit = (containerMemoryRequest / nodeTotalMemory) × totalPodsSwapAvailablerequest 越小,分配到的 swap 额度越小。这里的 totalPodsSwapAvailable 指节点上可供 Pod 使用的 swap 总量。
swap 不参与调度容量计算
调度器仍按节点物理 RAM 和工作负载的 memory requests 调度。将 swap 当作额外 RAM 超卖,可能导致频繁换页和节点抖动。
在 k3s 中配置 kubelet
使用独立的 drop-in 文件
k3s 管理默认配置文件:
/var/lib/rancher/k3s/agent/etc/kubelet.conf.d/00-k3s-defaults.conf
原文说明该文件会在 k3s 启动时重写,因此自定义配置应放在同一目录的独立文件中。
drop-in 文件需要满足两个条件:
- 文件名以
.conf结尾。 - 文件按字典序加载;覆盖默认值的文件应排在
00-k3s-defaults.conf之后。
本例使用 90-swap.conf,完整路径为:
/var/lib/rancher/k3s/agent/etc/kubelet.conf.d/90-swap.conf
文件内容如下:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
failSwapOn: false
memorySwap:
swapBehavior: LimitedSwap显式写入 failSwapOn: false,避免依赖已有配置。保留 k3s 自己维护的 00-k3s-defaults.conf,不要覆盖或删除。
配置文件支持范围
官方 k3s 配置文档说明,kubelet drop-in 配置文件的支持从 k3s v1.32 开始;本文 v1.34 及以上的适用范围已覆盖这一前提。配置文件和命令行参数混用时,还需要考虑参数优先级,最终以 kubelet 实际生效的配置为准。
逐节点上线
在 k3s 中,重启 kubelet 对应重启所在节点的 k3s 服务。作者的 Homelab 按以下顺序上线:
- 先处理 worker 节点。
- 再逐台处理 master(控制平面)节点。
- 每处理一台,都确认
kubectl get nodes显示全部节点 Ready,且 etcd 成员健康,再继续下一台。
避免同时重启多台 master,导致 etcd 失去维持 quorum 所需的成员数量。作者记录的操作过程没有重启节点,也没有主动驱逐 Pod。
控制平面的适用边界
上述顺序保留了作者的实验过程。官方建议控制平面不配置 swap,详见 官方资料核对。
验证清单
验证应覆盖实际配置、节点容量、使用量和容器 cgroup 额度四个方面。以下输出为作者的实验记录。
1. 确认 kubelet 的实际配置
查询目标节点的 configz:
kubectl get --raw "/api/v1/nodes/<node>/proxy/configz" \
| jq '.kubeletconfig | {failSwapOn, memorySwap}'期望看到 failSwapOn: false,且 memorySwap.swapBehavior == "LimitedSwap"。
作者的输出:
❯ kubectl get --raw "/api/v1/nodes/n100-cheshi-0/proxy/configz" | jq '.kubeletconfig | {failSwapOn, memorySwap}'
{
"failSwapOn": false,
"memorySwap": {
"swapBehavior": "LimitedSwap"
}
}2. 确认节点上报 swap 容量
检查 .status.nodeInfo.swap.capacity:
❯ kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.nodeInfo.swap.capacity}{"\n"}{end}'
n100-cheshi-0 8589930496
n100-jumper-0 4294963200
n100-jumper-1 4294963200
n100-jumper-2 4294963200实验中的 4 台节点均有容量值。该字段缺失时需要进一步检查;在相关工具输出中,它可能表现为 unknown。
3. 确认 swap 使用量可见
检查最后两列 SWAP(bytes) 和 SWAP(%):
❯ kubectl top nodes --show-swap
NAME CPU(cores) CPU(%) MEMORY(bytes) MEMORY(%) SWAP(bytes) SWAP(%)
n100-cheshi-0 671m 16% 11088Mi 35% 0Mi 0%
n100-jumper-0 853m 21% 8065Mi 53% 0Mi 0%
n100-jumper-1 759m 18% 6317Mi 41% 0Mi 0%
n100-jumper-2 466m 11% 7270Mi 47% 0Mi 0%这里的 0Mi 是作者记录的当时使用量;容器是否获得 swap 额度,还需要检查下一项。
4. 确认容器 cgroup 的 swap 额度
进入容器查看 memory.swap.max:
kubectl exec <pod> -- cat /sys/fs/cgroup/memory.swap.max对比以下情况:
- request 为
64Mi、limit 为256Mi的 Burstable Pod,预期memory.swap.max > 0。 - memory request 等于 limit 的容器,以及 request/limit 均未设置的 BestEffort Pod,预期
memory.swap.max == 0。
作者记录的 Burstable Pod:
cat /sys/fs/cgroup/memory.swap.max
36200448作者记录的 request/limit 均未设置的 Pod:
cat /sys/fs/cgroup/memory.swap.max
0作者当时没有找到 memory request 等于 limit 的 Pod,因此原文未提供这类 Pod 的实测输出。上述记录验证了已展示的两类情况,不能视为所有边界条件都已实测。
官方资料核对
以下内容于 2026-10-20 对照官方资料补充,与上文的作者实验记录区分:
- 稳定版本与默认策略:Kubernetes v1.34 发布说明确认 Linux 节点 swap 支持进入稳定阶段,默认仍为
NoSwap。Kubernetes v1.34 发布说明 - 控制平面:官方建议控制平面不配置 swap,避免关键服务换页影响性能。原文对 master 的操作顺序属于 Homelab 经验,不应直接作为生产控制平面的启用建议。控制平面与 swap
- 存储条件:官方关注实际承载 swap 的存储性能及其与系统进程的 I/O 竞争;本地 SSD 或 NVMe 是原文提出的部署建议,并非 NodeSwap API 的硬性限定。官方同时建议使用加密 swap,并考虑独立设备或 I/O 优先级隔离。swap 存储实践
- 收益与验证范围:原文没有提供成本、Pod 密度或性能的前后对比数据,也未展示 memory request 等于 limit 的实测结果。收益描述保留为作者的启用理由,命令输出保留为该实验环境的观测结果。
要点回顾
- NodeSwap 在 Kubernetes v1.34 进入稳定阶段,但默认
swapBehavior仍是NoSwap;单独设置failSwapOn: false不会给容器分配 swap。 - 宿主机 swap 和 kubelet 启动条件已满足时,启用容器 swap 的关键配置是
memorySwap.swapBehavior: LimitedSwap。 LimitedSwap受 Burstable QoS、内存 request/limit 和关键 Pod 条件限制,额度按 request 占节点物理内存的比例计算。- k3s 可以通过
.confdrop-in 文件覆盖默认配置,文件名需排在00-k3s-defaults.conf之后;上线后仍需核对实际配置和容器额度。
参考资料
- 原文:K8s 最佳实践已更新:请使用 Node Swap!,东风微鸣,2026-10-17。
- Kubernetes:Swap memory management
- Kubernetes v1.34 发布说明:Linux node swap support
- k3s:Kubelet Configuration Files
- Kubernetes:通过配置文件设置 kubelet 参数
- KEP-2400:Node memory swap support
- Kubelet 配置 API:memorySwap
相关笔记
- cgroup v2 原理与迁移
- Kubernetes 生产环境优化
- NodeSwap 来源摘要
- Kubernetes 专题地图