在 Kubernetes 集群中使用 sysctls

特性状态: Kubernetes v1.21 [stable]

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

准备工作

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

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

列出所有 Sysctl 参数

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

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

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

sudo sysctl -a

安全和不安全的 Sysctl

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

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

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

  • 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+)。
  • net.ipv4.tcp_rmem (自 Kubernetes 1.32 起,需要内核 4.15+)。
  • net.ipv4.tcp_wmem (自 Kubernetes 1.32 起,需要内核 4.15+)。

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

启用不安全的 Sysctl

所有**安全**的 sysctl 默认启用。

所有**不安全**的 sysctl 默认禁用,必须由集群管理员在每个节点上手动允许。使用禁用的不安全 sysctl 的 Pod 将会被调度,但会启动失败。

考虑到上述警告,集群管理员可以在非常特殊的情况下(例如高性能或实时应用程序调优)允许某些**不安全**的 sysctl。**不安全**的 sysctl 通过 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"...

只有**命名空间**的 sysctl 才能通过这种方式启用。

为 Pod 设置 Sysctl

在今天的 Linux 内核中,许多 sysctl 是**命名空间化**的。这意味着它们可以为节点上的每个 Pod 独立设置。只有命名空间化的 sysctl 可以通过 Kubernetes 中的 Pod securityContext 进行配置。

以下 sysctl 已知为命名空间化。此列表可能会在未来的 Linux 内核版本中更改。

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

没有命名空间的 Sysctl 称为**节点级别**的 Sysctl。如果需要设置它们,你必须在每个节点的操作系统上手动配置,或者使用带有特权容器的 DaemonSet。

使用 Pod securityContext 配置命名空间的 sysctl。securityContext 适用于同一 Pod 中的所有容器。

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

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 的 **污点和容忍**特性 来实现这一点。

一个带有**不安全**sysctl 的 Pod 将无法在任何未明确启用这两个**不安全**sysctl 的节点上启动。与**节点级别**sysctl 一样,建议使用 **污点和容忍**特性节点污点 来将这些 Pod 调度到正确的节点上。

最后修改于 2024 年 9 月 20 日太平洋标准时间上午 11:36:同步 v1.32 的安全 sysctl ipv4.rmen 和 ipv4.wmem (de6ead9316)