7.4. 使用挂载命名空间封装优化 CPU 使用量

您可以使用 mount 命名空间封装来优化 OpenShift Container Platform 集群中的 CPU 使用量,以便为 kubelet 和 CRI-O 进程提供私有命名空间。这可减少 systemd 使用的集群 CPU 资源,且功能没有差别。

重要

挂载命名空间封装只是一个技术预览功能。技术预览功能不受红帽产品服务等级协议(SLA)支持,且功能可能并不完整。红帽不推荐在生产环境中使用它们。这些技术预览功能可以使用户提早试用新的功能,并有机会在开发阶段提供反馈意见。

有关红帽技术预览功能支持范围的更多信息,请参阅技术预览功能支持范围

7.4.1. 封装挂载命名空间

挂载命名空间用于隔离挂载点,以便不同命名空间中的进程无法查看彼此的文件。封装是将 Kubernetes 挂载命名空间移到备选位置的过程,这些位置不会由主机操作系统不断扫描。

主机操作系统使用 systemd 持续扫描所有挂载命名空间:标准 Linux 挂载和 Kubernetes 用来操作的大量挂载。kubelet 和 CRI-O 的当前实现都使用所有容器运行时和 kubelet 挂载点的顶级命名空间。但是,在私有命名空间中封装这些特定于容器的挂载点可减少 systemd 开销,且功能没有差别。为 CRI-O 和 kubelet 使用单独的挂载命名空间可以封装来自任何 systemd 或其他主机操作系统交互的容器特定挂载。

现在,所有 OpenShift Container Platform 管理员都可以获得潜在的 CPU 优化功能。封装也可以通过将 Kubernetes 特定的挂载点存储在非特权用户安全检查的位置来提高安全性。

下图显示了封装之前和之后的 Kubernetes 安装。这两种场景演示了具有双向、主机到容器和 none 挂载传播设置的示例容器。

封装前

在这里,我们看到 systemd、主机操作系统进程、kubelet 和容器运行时共享单个挂载命名空间。

  • systemd、主机操作系统进程、kubelet 和容器运行时都可以访问所有挂载点和可见性。
  • 容器 1 (使用双向挂载传播配置)可以访问 systemd 和主机挂载、kubelet 和 CRI-O 挂载。源自容器 1 的挂载(如 /run/a )对于 systemd、主机操作系统进程、kubelet、容器运行时和其他配置了主机的容器或双向挂载传播(如在容器 2 中)可见。
  • 容器 2 (使用 host-to-container 挂载传播配置)可以访问 systemd 和主机挂载、kubelet 和 CRI-O 挂载。源自容器 2 的挂载(如 /run/b)对任何其他上下文都不可见。
  • 容器 3 没有配置挂载传播,对外部挂载点没有可见性。源自容器 3 的挂载(如 /run/c)对任何其他上下文都不可见。

下图演示了封装后的系统状态。

封装后
  • 主 systemd 进程不再被禁止对特定于 Kubernetes 的挂载点进行不必要的扫描。它仅监控特定于 systemd 和主机挂载点。
  • 主机操作系统进程只能访问 systemd 和主机挂载点。
  • 为 CRI-O 和 kubelet 使用单独的挂载命名空间,可将所有特定于容器的挂载完全独立于任何 systemd 或其他主机操作系统交互。
  • 容器 1 的行为保持不变,但它创建的挂载(如 /run/a)不再对 systemd 或主机操作系统进程可见。仍然对 kubelet、CRI-O 和其他配置了主机到容器或双向挂载传播的容器(如 Container 2)可见。
  • 容器 2 和容器 3 的行为不会改变。

7.4.2. 配置挂载命名空间封装

您可以配置挂载命名空间封装,以便集群以较少的资源开销运行。

注意

挂载命名空间封装是一个技术预览功能,它默认是禁用的。要使用它,您必须手动启用该功能。

先决条件

  • 已安装 OpenShift CLI(oc)。
  • 您已以具有 cluster-admin 权限的用户身份登录。

流程

  1. 使用以下 YAML 创建名为 mount_namespace_config.yaml 的文件:

    apiVersion: machineconfiguration.openshift.io/v1
    kind: MachineConfig
    metadata:
      labels:
        machineconfiguration.openshift.io/role: master
      name: 99-kubens-master
    spec:
      config:
        ignition:
          version: 3.2.0
        systemd:
          units:
          - enabled: true
            name: kubens.service
    ---
    apiVersion: machineconfiguration.openshift.io/v1
    kind: MachineConfig
    metadata:
      labels:
        machineconfiguration.openshift.io/role: worker
      name: 99-kubens-worker
    spec:
      config:
        ignition:
          version: 3.2.0
        systemd:
          units:
          - enabled: true
            name: kubens.service
  2. 运行以下命令来应用挂载命名空间 MachineConfig CR:

    $ oc apply -f mount_namespace_config.yaml

    输出示例

    machineconfig.machineconfiguration.openshift.io/99-kubens-master created
    machineconfig.machineconfiguration.openshift.io/99-kubens-worker created

  3. MachineConfig CR 最多可能需要 30 分钟才能完成在集群中应用。您可以运行以下命令来检查 MachineConfig CR 的状态:

    $ oc get mcp

    输出示例

    NAME     CONFIG                                             UPDATED   UPDATING   DEGRADED   MACHINECOUNT   READYMACHINECOUNT   UPDATEDMACHINECOUNT   DEGRADEDMACHINECOUNT   AGE
    master   rendered-master-03d4bc4befb0f4ed3566a2c8f7636751   False     True       False      3              0                   0                     0                      45m
    worker   rendered-worker-10577f6ab0117ed1825f8af2ac687ddf   False     True       False      3              1                   1

  4. 运行以下命令,等待所有 control plane 和 worker 节点成功应用 MachineConfig CR:

    $ oc wait --for=condition=Updated mcp --all --timeout=30m

    输出示例

    machineconfigpool.machineconfiguration.openshift.io/master condition met
    machineconfigpool.machineconfiguration.openshift.io/worker condition met

