在 Kubernetes 集群中使用 sysctl
Kubernetes v1.21 [stable]
本文档描述了如何使用 sysctl 接口在 Kubernetes 集群中配置和使用内核参数。
说明
从 Kubernetes 1.23 版本开始,kubelet 支持使用/
或 .
作为 sysctl 名称的分隔符。从 Kubernetes 1.25 版本开始,为 Pod 设置 Sysctl 时支持使用斜杠。例如,你可以使用句点作为分隔符表示同一个 sysctl 名称,如 kernel.shm_rmid_forced
,也可以使用斜杠作为分隔符,如 kernel/shm_rmid_forced
。关于 sysctl 参数转换方法的更多细节,请参考 Linux man-pages 项目中的 sysctl.d(5) 页面。准备工作
说明
sysctl
是一个特定于 Linux 的命令行工具,用于配置各种内核参数,在非 Linux 操作系统上不可用。你需要拥有一个 Kubernetes 集群,并且配置 kubectl 命令行工具与你的集群通信。建议在至少有两个不是控制平面主机的节点的集群上运行本教程。如果你还没有集群,可以使用 minikube 创建一个,或者使用以下 Kubernetes 演练场之一:
对于某些步骤,你还需要能够重新配置在你的集群上运行的 kubelet 的命令行选项。
列出所有 Sysctl 参数
在 Linux 中,sysctl 接口允许管理员在运行时修改内核参数。参数通过 /proc/sys/
虚拟进程文件系统可用。参数涵盖各种子系统,例如:
- kernel (常见前缀:
kernel.
) - networking (常见前缀:
net.
) - virtual memory (常见前缀:
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+)。
说明
安全 sysctl 集合存在一些例外情况:
- 启用主机网络时,不允许使用
net.*
sysctl。 - 在 Linux 内核版本 4.5 或更低版本上,
net.ipv4.tcp_syncookies
sysctl 没有命名空间。
将来,当 kubelet 支持更好的隔离机制时,此列表将进行扩展。
启用不安全的 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_max
和net.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.somaxconn
和 kernel.msgmax
。规范中没有区分**安全**和**不安全** sysctl。
警告
仅在你理解 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 设置的节点视为集群中的**污点**(tainted),并且只将需要这些 sysctl 设置的 Pod 调度到它们上面。建议使用 Kubernetes 的**污点和容忍**特性来实现这一点。
配置了**不安全** sysctl 的 Pod 将无法在未明确启用这两个**不安全** sysctl 的任何节点上启动。与**节点级** sysctl 一样,建议使用**污点和容忍**特性或节点上的污点将这些 Pod 调度到正确的节点上。