在 Kubernetes 集群中使用 sysctls
Kubernetes v1.21 [稳定]
本文档介绍了如何在 Kubernetes 集群中使用 sysctl 接口配置和使用内核参数。
注意
从 Kubernetes 1.23 版本开始,kubelet 支持使用/
或 .
作为 sysctl 名称的分隔符。 从 Kubernetes 1.25 版本开始,为 Pod 设置 Sysctl 支持使用斜杠设置 sysctl。 例如,你可以使用句点作为分隔符将相同的 sysctl 名称表示为 kernel.shm_rmid_forced
,或者使用斜杠作为分隔符表示为 kernel/shm_rmid_forced
。 有关更多 sysctl 参数转换方法详细信息,请参阅 Linux 手册页项目中的 sysctl.d(5) 页面。开始之前
注意
sysctl
是一个 Linux 特定的命令行工具,用于配置各种内核参数,它在非 Linux 操作系统上不可用。你需要有一个 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+)。
注意
安全 sysctl 集合有一些例外
- 启用主机网络后,不允许使用
net.*
sysctl。 net.ipv4.tcp_syncookies
sysctl 在 Linux 内核 4.5 或更低版本上不是命名空间的。
当 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_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 设置的节点视为集群中污点,并且只将需要这些 sysctl 设置的 Pod 调度到这些节点上。 建议使用 Kubernetes 污点和容忍度特性来实现这一点。
具有不安全的 sysctl 的 Pod 将无法在任何未明确启用这两个不安全的 sysctl 的节点上启动。 与节点级 sysctl 一样,建议使用污点和容忍度特性或节点上的污点将这些 Pod 调度到正确的节点上。