--protect-kernel-defaults 开启后 kubelet 会严格校验宿主机内核参数是否符合安全默认值,任一不匹配(如 vm.swappiness=60)即硬性退出;需提前将正确值写入 /etc/sysctl.d/99-kubernetes.conf 并执行 sysctl --system 生效,临时修改无效。

为什么 --protect-kernel-defaults 一开就报错?
因为 kubelet 启动时会检查一系列内核参数是否处于“安全默认值”,只要有一个不匹配(比如 vm.swappiness 是 60,而它期望 0),就会直接退出并报错:failed to run Kubelet: kernel has not been configured correctly。这不是警告,是硬性拒绝启动。
常见触发点包括:net.ipv4.conf.all.forwarding、net.bridge.bridge-nf-call-iptables、vm.overcommit_memory、kernel.panic 等——它们往往被发行版默认设为非 kubelet 认可的值,或被其他组件(如 Docker、firewalld)悄悄改过。
- 别在没确认当前值的情况下直接加这个 flag;先用
sysctl -a | grep -E "(forwarding|bridge-nf|swappiness|overcommit)"快速扫一遍 - 修改必须写入
/etc/sysctl.d/99-kubernetes.conf并执行sysctl --system生效,仅sysctl -w临时改无效 - 某些云厂商镜像(如 AWS AL2、Azure Ubuntu)默认禁用
net.bridge.bridge-nf-call-iptables,必须显式开启,否则 kube-proxy 无法正常工作
--protect-kernel-defaults 和 SELinux/AppArmor 冲突吗?
不直接冲突,但会放大权限问题。这个 flag 只管 sysctl 值,不管 LSM 策略。但它要求 kubelet 对内核参数有读写权限,而 SELinux 或 AppArmor 若限制了 sysctl_write 能力,kubelet 就会在启动阶段卡在参数校验环节,错误日志里看不到明显提示,只显示 “failed to validate kernel defaults”。
- 检查 SELinux 是否启用:
getenforce;若为Enforcing,临时设为Permissive测试是否绕过问题 - AppArmor 配置文件中需包含
capability sys_module,和sysctl * rw,(注意:生产环境慎开sysctl *,应精确到具体路径如sysctl net/ ipv4/ conf/ all/ forwarding rw,) - Ubuntu 22.04+ 默认用 systemd-sysctl 加载配置,但若 AppArmor profile 在 sysctl 加载前已加载,可能导致参数未生效就被 kubelet 检查——顺序很重要
和 securityContext.sysctls 在 Pod 级别的设置有什么关系?
完全无关。前者是 kubelet 启动时对**宿主机内核全局状态**的强制校验;后者是运行时对**单个容器命名空间内可调参数**的白名单控制。即使开了 --protect-kernel-defaults,Pod 仍可通过 securityContext.sysctls 设置 net.core.somaxconn 这类 namespaced 参数——前提是该参数被 kubelet 的 --allowed-unsafe-sysctls 显式放行。
-
--protect-kernel-defaults不影响 Pod 里能设什么 sysctl,只决定 kubelet 自己能不能起来 - 若你同时用了
--allowed-unsafe-sysctls="net.*",请确保宿主机上对应全局参数(如net.ipv4.ip_forward)也满足--protect-kernel-defaults的要求,否则 kubelet 根本不会走到允许 Pod 设置那步 - 常见误操作:以为开了
--protect-kernel-defaults就自动加固了所有容器 sysctl,其实它对 Pod 完全透明
要不要在生产集群里开这个 flag?
要看你的运维成熟度。它不是“开了就更安全”,而是“开了就强制你把内核参数管起来”。很多团队开了之后反复重启 kubelet,最后默默关掉——根本原因是缺乏统一的内核参数基线管理机制。
- 如果你用 Ansible / Terraform / Packer 构建节点镜像,且所有 sysctl 配置固化在镜像中,那可以开;否则建议先用
--protect-kernel-defaults=false+ 定期巡检脚本替代 - 注意:Kubernetes v1.28+ 已将该 flag 标记为 deprecated,未来会被移除,替代方案是通过
KubeletConfiguration的protectKernelDefaults字段配置,但行为一致 - 真正容易被忽略的是:它只检查“值”,不检查“来源”。比如
vm.swappiness=0是手动写的,还是某个 systemd service 动态覆盖的?没人保证下次 reboot 后还有效