验证

要验证集群主机的封装,请运行以下命令:

  1. 打开集群主机的默认 shell:

    $ oc debug node/<node_name>
  2. 打开 chroot 会话:

    sh-4.4# chroot /host
  3. 检查 systemd 挂载命名空间:

    sh-4.4# readlink /proc/1/ns/mnt

    输出示例

    mnt:[4026531953]

  4. 检查 kubelet 挂载命名空间:

    sh-4.4# readlink /proc/$(pgrep kubelet)/ns/mnt

    输出示例

    mnt:[4026531840]

  5. 检查 CRI-O 挂载命名空间:

    sh-4.4# readlink /proc/$(pgrep crio)/ns/mnt

    输出示例

    mnt:[4026531840]

这些命令返回与 systemd、kubelet 和容器运行时关联的挂载命名空间。在 OpenShift Container Platform 中,容器运行时是 CRI-O。

如果 systemd 位于 kubelet 和 CRI-O 的挂载命名空间中,则封装生效,如上例中所示。如果所有三个进程都位于同一挂载命名空间中,则封装无效。

7.4.3. 检查封装的命名空间

您可以使用 Red Hat Enterprise Linux CoreOS (RHCOS) 中的 kubensenter 脚本检查集群主机操作系统中特定于 Kubernetes 的挂载点以进行调试或审核目的。

到集群主机的 SSH shell 会话位于 default 命名空间中。要在 SSH shell 提示符中检查特定于 Kubernetes 的挂载点,您需要以 root 用户身份运行 kubensenter 脚本。kubensenter 脚本了解挂载封装的状态,即使未启用封装,也可以安全地运行。

注意

默认情况下,oc debug 远程 shell 会话在 Kubernetes 命名空间内启动。使用 oc debug 时,您不需要运行 kubensenter 来检查挂载点。

如果没有启用封装功能,kubensenter findmntfindmnt 命令会返回相同的输出,无论它们是否在 oc debug 会话或 SSH shell 提示符中运行。

先决条件

  • 已安装 OpenShift CLI(oc)。
  • 您已以具有 cluster-admin 权限的用户身份登录。
  • 您已配置了到集群主机的 SSH 访问。

流程

  1. 打开到集群主机的远程 SSH shell。例如:

    $ ssh core@<node_name>
  2. 以 root 用户身份使用提供的 kubensenter 脚本运行命令。要在 Kubernetes 命名空间中运行单个命令,请为 kubensenter 脚本提供命令和任何参数。例如,要在 Kubernetes 命名空间中运行 findmnt 命令,请运行以下命令:

    [core@control-plane-1 ~]$ sudo kubensenter findmnt

    输出示例

    kubensenter: Autodetect: kubens.service namespace found at /run/kubens/mnt
    TARGET                                SOURCE                 FSTYPE     OPTIONS
    /                                     /dev/sda4[/ostree/deploy/rhcos/deploy/32074f0e8e5ec453e56f5a8a7bc9347eaa4172349ceab9c22b709d9d71a3f4b0.0]
    |                                                            xfs        rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,prjquota
                                          shm                    tmpfs
    ...

  3. 要在 Kubernetes 命名空间中启动新的交互式 shell,请运行没有任何参数的 kubensenter 脚本:

    [core@control-plane-1 ~]$ sudo kubensenter

    输出示例

    kubensenter: Autodetect: kubens.service namespace found at /run/kubens/mnt

7.4.4. 在封装的命名空间中运行额外的服务

任何依赖于可以在主机操作系统中运行的能力,以及由 kubelet、CRI-O 或容器本身创建的挂载点的监控工具,都必须输入容器挂载命名空间来查看这些挂载点。OpenShift Container Platform 提供的 kubensenter 脚本在 Kubernetes 挂载点中执行另一个命令,并可用于适配任何现有工具。

kubensenter 脚本了解挂载封装功能状态,即使未启用封装功能,也可以安全地运行。在这种情况下,脚本会在默认挂载命名空间中执行提供的命令。

例如,如果 systemd 服务需要在新的 Kubernetes 挂载命名空间中运行,请编辑服务文件,并使用带有 kubensenterExecStart= 命令行。

[Unit]
Description=Example service
[Service]
ExecStart=/usr/bin/kubensenter /path/to/original/command arg1 arg2

7.4.5. 其他资源