
K8s 最佳实践已更新:
满足以下条件:
请使用 node swap!
要启用,推荐 kubelet config 添加如下配置:
failSwapOn: false
memorySwap:
swapBehavior: LimitedSwap👍️优点
/etc/fstab 一行没改,改动面就一个 kubelet 配置项;node.status.nodeInfo.swap.capacity 和 kubectl top nodes --show-swap 检查 swap。📝备忘:
社区普遍的看法是:把 swap 当内存尖峰的保险,不当 RAM 的替代。
接下来是我在 Homelab 的实战总结:
4 台 N100 小主机,cgroup v2,宿主机 /swap.img 早就 swapon 起来了(swap没开的实战时还需要开下swap)。上面跑的是 k3s v1.36.5+k3s1。
NodeSwap 在 Kubernetes v1.34 已经 GA,我们来启用看看。
kubelet 的 memorySwap.swapBehavior 默认值是 NoSwap。
这个默认值下,即使宿主机开了 swap、即使你写了 failSwapOn: false,容器 cgroup 的 memory.swap.max 依然是 0。
📝Notes:
failSwapOn: false管的是「节点有 swap 时 kubelet 要不要拒绝启动」,swapBehavior管的是「容器能不能用 swap」。两个开关,两件事。
宿主机层面的 swapon、分区、/etc/fstab,在我的 Homelab 集群上都是现成的。缺的只是 kubelet 里的那一行。
stat -fc %T /sys/fs/cgroup 返回 cgroup2fs;swapon --show 有输出,我的 Homelab 集群是 /swap.img;前置条件不满足,改 kubelet 配置也没意义。
上游推荐的值是 LimitedSwap。它不是一个「全部放开」的策略。
适用边界由上游确定:
IsCriticalPod)也是 NoSwap,不看 QoS。Pod QoS | request vs limit | 能否用 swap |
|---|---|---|
Burstable | request != limit | ✓ LimitedSwap |
Burstable | request == limit | ✗ NoSwap |
Guaranteed | request == limit | ✗ NoSwap |
BestEffort | 都没设 | ✗ NoSwap |
任意 | IsCriticalPod | ✗ NoSwap |
额度按这个公式算:
containerSwapLimit = (containerMemoryRequest / nodeTotalMemory) × totalPodsSwapAvailablerequest 越小,能换出去的空间越小。这是刻意的设计:swap 只用来兜住内存尖峰,不参与容量规划。
🐾 注意: 调度器不感知 swap。它看到的内存还是节点物理 RAM。不要把 swap 当成「多出来的内存」去超卖,节点迟早会抖。
k3s 每次启动都会重写 /var/lib/rancher/k3s/agent/etc/kubelet.conf.d/00-k3s-defaults.conf。
要覆盖默认值,就得往同一个目录里放一个排在后边的文件。
文件名必须以 .conf 结尾,按字典序加载。这里用的是 90-swap.conf。
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
failSwapOn: false
memorySwap:
swapBehavior: LimitedSwapfailSwapOn: false 显式写进去,别依赖默认。
00-k3s-defaults.conf 不要覆盖、不要删除,那是 k3s 自己管的。
重启 kubelet, 对于 k3s 就是重启 k3s 服务。
上线顺序:worker 先,master 逐台来。
每台之间确认 kubectl get nodes 全部 Ready、etcd 成员健康,再动下一台。多台 master 同时重启,etcd quorum 会短暂丢失。
整个过程不重启节点,不驱逐 Pod。
配置写完不算完,四条命令逐条过。
kubectl get --raw "/api/v1/nodes/<node>/proxy/configz" \
| jq '.kubeletconfig | {failSwapOn, memorySwap}'期望 memorySwap.swapBehavior == "LimitedSwap"。
示例如下:
❯ kubectl get --raw "/api/v1/nodes/n100-cheshi-0/proxy/configz" | jq '.kubeletconfig | {failSwapOn, memorySwap}'
{
"failSwapOn": false,
"memorySwap": {
"swapBehavior": "LimitedSwap"
}
}unknown:❯ 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 42949632004 台节点都应有值。
❯ 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%在最后两列 - SWAP(bytes) SWAP(%)。
kubectl exec <pod> -- cat /sys/fs/cgroup/memory.swap.max拿两个 Pod 对比:
64Mi / limit 256Mi 的 Burstable Pod,memory.swap.max > 0;memory.swap.max == 0。这两组数字对得上,说明边界按预期生效了。示例如下:
Burstable Pod:
cat /sys/fs/cgroup/memory.swap.max
36200448request/limit 都没设的 Pod:
cat /sys/fs/cgroup/memory.swap.max
0我的 homelab 集群一时间没找到 request == limit 的 Pod,这里就不展示了。
swapBehavior 还是 NoSwap,单独写 failSwapOn: false 不会让容器拿到 swap 额度;memorySwap.swapBehavior: LimitedSwap;.conf 后缀 + 字典序排在 00-k3s-defaults.conf 之后;以上。
memorySwap 字段定义原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。