×

Sysctl 设置通过 Kubernetes 公开,允许用户在运行时修改某些内核参数。只有命名空间的 sysctls 才能在 Pod 上独立设置。如果 sysctl 不是命名空间的,称为节点级,则必须使用其他方法设置 sysctl,例如使用节点调优操作符。

网络 sysctls 是 sysctl 的一个特殊类别。网络 sysctls 包括:

  • 系统范围的 sysctls,例如net.ipv4.ip_local_port_range,对所有网络有效。您可以为节点上的每个 Pod 独立设置这些 sysctls。

  • 接口特定的 sysctls,例如net.ipv4.conf.IFNAME.accept_local,仅适用于给定 Pod 的特定附加网络接口。您可以为每个附加网络配置独立设置这些 sysctls。您可以使用tuning-cni中的配置在创建网络接口后设置这些 sysctls。

此外,默认情况下,只有那些被认为是安全的 sysctls 才是白名单;您可以手动启用节点上其他不安全的 sysctls 以供用户使用。

如果您正在设置 sysctl 且它不是节点级的,您可以在使用节点调优操作符部分中找到此过程的信息。

关于 sysctls

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

  • 内核(通用前缀:kernel.

  • 网络(通用前缀:net.

  • 虚拟内存(通用前缀:vm.

  • MDADM(通用前缀:dev.

更多子系统在内核文档中有所描述。要获取所有参数的列表,请运行:

$ sudo sysctl -a

命名空间和节点级 sysctls

许多 sysctls 在 Linux 内核中是命名空间的。这意味着您可以为节点上的每个 Pod 独立设置它们。命名空间是 sysctls 在 Kubernetes 中的 Pod 上下文中可访问的必要条件。

已知以下 sysctls 是命名空间的:

  • kernel.shm*

  • kernel.msg*

  • kernel.sem

  • fs.mqueue.*

此外,net.*组中的大多数 sysctls 已知是命名空间的。它们的命名空间采用情况因内核版本和发行版而异。

不是命名空间的 sysctls 称为节点级,必须由集群管理员手动设置,可以通过节点的基础 Linux 发行版来设置,例如通过修改/etc/sysctls.conf文件,或使用具有特权容器的守护进程集。您可以使用节点调优操作符来设置节点级 sysctls。

考虑将具有特殊 sysctls 的节点标记为受损。仅将需要这些 sysctl 设置的 Pod 调度到这些节点上。使用污点和容忍功能来标记节点。

安全和不安全的 sysctls

Sysctls 分为安全不安全的 sysctls。

对于系统范围的 sysctls 来说,要被认为是安全的,它们必须是命名空间的。命名空间 sysctl 确保命名空间和 Pod 之间存在隔离。如果您为一个 Pod 设置 sysctl,它不能添加以下任何内容:

  • 影响节点上的任何其他 Pod

  • 损害节点健康

  • 获取超出 Pod 资源限制的 CPU 或内存资源

仅命名空间不足以使 sysctl 被认为是安全的。

任何未添加到 OpenShift Container Platform 允许列表中的 sysctl 对于 OpenShift Container Platform 而言都被认为是不安全的。

默认情况下不允许使用不安全的 sysctls。对于系统范围的 sysctls,集群管理员必须在每个节点的基础上手动启用它们。具有禁用的不安全 sysctls 的 Pod 将被调度但不会启动。

您无法手动启用接口特定的不安全 sysctls。

OpenShift Container Platform 将以下系统范围和接口特定的安全 sysctls 添加到允许的安全列表中:

表 1. 系统范围的安全 sysctls
sysctl 描述

kernel.shm_rmid_forced

设置为1时,当前IPC命名空间中的所有共享内存对象将自动强制使用IPC_RMID。更多信息,请参见 shm_rmid_forced

net.ipv4.ip_local_port_range

定义TCP和UDP用于选择本地端口的本地端口范围。第一个数字是第一个端口号,第二个数字是最后一个本地端口号。如果可能,最好这两个数字奇偶性不同(一个偶数,一个奇数)。它们必须大于或等于ip_unprivileged_port_start。默认值分别为3276860999。更多信息,请参见 ip_local_port_range

net.ipv4.tcp_syncookies

当设置net.ipv4.tcp_syncookies时,内核正常处理TCP SYN数据包,直到半打开连接队列已满,此时,SYN cookie功能启动。此功能允许系统即使在拒绝服务攻击下也能继续接受有效连接。更多信息,请参见 tcp_syncookies

net.ipv4.ping_group_range

这将ICMP_PROTO数据报套接字限制为组范围内的用户。默认值为1 0,这意味着没有人,甚至root用户,都不能创建ping套接字。更多信息,请参见 ping_group_range

net.ipv4.ip_unprivileged_port_start

这定义了网络命名空间中的第一个非特权端口。要禁用所有特权端口,请将其设置为0。特权端口不得与ip_local_port_range重叠。更多信息,请参见 ip_unprivileged_port_start

net.ipv4.ip_local_reserved_ports

指定要为应用程序或服务保留的逗号分隔的本地端口范围。

net.ipv4.tcp_keepalive_time

指定连接空闲后应发送第一个keepalive探测之前的间隔(秒)。

net.ipv4.tcp_fin_timeout

指定连接在FIN-WAIT-2状态下保留的时间(秒),之后连接将被中止。

net.ipv4.tcp_keepalive_intvl

指定keepalive探测之间的间隔(秒)。此值乘以tcp_keepalive_probes值以确定确定连接已断开之前所需的时间。

net.ipv4.tcp_keepalive_probes

指定要发送的keepalive探测次数,直到确定连接已断开。

表2. 接口特定的安全sysctls
sysctl 描述

net.ipv4.conf.IFNAME.accept_redirects

接受IPv4 ICMP重定向消息。

net.ipv4.conf.IFNAME.accept_source_route

接受具有严格源路由(SRR)选项的IPv4数据包。

net.ipv4.conf.IFNAME.arp_accept

定义对于ARP表中尚不存在IPv4地址的 gratuitous ARP 帧的行为

  • 0 - 不在ARP表中创建新条目。

  • 1 - 在ARP表中创建新条目。

net.ipv4.conf.IFNAME.arp_notify

定义IPv4地址和设备更改通知的模式。

net.ipv4.conf.IFNAME.disable_policy

禁用此IPv4接口的IPSEC策略(SPD)。

net.ipv4.conf.IFNAME.secure_redirects

仅接受发送到接口当前网关列表中列出的网关的ICMP重定向消息。

net.ipv4.conf.IFNAME.send_redirects

仅当节点充当路由器时才启用发送重定向。也就是说,主机不应发送ICMP重定向消息。路由器使用它来通知主机特定目的地的更好的路由路径。

net.ipv6.conf.IFNAME.accept_ra

接受IPv6路由器通告;使用它们自动配置。它还确定是否传输路由器请求。只有当功能设置是接受路由器通告时,才会传输路由器请求。

net.ipv6.conf.IFNAME.accept_redirects

接受IPv6 ICMP重定向消息。

net.ipv6.conf.IFNAME.accept_source_route

接受具有SRR选项的IPv6数据包。

net.ipv6.conf.IFNAME.arp_accept

定义对于ARP表中尚不存在IPv6地址的 gratuitous ARP 帧的行为

  • 0 - 不在ARP表中创建新条目。

  • 1 - 在ARP表中创建新条目。

net.ipv6.conf.IFNAME.arp_notify

定义IPv6地址和设备更改通知的模式。

net.ipv6.neigh.IFNAME.base_reachable_time_ms

此参数控制IPv6邻居表中硬件地址到IP映射的生存期。

net.ipv6.neigh.IFNAME.retrans_time_ms

设置邻居发现消息的重传计时器。

使用tuning CNI插件设置这些值时,请按字面意思使用值IFNAME。接口名称由IFNAME标记表示,并在运行时替换为接口的实际名称。

更新接口特定的安全sysctls列表

OpenShift Container Platform包含一个预定义的安全接口特定sysctls列表。您可以通过更新openshift-multus命名空间中的cni-sysctl-allowlist来修改此列表。

更新接口特定安全sysctls列表的支持仅为技术预览功能。技术预览功能不受Red Hat生产服务级别协议(SLA)的支持,并且可能功能不完整。Red Hat不建议在生产环境中使用它们。这些功能可提前访问即将推出的产品功能,使客户能够在开发过程中测试功能并提供反馈。

有关Red Hat技术预览功能支持范围的更多信息,请参见 技术预览功能支持范围

请按照此步骤修改预定义的安全sysctls列表。此步骤描述如何扩展默认允许列表。

步骤
  1. 运行以下命令查看现有的预定义列表

    $ oc get cm -n openshift-multus cni-sysctl-allowlist -oyaml
    预期输出
    apiVersion: v1
    data:
      allowlist.conf: |-
        ^net.ipv4.conf.IFNAME.accept_redirects$
        ^net.ipv4.conf.IFNAME.accept_source_route$
        ^net.ipv4.conf.IFNAME.arp_accept$
        ^net.ipv4.conf.IFNAME.arp_notify$
        ^net.ipv4.conf.IFNAME.disable_policy$
        ^net.ipv4.conf.IFNAME.secure_redirects$
        ^net.ipv4.conf.IFNAME.send_redirects$
        ^net.ipv6.conf.IFNAME.accept_ra$
        ^net.ipv6.conf.IFNAME.accept_redirects$
        ^net.ipv6.conf.IFNAME.accept_source_route$
        ^net.ipv6.conf.IFNAME.arp_accept$
        ^net.ipv6.conf.IFNAME.arp_notify$
        ^net.ipv6.neigh.IFNAME.base_reachable_time_ms$
        ^net.ipv6.neigh.IFNAME.retrans_time_ms$
    kind: ConfigMap
    metadata:
      annotations:
        kubernetes.io/description: |
          Sysctl allowlist for nodes.
        release.openshift.io/version: 4.17.0-0.nightly-2022-11-16-003434
      creationTimestamp: "2022-11-17T14:09:27Z"
      name: cni-sysctl-allowlist
      namespace: openshift-multus
      resourceVersion: "2422"
      uid: 96d138a3-160e-4943-90ff-6108fa7c50c3
  2. 使用以下命令编辑列表

    $ oc edit cm -n openshift-multus cni-sysctl-allowlist -oyaml

    例如,要允许您实现更严格的反向路径转发,您需要将^net.ipv4.conf.IFNAME.rp_filter$^net.ipv6.conf.IFNAME.rp_filter$添加到列表中,如下所示

    # Please edit the object below. Lines beginning with a '#' will be ignored,
    # and an empty file will abort the edit. If an error occurs while saving this file will be
    # reopened with the relevant failures.
    #
    apiVersion: v1
    data:
      allowlist.conf: |-
        ^net.ipv4.conf.IFNAME.accept_redirects$
        ^net.ipv4.conf.IFNAME.accept_source_route$
        ^net.ipv4.conf.IFNAME.arp_accept$
        ^net.ipv4.conf.IFNAME.arp_notify$
        ^net.ipv4.conf.IFNAME.disable_policy$
        ^net.ipv4.conf.IFNAME.secure_redirects$
        ^net.ipv4.conf.IFNAME.send_redirects$
        ^net.ipv4.conf.IFNAME.rp_filter$
        ^net.ipv6.conf.IFNAME.accept_ra$
        ^net.ipv6.conf.IFNAME.accept_redirects$
        ^net.ipv6.conf.IFNAME.accept_source_route$
        ^net.ipv6.conf.IFNAME.arp_accept$
        ^net.ipv6.conf.IFNAME.arp_notify$
        ^net.ipv6.neigh.IFNAME.base_reachable_time_ms$
        ^net.ipv6.neigh.IFNAME.retrans_time_ms$
        ^net.ipv6.conf.IFNAME.rp_filter$
  3. 保存对文件的更改并退出。

    也支持删除sysctls。编辑文件,删除sysctlsysctls,然后保存更改并退出。

验证

请按照此步骤为IPv4强制执行更严格的反向路径转发。有关反向路径转发的更多信息,请参见 反向路径转发

  1. 创建一个网络附件定义,例如reverse-path-fwd-example.yaml,内容如下

    apiVersion: "k8s.cni.cncf.io/v1"
    kind: NetworkAttachmentDefinition
    metadata:
      name: tuningnad
      namespace: default
    spec:
      config: '{
        "cniVersion": "0.4.0",
        "name": "tuningnad",
        "plugins": [{
          "type": "bridge"
          },
          {
          "type": "tuning",
          "sysctl": {
             "net.ipv4.conf.IFNAME.rp_filter": "1"
            }
        }
      ]
    }'
  2. 运行以下命令应用yaml

    $ oc apply -f reverse-path-fwd-example.yaml
    示例输出
    networkattachmentdefinition.k8.cni.cncf.io/tuningnad created
  3. 使用以下YAML创建一个pod,例如examplepod.yaml

    apiVersion: v1
    kind: Pod
    metadata:
      name: example
      labels:
        app: httpd
      namespace: default
      annotations:
        k8s.v1.cni.cncf.io/networks: tuningnad  (1)
    spec:
      securityContext:
        runAsNonRoot: true
        seccompProfile:
          type: RuntimeDefault
      containers:
        - name: httpd
          image: 'image-registry.openshift-image-registry.svc:5000/openshift/httpd:latest'
          ports:
            - containerPort: 8080
          securityContext:
            allowPrivilegeEscalation: false
            capabilities:
              drop:
                - ALL
    1 指定已配置的NetworkAttachmentDefinition的名称。
  4. 运行以下命令应用yaml

    $ oc apply -f examplepod.yaml
  5. 运行以下命令验证pod是否已创建

    $ oc get pod
    示例输出
    NAME      READY   STATUS    RESTARTS   AGE
    example   1/1     Running   0          47s
  6. 运行以下命令登录到pod

    $ oc rsh example
  7. 验证已配置的sysctl标志的值。例如,运行以下命令查找值net.ipv4.conf.net1.rp_filter

    sh-4.4# sysctl net.ipv4.conf.net1.rp_filter
    预期输出
    net.ipv4.conf.net1.rp_filter = 1
其他资源

使用安全sysctl启动Pod

您可以使用Pod的securityContext在Pod上设置sysctl。securityContext适用于同一Pod中的所有容器。

默认情况下允许使用安全sysctl。

此示例使用Pod securityContext设置以下安全sysctl

  • kernel.shm_rmid_forced

  • net.ipv4.ip_local_port_range

  • net.ipv4.tcp_syncookies

  • net.ipv4.ping_group_range

为避免使您的操作系统不稳定,请仅在了解其影响后修改sysctl参数。

使用此过程启动具有已配置sysctl设置的Pod。

在大多数情况下,您需要修改现有的Pod定义并添加securityContext规范。

步骤
  1. 创建一个YAML文件sysctl_pod.yaml,定义一个示例Pod并添加securityContext规范,如下例所示

    apiVersion: v1
    kind: Pod
    metadata:
      name: sysctl-example
      namespace: default
    spec:
      containers:
      - name: podexample
        image: centos
        command: ["bin/bash", "-c", "sleep INF"]
        securityContext:
          runAsUser: 2000 (1)
          runAsGroup: 3000 (2)
          allowPrivilegeEscalation: false (3)
          capabilities: (4)
            drop: ["ALL"]
      securityContext:
        runAsNonRoot: true (5)
        seccompProfile: (6)
          type: RuntimeDefault
        sysctls:
        - name: kernel.shm_rmid_forced
          value: "1"
        - name: net.ipv4.ip_local_port_range
          value: "32770       60666"
        - name: net.ipv4.tcp_syncookies
          value: "0"
        - name: net.ipv4.ping_group_range
          value: "0           200000000"
    1 runAsUser控制使用哪个用户ID运行容器。
    2 runAsGroup控制使用哪个主组ID运行容器。
    3 allowPrivilegeEscalation确定Pod是否可以请求允许权限提升。如果未指定,则默认为true。此布尔值直接控制容器进程上是否设置no_new_privs标志。
    4 capabilities允许特权操作,而无需完全访问root权限。此策略确保从Pod中删除所有功能。
    5 runAsNonRoot: true要求容器将使用任何UID(非0)的用户运行。
    6 RuntimeDefault为Pod或容器工作负载启用默认seccomp配置文件。
  2. 运行以下命令创建Pod

    $ oc apply -f sysctl_pod.yaml
  3. 运行以下命令验证pod是否已创建

    $ oc get pod
    示例输出
    NAME              READY   STATUS            RESTARTS   AGE
    sysctl-example    1/1     Running           0          14s
  4. 运行以下命令登录到pod

    $ oc rsh sysctl-example
  5. 验证已配置sysctl标志的值。例如,通过运行以下命令查找值kernel.shm_rmid_forced

    sh-4.4# sysctl kernel.shm_rmid_forced
    预期输出
    kernel.shm_rmid_forced = 1

使用不安全sysctl启动Pod

除非集群管理员显式为该节点启用不安全sysctl,否则使用不安全sysctl的Pod将无法在任何节点上启动。与节点级sysctl一样,使用节点上的污点和容忍功能或标签将这些Pod调度到正确的节点上。

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

为避免使您的操作系统不稳定,请仅在了解其影响后修改sysctl参数。

以下示例说明将安全和不安全sysctl添加到Pod规范时会发生的情况

步骤
  1. 创建一个YAML文件sysctl-example-unsafe.yaml,定义一个示例Pod并添加securityContext规范,如下例所示

    apiVersion: v1
    kind: Pod
    metadata:
      name: sysctl-example-unsafe
    spec:
      containers:
      - name: podexample
        image: centos
        command: ["bin/bash", "-c", "sleep INF"]
        securityContext:
          runAsUser: 2000
          runAsGroup: 3000
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
      securityContext:
        runAsNonRoot: true
        seccompProfile:
          type: RuntimeDefault
        sysctls:
        - name: kernel.shm_rmid_forced
          value: "0"
        - name: net.core.somaxconn
          value: "1024"
        - name: kernel.msgmax
          value: "65536"
  2. 使用以下命令创建Pod

    $ oc apply -f sysctl-example-unsafe.yaml
  3. 使用以下命令验证Pod是否已调度但未部署,因为节点不允许使用不安全sysctl

    $ oc get pod
    示例输出
    NAME                       READY             STATUS            RESTARTS   AGE
    sysctl-example-unsafe      0/1               SysctlForbidden   0          14s

启用不安全sysctl

集群管理员可以允许某些不安全sysctl用于非常特殊的情况,例如高性能或实时应用程序调整。

如果要使用不安全sysctl,集群管理员必须为特定类型的节点单独启用它们。sysctl必须是命名空间的。

您可以通过在安全上下文约束的allowedUnsafeSysctls字段中指定sysctl或sysctl模式列表来进一步控制在Pod中设置哪些sysctl。

  • allowedUnsafeSysctls选项控制特定需求,例如高性能或实时应用程序调整。

由于其不安全的性质,使用不安全sysctl的风险自负,并可能导致严重问题,例如容器行为不当、资源短缺或节点中断。

步骤
  1. 列出OpenShift Container Platform集群的现有MachineConfig对象,以决定如何标记您的机器配置,请运行以下命令

    $ oc get machineconfigpool
    示例输出
    NAME     CONFIG                                             UPDATED   UPDATING   DEGRADED   MACHINECOUNT   READYMACHINECOUNT   UPDATEDMACHINECOUNT   DEGRADEDMACHINECOUNT   AGE
    master   rendered-master-bfb92f0cd1684e54d8e234ab7423cc96   True      False      False      3              3                   3                     0                      42m
    worker   rendered-worker-21b6cb9a0f8919c88caf39db80ac1fce   True      False      False      3              3                   3                     0                      42m
  2. 使用以下命令向将运行具有不安全sysctl的容器的机器配置池添加标签

    $ oc label machineconfigpool worker custom-kubelet=sysctl
  3. 创建一个YAML文件set-sysctl-worker.yaml,定义一个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.core.somaxconn"
    1 指定机器配置池中的标签。
    2 列出您要允许的不安全sysctl。
  4. 运行以下命令创建对象

    $ oc apply -f set-sysctl-worker.yaml
  5. 等待Machine Config Operator生成新的渲染配置并将其应用于机器,请运行以下命令

    $ oc get machineconfigpool worker -w

    几分钟后,UPDATING状态将从True变为False

    NAME     CONFIG                                             UPDATED   UPDATING   DEGRADED   MACHINECOUNT   READYMACHINECOUNT   UPDATEDMACHINECOUNT   DEGRADEDMACHINECOUNT   AGE
    worker   rendered-worker-f1704a00fc6f30d3a7de9a15fd68a800   False     True       False      3              2                   2                     0                      71m
    worker   rendered-worker-f1704a00fc6f30d3a7de9a15fd68a800   False     True       False      3              2                   3                     0                      72m
    worker   rendered-worker-0188658afe1f3a183ec8c4f14186f4d5   True      False      False      3              3                   3                     0                      72m
  6. 创建一个YAML文件sysctl-example-safe-unsafe.yaml,定义一个示例Pod并添加securityContext规范,如下例所示

    apiVersion: v1
    kind: Pod
    metadata:
      name: sysctl-example-safe-unsafe
    spec:
      containers:
      - name: podexample
        image: centos
        command: ["bin/bash", "-c", "sleep INF"]
        securityContext:
          runAsUser: 2000
          runAsGroup: 3000
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
      securityContext:
        runAsNonRoot: true
        seccompProfile:
          type: RuntimeDefault
        sysctls:
        - name: kernel.shm_rmid_forced
          value: "0"
        - name: net.core.somaxconn
          value: "1024"
        - name: kernel.msgmax
          value: "65536"
  7. 运行以下命令创建Pod

    $ oc apply -f sysctl-example-safe-unsafe.yaml
    预期输出
    Warning: would violate PodSecurity "restricted:latest": forbidden sysctls (net.core.somaxconn, kernel.msgmax)
    pod/sysctl-example-safe-unsafe created
  8. 运行以下命令验证pod是否已创建

    $ oc get pod
    示例输出
    NAME                         READY   STATUS    RESTARTS   AGE
    sysctl-example-safe-unsafe   1/1     Running   0          19s
  9. 运行以下命令登录到pod

    $ oc rsh sysctl-example-safe-unsafe
  10. 验证已配置sysctl标志的值。例如,通过运行以下命令查找值net.core.somaxconn

    sh-4.4# sysctl net.core.somaxconn
    预期输出
    net.core.somaxconn = 1024

现在允许使用不安全sysctl,并且其值设置为更新后的Pod规范的securityContext规范中定义的值。