在 Kubernetes 集群中使用 sysctl

特性状态: Kubernetes v1.21 [稳定]

本文档介绍了如何使用 sysctl 接口在 Kubernetes 集群中配置和使用内核参数。

开始之前

您需要拥有一个 Kubernetes 集群,并且 kubectl 命令行工具必须配置为与您的集群通信。建议在至少有两个节点(不充当控制平面主机)的集群上运行本教程。如果您还没有集群,可以使用 minikube 创建一个,也可以使用以下 Kubernetes 游乐场之一

对于某些步骤,您还需要能够重新配置运行在集群中的 kubelet 的命令行选项。

列出所有 Sysctl 参数

在 Linux 中,sysctl 接口允许管理员在运行时修改内核参数。参数可通过 /proc/sys/ 虚拟进程文件系统获得。这些参数涵盖了各种子系统,例如

  • 内核(通用前缀:kernel.
  • 网络(通用前缀:net.
  • 虚拟内存(通用前缀:vm.
  • MDADM(通用前缀:dev.
  • 更多子系统在 内核文档 中有描述。

要获取所有参数的列表,您可以运行

sudo sysctl -a

安全和不安全的 Sysctls

Kubernetes 将 sysctls 分类为安全不安全。除了正确的命名空间外,安全 sysctl 必须在同一节点上的 Pod 之间进行正确的隔离。这意味着为一个 Pod 设置安全 sysctl

  • 不能对节点上的任何其他 Pod 产生任何影响
  • 不能允许损害节点的健康状况
  • 不能允许获取超出 Pod 资源限制的 CPU 或内存资源。

到目前为止,大多数命名空间 sysctls 不一定被认为是安全的。以下 sysctls 在安全集中受支持

  • kernel.shm_rmid_forced;
  • net.ipv4.ip_local_port_range;
  • net.ipv4.tcp_syncookies;
  • net.ipv4.ping_group_range(自 Kubernetes 1.18 起);
  • net.ipv4.ip_unprivileged_port_start(自 Kubernetes 1.22 起);
  • net.ipv4.ip_local_reserved_ports(自 Kubernetes 1.27 起,需要内核 3.16+);
  • net.ipv4.tcp_keepalive_time(自 Kubernetes 1.29 起,需要内核 4.5+);
  • net.ipv4.tcp_fin_timeout(自 Kubernetes 1.29 起,需要内核 4.6+);
  • net.ipv4.tcp_keepalive_intvl(自 Kubernetes 1.29 起,需要内核 4.5+);
  • net.ipv4.tcp_keepalive_probes(自 Kubernetes 1.29 起,需要内核 4.5+)。

此列表将在未来 Kubernetes 版本中扩展,届时 kubelet 将支持更好的隔离机制。

启用不安全的 Sysctls

所有安全 sysctls 默认启用。

所有不安全 sysctls 默认禁用,必须由集群管理员在每个节点的基础上手动允许。禁用不安全 sysctls 的 Pod 将被调度,但无法启动。

在了解上述警告的情况下,集群管理员可以为某些特殊情况(例如高性能或实时应用程序调整)允许某些不安全 sysctls。不安全 sysctls 在每个节点的基础上使用 kubelet 的标志启用;例如

kubelet --allowed-unsafe-sysctls \
  'kernel.msg*,net.core.somaxconn' ...

对于 Minikube,这可以通过 extra-config 标志完成

minikube start --extra-config="kubelet.allowed-unsafe-sysctls=kernel.msg*,net.core.somaxconn"...

只有命名空间 sysctls 可以通过这种方式启用。

为 Pod 设置 Sysctls

许多 sysctls 在当今的 Linux 内核中是命名空间的。这意味着它们可以为节点上的每个 Pod 独立设置。只有命名空间 sysctls 才能通过 Kubernetes 中的 Pod 安全上下文进行配置。

以下 sysctls 已知是命名空间的。此列表可能会在未来版本的 Linux 内核中发生变化。

  • kernel.shm*,
  • kernel.msg*,
  • kernel.sem,
  • fs.mqueue.*,
  • 那些可以在容器网络命名空间中设置的 net.*。但是,也存在例外情况(例如,net.netfilter.nf_conntrack_maxnet.netfilter.nf_conntrack_expect_max 可以在容器网络命名空间中设置,但在 Linux 5.12.2 之前是未进行命名空间划分的)。

没有命名空间的 Sysctls 被称为节点级 sysctls。如果您需要设置它们,必须手动在每个节点的操作系统上进行配置,或者使用具有特权容器的 DaemonSet。

使用 Pod 安全上下文配置命名空间 sysctls。安全上下文适用于同一 Pod 中的所有容器。

此示例使用 Pod 安全上下文设置安全 sysctl kernel.shm_rmid_forced 和两个不安全 sysctls net.core.somaxconnkernel.msgmax。在规范中,安全不安全 sysctls 之间没有区别。

apiVersion: v1
kind: Pod
metadata:
  name: sysctl-example
spec:
  securityContext:
    sysctls:
    - name: kernel.shm_rmid_forced
      value: "0"
    - name: net.core.somaxconn
      value: "1024"
    - name: kernel.msgmax
      value: "65536"
  ...

一个好的做法是将具有特殊 sysctl 设置的节点视为集群中的受污染节点,并且只将需要这些 sysctl 设置的 Pod 调度到这些节点上。建议使用 Kubernetes 污点和容忍度功能 来实现这一点。

具有不安全 sysctls 的 Pod 将无法在任何未明确启用这两个不安全 sysctls 的节点上启动。与节点级 sysctls 一样,建议使用 污点和容忍度功能节点上的污点 将这些 Pod 调度到正确的节点上。

上次修改时间:2023 年 12 月 25 日下午 10:47 PST: 更新安全 sysctl (fc8e79b96c)