Linux Kubernetes kubelet 的 –protect-kernel-defaults 与安全加固

1次阅读

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

Linux Kubernetes kubelet 的 –protect-kernel-defaults 与安全加固

为什么 --protect-kernel-defaults 一开就报错?

因为 kubelet 启动时会检查一系列内核参数是否处于“安全默认值”,只要有一个不匹配(比如 vm.swappiness 是 60,而它期望 0),就会直接退出并报错:failed to run Kubelet: kernel has not been configured correctly。这不是警告,是硬性拒绝启动。

常见触发点包括:net.ipv4.conf.all.forwardingnet.bridge.bridge-nf-call-iptablesvm.overcommit_memorykernel.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,未来会被移除,替代方案是通过 KubeletConfigurationprotectKernelDefaults 字段配置,但行为一致
  • 真正容易被忽略的是:它只检查“值”,不检查“来源”。比如 vm.swappiness=0 是手动写的,还是某个 systemd service 动态覆盖的?没人保证下次 reboot 后还有效
text=ZqhQzanResources