在Kuberentes集群中使用sysctl
本文将描述如何使用sysctl接口在Kubernetes集群中配置和使用内核参数。
获取sysctl参数列表
在Linux中,sysctl接口允许管理员在运行时修改内核参数。参数可以通过/proc/sys/
虚拟进程文件系统获得。参数涵盖多个子系统,例如:
- 内核 (通用前缀:kernel.)
- 网络 (通用前缀:net.)
- 虚拟内存 (通用前缀:vm.)
- 设备专用 (通用前缀:dev.)
- 更多子系统描述见 Kernel docs.
要获取所有参数列表,你可以运行:
1 |
|
启用非安全的 Sysctl 参数
sysctl 参数分为 安全 和 非安全的。安全 sysctl 参数除了需要设置恰当的命名空间外,在同一 node 上的不同 Pod 之间也必须是相互隔离的。这意味着在 Pod 上设置 安全 sysctl 参数
- 必须不能影响到节点上的其他 Pod
- 必须不能损害节点的健康
- 必须不允许使用超出 Pod 的资源限制的 CPU 或内存资源。
至今为止,大多数 有命名空间的 sysctl 参数不一定被认为是 安全 的。以下几种 sysctl 参数是 安全的:
- kernel.shm_rmid_forced,
- net.ipv4.ip_local_port_range,
- net.ipv4.tcp_syncookies.
注意: 示例中的 net.ipv4.tcp_syncookies
在Linux 内核 4.4 或更低的版本中是无命名空间的。
在未来的 Kubernetes 版本中,若kubelet 支持更好的隔离机制,则上述列表中将会列出更多 安全的 sysctl 参数。
所有 安全的 sysctl 参数都默认启用。
所有 非安全的 sysctl 参数都默认禁用,且必须由集群管理员在每个节点上手动开启。那些设置了不安全 sysctl 参数的 Pod 仍会被调度,但无法正常启动。
参考上述警告,集群管理员只有在一些非常特殊的情况下(如:高可用或实时应用调整),才可以启用特定的 非安全的 sysctl 参数。如需启用 非安全的 sysctl 参数,请您在每个节点上分别设置 kubelet 命令行参数,例如:
1 |
|
只有有命名空间的sysctl可以通过这种方式启用。
设置 Pod 的 Sysctl 参数
目前,在 Linux 内核中,有许多的 sysctl 参数都是 有命名空间的 。 这就意味着可以为节点上的每个 Pod 分别去设置它们的 sysctl 参数。 在 Kubernetes 中,只有那些有命名空间的 sysctl 参数可以通过 Pod 的 securityContext 对其进行配置。
以下列出有命名空间的 sysctl 参数,在未来的 Linux 内核版本中,此列表可能会发生变化。
- kernel.shm*,
- kernel.msg*,
- kernel.sem,
- fs.mqueue.*,
- net.*(内核中网络配置项相关参数),它可以在容器命名空间里被更改。然而,也有一些特例 (例如,net.netfilter.nf_conntrack_max 和 net.netfilter.nf_conntrack_expect_max 可以在容器命名空间里被更改,但它们是非命名空间的)。
没有命名空间的 sysctl 参数称为 节点级别的 sysctl 参数。 如果需要对其进行设置,则必须在每个节点的操作系统上手动地去配置它们,或者通过在 DaemonSet 中运行特权模式容器来配置。
可使用 pod 的 securityContext 来配置有命名空间的 sysctl 参数,securityContext 应用于同一个 pod 中的所有容器。
此示例中,使用 Pod SecurityContext 来对一个安全的 sysctl 参数 kernel.shm_rmid_forced
以及两个非安全的 sysctl 参数 net.core.somaxconn
和 kernel.msgmax
进行设置。在 Pod 定义中对 安全的 和 非安全的 sysctl 参数不做区分。
警告:为了避免破坏操作系统的稳定性,请您在了解变更后果之后再修改 sysctl 参数。
1 |
|
最佳实践方案是将具有特殊sysctl设置的节点视为集群中的污染节点
,并且只将需要使用到特殊 sysctl 设置的 Pod 调度到这些节点上。建议使用Kubernetes的污染和容忍特性来实现这一点。
带有非安全sysctl的pod将无法在任何没有显式启用这两个不安全sysctl的节点上启动(启动将会失败)。与节点级sysctl一样,建议使用污染和容忍特性和节点污染将这些pod调度到正确的节点上。
PodSecurityPolicy
您可以通过在 PodSecurityPolicy 的 forbiddenSysctls
和/或 allowedUnsafeSysctls
字段中,指定 sysctl 或填写 sysctl 匹配模式来进一步为 Pod 设置 sysctl 参数。sysctl 参数匹配模式以 *
字符结尾,如 kernel.*
。 单独的 *
字符匹配所有 sysctl 参数。
所有 安全的 sysctl 参数都默认启用。
forbiddenSysctls
和 allowedUnsafeSysctls
的值都是字符串列表类型,可以添加 sysctl 参数名称,也可以添加 sysctl 参数匹配模式(以*
结尾)。 只填写 *
则匹配所有的 sysctl 参数。
forbiddenSysctls
字段用于禁用特定的 sysctl 参数。 您可以在列表中禁用安全和非安全的 sysctl 参数的组合。 要禁用所有的 sysctl 参数,请设置为 *
。
如果要在 allowedUnsafeSysctls
字段中指定一个非安全的 sysctl 参数,并且它在forbiddenSysctls
字段中未被禁用,则可以在 Pod 中通过 PodSecurityPolicy 启用该 sysctl 参数。 若要在 PodSecurityPolicy 中开启所有非安全的 sysctl 参数,请设 allowedUnsafeSysctls
字段值为 *
。
allowedUnsafeSysctls
与 forbiddenSysctls
两字段的配置不能重叠,否则这就意味着存在某个 sysctl 参数既被启用又被禁用。
警告:如果您通过 PodSecurityPolicy 中的 allowedUnsafeSysctls
字段将非安全的 sysctl 参数列入白名单,但该 sysctl 参数未通过 kubelet 命令行参数 --allowed-unsafe-sysctls
在节点上将其列入白名单,则设置了这个 sysctl 参数的 Pod 将会启动失败。
以下示例设置启用了以 kernel.msg
为前缀的非安全的 sysctl 参数,以及禁用了 sysctl 参数 kernel.shm_rmid_forced
。
1 |
|