5.9. 在容器中使用 sysctl
Sysctl 设置可以通过 Kubernetes 来公开,允许用户在运行时为容器内的命名空间修改某些内核参数。只有拥有命名空间的 sysctl 才能独立于 pod 进行设置。如果 sysctl 没有命名空间,则称为节点级别,无法在 OpenShift Container Platform 中设置。此外,只有被认为是安全的 sysctl 才会默认列在白名单中;您可以在节点上手动启用其他不安全 sysctl 来供用户使用。
5.9.1. 关于 sysctl
在 Linux 中,管理员可通过 sysctl 接口在运行时修改内核参数。参数可通过 /proc/sys/ 虚拟进程文件系统提供。这些参数涵盖了各种不同的子系统,例如:
- 内核(通用前缀:kernel.)
- 网络(通用前缀:net.)
- 虚拟内存(通用前缀:vm.)
- MDADM(通用前缀:dev.)
如需了解更多子系统,请参阅 Kernel 文档。要获取所有参数的列表,请运行:
$ sudo sysctl -a
5.9.1.1. 命名空间和节点级 sysctl
许多 sysctl 在 Linux 内核中是有命名空间的。这意味着您可以针对节点上的每个 pod 单独设置它们。sysctl 必须拥有命名空间,才能在 Kubernetes 内的 pod 上下文中访问它们。
以下 sysctl 已知是拥有命名空间的:
- kernel.shm*
- kernel.msg*
- kernel.sem
- fs.mqueue.*
另外,net.* 组中的大多数 sysctl 都已知是拥有命名空间的。其命名空间的采用根据内核版本和发行方而有所不同。
无命名空间的 sysctl 被视为节点级别,且必须由集群管理员手动设置,或者通过使用节点的底层 Linux 发行版,如修改 /etc/sysctls.conf 文件,或者通过使用带有特权容器的 DaemonSet。
可以考虑将带有特殊 sysctl 节点标记为污点。仅将 pod 调度到需要这些 sysctl 设置的节点。使用污点和容限功能来标记节点。
5.9.1.2. 安全与不安全 sysctl
sysctl 划分为安全和不安全 sysctl。
sysctl 若要被视为安全,必须使用正确的命名空间,且必须在同一节点的不同 pod 之间进行适当的隔离。也就是说,如果您为一个 pod 设置了 sysctl,它不得:
- 影响节点上的其他任何 pod
- 危害节点的健康
- 获取超过 pod 资源限制的 CPU 或内存资源
OpenShift Container Platform 支持(或列入白名单)安全集合中的以下 sysctl:
- kernel.shm_rmid_forced
- net.ipv4.ip_local_port_range
- net.ipv4.tcp_syncookies
所有安全 sysctl 都默认启用。您可以通过修改 pod 规格在 pod 中使用 sysctl。
任何未在 OpenShift Container Platform 白名单中列出的 sysctl 都被视为对 OpenShift Container Platform 而言不安全。请注意,仅拥有命名空间还不足以使 sysctl 被视为安全。
所有不安全 sysctl 都默认禁用,集群管理员必须逐个节点手动启用它们。禁用了不安全 sysctl 的 Pod 会被调度,但不会启动。
$ oc get pod NAME READY STATUS RESTARTS AGE hello-pod 0/1 SysctlForbidden 0 14s
5.9.2. 为 pod 设置 sysctl
您可以使用 pod 的 securityContext
在 pod 上设置 sysctl。securityContext
适用于同一 pod 中的所有容器。
默认允许安全 sysctl。带有不安全 sysctl 的 pod 无法在任何节点上启动,除非集群管理员在某个节点上明确启用了不安全 sysctl。与节点级 sysctl 一样,使用污点和容限功能或节点上的标签将这些 pod 调度到正确的节点。
以下示例使用 pod securityContext
设置一个安全 sysctl kernel.shm_rmid_forced
,以及两个不安全 sysctl net.ipv4.route.min_pmtu
和 kernel.msgmax
。在规格中,安全和不安全 sysctl 并无区别。
为了避免让操作系统变得不稳定,只有在了解了参数的作用后才修改 sysctl 参数。
流程
使用安全和不安全 sysctl:
修改定义 pod 的 YAML 文件并添加
securityContext
规格,如下例所示:apiVersion: v1 kind: Pod metadata: name: sysctl-example spec: securityContext: sysctls: - name: kernel.shm_rmid_forced value: "0" - name: net.ipv4.route.min_pmtu value: "552" - name: kernel.msgmax value: "65536" ...
创建 pod:
$ oc apply -f <file-name>.yaml
如果节点不允许不安全 sysctl,则 pod 会被调度,但不会部署:
$ oc get pod NAME READY STATUS RESTARTS AGE hello-pod 0/1 SysctlForbidden 0 14s
5.9.3. 启用不安全 sysctl
集群管理员可在非常特殊的情况下允许某些不安全 sysctl,比如高性能或实时应用程序性能优化。
如果要使用不安全 sysctl,集群管理员必须为特定类型的节点单独启用它们。sysctl 必须拥有命名空间。
由于其不安全特性,使用不安全 sysctl 的风险由您自行承担,而且可能会造成严重问题,例如容器行为不当、资源短缺或节点受损。
流程
在要运行带有不安全 sysctl 的容器的 MachineConfigPool 中添加标签:
$ oc edit machineconfigpool worker
apiVersion: machineconfiguration.openshift.io/v1 kind: MachineConfigPool metadata: creationTimestamp: 2019-02-08T14:52:39Z generation: 1 labels: custom-kubelet: sysctl 1
- 1
- 添加
key: pair
标签。
创建 KubeletConfig 自定义资源 (CR):
apiVersion: machineconfiguration.openshift.io/v1 kind: KubeletConfig metadata: name: custom-kubelet spec: machineConfigPoolSelector: matchLabels: custom-kubelet: sysctl 1 kubeletConfig: allowedUnsafeSysctls: 2 - "kernel.msg*" - "net.ipv4.route.min_pmtu"
创建对象:
$ oc apply -f set-sysctl-worker.yaml
创建了名称采用
99-worker-XXXXXX-XXXXX-XXXX-XXXXX-kubelet
格式的 MachineConfig。使用
machineconfigpool
对象status
字段等待集群重启:例如:
status: conditions: - lastTransitionTime: '2019-08-11T15:32:00Z' message: >- All nodes are updating to rendered-worker-ccbfb5d2838d65013ab36300b7b3dc13 reason: '' status: 'True' type: Updating
集群就绪时会显示类似如下的消息:
- lastTransitionTime: '2019-08-11T16:00:00Z' message: >- All nodes are updated with rendered-worker-ccbfb5d2838d65013ab36300b7b3dc13 reason: '' status: 'True' type: Updated
集群就绪后,在新的 MachineConfig 中检查合并的
KubeletConfig
:$ oc get machineconfig 99-worker-XXXXXX-XXXXX-XXXX-XXXXX-kubelet -o json | grep ownerReference -A7
"ownerReferences": [ { "apiVersion": "machineconfiguration.openshift.io/v1", "blockOwnerDeletion": true, "controller": true, "kind": "KubeletConfig", "name": "custom-kubelet", "uid": "3f64a766-bae8-11e9-abe8-0a1a2a4813f2"
现在,您可以根据需要为 pod 添加不安全 sysctl。