×

安装OpenShift Container Platform之后,您可以通过某些节点任务进一步扩展和自定义集群以满足您的需求。

将RHEL计算机器添加到OpenShift Container Platform集群

了解和使用RHEL计算节点。

关于将RHEL计算节点添加到集群

在OpenShift Container Platform 4.17中,如果您在x86_64架构上使用用户预配或安装程序预配的基础设施安装,则可以选择在集群中使用Red Hat Enterprise Linux (RHEL)机器作为计算机器。集群中的控制平面机器必须使用Red Hat Enterprise Linux CoreOS (RHCOS)机器。

如果您选择在集群中使用RHEL计算机器,则您负责所有操作系统生命周期管理和维护。您必须执行系统更新、应用补丁并完成所有其他必需的任务。

对于安装程序预配的基础设施集群,您必须手动添加RHEL计算机器,因为安装程序预配的基础设施集群中的自动扩展默认情况下会添加Red Hat Enterprise Linux CoreOS (RHCOS)计算机器。

  • 由于从集群中的机器中删除OpenShift Container Platform需要销毁操作系统,因此您必须为添加到集群的任何RHEL机器使用专用硬件。

  • 添加到OpenShift Container Platform集群中的所有RHEL机器上的交换内存都已禁用。您无法在这些机器上启用交换内存。

RHEL计算节点的系统要求

OpenShift Container Platform环境中的Red Hat Enterprise Linux (RHEL)计算机器主机必须满足以下最低硬件规格和系统级要求

  • 您必须在您的Red Hat帐户上拥有活动的OpenShift Container Platform订阅。如果没有,请联系您的销售代表了解更多信息。

  • 生产环境必须提供计算机器来支持您预期的工作负载。作为集群管理员,您必须计算预期的工作负载,并增加约10%的开销。对于生产环境,请分配足够的资源,以便节点主机故障不会影响您的最大容量。

  • 每个系统必须满足以下硬件要求

    • 物理或虚拟系统,或在公共或私有IaaS上运行的实例。

    • 基本操作系统:使用RHEL 8.8或更高版本,并选择最小安装选项。

      不支持将RHEL 7计算机器添加到OpenShift Container Platform集群。

      如果您有在过去的OpenShift Container Platform版本中以前受支持的RHEL 7计算机器,则无法将它们升级到RHEL 8。您必须部署新的RHEL 8主机,并且应删除旧的RHEL 7主机。有关更多信息,请参阅“删除节点”部分。

      有关OpenShift Container Platform中已弃用或删除的主要功能的最新列表,请参阅OpenShift Container Platform发行说明中的“已弃用和已删除的功能”部分。

    • 如果您在FIPS模式下部署了OpenShift Container Platform,则必须在启动RHEL机器之前在其上启用FIPS。请参阅RHEL 8文档中的启用FIPS模式安装RHEL 8系统

      要为您的集群启用FIPS模式,您必须从配置为在FIPS模式下运行的Red Hat Enterprise Linux (RHEL)计算机运行安装程序。有关在RHEL上配置FIPS模式的更多信息,请参阅将RHEL切换到FIPS模式

      在FIPS模式下启动Red Hat Enterprise Linux (RHEL)或Red Hat Enterprise Linux CoreOS (RHCOS)时,OpenShift Container Platform核心组件仅在x86_64、ppc64le和s390x架构上使用已提交给NIST进行FIPS 140-2/140-3验证的RHEL加密库。

    • NetworkManager 1.0或更高版本。

    • 1 个vCPU。

    • 最小8 GB RAM。

    • 包含/var/的文件系统的最小15 GB硬盘空间。

    • 包含/usr/local/bin/的文件系统的最小1 GB硬盘空间。

    • 包含其临时目录的文件系统的最小1 GB硬盘空间。临时系统目录根据Python标准库中tempfile模块中定义的规则确定。

  • 每个系统必须满足系统提供商的任何其他要求。例如,如果您在VMware vSphere上安装了集群,则必须根据其存储指南配置磁盘,并且必须设置disk.enableUUID=true属性。

  • 每个系统都必须能够通过使用DNS可解析的主机名访问集群的API端点。任何已实施的网络安全访问控制都必须允许系统访问集群的API服务端点。

  • 对于在Microsoft Azure上安装的集群

    • 确保系统包含Standard_D8s_v3虚拟机的硬件要求。

    • 启用加速网络。加速网络使用单根I/O虚拟化(SR-IOV)为Microsoft Azure VM提供更直接的交换机路径。

证书签名请求管理

由于您使用的基础设施由您自行配置,集群对自动机器管理的访问权限有限,因此您必须提供一种机制来批准集群证书签名请求 (CSR)(安装后)。kube-controller-manager 仅批准 kubelet 客户端 CSR。machine-approver 无法保证使用 kubelet 凭据请求的服务证书的有效性,因为它无法确认是正确的机器发出了请求。您必须确定并实施一种验证 kubelet 服务证书请求的有效性并批准它们的方法。

准备运行 playbook 的机器

在将使用 Red Hat Enterprise Linux (RHEL) 作为操作系统的计算机器添加到 OpenShift Container Platform 4.17 集群之前,您必须准备一台 RHEL 8 机器来运行 Ansible playbook,该 playbook 将新节点添加到集群中。这台机器不是集群的一部分,但必须能够访问它。

先决条件
  • 在运行 playbook 的机器上安装 OpenShift CLI (oc)。

  • 以具有 cluster-admin 权限的用户身份登录。

步骤
  1. 确保集群的 kubeconfig 文件和用于安装集群的安装程序位于 RHEL 8 机器上。一种方法是使用与安装集群相同的机器。

  2. 配置机器以访问您计划用作计算机器的所有 RHEL 主机。您可以使用公司允许的任何方法,包括带有 SSH 代理的堡垒机或 VPN。

  3. 在运行 playbook 的机器上配置一个用户,该用户具有对所有 RHEL 主机的 SSH 访问权限。

    如果您使用基于 SSH 密钥的身份验证,则必须使用 SSH 代理管理密钥。

  4. 如果您尚未注册,请将机器注册到 RHSM 并为其附加一个具有 OpenShift 订阅的池。

    1. 将机器注册到 RHSM

      # subscription-manager register --username=<user_name> --password=<password>
    2. 从 RHSM 拉取最新的订阅数据

      # subscription-manager refresh
    3. 列出可用的订阅

      # subscription-manager list --available --matches '*OpenShift*'
    4. 在前面命令的输出中,找到 OpenShift Container Platform 订阅的池 ID 并附加它

      # subscription-manager attach --pool=<pool_id>
  5. 启用 OpenShift Container Platform 4.17所需的存储库

    # subscription-manager repos \
        --enable="rhel-8-for-x86_64-baseos-rpms" \
        --enable="rhel-8-for-x86_64-appstream-rpms" \
        --enable="rhocp-4.17-for-rhel-8-x86_64-rpms"
  6. 安装必需的软件包,包括 openshift-ansible

    # yum install openshift-ansible openshift-clients jq

    openshift-ansible 软件包提供安装程序实用程序,并引入将 RHEL 计算节点添加到集群所需的其它软件包,例如 Ansible、playbook 和相关的配置文件。openshift-clients 提供 oc CLI,而 jq 软件包则改善了命令行上 JSON 输出的显示。

准备 RHEL 计算节点

在将 Red Hat Enterprise Linux (RHEL) 机器添加到 OpenShift Container Platform 集群之前,必须将每个主机注册到 Red Hat Subscription Manager (RHSM),附加活动的 OpenShift Container Platform 订阅并启用所需的存储库。

  1. 在每个主机上,注册到 RHSM

    # subscription-manager register --username=<user_name> --password=<password>
  2. 从 RHSM 拉取最新的订阅数据

    # subscription-manager refresh
  3. 列出可用的订阅

    # subscription-manager list --available --matches '*OpenShift*'
  4. 在前面命令的输出中,找到 OpenShift Container Platform 订阅的池 ID 并附加它

    # subscription-manager attach --pool=<pool_id>
  5. 禁用所有 yum 存储库

    1. 禁用所有启用的 RHSM 存储库

      # subscription-manager repos --disable="*"
    2. 列出剩余的 yum 存储库,并记下其在 repo id 下的名称(如有)。

      # yum repolist
    3. 使用 yum-config-manager 禁用剩余的 yum 存储库

      # yum-config-manager --disable <repo_id>

      或者,禁用所有存储库

      # yum-config-manager --disable \*

      请注意,如果您有大量可用的存储库,这可能需要几分钟时间。

  6. 仅启用 OpenShift Container Platform 4.17所需的存储库

    # subscription-manager repos \
        --enable="rhel-8-for-x86_64-baseos-rpms" \
        --enable="rhel-8-for-x86_64-appstream-rpms" \
        --enable="rhocp-4.17-for-rhel-8-x86_64-rpms" \
        --enable="fast-datapath-for-rhel-8-x86_64-rpms"
  7. 停止并禁用主机上的 firewalld。

    # systemctl disable --now firewalld.service

    您以后不能启用 firewalld。如果您这样做,则无法访问工作程序上的 OpenShift Container Platform 日志。

将 RHEL 计算机器添加到您的集群

您可以将使用 Red Hat Enterprise Linux 作为操作系统的计算机器添加到 OpenShift Container Platform 4.17 集群。

先决条件
  • 您已在运行 playbook 的机器上安装了所需的软件包并执行了必要的配置。

  • 您已准备好在安装时使用的 RHEL 主机。

步骤

在您准备运行 playbook 的机器上执行以下步骤

  1. 创建一个名为 /<path>/inventory/hosts 的 Ansible 清单文件,该文件定义您的计算机器主机和所需的变量。

    [all:vars]
    ansible_user=root (1)
    #ansible_become=True (2)
    
    openshift_kubeconfig_path="~/.kube/config" (3)
    
    [new_workers] (4)
    mycluster-rhel8-0.example.com
    mycluster-rhel8-1.example.com
    1 指定在远程计算机器上运行 Ansible 任务的用户名。
    2 如果您没有为 ansible_user 指定 root,则必须将 ansible_become 设置为 True 并为用户分配 sudo 权限。
    3 指定集群 kubeconfig 文件的路径和文件名。
    4 列出要添加到集群中的每个 RHEL 机器。您必须为每个主机提供完全限定域名。此名称是集群用于访问机器的主机名,因此请设置正确的公共或私有名称以访问机器。
  2. 导航到 Ansible playbook 目录

    $ cd /usr/share/ansible/openshift-ansible
  3. 运行 playbook

    $ ansible-playbook -i /<path>/inventory/hosts playbooks/scaleup.yml (1)
    1 对于 <path>,请指定您创建的 Ansible 清单文件的路径。

Ansible 主机文件所需的參數

在将 Red Hat Enterprise Linux (RHEL) 计算机器添加到集群之前,必须在 Ansible 主机文件中定义以下参数。

参数 描述

ansible_user

允许基于 SSH 的身份验证而无需密码的 SSH 用户。如果您使用基于 SSH 密钥的身份验证,则必须使用 SSH 代理管理密钥。

系统上的用户名。默认值为 root

ansible_become

如果 ansible_user 的值不是 root,则必须将 ansible_become 设置为 True,并且您指定为 ansible_user 的用户必须配置为无密码 sudo 访问。

True。如果该值不是 True,则不要指定和定义此参数。

openshift_kubeconfig_path

指定包含集群 kubeconfig 文件的本地目录的路径和文件名。

配置文件的路径和名称。

可选:从集群中移除 RHCOS 计算机器

将 Red Hat Enterprise Linux (RHEL) 计算机器添加到集群后,您可以选择移除 Red Hat Enterprise Linux CoreOS (RHCOS) 计算机器以释放资源。

先决条件
  • 您已将 RHEL 计算机器添加到集群。

步骤
  1. 查看机器列表并记录 RHCOS 计算机器的节点名称

    $ oc get nodes -o wide
  2. 对于每个 RHCOS 计算机器,删除节点

    1. 通过运行 oc adm cordon 命令将节点标记为不可调度。

      $ oc adm cordon <node_name> (1)
      1 指定其中一台 RHCOS 计算机器的节点名称。
    2. 从节点中排出所有 Pod

      $ oc adm drain <node_name> --force --delete-emptydir-data --ignore-daemonsets (1)
      1 指定您已隔离的 RHCOS 计算机器的节点名称。
    3. 删除节点

      $ oc delete nodes <node_name> (1)
      1 指定您已排出的 RHCOS 计算机器的节点名称。
  3. 查看计算机器列表,确保只有 RHEL 节点保留。

    $ oc get nodes -o wide
  4. 从集群计算机器的负载均衡器中移除 RHCOS 机器。您可以删除虚拟机或重新映像 RHCOS 计算机器的物理硬件。

将 RHCOS 计算机器添加到 OpenShift Container Platform 集群

您可以将更多 Red Hat Enterprise Linux CoreOS (RHCOS) 计算机器添加到裸机上的 OpenShift Container Platform 集群。

在将更多计算机器添加到您在裸机基础设施上安装的集群之前,必须为此创建 RHCOS 机器。您可以使用 ISO 镜像或网络 PXE 引导来创建机器。

先决条件

  • 您已在裸机上安装了集群。

  • 您拥有用于创建集群的安装介质和 Red Hat Enterprise Linux CoreOS (RHCOS) 镜像。如果您没有这些文件,则必须按照安装步骤中的说明获取它们。

使用 ISO 镜像创建 RHCOS 机器

您可以使用 ISO 镜像创建更多 Red Hat Enterprise Linux CoreOS (RHCOS) 计算机器,用于您的裸机集群。

先决条件
  • 获取集群计算机器的 Ignition 配置文件的 URL。您在安装过程中已将此文件上传到您的 HTTP 服务器。

  • 您必须安装 OpenShift CLI (oc)。

步骤
  1. 运行以下命令从集群中提取 Ignition 配置文件:

    $ oc extract -n openshift-machine-api secret/worker-user-data-managed --keys=userData --to=- > worker.ign
  2. 将您从集群导出的 worker.ign Ignition 配置文件上传到您的 HTTP 服务器。记下这些文件的 URL。

  3. 您可以验证 Ignition 文件是否可在 URL 上访问。以下示例获取计算节点的 Ignition 配置文件:

    $ curl -k http://<HTTP_server>/worker.ign
  4. 您可以运行以下命令访问用于启动新机器的 ISO 镜像:

    RHCOS_VHD_ORIGIN_URL=$(oc -n openshift-machine-config-operator get configmap/coreos-bootimages -o jsonpath='{.data.stream}' | jq -r '.architectures.<architecture>.artifacts.metal.formats.iso.disk.location')
  5. 使用 ISO 文件在更多计算机器上安装 RHCOS。使用您在安装集群之前创建机器时所用的相同方法。

    • 将 ISO 镜像刻录到磁盘并直接引导。

    • 使用带有 LOM 接口的 ISO 重定向。

  6. 引导 RHCOS ISO 镜像,无需指定任何选项或中断实时引导序列。等待安装程序引导到 RHCOS 实时环境中的 shell 提示符。

    您可以中断 RHCOS 安装引导过程以添加内核参数。但是,对于此 ISO 过程,您必须使用以下步骤中概述的 coreos-installer 命令,而不是添加内核参数。

  7. 运行 coreos-installer 命令并指定满足您的安装要求的选项。至少,您必须指定指向节点类型 Ignition 配置文件的 URL,以及您要安装到的设备。

    $ sudo coreos-installer install --ignition-url=http://<HTTP_server>/<node_type>.ign <device> --ignition-hash=sha512-<digest> (1) (2)
    1 您必须使用 sudo 运行 coreos-installer 命令,因为 core 用户没有执行安装所需的 root 权限。
    2 当通过 HTTP URL 获取 Ignition 配置文件时,需要 --ignition-hash 选项来验证集群节点上 Ignition 配置文件的真实性。<digest> 是在前面步骤中获得的 Ignition 配置文件 SHA512 散列值。

    如果您想通过使用 TLS 的 HTTPS 服务器提供 Ignition 配置文件,则可以在运行 coreos-installer 之前将内部证书颁发机构 (CA) 添加到系统信任存储区。

    以下示例将引导节点安装初始化到 /dev/sda 设备。引导节点的 Ignition 配置文件是从具有 IP 地址 192.168.1.2 的 HTTP Web 服务器获取的。

    $ sudo coreos-installer install --ignition-url=http://192.168.1.2:80/installation_directory/bootstrap.ign /dev/sda --ignition-hash=sha512-a5a2d43879223273c9b60af66b44202a1d1248fc01cf156c46d4a79f552b6bad47bc8cc78ddf0116e80c59d2ea9e32ba53bc807afbca581aa059311def2c3e3b
  8. 监控机器控制台上 RHCOS 安装的进度。

    在开始 OpenShift Container Platform 安装之前,请确保每个节点上的安装都成功。观察安装过程还可以帮助确定可能出现的 RHCOS 安装问题的根本原因。

  9. 继续为您的集群创建更多计算机器。

通过 PXE 或 iPXE 引导创建 RHCOS 机器

您可以使用 PXE 或 iPXE 引导为您的裸机集群创建更多 Red Hat Enterprise Linux CoreOS (RHCOS) 计算机器。

先决条件
  • 获取集群计算机器的 Ignition 配置文件的 URL。您在安装过程中已将此文件上传到您的 HTTP 服务器。

  • 获取在集群安装期间上传到您的 HTTP 服务器的 RHCOS ISO 镜像、压缩金属 BIOS、kernelinitramfs 文件的 URL。

  • 您可以访问 PXE 引导基础架构,您在安装期间使用它为您的 OpenShift Container Platform 集群创建机器。在 RHCOS 安装到机器上之后,机器必须从其本地磁盘引导。

  • 如果您使用 UEFI,则可以访问您在 OpenShift Container Platform 安装期间修改的 grub.conf 文件。

步骤
  1. 确认您的 RHCOS 镜像的 PXE 或 iPXE 安装是否正确。

    • 对于 PXE

      DEFAULT pxeboot
      TIMEOUT 20
      PROMPT 0
      LABEL pxeboot
          KERNEL http://<HTTP_server>/rhcos-<version>-live-kernel-<architecture> (1)
          APPEND initrd=http://<HTTP_server>/rhcos-<version>-live-initramfs.<architecture>.img coreos.inst.install_dev=/dev/sda coreos.inst.ignition_url=http://<HTTP_server>/worker.ign coreos.live.rootfs_url=http://<HTTP_server>/rhcos-<version>-live-rootfs.<architecture>.img (2)
      1 指定您上传到 HTTP 服务器的实时 kernel 文件的位置。
      2 指定您上传到 HTTP 服务器的 RHCOS 文件的位置。initrd 参数值是实时 initramfs 文件的位置,coreos.inst.ignition_url 参数值是 worker Ignition 配置文件的位置,coreos.live.rootfs_url 参数值是实时 rootfs 文件的位置。coreos.inst.ignition_urlcoreos.live.rootfs_url 参数仅支持 HTTP 和 HTTPS。

      此配置不会在具有图形控制台的机器上启用串行控制台访问。要配置不同的控制台,请向 APPEND 行添加一个或多个 console= 参数。例如,添加 console=tty0 console=ttyS0 可将第一个 PC 串行端口设置为主控制台,并将图形控制台设置为辅助控制台。有关更多信息,请参阅 如何在 Red Hat Enterprise Linux 中设置串行终端和/或控制台?

    • 对于 iPXE (x86_64 + aarch64)

      kernel http://<HTTP_server>/rhcos-<version>-live-kernel-<architecture> initrd=main coreos.live.rootfs_url=http://<HTTP_server>/rhcos-<version>-live-rootfs.<architecture>.img coreos.inst.install_dev=/dev/sda coreos.inst.ignition_url=http://<HTTP_server>/worker.ign (1) (2)
      initrd --name main http://<HTTP_server>/rhcos-<version>-live-initramfs.<architecture>.img (3)
      boot
      1 指定您上传到 HTTP 服务器的 RHCOS 文件的位置。kernel 参数值是 kernel 文件的位置,initrd=main 参数对于在 UEFI 系统上引导是必需的,coreos.live.rootfs_url 参数值是 rootfs 文件的位置,coreos.inst.ignition_url 参数值是 worker Ignition 配置文件的位置。
      2 如果您使用多个网卡,请在 ip 选项中指定单个接口。例如,要在名为 eno1 的网卡上使用 DHCP,请设置 ip=eno1:dhcp
      3 指定您上传到 HTTP 服务器的 initramfs 文件的位置。

      此配置不会在具有图形控制台的机器上启用串行控制台访问。要配置不同的控制台,请向 kernel 行添加一个或多个 console= 参数。例如,添加 console=tty0 console=ttyS0 可将第一个 PC 串行端口设置为主控制台,并将图形控制台设置为辅助控制台。有关更多信息,请参阅 如何在 Red Hat Enterprise Linux 中设置串行终端和/或控制台? 和“高级 RHCOS 安装配置”部分中的“为 PXE 和 ISO 安装启用串行控制台”。

      要在 aarch64 架构上网络引导 CoreOS kernel,您需要使用启用了 IMAGE_GZIP 选项的 iPXE 版本构建。请参阅 iPXE 中的 IMAGE_GZIP 选项

    • 对于 aarch64 上的 PXE(使用 UEFI 和 GRUB 作为第二阶段)

      menuentry 'Install CoreOS' {
          linux rhcos-<version>-live-kernel-<architecture>  coreos.live.rootfs_url=http://<HTTP_server>/rhcos-<version>-live-rootfs.<architecture>.img coreos.inst.install_dev=/dev/sda coreos.inst.ignition_url=http://<HTTP_server>/worker.ign (1) (2)
          initrd rhcos-<version>-live-initramfs.<architecture>.img (3)
      }
      1 指定您上传到 HTTP/TFTP 服务器的 RHCOS 文件位置。kernel 参数值是 TFTP 服务器上 kernel 文件的位置。coreos.live.rootfs_url 参数值是 rootfs 文件的位置,coreos.inst.ignition_url 参数值是 HTTP 服务器上 worker Ignition 配置文件的位置。
      2 如果您使用多个网卡,请在 ip 选项中指定单个接口。例如,要在名为 eno1 的网卡上使用 DHCP,请设置 ip=eno1:dhcp
      3 指定您上传到 TFTP 服务器的 initramfs 文件位置。
  2. 使用 PXE 或 iPXE 基础架构创建集群所需的计算机器。

批准您的机器的证书签名请求

将机器添加到集群时,会为每个添加的机器生成两个待处理的证书签名请求 (CSR)。您必须确认这些 CSR 已获批准,或者如有必要,自行批准它们。必须先批准客户端请求,然后再批准服务器请求。

先决条件
  • 您已将机器添加到集群。

步骤
  1. 确认集群是否识别这些机器

    $ oc get nodes
    示例输出
    NAME      STATUS    ROLES   AGE  VERSION
    master-0  Ready     master  63m  v1.30.3
    master-1  Ready     master  63m  v1.30.3
    master-2  Ready     master  64m  v1.30.3

    输出列出了您创建的所有机器。

    在批准一些 CSR 之前,上述输出可能不包括计算节点(也称为工作节点)。

  2. 查看待处理的 CSR,并确保您看到为添加到集群的每台机器的客户端请求显示“待处理”或“已批准”状态。

    $ oc get csr
    示例输出
    NAME        AGE     REQUESTOR                                                                   CONDITION
    csr-8b2br   15m     system:serviceaccount:openshift-machine-config-operator:node-bootstrapper   Pending
    csr-8vnps   15m     system:serviceaccount:openshift-machine-config-operator:node-bootstrapper   Pending
    ...

    在此示例中,两台机器正在加入集群。您可能会在列表中看到更多已批准的 CSR。

  3. 如果 CSR 未获批准,在您添加的所有机器的待处理 CSR 都处于“待处理”状态后,请批准集群机器的 CSR。

    由于 CSR 会自动轮换,请在将机器添加到集群后一小时内批准您的 CSR。如果您在一小时内未批准它们,证书将轮换,并且每个节点将存在两个以上的证书。您必须批准所有这些证书。批准客户端 CSR 后,Kubelet 将为服务证书创建辅助 CSR,这需要手动批准。然后,如果 Kubelet 请求具有相同参数的新证书,则 machine-approver 将自动批准后续的服务证书续订请求。

    对于在未启用机器 API 的平台(例如裸机和其他用户配置的基础架构)上运行的集群,您必须实现一种自动批准 kubelet 服务证书请求 (CSR) 的方法。如果未批准请求,则 oc execoc rshoc logs 命令将无法成功,因为 API 服务器连接到 kubelet 时需要服务证书。任何联系 Kubelet 端点的操作都需要此证书批准到位。该方法必须监视新的 CSR,确认 CSR 是由 system:nodesystem:admin 组中的 node-bootstrapper 服务帐户提交的,并确认节点的身份。

    • 要单独批准它们,请对每个有效的 CSR 运行以下命令

      $ oc adm certificate approve <csr_name> (1)
      1 <csr_name> 是当前 CSR 列表中 CSR 的名称。
    • 要批准所有待处理的 CSR,请运行以下命令

      $ oc get csr -o go-template='{{range .items}}{{if not .status}}{{.metadata.name}}{{"\n"}}{{end}}{{end}}' | xargs --no-run-if-empty oc adm certificate approve

      在批准一些 CSR 之前,某些 Operator 可能无法使用。

  4. 现在您的客户端请求已获批准,您必须查看为添加到集群的每台机器的服务器请求。

    $ oc get csr
    示例输出
    NAME        AGE     REQUESTOR                                                                   CONDITION
    csr-bfd72   5m26s   system:node:ip-10-0-50-126.us-east-2.compute.internal                       Pending
    csr-c57lv   5m26s   system:node:ip-10-0-95-157.us-east-2.compute.internal                       Pending
    ...
  5. 如果剩余的 CSR 未获批准且处于“待处理”状态,请批准集群机器的 CSR。

    • 要单独批准它们,请对每个有效的 CSR 运行以下命令

      $ oc adm certificate approve <csr_name> (1)
      1 <csr_name> 是当前 CSR 列表中 CSR 的名称。
    • 要批准所有待处理的 CSR,请运行以下命令

      $ oc get csr -o go-template='{{range .items}}{{if not .status}}{{.metadata.name}}{{"\n"}}{{end}}{{end}}' | xargs oc adm certificate approve
  6. 批准所有客户端和服务器 CSR 后,机器将具有“就绪”状态。通过运行以下命令来验证这一点

    $ oc get nodes
    示例输出
    NAME      STATUS    ROLES   AGE  VERSION
    master-0  Ready     master  73m  v1.30.3
    master-1  Ready     master  73m  v1.30.3
    master-2  Ready     master  74m  v1.30.3
    worker-0  Ready     worker  11m  v1.30.3
    worker-1  Ready     worker  11m  v1.30.3

    批准服务器 CSR 后,机器可能需要几分钟才能过渡到“就绪”状态。

附加信息

在 AWS 中添加具有自定义 /var 分区的新 RHCOS 工作节点

OpenShift Container Platform 支持在安装期间使用在引导期间处理的机器配置来对设备进行分区。但是,如果您使用 /var 分区,则必须在安装时确定设备名称,并且不能更改。如果节点具有不同的设备命名方案,则不能将不同的实例类型添加为节点。例如,如果您使用 m4.large 实例的默认 AWS 设备名称 dev/xvdb 配置了 /var 分区,则不能直接添加 AWS m5.large 实例,因为 m5.large 实例默认使用 /dev/nvme1n1 设备。由于命名方案不同,设备分区可能会失败。

本节中的过程演示如何添加一个新的 Red Hat Enterprise Linux CoreOS (RHCOS) 计算节点,该节点使用与安装时配置的不同的设备名称的实例。您创建自定义用户数据密钥并配置新的计算机器集。这些步骤特定于 AWS 集群。这些原则也适用于其他云部署。但是,其他部署的设备命名方案不同,应根据具体情况确定。

步骤
  1. 在命令行上,更改到 openshift-machine-api 命名空间

    $ oc project openshift-machine-api
  2. worker-user-data 密钥创建新的密钥

    1. 将密钥的 userData 部分导出到文本文件

      $ oc get secret worker-user-data --template='{{index .data.userData | base64decode}}' | jq > userData.txt
    2. 编辑文本文件以添加您要用于新节点的分区的 storagefilesystemssystemd 节。您可以根据需要指定任何Ignition 配置参数

      不要更改 ignition 节中的值。

      {
        "ignition": {
          "config": {
            "merge": [
              {
                "source": "https:...."
              }
            ]
          },
          "security": {
            "tls": {
              "certificateAuthorities": [
                {
                  "source": "data:text/plain;charset=utf-8;base64,.....=="
                }
              ]
            }
          },
          "version": "3.2.0"
        },
        "storage": {
          "disks": [
            {
              "device": "/dev/nvme1n1", (1)
              "partitions": [
                {
                  "label": "var",
                  "sizeMiB": 50000, (2)
                  "startMiB": 0 (3)
                }
              ]
            }
          ],
          "filesystems": [
            {
              "device": "/dev/disk/by-partlabel/var", (4)
              "format": "xfs", (5)
              "path": "/var" (6)
            }
          ]
        },
        "systemd": {
          "units": [ (7)
            {
              "contents": "[Unit]\nBefore=local-fs.target\n[Mount]\nWhere=/var\nWhat=/dev/disk/by-partlabel/var\nOptions=defaults,pquota\n[Install]\nWantedBy=local-fs.target\n",
              "enabled": true,
              "name": "var.mount"
            }
          ]
        }
      }
      1 指定 AWS 块设备的绝对路径。
      2 指定数据分区的大小(以兆字节为单位)。
      3 指定分区的起始位置(以兆字节为单位)。将数据分区添加到引导磁盘时,建议最小值为 25000 MB(兆字节)。根文件系统将自动调整大小以填充所有可用空间,直至指定的偏移量。如果未指定值,或指定的值小于建议的最小值,则生成的根文件系统将太小,并且将来重新安装 RHCOS 可能会覆盖数据分区的开头。
      4 指定 /var 分区的绝对路径。
      5 指定文件系统格式。
      6 指定 Ignition 运行时文件系统的挂载点(相对于根文件系统将被挂载的位置)。这未必与它在真实根目录中应被挂载的位置相同,但建议使其相同。
      7 定义一个 systemd 挂载单元,该单元将 /dev/disk/by-partlabel/var 设备挂载到 /var 分区。
    3. disableTemplating 部分从 work-user-data 密钥提取到文本文件

      $ oc get secret worker-user-data --template='{{index .data.disableTemplating | base64decode}}' | jq > disableTemplating.txt
    4. 从两个文本文件创建新的用户数据密钥文件。此用户数据密钥将附加节点分区信息(在 userData.txt 文件中)传递到新创建的节点。

      $ oc create secret generic worker-user-data-x5 --from-file=userData=userData.txt --from-file=disableTemplating=disableTemplating.txt
  3. 为新节点创建新的计算机器集

    1. 创建新的计算机器集 YAML 文件,类似于以下内容(针对 AWS 配置)。添加所需的分区和新创建的用户数据密钥

      使用现有计算机器集作为模板,并根据新节点的需要更改参数。

      apiVersion: machine.openshift.io/v1beta1
      kind: MachineSet
      metadata:
        labels:
          machine.openshift.io/cluster-api-cluster: auto-52-92tf4
        name: worker-us-east-2-nvme1n1 (1)
        namespace: openshift-machine-api
      spec:
        replicas: 1
        selector:
          matchLabels:
            machine.openshift.io/cluster-api-cluster: auto-52-92tf4
            machine.openshift.io/cluster-api-machineset: auto-52-92tf4-worker-us-east-2b
        template:
          metadata:
            labels:
              machine.openshift.io/cluster-api-cluster: auto-52-92tf4
              machine.openshift.io/cluster-api-machine-role: worker
              machine.openshift.io/cluster-api-machine-type: worker
              machine.openshift.io/cluster-api-machineset: auto-52-92tf4-worker-us-east-2b
          spec:
            metadata: {}
            providerSpec:
              value:
                ami:
                  id: ami-0c2dbd95931a
                apiVersion: awsproviderconfig.openshift.io/v1beta1
                blockDevices:
                - DeviceName: /dev/nvme1n1 (2)
                  ebs:
                    encrypted: true
                    iops: 0
                    volumeSize: 120
                    volumeType: gp2
                - DeviceName: /dev/nvme1n2 (3)
                  ebs:
                    encrypted: true
                    iops: 0
                    volumeSize: 50
                    volumeType: gp2
                credentialsSecret:
                  name: aws-cloud-credentials
                deviceIndex: 0
                iamInstanceProfile:
                  id: auto-52-92tf4-worker-profile
                instanceType: m6i.large
                kind: AWSMachineProviderConfig
                metadata:
                  creationTimestamp: null
                placement:
                  availabilityZone: us-east-2b
                  region: us-east-2
                securityGroups:
                - filters:
                  - name: tag:Name
                    values:
                    - auto-52-92tf4-worker-sg
                subnet:
                  id: subnet-07a90e5db1
                tags:
                - name: kubernetes.io/cluster/auto-52-92tf4
                  value: owned
                userDataSecret:
                  name: worker-user-data-x5 (4)
      
      1 指定新节点的名称。
      2 指定 AWS 块设备的绝对路径,此处为加密的 EBS 卷。
      3 可选。指定附加的 EBS 卷。
      4 指定用户数据密钥文件。
    2. 创建计算机器集

      $ oc create -f <file-name>.yaml

      机器可能需要几分钟才能可用。

  4. 验证新的分区和节点是否已创建

    1. 验证计算机器集是否已创建

      $ oc get machineset
      示例输出
      NAME                                               DESIRED   CURRENT   READY   AVAILABLE   AGE
      ci-ln-2675bt2-76ef8-bdgsc-worker-us-east-1a        1         1         1       1           124m
      ci-ln-2675bt2-76ef8-bdgsc-worker-us-east-1b        2         2         2       2           124m
      worker-us-east-2-nvme1n1                           1         1         1       1           2m35s (1)
      
      1 这是新的计算机器集。
    2. 验证新的节点是否已创建

      $ oc get nodes
      示例输出
      NAME                           STATUS   ROLES    AGE     VERSION
      ip-10-0-128-78.ec2.internal    Ready    worker   117m    v1.30.3
      ip-10-0-146-113.ec2.internal   Ready    master   127m    v1.30.3
      ip-10-0-153-35.ec2.internal    Ready    worker   118m    v1.30.3
      ip-10-0-176-58.ec2.internal    Ready    master   126m    v1.30.3
      ip-10-0-217-135.ec2.internal   Ready    worker   2m57s   v1.30.3 (1)
      ip-10-0-225-248.ec2.internal   Ready    master   127m    v1.30.3
      ip-10-0-245-59.ec2.internal    Ready    worker   116m    v1.30.3
      1 这是新的节点。
    3. 验证新的节点上是否创建了自定义的/var分区

      $ oc debug node/<node-name> -- chroot /host lsblk

      例如

      $ oc debug node/ip-10-0-217-135.ec2.internal -- chroot /host lsblk
      示例输出
      NAME        MAJ:MIN  RM  SIZE RO TYPE MOUNTPOINT
      nvme0n1     202:0    0   120G  0 disk
      |-nvme0n1p1 202:1    0     1M  0 part
      |-nvme0n1p2 202:2    0   127M  0 part
      |-nvme0n1p3 202:3    0   384M  0 part /boot
      `-nvme0n1p4 202:4    0 119.5G  0 part /sysroot
      nvme1n1     202:16   0    50G  0 disk
      `-nvme1n1p1 202:17   0  48.8G  0 part /var (1)
      
      1 nvme1n1设备已挂载到/var分区。
其他资源
  • 有关 OpenShift Container Platform 如何使用磁盘分区的更多信息,请参阅 磁盘分区

部署机器健康检查

了解并部署机器健康检查。

只有在 Machine API 可运行的集群中才能使用高级机器管理和扩展功能。使用用户预配基础设施的集群需要额外的验证和配置才能使用 Machine API。

基础设施平台类型为none的集群无法使用 Machine API。即使连接到集群的计算机器安装在支持此功能的平台上,此限制也适用。此参数安装后无法更改。

要查看集群的平台类型,请运行以下命令

$ oc get infrastructure cluster -o jsonpath='{.status.platform}'

关于机器健康检查

您只能将机器健康检查应用于由计算机器集或控制平面机器集管理的机器。

要监控机器运行状况,请创建一个资源来定义控制器的配置。设置要检查的条件,例如在NotReady状态下保持五分钟或在节点问题检测器中显示永久性条件,以及要监控的机器集的标签。

观察MachineHealthCheck资源的控制器会检查定义的条件。如果机器未能通过健康检查,则会自动删除该机器,并创建一个机器来替代它。删除机器时,您会看到machine deleted事件。

为了限制机器删除的破坏性影响,控制器一次只排空并删除一个节点。如果存在比目标机器池中maxUnhealthy阈值允许的更多不健康的机器,则补救措施将停止,从而允许手动干预。

仔细考虑超时时间,考虑工作负载和要求。

  • 长时间超时会导致不健康机器上的工作负载长时间停机。

  • 超时时间太短会导致补救循环。例如,检查NotReady状态的超时时间必须足够长,以允许机器完成启动过程。

要停止检查,请删除资源。

部署机器健康检查时的限制

在部署机器健康检查之前,需要考虑一些限制

  • 只有机器集拥有的机器才能通过机器健康检查进行补救。

  • 如果从集群中删除机器的节点,则机器健康检查会认为该机器不健康并立即对其进行补救。

  • 如果机器的相应节点在nodeStartupTimeout之后未加入集群,则会对该机器进行补救。

  • 如果Machine资源阶段为Failed,则会立即对机器进行补救。

示例 MachineHealthCheck 资源

所有基于云的安装类型以及除裸机以外的其他类型的MachineHealthCheck资源类似于以下 YAML 文件

apiVersion: machine.openshift.io/v1beta1
kind: MachineHealthCheck
metadata:
  name: example (1)
  namespace: openshift-machine-api
spec:
  selector:
    matchLabels:
      machine.openshift.io/cluster-api-machine-role: <role> (2)
      machine.openshift.io/cluster-api-machine-type: <role> (2)
      machine.openshift.io/cluster-api-machineset: <cluster_name>-<label>-<zone> (3)
  unhealthyConditions:
  - type:    "Ready"
    timeout: "300s" (4)
    status: "False"
  - type:    "Ready"
    timeout: "300s" (4)
    status: "Unknown"
  maxUnhealthy: "40%" (5)
  nodeStartupTimeout: "10m" (6)
1 指定要部署的机器健康检查的名称。
2 为要检查的机器池指定标签。
3 <cluster_name>-<label>-<zone>格式指定要跟踪的机器集。例如,prod-node-us-east-1a
4 指定节点条件的超时持续时间。如果条件在超时持续时间内满足,则将对机器进行补救。长时间超时会导致不健康机器上的工作负载长时间停机。
5 指定在目标池中允许同时补救的机器数量。这可以设置为百分比或整数。如果不健康机器的数量超过maxUnhealthy设置的限制,则不会执行补救。
6 指定机器健康检查必须等待节点加入集群才能确定机器不健康的超时持续时间。

matchLabels仅为示例;您必须根据您的特定需求映射您的机器组。

短路机器健康检查补救

短路确保机器健康检查仅在集群健康时才对机器进行补救。短路是通过MachineHealthCheck资源中的maxUnhealthy字段进行配置的。

如果用户为maxUnhealthy字段定义了一个值,则在对任何机器进行补救之前,MachineHealthCheck会将maxUnhealthy的值与其已确定为不健康的其目标池中的机器数量进行比较。如果不健康机器的数量超过maxUnhealthy限制,则不会执行补救。

如果未设置maxUnhealthy,则该值默认为100%,并且无论集群状态如何都会对机器进行补救。

合适的maxUnhealthy值取决于您部署的集群的规模以及MachineHealthCheck涵盖的机器数量。例如,您可以使用maxUnhealthy值来覆盖多个可用区中的多个计算机器集,以便如果您丢失了整个可用区,您的maxUnhealthy设置将阻止集群内进一步的补救。在没有多个可用区的全球 Azure 区域中,您可以使用可用性集来确保高可用性。

如果为控制平面配置MachineHealthCheck资源,请将maxUnhealthy的值设置为1

此配置确保机器健康检查在多个控制平面机器似乎不健康时不会采取任何操作。多个不健康的控制平面机器可能表示 etcd 集群已降级或正在进行替换故障机器的扩展操作。

如果 etcd 集群已降级,则可能需要手动干预。如果扩展操作正在进行中,则机器健康检查应允许其完成。

maxUnhealthy字段可以设置为整数或百分比。根据maxUnhealthy值,补救实现方式不同。

使用绝对值设置 maxUnhealthy

如果maxUnhealthy设置为2

  • 如果2个或更少的节点不健康,将执行补救

  • 如果3个或更多节点不健康,则不会执行补救

这些值与机器健康检查检查的机器数量无关。

使用百分比设置 maxUnhealthy

如果maxUnhealthy设置为40%,并且正在检查25台机器

  • 如果10个或更少的节点不健康,将执行补救

  • 如果存在11个或更多不健康的节点,则不会执行修复操作。

如果maxUnhealthy设置为40%,并且有6台机器正在检查

  • 如果2个或更少的节点不健康,将执行补救

  • 如果3个或更多节点不健康,则不会执行补救

当被检查的maxUnhealthy机器的百分比不是整数时,允许的机器数量将向下取整。

创建机器健康检查资源

您可以为集群中的机器集创建MachineHealthCheck资源。

您只能将机器健康检查应用于由计算机器集或控制平面机器集管理的机器。

先决条件
  • 安装oc命令行界面。

步骤
  1. 创建一个包含机器健康检查定义的healthcheck.yml文件。

  2. healthcheck.yml文件应用到您的集群。

    $ oc apply -f healthcheck.yml

手动扩展计算机器集

要添加或删除计算机器集中的机器实例,您可以手动扩展计算机器集。

此指南适用于完全自动化的、安装程序预配的基础设施安装。自定义的、用户预配的基础设施安装不包含计算机器集。

先决条件
  • 安装OpenShift Container Platform集群和oc命令行。

  • 以具有cluster-admin权限的用户身份登录oc

步骤
  1. 通过运行以下命令查看集群中的计算机器集

    $ oc get machinesets.machine.openshift.io -n openshift-machine-api

    计算机器集以<clusterid>-worker-<aws-region-az>的形式列出。

  2. 通过运行以下命令查看集群中的计算机器

    $ oc get machines.machine.openshift.io -n openshift-machine-api
  3. 通过运行以下命令设置要删除的计算机器上的注释

    $ oc annotate machines.machine.openshift.io/<machine_name> -n openshift-machine-api machine.openshift.io/delete-machine="true"
  4. 通过运行以下命令之一来扩展计算机器集

    $ oc scale --replicas=2 machinesets.machine.openshift.io <machineset> -n openshift-machine-api

    或者

    $ oc edit machinesets.machine.openshift.io <machineset> -n openshift-machine-api

    或者,您可以应用以下YAML来扩展计算机器集

    apiVersion: machine.openshift.io/v1beta1
    kind: MachineSet
    metadata:
      name: <machineset>
      namespace: openshift-machine-api
    spec:
      replicas: 2

    您可以向上或向下扩展计算机器集。新机器需要几分钟才能可用。

    默认情况下,机器控制器会尝试一直排空由机器支持的节点,直到成功。在某些情况下,例如Pod中断预算配置错误,排空操作可能无法成功。如果排空操作失败,机器控制器将无法继续删除机器。

    您可以通过在特定机器中添加注释machine.openshift.io/exclude-node-draining来跳过排空节点。

验证
  • 通过运行以下命令验证目标机器的删除

    $ oc get machines.machine.openshift.io

了解计算机器集和机器配置池之间的区别

MachineSet对象描述了关于云或机器提供程序的OpenShift Container Platform节点。

MachineConfigPool对象允许MachineConfigController组件定义和提供升级环境中机器的状态。

MachineConfigPool对象允许用户配置如何将升级推广到机器配置池中的OpenShift Container Platform节点。

NodeSelector对象可以用对MachineSet对象的引用来替换。

推荐的节点主机实践

OpenShift Container Platform节点配置文件包含重要的选项。例如,两个参数控制可以调度到节点上的Pod的最大数量:podsPerCoremaxPods

当同时使用这两个选项时,较小的值会限制节点上的Pod数量。超过这些值可能会导致:

  • CPU利用率增加。

  • Pod调度缓慢。

  • 潜在的内存不足情况,具体取决于节点的内存量。

  • 耗尽IP地址池。

  • 资源过度承诺,导致用户应用程序性能下降。

在Kubernetes中,持有单个容器的Pod实际上使用两个容器。第二个容器用于在实际容器启动之前设置网络。因此,运行10个Pod的系统实际上将运行20个容器。

云提供商的磁盘IOPS限制可能会影响CRI-O和kubelet。当节点上运行大量I/O密集型Pod时,它们可能会过载。建议您监控节点上的磁盘I/O,并为工作负载使用具有足够吞吐量的卷。

podsPerCore参数根据节点上的处理器核心数量设置节点可以运行的Pod数量。例如,如果在具有4个处理器核心的节点上将podsPerCore设置为10,则节点上允许的最大Pod数量将为40

kubeletConfig:
  podsPerCore: 10

podsPerCore设置为0将禁用此限制。默认为0podsPerCore参数的值不能超过maxPods参数的值。

maxPods参数将节点可以运行的Pod数量设置为固定值,而不管节点的属性如何。

 kubeletConfig:
    maxPods: 250

创建KubeletConfig CRD以编辑kubelet参数

kubelet配置当前序列化为Ignition配置,因此可以直接编辑。但是,还向Machine Config Controller (MCC)添加了一个新的kubelet-config-controller。这允许您使用KubeletConfig自定义资源(CR)来编辑kubelet参数。

由于kubeletConfig对象中的字段直接从上游Kubernetes传递到kubelet,因此kubelet会直接验证这些值。kubeletConfig对象中的无效值可能会导致集群节点不可用。有关有效值,请参阅Kubernetes文档

请考虑以下指导:

  • 编辑现有的KubeletConfig CR以修改现有设置或添加新设置,而不是为每次更改创建CR。建议您仅创建CR以修改不同的机器配置池,或用于旨在临时的更改,以便您可以撤消更改。

  • 为每个机器配置池创建一个KubeletConfig CR,其中包含您想要为此池进行的所有配置更改。

  • 根据需要,创建多个KubeletConfig CR,每个集群最多10个。对于第一个KubeletConfig CR,Machine Config Operator (MCO)会创建一个附加了kubelet的机器配置。对于每个后续的CR,控制器都会创建另一个附加了数字后缀的kubelet机器配置。例如,如果您有一个带有-2后缀的kubelet机器配置,则下一个kubelet机器配置将附加-3

如果您将kubelet或容器运行时配置应用于自定义机器配置池,则machineConfigSelector中的自定义角色必须与自定义机器配置池的名称匹配。

例如,因为以下自定义机器配置池名为infra,所以自定义角色也必须为infra

apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfigPool
metadata:
  name: infra
spec:
  machineConfigSelector:
    matchExpressions:
      - {key: machineconfiguration.openshift.io/role, operator: In, values: [worker,infra]}
# ...

如果您要删除机器配置,请按相反的顺序删除它们,以避免超过限制。例如,您先删除kubelet-3机器配置,然后再删除kubelet-2机器配置。

如果您有一个带有kubelet-9后缀的机器配置,并且您创建另一个KubeletConfig CR,则不会创建新的机器配置,即使少于10个kubelet机器配置也是如此。

KubeletConfig CR示例
$ oc get kubeletconfig
NAME                AGE
set-max-pods        15m
显示KubeletConfig机器配置的示例
$ oc get mc | grep kubelet
...
99-worker-generated-kubelet-1                  b5c5119de007945b6fe6fb215db3b8e2ceb12511   3.2.0             26m
...

以下过程是一个示例,说明如何在工作节点上配置每个节点的最大Pod数量。

先决条件
  1. 获取与您要配置的节点类型的静态MachineConfigPool CR关联的标签。执行以下步骤之一:

    1. 查看机器配置池

      $ oc describe machineconfigpool <name>

      例如

      $ oc describe machineconfigpool worker
      示例输出
      apiVersion: machineconfiguration.openshift.io/v1
      kind: MachineConfigPool
      metadata:
        creationTimestamp: 2019-02-08T14:52:39Z
        generation: 1
        labels:
          custom-kubelet: set-max-pods (1)
      1 如果添加了标签,它将显示在labels下。
    2. 如果标签不存在,请添加键值对

      $ oc label machineconfigpool worker custom-kubelet=set-max-pods
步骤
  1. 查看您可以选择的可用机器配置对象

    $ oc get machineconfig

    默认情况下,两个与kubelet相关的配置是01-master-kubelet01-worker-kubelet

  2. 检查每个节点最大Pod数量的当前值

    $ oc describe node <node_name>

    例如

    $ oc describe node ci-ln-5grqprb-f76d1-ncnqq-worker-a-mdv94

    Allocatable 部分查找value: pods: <value>

    示例输出
    Allocatable:
     attachable-volumes-aws-ebs:  25
     cpu:                         3500m
     hugepages-1Gi:               0
     hugepages-2Mi:               0
     memory:                      15341844Ki
     pods:                        250
  3. 通过创建包含 kubelet 配置的自定义资源文件,设置工作节点上的每个节点的最大 Pod 数。

    针对特定机器配置池的 Kubelet 配置也会影响任何依赖的池。例如,为包含工作节点的池创建 kubelet 配置也会应用于任何子集池,包括包含基础架构节点的池。为避免这种情况,必须创建一个新的机器配置池,其选择表达式仅包含工作节点,并使 kubelet 配置针对此新池。

    apiVersion: machineconfiguration.openshift.io/v1
    kind: KubeletConfig
    metadata:
      name: set-max-pods
    spec:
      machineConfigPoolSelector:
        matchLabels:
          custom-kubelet: set-max-pods (1)
      kubeletConfig:
        maxPods: 500 (2)
    1 输入机器配置池的标签。
    2 添加 kubelet 配置。在此示例中,使用maxPods设置每个节点的最大 Pod 数。

    kubelet 与 API 服务器通信的速率取决于每秒查询数 (QPS) 和突发值。如果每个节点上运行的 Pod 数量有限,则默认值(kubeAPIQPS50kubeAPIBurst100)就足够了。如果节点上有足够的 CPU 和内存资源,建议更新 kubelet 的 QPS 和突发速率。

    apiVersion: machineconfiguration.openshift.io/v1
    kind: KubeletConfig
    metadata:
      name: set-max-pods
    spec:
      machineConfigPoolSelector:
        matchLabels:
          custom-kubelet: set-max-pods
      kubeletConfig:
        maxPods: <pod_count>
        kubeAPIBurst: <burst_rate>
        kubeAPIQPS: <QPS>
    1. 使用标签更新工作节点的机器配置池。

      $ oc label machineconfigpool worker custom-kubelet=set-max-pods
    2. 创建KubeletConfig 对象。

      $ oc create -f change-maxPods-cr.yaml
    3. 验证是否已创建KubeletConfig 对象。

      $ oc get kubeletconfig
      示例输出
      NAME                AGE
      set-max-pods        15m

      根据集群中工作节点的数量,等待工作节点逐个重启。对于具有 3 个工作节点的集群,这可能需要大约 10 到 15 分钟。

  4. 验证更改是否已应用于节点。

    1. 检查工作节点上maxPods 值是否已更改。

      $ oc describe node <node_name>
    2. 找到Allocatable 部分。

       ...
      Allocatable:
        attachable-volumes-gce-pd:  127
        cpu:                        3500m
        ephemeral-storage:          123201474766
        hugepages-1Gi:              0
        hugepages-2Mi:              0
        memory:                     14225400Ki
        pods:                       500 (1)
       ...
      1 在此示例中,pods 参数应报告在KubeletConfig 对象中设置的值。
  5. 验证KubeletConfig 对象中的更改。

    $ oc get kubeletconfigs set-max-pods -o yaml

    这应该显示状态为Truetype:Success,如下例所示

    spec:
      kubeletConfig:
        maxPods: 500
      machineConfigPoolSelector:
        matchLabels:
          custom-kubelet: set-max-pods
    status:
      conditions:
      - lastTransitionTime: "2021-06-30T17:04:07Z"
        message: Success
        status: "True"
        type: Success

修改不可用工作节点的数量

默认情况下,在将与 kubelet 相关的配置应用于可用的工作节点时,只允许一台机器不可用。对于大型集群,配置更改的反映可能需要很长时间。您可以随时调整正在更新的机器数量以加快此过程。

步骤
  1. 编辑worker 机器配置池。

    $ oc edit machineconfigpool worker
  2. 添加maxUnavailable 字段并设置值。

    spec:
      maxUnavailable: <node_count>

    设置值时,请考虑在不影响集群上运行的应用程序的情况下可以有多少个工作节点不可用。

控制平面节点大小调整

控制平面节点的资源需求取决于集群中节点和对象的数量和类型。以下控制平面节点大小建议基于控制平面密度重点测试(或集群密度)的结果。此测试在给定数量的命名空间中创建以下对象:

  • 1 个镜像流

  • 1 个构建

  • 5 个部署,每个部署包含 2 个处于sleep 状态的 Pod 副本,每个副本都挂载了 4 个密钥、4 个配置映射和 1 个向下 API 卷。

  • 5 个服务,每个服务都指向前面部署之一的 TCP/8080 和 TCP/8443 端口。

  • 1 个指向前面服务中的第一个服务的路由。

  • 10 个密钥,包含 2048 个随机字符串字符。

  • 10 个配置映射,包含 2048 个随机字符串字符。

工作节点数量 集群密度(命名空间) CPU 核心数 内存 (GB)

24

500

4

16

120

1000

8

32

252

4000

16,但如果使用 OVN-Kubernetes 网络插件,则为 24

64,但如果使用 OVN-Kubernetes 网络插件,则为 128

501,但未在 OVN-Kubernetes 网络插件中测试

4000

16

96

上表中的数据基于在 AWS 上运行的 OpenShift Container Platform,使用 r5.4xlarge 实例作为控制平面节点,使用 m5.2xlarge 实例作为工作节点。

在一个大型且密集的具有三个控制平面节点的集群中,当其中一个节点停止、重启或发生故障时,CPU 和内存使用率将会飙升。故障可能是由于电源、网络、底层基础架构的意外问题,也可能是由于在关闭集群以节省成本后重新启动集群的故意情况造成的。其余两个控制平面节点必须处理负载才能保持高可用性,这会导致资源使用率增加。在升级期间也预计会出现这种情况,因为控制平面节点是按顺序被隔离、排空和重启以应用操作系统更新以及控制平面 Operators 更新。为避免级联故障,请将控制平面节点上的总体 CPU 和内存资源使用率保持在所有可用容量的 60% 以内,以处理资源使用率的峰值。相应地增加控制平面节点上的 CPU 和内存,以避免由于资源不足而导致的潜在停机。

节点大小因集群中的节点数量和对象数量而异。它还取决于对象是否正在集群中积极创建。在对象创建期间,与对象处于running 阶段相比,控制平面在资源使用方面更为活跃。

Operator Lifecycle Manager (OLM) 在控制平面节点上运行,其内存占用取决于 OLM 需要在集群上管理的命名空间和用户安装的 Operators 的数量。需要相应地调整控制平面节点的大小,以避免 OOM 终止。以下数据点基于集群最大值测试的结果。

命名空间数量 OLM 空闲状态下的内存 (GB) 安装了 5 个用户 Operators 的 OLM 内存 (GB)

500

0.823

1.7

1000

1.2

2.5

1500

1.7

3.2

2000

2

4.4

3000

2.7

5.6

4000

3.8

7.6

5000

4.2

9.02

6000

5.8

11.3

7000

6.6

12.9

8000

6.9

14.8

9000

8

17.7

10,000

9.9

21.6

您只能针对以下配置修改正在运行的 OpenShift Container Platform 4.17 集群中的控制平面节点大小:

  • 使用用户预配的安装方法安装的集群。

  • 使用安装程序预配的基础架构安装方法安装的 AWS 集群。

  • 使用控制平面机器集来管理控制平面机器的集群。

对于所有其他配置,必须估算总节点数并在安装期间使用建议的控制平面节点大小。

在 OpenShift Container Platform 4.17 中,与 OpenShift Container Platform 3.11 和之前的版本相比,现在默认情况下系统保留了半个 CPU 核心 (500 毫核)。大小是在考虑这一点的情况下确定的。

设置 CPU 管理器

要配置 CPU 管理器,请创建一个 KubeletConfig 自定义资源 (CR) 并将其应用于所需的节点集。

步骤
  1. 运行以下命令为节点添加标签

    # oc label node perf-node.example.com cpumanager=true
  2. 要为所有计算节点启用 CPU 管理器,请运行以下命令编辑 CR:

    # oc edit machineconfigpool worker
  3. custom-kubelet: cpumanager-enabled 标签添加到metadata.labels 部分。

    metadata:
      creationTimestamp: 2020-xx-xxx
      generation: 3
      labels:
        custom-kubelet: cpumanager-enabled
  4. 创建一个KubeletConfigcpumanager-kubeletconfig.yaml,自定义资源 (CR)。请参考上一步中创建的标签,以确保使用新的 kubelet 配置更新正确的节点。请参阅machineConfigPoolSelector 部分。

    apiVersion: machineconfiguration.openshift.io/v1
    kind: KubeletConfig
    metadata:
      name: cpumanager-enabled
    spec:
      machineConfigPoolSelector:
        matchLabels:
          custom-kubelet: cpumanager-enabled
      kubeletConfig:
         cpuManagerPolicy: static (1)
         cpuManagerReconcilePeriod: 5s (2)
    1 指定策略
    • none。此策略显式启用现有的默认 CPU 亲和性方案,除了调度程序自动执行的操作之外,不提供任何亲和性。这是默认策略。

    • static。此策略允许在具有整数 CPU 请求的保证型 Pod 中使用容器。它还限制对节点上独占 CPU 的访问。如果使用static,则必须使用小写字母s

    2 可选。指定 CPU 管理器协调频率。默认为5s
  5. 运行以下命令创建动态 kubelet 配置

    # oc create -f cpumanager-kubeletconfig.yaml

    这会将 CPU 管理器功能添加到 kubelet 配置中,如果需要,机器配置操作员 (MCO) 会重新引导节点。要启用 CPU 管理器,无需重新引导。

  6. 运行以下命令检查合并后的 kubelet 配置

    # oc get machineconfig 99-worker-XXXXXX-XXXXX-XXXX-XXXXX-kubelet -o json | grep ownerReference -A7
    示例输出
           "ownerReferences": [
                {
                    "apiVersion": "machineconfiguration.openshift.io/v1",
                    "kind": "KubeletConfig",
                    "name": "cpumanager-enabled",
                    "uid": "7ed5616d-6b72-11e9-aae1-021e1ce18878"
                }
            ]
  7. 运行以下命令检查计算节点的更新的kubelet.conf文件

    # oc debug node/perf-node.example.com
    sh-4.2# cat /host/etc/kubernetes/kubelet.conf | grep cpuManager
    示例输出
    cpuManagerPolicy: static        (1)
    cpuManagerReconcilePeriod: 5s   (2)
    
    1 创建KubeletConfig CR 时定义cpuManagerPolicy
    2 创建KubeletConfig CR 时定义cpuManagerReconcilePeriod
  8. 运行以下命令创建一个项目

    $ oc new-project <project_name>
  9. 创建一个请求一个或多个核心的 Pod。限制和请求都必须将其 CPU 值设置为整数。这就是将专用于此 Pod 的核心数。

    # cat cpumanager-pod.yaml
    示例输出
    apiVersion: v1
    kind: Pod
    metadata:
      generateName: cpumanager-
    spec:
      securityContext:
        runAsNonRoot: true
        seccompProfile:
          type: RuntimeDefault
      containers:
      - name: cpumanager
        image: gcr.io/google_containers/pause:3.2
        resources:
          requests:
            cpu: 1
            memory: "1G"
          limits:
            cpu: 1
            memory: "1G"
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: [ALL]
      nodeSelector:
        cpumanager: "true"
  10. 创建 Pod

    # oc create -f cpumanager-pod.yaml
验证
  1. 运行以下命令验证 Pod 是否已调度到您标记的节点

    # oc describe pod cpumanager
    示例输出
    Name:               cpumanager-6cqz7
    Namespace:          default
    Priority:           0
    PriorityClassName:  <none>
    Node:  perf-node.example.com/xxx.xx.xx.xxx
    ...
     Limits:
          cpu:     1
          memory:  1G
        Requests:
          cpu:        1
          memory:     1G
    ...
    QoS Class:       Guaranteed
    Node-Selectors:  cpumanager=true
  2. 运行以下命令验证 CPU 是否已独占分配给 Pod

    # oc describe node --selector='cpumanager=true' | grep -i cpumanager- -B2
    示例输出
    NAMESPACE    NAME                CPU Requests  CPU Limits  Memory Requests  Memory Limits  Age
    cpuman       cpumanager-mlrrz    1 (28%)       1 (28%)     1G (13%)         1G (13%)       27m
  3. 验证cgroups是否设置正确。运行以下命令获取pause进程的进程 ID (PID)

    # oc debug node/perf-node.example.com
    sh-4.2# systemctl status | grep -B5 pause

    如果输出返回多个 pause 进程条目,则必须识别正确的 pause 进程。

    示例输出
    # ├─init.scope
    │ └─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 17
    └─kubepods.slice
      ├─kubepods-pod69c01f8e_6b74_11e9_ac0f_0a2b62178a22.slice
      │ ├─crio-b5437308f1a574c542bdf08563b865c0345c8f8c0b0a655612c.scope
      │ └─32706 /pause
  4. 运行以下命令验证服务质量 (QoS) 等级为Guaranteed的 Pod 是否位于kubepods.slice子目录中

    # cd /sys/fs/cgroup/kubepods.slice/kubepods-pod69c01f8e_6b74_11e9_ac0f_0a2b62178a22.slice/crio-b5437308f1ad1a7db0574c542bdf08563b865c0345c86e9585f8c0b0a655612c.scope
    # for i in `ls cpuset.cpus cgroup.procs` ; do echo -n "$i "; cat $i ; done

    其他 QoS 等级的 Pod 最终位于父kubepods的子cgroups中。

    示例输出
    cpuset.cpus 1
    tasks 32706
  5. 运行以下命令检查任务的允许 CPU 列表

    # grep ^Cpus_allowed_list /proc/32706/status
    示例输出
     Cpus_allowed_list:    1
  6. 验证系统上的另一个 Pod 是否无法在为Guaranteed Pod 分配的核心上运行。例如,要验证besteffort QoS 等级的 Pod,请运行以下命令

    # cat /sys/fs/cgroup/kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-podc494a073_6b77_11e9_98c0_06bba5c387ea.slice/crio-c56982f57b75a2420947f0afc6cafe7534c5734efc34157525fa9abbf99e3849.scope/cpuset.cpus
    # oc describe node perf-node.example.com
    示例输出
    ...
    Capacity:
     attachable-volumes-aws-ebs:  39
     cpu:                         2
     ephemeral-storage:           124768236Ki
     hugepages-1Gi:               0
     hugepages-2Mi:               0
     memory:                      8162900Ki
     pods:                        250
    Allocatable:
     attachable-volumes-aws-ebs:  39
     cpu:                         1500m
     ephemeral-storage:           124768236Ki
     hugepages-1Gi:               0
     hugepages-2Mi:               0
     memory:                      7548500Ki
     pods:                        250
    -------                               ----                           ------------  ----------  ---------------  -------------  ---
      default                                 cpumanager-6cqz7               1 (66%)       1 (66%)     1G (12%)         1G (12%)       29m
    
    Allocated resources:
      (Total limits may be over 100 percent, i.e., overcommitted.)
      Resource                    Requests          Limits
      --------                    --------          ------
      cpu                         1440m (96%)       1 (66%)

    此虚拟机有两个 CPU 内核。system-reserved设置保留 500 毫核,这意味着从节点的总容量中减去半个核心,以得出Node Allocatable数量。您可以看到Allocatable CPU为 1500 毫核。这意味着您可以运行一个 CPU 管理器 Pod,因为每个 Pod 都将占用一个完整的核心。一个完整的核心相当于 1000 毫核。如果您尝试调度第二个 Pod,系统将接受该 Pod,但它永远不会被调度。

    NAME                    READY   STATUS    RESTARTS   AGE
    cpumanager-6cqz7        1/1     Running   0          33m
    cpumanager-7qc2t        0/1     Pending   0          11s

巨页

了解和配置巨页。

巨页的作用

内存以称为页面的块进行管理。在大多数系统上,一个页面为 4Ki。1Mi 内存等于 256 个页面;1Gi 内存为 256,000 个页面,依此类推。CPU 具有内置的内存管理单元,用于在硬件中管理这些页面的列表。转换旁路缓冲区 (TLB) 是虚拟到物理页面映射的小型硬件缓存。如果在硬件指令中传递的虚拟地址可以在 TLB 中找到,则可以快速确定映射。如果没有,则会发生 TLB 未命中,系统将回退到较慢的基于软件的地址转换,从而导致性能问题。由于 TLB 的大小是固定的,因此减少 TLB 未命中几率的唯一方法是增加页面大小。

巨页是一个大于 4Ki 的内存页面。在 x86_64 架构上,有两种常见的巨页大小:2Mi 和 1Gi。其他架构上的大小会有所不同。要使用巨页,必须编写代码以便应用程序了解它们。透明巨页 (THP) 试图在无需应用程序了解的情况下自动管理巨页,但它们有局限性。特别是,它们仅限于 2Mi 页面大小。由于 THP 的碎片整理工作可能会锁定内存页面,因此在内存利用率高或碎片严重的节点上,THP 会导致性能下降。因此,某些应用程序可能设计为(或建议)使用预分配的巨页而不是 THP。

应用程序如何使用巨页

节点必须预分配巨页,以便节点报告其巨页容量。节点只能为单个大小预分配巨页。

可以使用资源名称hugepages-<size>通过容器级资源需求来使用巨页,其中 size 是在特定节点上支持的整数值得最紧凑的二进制表示法。例如,如果节点支持 2048KiB 页面大小,则它会公开一个可调度的资源hugepages-2Mi。与 CPU 或内存不同,巨页不支持过度承诺。

apiVersion: v1
kind: Pod
metadata:
  generateName: hugepages-volume-
spec:
  containers:
  - securityContext:
      privileged: true
    image: rhel7:latest
    command:
    - sleep
    - inf
    name: example
    volumeMounts:
    - mountPath: /dev/hugepages
      name: hugepage
    resources:
      limits:
        hugepages-2Mi: 100Mi (1)
        memory: "1Gi"
        cpu: "1"
  volumes:
  - name: hugepage
    emptyDir:
      medium: HugePages
1 hugepages的内存量指定为要分配的确切量。不要将此值指定为hugepages的内存量乘以页面的大小。例如,给定 2MB 的巨页大小,如果要为应用程序使用 100MB 的巨页支持的 RAM,则应分配 50 个巨页。OpenShift Container Platform 会为您处理计算。如上例所示,您可以直接指定100MB

分配特定大小的巨页

某些平台支持多种巨页大小。要分配特定大小的巨页,请在巨页引导命令参数前加上巨页大小选择参数hugepagesz=<size><size>值必须以字节为单位指定,并带有一个可选的比例后缀 [kKmMgG]。可以使用default_hugepagesz=<size>引导参数定义默认巨页大小。

巨页需求

  • 巨页请求必须等于限制。如果指定了限制但未指定请求,则这是默认值。

  • 巨页在 Pod 范围内隔离。容器隔离计划在未来的迭代中实现。

  • 由巨页支持的EmptyDir卷不得消耗超过 Pod 请求的巨页内存。

  • 使用SHM_HUGETLB通过shmget()使用巨页的应用程序必须使用与**proc/sys/vm/hugetlb_shm_group**匹配的补充组运行。

在启动时配置巨页

节点必须预分配在 OpenShift Container Platform 集群中使用的巨页。预留巨页有两种方法:启动时和运行时。启动时预留成功的可能性更高,因为内存尚未严重碎片化。节点调整操作员目前支持在特定节点上启动时分配巨页。

步骤

为了最大限度地减少节点重新引导,需要按照以下步骤的顺序进行操作

  1. 使用标签标记所有需要相同巨页设置的节点。

    $ oc label node <node_using_hugepages> node-role.kubernetes.io/worker-hp=
  2. 创建一个包含以下内容的文件,并将其命名为hugepages-tuned-boottime.yaml

    apiVersion: tuned.openshift.io/v1
    kind: Tuned
    metadata:
      name: hugepages (1)
      namespace: openshift-cluster-node-tuning-operator
    spec:
      profile: (2)
      - data: |
          [main]
          summary=Boot time configuration for hugepages
          include=openshift-node
          [bootloader]
          cmdline_openshift_node_hugepages=hugepagesz=2M hugepages=50 (3)
        name: openshift-node-hugepages
    
      recommend:
      - machineConfigLabels: (4)
          machineconfiguration.openshift.io/role: "worker-hp"
        priority: 30
        profile: openshift-node-hugepages
    1 将 Tuned 资源的name设置为hugepages
    2 profile部分设置为分配巨页。
    3 请注意参数的顺序很重要,因为某些平台支持各种大小的巨页。
    4 启用基于机器配置池的匹配。
  3. 创建已调优的hugepages对象

    $ oc create -f hugepages-tuned-boottime.yaml
  4. 创建一个包含以下内容的文件,并将其命名为hugepages-mcp.yaml

    apiVersion: machineconfiguration.openshift.io/v1
    kind: MachineConfigPool
    metadata:
      name: worker-hp
      labels:
        worker-hp: ""
    spec:
      machineConfigSelector:
        matchExpressions:
          - {key: machineconfiguration.openshift.io/role, operator: In, values: [worker,worker-hp]}
      nodeSelector:
        matchLabels:
          node-role.kubernetes.io/worker-hp: ""
  5. 创建机器配置池

    $ oc create -f hugepages-mcp.yaml

如果拥有足够的非碎片内存,worker-hp机器配置池中的所有节点现在都应该分配了50个2Mi的巨页。

$ oc get node <node_using_hugepages> -o jsonpath="{.status.allocatable.hugepages-2Mi}"
100Mi

TuneD引导加载程序插件仅支持Red Hat Enterprise Linux CoreOS (RHCOS)工作节点。

理解设备插件

设备插件提供了一种一致且可移植的解决方案,用于在集群中使用硬件设备。设备插件通过扩展机制为这些设备提供支持,这使得这些设备可用于容器,提供这些设备的健康检查,并安全地共享它们。

OpenShift Container Platform支持设备插件API,但设备插件容器由各个供应商支持。

设备插件是在节点上运行的gRPC服务(位于kubelet外部),负责管理特定的硬件资源。任何设备插件都必须支持以下远程过程调用 (RPC)

service DevicePlugin {
      // GetDevicePluginOptions returns options to be communicated with Device
      // Manager
      rpc GetDevicePluginOptions(Empty) returns (DevicePluginOptions) {}

      // ListAndWatch returns a stream of List of Devices
      // Whenever a Device state change or a Device disappears, ListAndWatch
      // returns the new list
      rpc ListAndWatch(Empty) returns (stream ListAndWatchResponse) {}

      // Allocate is called during container creation so that the Device
      // Plug-in can run device specific operations and instruct Kubelet
      // of the steps to make the Device available in the container
      rpc Allocate(AllocateRequest) returns (AllocateResponse) {}

      // PreStartcontainer is called, if indicated by Device Plug-in during
      // registration phase, before each container start. Device plug-in
      // can run device specific operations such as resetting the device
      // before making devices available to the container
      rpc PreStartcontainer(PreStartcontainerRequest) returns (PreStartcontainerResponse) {}
}

设备插件示例

为了方便设备插件参考实现,在设备管理器代码中有一个存根设备插件:vendor/k8s.io/kubernetes/pkg/kubelet/cm/deviceplugin/device_plugin_stub.go

部署设备插件的方法

  • 守护程序集是推荐的设备插件部署方法。

  • 启动时,设备插件将尝试在节点上的/var/lib/kubelet/device-plugin/创建UNIX域套接字,以服务来自设备管理器的RPC。

  • 由于设备插件必须管理硬件资源,访问主机文件系统以及套接字创建,因此必须在特权安全上下文中运行它们。

  • 有关部署步骤的更具体详细信息,请参阅每个设备插件实现。

理解设备管理器

设备管理器提供了一种机制,可以借助称为设备插件的插件来宣传专用节点硬件资源。

您可以宣传专用硬件,而无需任何上游代码更改。

OpenShift Container Platform支持设备插件API,但设备插件容器由各个供应商支持。

设备管理器将设备宣传为扩展资源。用户Pod可以使用与请求任何其他扩展资源相同的Limit/Request机制来使用设备管理器宣传的设备。

启动时,设备插件通过调用/var/lib/kubelet/device-plugins/kubelet.sock上的Register向设备管理器注册自身,并在/var/lib/kubelet/device-plugins/<plugin>.sock启动gRPC服务以服务设备管理器请求。

设备管理器在处理新的注册请求时,会在设备插件服务上调用ListAndWatch远程过程调用 (RPC)。作为响应,设备管理器通过gRPC流从插件获取设备对象的列表。设备管理器将继续监视流以获取来自插件的更新。在插件端,插件也将保持流打开,每当任何设备的状态发生变化时,新的设备列表都会通过相同的流连接发送到设备管理器。

在处理新的Pod准入请求时,Kubelet将请求的扩展资源传递给设备管理器以进行设备分配。设备管理器检查其数据库以验证是否存在相应的插件。如果插件存在并且存在可分配的空闲设备以及本地缓存,则会在该特定设备插件上调用Allocate RPC。

此外,设备插件还可以执行其他一些特定于设备的操作,例如驱动程序安装、设备初始化和设备重置。这些功能因实现而异。

启用设备管理器

启用设备管理器以实现设备插件,从而无需任何上游代码更改即可宣传专用硬件。

设备管理器提供了一种机制,可以借助称为设备插件的插件来宣传专用节点硬件资源。

  1. 通过输入以下命令,获取与您要配置的节点类型的静态MachineConfigPool CRD关联的标签。执行以下步骤之一

    1. 查看机器配置

      # oc describe machineconfig <name>

      例如

      # oc describe machineconfig 00-worker
      示例输出
      Name:         00-worker
      Namespace:
      Labels:       machineconfiguration.openshift.io/role=worker (1)
      
      1 设备管理器所需的标签。
步骤
  1. 为您的配置更改创建一个自定义资源 (CR)。

    设备管理器CR的示例配置
    apiVersion: machineconfiguration.openshift.io/v1
    kind: KubeletConfig
    metadata:
      name: devicemgr (1)
    spec:
      machineConfigPoolSelector:
        matchLabels:
           machineconfiguration.openshift.io: devicemgr (2)
      kubeletConfig:
        feature-gates:
          - DevicePlugins=true (3)
    1 为CR分配一个名称。
    2 输入来自机器配置池的标签。
    3 DevicePlugins设置为'true`。
  2. 创建设备管理器

    $ oc create -f devicemgr.yaml
    示例输出
    kubeletconfig.machineconfiguration.openshift.io/devicemgr created
  3. 确保设备管理器已实际启用,方法是确认节点上已创建/var/lib/kubelet/device-plugins/kubelet.sock。这是UNIX域套接字,设备管理器gRPC服务器在其上侦听新的插件注册。只有在启用设备管理器的情况下,启动Kubelet时才会创建此sock文件。

污点和容忍度

了解并使用污点和容忍度。

理解污点和容忍度

污点允许节点拒绝调度Pod,除非该Pod具有匹配的容忍度

您可以通过Node规范 (NodeSpec) 将污点应用于节点,并通过Pod规范 (PodSpec) 将容忍度应用于Pod。当您将污点应用于节点时,除非Pod能够容忍该污点,否则调度程序无法将Pod放置在该节点上。

节点规范中的污点示例
apiVersion: v1
kind: Node
metadata:
  name: my-node
#...
spec:
  taints:
  - effect: NoExecute
    key: key1
    value: value1
#...
Pod规范中的容忍度示例
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
#...
spec:
  tolerations:
  - key: "key1"
    operator: "Equal"
    value: "value1"
    effect: "NoExecute"
    tolerationSeconds: 3600
#...

污点和容忍度由键、值和效果组成。

表1. 污点和容忍度组件
参数 描述

是任何字符串,最多253个字符。键必须以字母或数字开头,可以包含字母、数字、连字符、点和下划线。

是任何字符串,最多63个字符。值必须以字母或数字开头,可以包含字母、数字、连字符、点和下划线。

效果

效果是以下之一

NoSchedule [1]

  • 与污点不匹配的新Pod不会调度到该节点上。

  • 节点上的现有Pod保持不变。

PreferNoSchedule

  • 与污点不匹配的新Pod可能会调度到该节点上,但调度程序会尽量避免。

  • 节点上的现有Pod保持不变。

NoExecute

  • 与污点不匹配的新Pod无法调度到该节点上。

  • 节点上没有匹配容忍度的现有Pod将被移除。

运算符

等于

key/value/effect 参数必须匹配。这是默认设置。

存在

key/effect 参数必须匹配。您必须保留一个空白的 value 参数,它匹配任何值。

  1. 如果您向控制平面节点添加 NoSchedule 污点,则该节点必须具有 node-role.kubernetes.io/master=:NoSchedule 污点,该污点默认添加。

    例如

    apiVersion: v1
    kind: Node
    metadata:
      annotations:
        machine.openshift.io/machine: openshift-machine-api/ci-ln-62s7gtb-f76d1-v8jxv-master-0
        machineconfiguration.openshift.io/currentConfig: rendered-master-cdc1ab7da414629332cc4c3926e6e59c
      name: my-node
    #...
    spec:
      taints:
      - effect: NoSchedule
        key: node-role.kubernetes.io/master
    #...

容忍度与污点匹配

  • 如果 operator 参数设置为 Equal

    • key 参数相同;

    • value 参数相同;

    • effect 参数相同。

  • 如果 operator 参数设置为 Exists

    • key 参数相同;

    • effect 参数相同。

以下污点内置于 OpenShift Container Platform 中

  • node.kubernetes.io/not-ready:节点未就绪。这对应于节点条件 Ready=False

  • node.kubernetes.io/unreachable:节点控制器无法访问该节点。这对应于节点条件 Ready=Unknown

  • node.kubernetes.io/memory-pressure:节点存在内存压力问题。这对应于节点条件 MemoryPressure=True

  • node.kubernetes.io/disk-pressure:节点存在磁盘压力问题。这对应于节点条件 DiskPressure=True

  • node.kubernetes.io/network-unavailable:节点网络不可用。

  • node.kubernetes.io/unschedulable:节点不可调度。

  • node.cloudprovider.kubernetes.io/uninitialized:当节点控制器使用外部云提供程序启动时,此污点将设置在节点上以将其标记为不可用。云控制器管理器中的控制器初始化此节点后,kubelet 会删除此污点。

  • node.kubernetes.io/pid-pressure:节点存在 PID 压力。这对应于节点条件 PIDPressure=True

    OpenShift Container Platform 没有设置默认的 pid.available evictionHard

添加污点和容忍度

您可以向 Pod 添加容忍度,向节点添加污点,以允许节点控制哪些 Pod 应该或不应该在其上调度。对于现有 Pod 和节点,应先向 Pod 添加容忍度,然后向节点添加污点,以避免在添加容忍度之前 Pod 从节点中删除。

步骤
  1. 通过编辑 Pod 规范以包含 tolerations 节来向 Pod 添加容忍度

    使用 Equal 运算符的示例 Pod 配置文件
    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    #...
    spec:
      tolerations:
      - key: "key1" (1)
        value: "value1"
        operator: "Equal"
        effect: "NoExecute"
        tolerationSeconds: 3600 (2)
    #...
    1 容忍度参数,如**污点和容忍度组件**表中所述。
    2 tolerationSeconds 参数指定 Pod 在被驱逐之前可以绑定到节点的时间长度。

    例如

    使用 Exists 运算符的示例 Pod 配置文件
    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    #...
    spec:
       tolerations:
        - key: "key1"
          operator: "Exists" (1)
          effect: "NoExecute"
          tolerationSeconds: 3600
    #...
    1 Exists 运算符不接受 value

    此示例在 node1 上放置一个污点,该污点具有键 key1、值 value1 和污点效果 NoExecute

  2. 使用以下命令并使用**污点和容忍度组件**表中描述的参数向节点添加污点

    $ oc adm taint nodes <node_name> <key>=<value>:<effect>

    例如

    $ oc adm taint nodes node1 key1=value1:NoExecute

    此命令在 node1 上放置一个污点,该污点具有键 key1、值 value1 和效果 NoExecute

    如果您向控制平面节点添加 NoSchedule 污点,则该节点必须具有 node-role.kubernetes.io/master=:NoSchedule 污点,该污点默认添加。

    例如

    apiVersion: v1
    kind: Node
    metadata:
      annotations:
        machine.openshift.io/machine: openshift-machine-api/ci-ln-62s7gtb-f76d1-v8jxv-master-0
        machineconfiguration.openshift.io/currentConfig: rendered-master-cdc1ab7da414629332cc4c3926e6e59c
      name: my-node
    #...
    spec:
      taints:
      - effect: NoSchedule
        key: node-role.kubernetes.io/master
    #...

    Pod 上的容忍度与节点上的污点匹配。具有任一容忍度的 Pod 都可以调度到 node1 上。

使用计算机器集添加污点和容忍度

您可以使用计算机器集向节点添加污点。与 MachineSet 对象关联的所有节点都将使用污点进行更新。容忍度对计算机器集添加的污点的响应方式与直接添加到节点的污点相同。

步骤
  1. 通过编辑 Pod 规范以包含 tolerations 节来向 Pod 添加容忍度

    使用 Equal 运算符的示例 Pod 配置文件
    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    #...
    spec:
      tolerations:
      - key: "key1" (1)
        value: "value1"
        operator: "Equal"
        effect: "NoExecute"
        tolerationSeconds: 3600 (2)
    #...
    1 容忍度参数,如**污点和容忍度组件**表中所述。
    2 tolerationSeconds 参数指定 Pod 在被驱逐之前绑定到节点的时间长度。

    例如

    使用 Exists 运算符的示例 Pod 配置文件
    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    #...
    spec:
      tolerations:
      - key: "key1"
        operator: "Exists"
        effect: "NoExecute"
        tolerationSeconds: 3600
    #...
  2. 将污点添加到 MachineSet 对象

    1. 编辑您要添加污点的节点的 MachineSet YAML,或者您可以创建一个新的 MachineSet 对象

      $ oc edit machineset <machineset>
    2. 将污点添加到 spec.template.spec 部分

      计算机器集规范中的示例污点
      apiVersion: machine.openshift.io/v1beta1
      kind: MachineSet
      metadata:
        name: my-machineset
      #...
      spec:
      #...
        template:
      #...
          spec:
            taints:
            - effect: NoExecute
              key: key1
              value: value1
      #...

      此示例在节点上放置一个污点,该污点具有键 key1、值 value1 和污点效果 NoExecute

    3. 将计算机器集缩减到 0

      $ oc scale --replicas=0 machineset <machineset> -n openshift-machine-api

      或者,您可以应用以下YAML来扩展计算机器集

      apiVersion: machine.openshift.io/v1beta1
      kind: MachineSet
      metadata:
        name: <machineset>
        namespace: openshift-machine-api
      spec:
        replicas: 0

      等待机器被移除。

    4. 根据需要扩展计算机器集

      $ oc scale --replicas=2 machineset <machineset> -n openshift-machine-api

      或者

      $ oc edit machineset <machineset> -n openshift-machine-api

      等待机器启动。污点将添加到与 MachineSet 对象关联的节点。

使用污点和容忍度将用户绑定到节点

如果您想为特定用户组的独占使用分配一组节点,请向其 Pod 添加容忍度。然后,向这些节点添加相应的污点。具有容忍度的 Pod 允许使用被污染的节点或集群中的任何其他节点。

如果您想确保 Pod 只调度到那些被污染的节点,也可以向同一组节点添加标签,并向 Pod 添加节点亲和性,以便 Pod 只能调度到具有该标签的节点上。

步骤

要配置一个节点,以便用户只能使用该节点

  1. 向这些节点添加相应的污点

    例如

    $ oc adm taint nodes node1 dedicated=groupName:NoSchedule

    或者,您可以应用以下 YAML 来添加污点

    kind: Node
    apiVersion: v1
    metadata:
      name: my-node
    #...
    spec:
      taints:
        - key: dedicated
          value: groupName
          effect: NoSchedule
    #...
  2. 通过编写自定义准入控制器向 Pod 添加容忍度。

使用污点和容忍度控制具有特殊硬件的节点

在只有一小部分节点具有专用硬件的集群中,您可以使用污点和容忍度来防止不需要专用硬件的 Pod 使用这些节点,从而将这些节点留给需要专用硬件的 Pod。您还可以要求需要专用硬件的 Pod 使用特定节点。

您可以通过向需要特殊硬件的 Pod 添加容忍度并污染具有专用硬件的节点来实现此目的。

步骤

确保具有专用硬件的节点仅供特定 Pod 预留

  1. 向需要特殊硬件的 Pod 添加容忍度。

    例如

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    #...
    spec:
      tolerations:
        - key: "disktype"
          value: "ssd"
          operator: "Equal"
          effect: "NoSchedule"
          tolerationSeconds: 3600
    #...
  2. 使用以下命令之一污染具有专用硬件的节点

    $ oc adm taint nodes <node-name> disktype=ssd:NoSchedule

    或者

    $ oc adm taint nodes <node-name> disktype=ssd:PreferNoSchedule

    或者,您可以应用以下 YAML 来添加污点

    kind: Node
    apiVersion: v1
    metadata:
      name: my_node
    #...
    spec:
      taints:
        - key: disktype
          value: ssd
          effect: PreferNoSchedule
    #...

删除污点和容忍度

您可以根据需要从节点中删除污点,从 Pod 中删除容忍度。应先向 Pod 添加容忍度,然后向节点添加污点,以避免在添加容忍度之前 Pod 从节点中删除。

步骤

删除污点和容忍度

  1. 要从节点中删除污点

    $ oc adm taint nodes <node-name> <key>-

    例如

    $ oc adm taint nodes ip-10-0-132-248.ec2.internal key1-
    示例输出
    node/ip-10-0-132-248.ec2.internal untainted
  2. 要从 Pod 中删除容忍度,请编辑 Pod 规范以删除容忍度

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    #...
    spec:
      tolerations:
      - key: "key2"
        operator: "Exists"
        effect: "NoExecute"
        tolerationSeconds: 3600
    #...

拓扑管理器

了解并使用拓扑管理器。

拓扑管理器策略

拓扑管理器通过从提示提供程序(例如 CPU 管理器和设备管理器)收集拓扑提示,并使用收集到的提示来对齐 Pod 资源,从而对齐所有服务质量 (QoS) 类别的 Pod 资源。

拓扑管理器支持四种分配策略,您可以在名为 cpumanager-enabledKubeletConfig 自定义资源 (CR) 中分配这些策略

none 策略

这是默认策略,不执行任何拓扑对齐。

best-effort 策略

对于具有`best-effort`拓扑管理策略的 Pod 中的每个容器,kubelet 会调用每个提示提供程序来发现它们的资源可用性。利用此信息,拓扑管理器会存储该容器的首选 NUMA 节点亲和性。如果未首选亲和性,拓扑管理器会存储此信息并将 Pod 接纳到节点。

restricted策略

对于具有`restricted`拓扑管理策略的 Pod 中的每个容器,kubelet 会调用每个提示提供程序来发现它们的资源可用性。利用此信息,拓扑管理器会存储该容器的首选 NUMA 节点亲和性。如果未首选亲和性,拓扑管理器会拒绝该 Pod 从节点接纳,导致 Pod 进入`Terminated`状态并出现 Pod 接纳失败。

single-numa-node策略

对于具有`single-numa-node`拓扑管理策略的 Pod 中的每个容器,kubelet 会调用每个提示提供程序来发现它们的资源可用性。利用此信息,拓扑管理器会确定是否可以实现单个 NUMA 节点亲和性。如果可以,则 Pod 会被接纳到节点。如果无法实现单个 NUMA 节点亲和性,拓扑管理器会拒绝该 Pod 从节点接纳。这会导致 Pod 进入 Terminated 状态并出现 Pod 接纳失败。

设置拓扑管理器

要使用拓扑管理器,必须在名为`cpumanager-enabled`的`KubeletConfig`自定义资源 (CR) 中配置分配策略。如果您已设置 CPU 管理器,则此文件可能已存在。如果文件不存在,您可以创建该文件。

先决条件
  • 将 CPU 管理器策略配置为`static`。

步骤

激活拓扑管理器

  1. 在自定义资源中配置拓扑管理器分配策略。

    $ oc edit KubeletConfig cpumanager-enabled
    apiVersion: machineconfiguration.openshift.io/v1
    kind: KubeletConfig
    metadata:
      name: cpumanager-enabled
    spec:
      machineConfigPoolSelector:
        matchLabels:
          custom-kubelet: cpumanager-enabled
      kubeletConfig:
         cpuManagerPolicy: static (1)
         cpuManagerReconcilePeriod: 5s
         topologyManagerPolicy: single-numa-node (2)
    1 此参数必须为`static`,其中`s`为小写。
    2 指定您选择的拓扑管理器分配策略。此处,策略为`single-numa-node`。可接受的值为:`default`、`best-effort`、`restricted`、`single-numa-node`。

Pod 与拓扑管理器策略的交互

以下示例`Pod`规范有助于说明 Pod 与拓扑管理器的交互。

以下 Pod 运行在`BestEffort` QoS 类中,因为没有指定资源请求或限制。

spec:
  containers:
  - name: nginx
    image: nginx

下一个 Pod 运行在`Burstable` QoS 类中,因为请求小于限制。

spec:
  containers:
  - name: nginx
    image: nginx
    resources:
      limits:
        memory: "200Mi"
      requests:
        memory: "100Mi"

如果选择的策略不是`none`,则拓扑管理器不会考虑这两个`Pod`规范。

以下最后一个示例 Pod 运行在 Guaranteed QoS 类中,因为请求等于限制。

spec:
  containers:
  - name: nginx
    image: nginx
    resources:
      limits:
        memory: "200Mi"
        cpu: "2"
        example.com/device: "1"
      requests:
        memory: "200Mi"
        cpu: "2"
        example.com/device: "1"

拓扑管理器将考虑此 Pod。拓扑管理器将咨询提示提供程序(即 CPU 管理器和设备管理器)以获取 Pod 的拓扑提示。

拓扑管理器将使用此信息来存储此容器的最佳拓扑。在此 Pod 的情况下,CPU 管理器和设备管理器将在资源分配阶段使用此存储的信息。

资源请求和超额承诺

对于每个计算资源,容器可以指定资源请求和限制。调度决策是基于请求做出的,以确保节点有足够的可用容量来满足请求的值。如果容器指定了限制,但省略了请求,则请求将默认为限制。容器无法超过节点上指定的限制。

限制的执行取决于计算资源类型。如果容器没有发出请求或限制,则该容器将被调度到没有资源保证的节点。实际上,容器能够消耗尽可能多的可用指定资源,且具有最低的本地优先级。在资源不足的情况下,未指定资源请求的容器将获得最低的服务质量。

调度基于请求的资源,而配额和硬限制则指的是资源限制,资源限制可以设置为高于请求的资源。请求和限制之间的差值决定了超额承诺的水平;例如,如果容器的内存请求为 1Gi,内存限制为 2Gi,则它是基于节点上可用 1Gi 请求进行调度的,但可以使用最多 2Gi;因此,它被超额承诺了 200%。

使用集群资源覆盖操作符进行集群级超额承诺

集群资源覆盖操作符是一个准入 Webhook,允许您控制超额承诺的水平并管理集群中所有节点的容器密度。该操作符控制特定项目中的节点如何超过定义的内存和 CPU 限制。

必须使用 OpenShift Container Platform 控制台或 CLI 安装集群资源覆盖操作符,如下节所示。在安装过程中,您将创建一个`ClusterResourceOverride`自定义资源 (CR),您可以在其中设置超额承诺的级别,如下例所示。

apiVersion: operator.autoscaling.openshift.io/v1
kind: ClusterResourceOverride
metadata:
    name: cluster (1)
spec:
  podResourceOverride:
    spec:
      memoryRequestToLimitPercent: 50 (2)
      cpuRequestToLimitPercent: 25 (3)
      limitCPUToMemoryPercent: 200 (4)
# ...
1 名称必须为`cluster`。
2 可选。如果已指定或默认为容器内存限制,则内存请求将被覆盖为限制的此百分比,介于 1-100 之间。默认为 50。
3 可选。如果已指定或默认为容器 CPU 限制,则 CPU 请求将被覆盖为限制的此百分比,介于 1-100 之间。默认为 25。
4 可选。如果已指定或默认为容器内存限制,则 CPU 限制将被覆盖为内存限制的百分比(如果已指定)。以 100% 的比例缩放 1Gi 的 RAM 等于 1 个 CPU 内核。这在覆盖 CPU 请求(如果已配置)之前进行处理。默认为 200。

如果容器未设置限制,则集群资源覆盖操作符覆盖无效。创建一个具有每个项目的默认限制的`LimitRange`对象,或在`Pod`规范中配置限制以应用覆盖。

配置后,可以通过将以下标签应用于每个项目的 Namespace 对象来按项目启用覆盖。

apiVersion: v1
kind: Namespace
metadata:

# ...

  labels:
    clusterresourceoverrides.admission.autoscaling.openshift.io/enabled: "true"

# ...

操作符监视`ClusterResourceOverride` CR 并确保`ClusterResourceOverride`准入 Webhook 安装到与操作符相同的命名空间中。

使用 Web 控制台安装集群资源覆盖操作符

您可以使用 OpenShift Container Platform CLI 安装集群资源覆盖操作符,以帮助控制集群中的超额承诺。

默认情况下,安装过程会在`clusterresourceoverride-operator`命名空间中的工作节点上创建一个集群资源覆盖操作符 Pod。您可以根据需要将此 Pod 移动到其他节点,例如基础设施节点。基础设施节点不计入运行环境所需的订阅总数。有关更多信息,请参阅“移动集群资源覆盖操作符 Pod”。

先决条件
  • 如果容器未设置限制,则集群资源覆盖操作符无效。必须使用LimitRange对象为项目指定默认限制,或在Pod规范中配置限制才能应用覆盖。

步骤

使用OpenShift Container Platform Web控制台安装集群资源覆盖操作符

  1. 在OpenShift Container Platform Web控制台中,导航到**主页** → **项目**

    1. 单击**创建项目**。

    2. 指定clusterresourceoverride-operator作为项目名称。

    3. 单击**创建**。

  2. 导航到**操作符** → **OperatorHub**。

    1. 从可用操作符列表中选择**集群资源覆盖操作符**,然后单击**安装**。

    2. 在**安装操作符**页面上,确保为**安装模式**选择**集群上的特定命名空间**。

    3. 确保为**已安装命名空间**选择**clusterresourceoverride-operator**。

    4. 选择**更新通道**和**批准策略**。

    5. 单击**安装**。

  3. 在**已安装操作符**页面上,单击**ClusterResourceOverride**。

    1. 在**ClusterResourceOverride操作符**详细信息页面上,单击**创建ClusterResourceOverride**。

    2. 在**创建ClusterResourceOverride**页面上,单击**YAML视图**并编辑YAML模板以根据需要设置超额分配值

      apiVersion: operator.autoscaling.openshift.io/v1
      kind: ClusterResourceOverride
      metadata:
        name: cluster (1)
      spec:
        podResourceOverride:
          spec:
            memoryRequestToLimitPercent: 50 (2)
            cpuRequestToLimitPercent: 25 (3)
            limitCPUToMemoryPercent: 200 (4)
      1 名称必须为`cluster`。
      2 可选:如果使用,请指定覆盖容器内存限制的百分比(1-100之间)。默认为50
      3 可选:如果使用,请指定覆盖容器CPU限制的百分比(1-100之间)。默认为25
      4 可选:如果使用,请指定覆盖容器内存限制的百分比。以100%比例扩展1 Gi RAM等于1个CPU核心。在配置的情况下,这会在覆盖CPU请求之前进行处理。默认为200
    3. 单击**创建**。

  4. 通过检查集群自定义资源的状态来检查准入Webhook的当前状态

    1. 在**ClusterResourceOverride操作符**页面上,单击**集群**。

    2. 在**ClusterResourceOverride详细信息**页面上,单击**YAML**。调用Webhook时,将显示mutatingWebhookConfigurationRef部分。

      apiVersion: operator.autoscaling.openshift.io/v1
      kind: ClusterResourceOverride
      metadata:
        annotations:
          kubectl.kubernetes.io/last-applied-configuration: |
            {"apiVersion":"operator.autoscaling.openshift.io/v1","kind":"ClusterResourceOverride","metadata":{"annotations":{},"name":"cluster"},"spec":{"podResourceOverride":{"spec":{"cpuRequestToLimitPercent":25,"limitCPUToMemoryPercent":200,"memoryRequestToLimitPercent":50}}}}
        creationTimestamp: "2019-12-18T22:35:02Z"
        generation: 1
        name: cluster
        resourceVersion: "127622"
        selfLink: /apis/operator.autoscaling.openshift.io/v1/clusterresourceoverrides/cluster
        uid: 978fc959-1717-4bd1-97d0-ae00ee111e8d
      spec:
        podResourceOverride:
          spec:
            cpuRequestToLimitPercent: 25
            limitCPUToMemoryPercent: 200
            memoryRequestToLimitPercent: 50
      status:
      
      # ...
      
          mutatingWebhookConfigurationRef: (1)
            apiVersion: admissionregistration.k8s.io/v1
            kind: MutatingWebhookConfiguration
            name: clusterresourceoverrides.admission.autoscaling.openshift.io
            resourceVersion: "127621"
            uid: 98b3b8ae-d5ce-462b-8ab5-a729ea8f38f3
      
      # ...
      1 ClusterResourceOverride准入Webhook的引用。

使用CLI安装集群资源覆盖操作符

您可以使用 OpenShift Container Platform CLI 安装集群资源覆盖操作符,以帮助控制集群中的超额承诺。

默认情况下,安装过程会在`clusterresourceoverride-operator`命名空间中的工作节点上创建一个集群资源覆盖操作符 Pod。您可以根据需要将此 Pod 移动到其他节点,例如基础设施节点。基础设施节点不计入运行环境所需的订阅总数。有关更多信息,请参阅“移动集群资源覆盖操作符 Pod”。

先决条件
  • 如果容器未设置限制,则集群资源覆盖操作符无效。必须使用LimitRange对象为项目指定默认限制,或在Pod规范中配置限制才能应用覆盖。

步骤

使用CLI安装集群资源覆盖操作符

  1. 为集群资源覆盖操作符创建一个命名空间

    1. 为集群资源覆盖操作符创建一个Namespace对象YAML文件(例如,cro-namespace.yaml

      apiVersion: v1
      kind: Namespace
      metadata:
        name: clusterresourceoverride-operator
    2. 创建命名空间

      $ oc create -f <file-name>.yaml

      例如

      $ oc create -f cro-namespace.yaml
  2. 创建一个操作符组

    1. 为集群资源覆盖操作符创建一个OperatorGroup对象YAML文件(例如,cro-og.yaml)

      apiVersion: operators.coreos.com/v1
      kind: OperatorGroup
      metadata:
        name: clusterresourceoverride-operator
        namespace: clusterresourceoverride-operator
      spec:
        targetNamespaces:
          - clusterresourceoverride-operator
    2. 创建操作符组

      $ oc create -f <file-name>.yaml

      例如

      $ oc create -f cro-og.yaml
  3. 创建一个订阅

    1. 为集群资源覆盖操作符创建一个Subscription对象YAML文件(例如,cro-sub.yaml)

      apiVersion: operators.coreos.com/v1alpha1
      kind: Subscription
      metadata:
        name: clusterresourceoverride
        namespace: clusterresourceoverride-operator
      spec:
        channel: "4.17"
        name: clusterresourceoverride
        source: redhat-operators
        sourceNamespace: openshift-marketplace
    2. 创建订阅

      $ oc create -f <file-name>.yaml

      例如

      $ oc create -f cro-sub.yaml
  4. clusterresourceoverride-operator命名空间中创建一个ClusterResourceOverride自定义资源(CR)对象

    1. 切换到clusterresourceoverride-operator命名空间。

      $ oc project clusterresourceoverride-operator
    2. 为集群资源覆盖操作符创建一个ClusterResourceOverride对象YAML文件(例如,cro-cr.yaml)

      apiVersion: operator.autoscaling.openshift.io/v1
      kind: ClusterResourceOverride
      metadata:
          name: cluster (1)
      spec:
        podResourceOverride:
          spec:
            memoryRequestToLimitPercent: 50 (2)
            cpuRequestToLimitPercent: 25 (3)
            limitCPUToMemoryPercent: 200 (4)
      1 名称必须为`cluster`。
      2 可选:如果使用,请指定覆盖容器内存限制的百分比(1-100之间)。默认为50
      3 可选:如果使用,请指定覆盖容器CPU限制的百分比(1-100之间)。默认为25
      4 可选:如果使用,请指定覆盖容器内存限制的百分比。以100%比例扩展1 Gi RAM等于1个CPU核心。在配置的情况下,这会在覆盖CPU请求之前进行处理。默认为200
    3. 创建ClusterResourceOverride对象

      $ oc create -f <file-name>.yaml

      例如

      $ oc create -f cro-cr.yaml
  5. 通过检查集群自定义资源的状态来验证准入Webhook的当前状态。

    $ oc get clusterresourceoverride cluster -n clusterresourceoverride-operator -o yaml

    调用Webhook时,将显示mutatingWebhookConfigurationRef部分。

    示例输出
    apiVersion: operator.autoscaling.openshift.io/v1
    kind: ClusterResourceOverride
    metadata:
      annotations:
        kubectl.kubernetes.io/last-applied-configuration: |
          {"apiVersion":"operator.autoscaling.openshift.io/v1","kind":"ClusterResourceOverride","metadata":{"annotations":{},"name":"cluster"},"spec":{"podResourceOverride":{"spec":{"cpuRequestToLimitPercent":25,"limitCPUToMemoryPercent":200,"memoryRequestToLimitPercent":50}}}}
      creationTimestamp: "2019-12-18T22:35:02Z"
      generation: 1
      name: cluster
      resourceVersion: "127622"
      selfLink: /apis/operator.autoscaling.openshift.io/v1/clusterresourceoverrides/cluster
      uid: 978fc959-1717-4bd1-97d0-ae00ee111e8d
    spec:
      podResourceOverride:
        spec:
          cpuRequestToLimitPercent: 25
          limitCPUToMemoryPercent: 200
          memoryRequestToLimitPercent: 50
    status:
    
    # ...
    
        mutatingWebhookConfigurationRef: (1)
          apiVersion: admissionregistration.k8s.io/v1
          kind: MutatingWebhookConfiguration
          name: clusterresourceoverrides.admission.autoscaling.openshift.io
          resourceVersion: "127621"
          uid: 98b3b8ae-d5ce-462b-8ab5-a729ea8f38f3
    
    # ...
    1 ClusterResourceOverride准入Webhook的引用。

配置集群级超额分配

集群资源覆盖操作符需要一个ClusterResourceOverride自定义资源(CR)和一个标签,用于您希望操作符控制超额分配的每个项目。

默认情况下,安装过程会在clusterresourceoverride-operator命名空间中的控制平面节点上创建两个集群资源覆盖Pod。您可以根据需要将这些Pod移动到其他节点,例如基础设施节点。基础设施节点不计入运行环境所需的总订阅数。有关更多信息,请参见“移动集群资源覆盖操作符Pod”。

先决条件
  • 如果容器未设置限制,则集群资源覆盖操作符无效。必须使用LimitRange对象为项目指定默认限制,或在Pod规范中配置限制才能应用覆盖。

步骤

修改集群级超额分配

  1. 编辑ClusterResourceOverride CR

    apiVersion: operator.autoscaling.openshift.io/v1
    kind: ClusterResourceOverride
    metadata:
        name: cluster
    spec:
      podResourceOverride:
        spec:
          memoryRequestToLimitPercent: 50 (1)
          cpuRequestToLimitPercent: 25 (2)
          limitCPUToMemoryPercent: 200 (3)
    # ...
    1 可选:如果使用,请指定覆盖容器内存限制的百分比(1-100之间)。默认为50
    2 可选:如果使用,请指定覆盖容器CPU限制的百分比(1-100之间)。默认为25
    3 可选:如果使用,请指定覆盖容器内存限制的百分比。以100%比例扩展1Gi RAM等于1个CPU核心。在配置的情况下,这会在覆盖CPU请求之前进行处理。默认为200
  2. 确保已将以下标签添加到您希望集群资源覆盖操作符控制超额分配的每个项目的命名空间对象中

    apiVersion: v1
    kind: Namespace
    metadata:
    
    # ...
    
      labels:
        clusterresourceoverrides.admission.autoscaling.openshift.io/enabled: "true" (1)
    
    # ...
    1 将此标签添加到每个项目。

节点级超额分配

您可以使用各种方法来控制特定节点上的超额分配,例如服务质量 (QOS) 保证、CPU 限制或预留资源。您还可以为特定节点和特定项目禁用超额分配。

了解计算资源和容器

节点强制执行的计算资源行为特定于资源类型。

了解容器CPU请求

容器保证其请求的CPU数量,并且还可以使用节点上可用的额外CPU,直至容器指定的任何限制。如果多个容器试图使用多余的CPU,则根据每个容器请求的CPU数量分配CPU时间。例如,如果一个容器请求500m的CPU时间,另一个容器请求250m的CPU时间,那么节点上可用的任何额外CPU时间将以2:1的比例分配给这些容器。如果容器指定了限制,则它将被限制为不使用超过指定限制的CPU。CPU请求使用Linux内核中的CFS共享支持来强制执行。默认情况下,CPU限制使用Linux内核中的CFS配额支持在100毫秒的测量间隔内强制执行,但这可以禁用。

例如,如果一个容器请求 500m 的 CPU 时间,另一个容器请求 250m 的 CPU 时间,那么节点上任何额外的 CPU 时间将以 2:1 的比例分配给这些容器。如果容器指定了限制,它将被限制为不使用超过指定限制的 CPU。CPU 请求使用 Linux 内核中的 CFS 共享支持强制执行。默认情况下,CPU 限制使用 Linux 内核中的 CFS 配额支持在 100 毫秒的测量间隔内强制执行,但这可以禁用。

了解容器内存请求

容器保证其请求的内存量。容器可以使用超过请求量的内存,但是一旦超过其请求量,它可能会在节点上的低内存情况下被终止。如果容器使用的内存少于请求量,则除非系统任务或守护进程需要超过节点资源预留中所考虑的内存量,否则它不会被终止。如果容器指定了内存限制,则如果超过限制量,它将立即被终止。

了解超额分配和服务质量类别

当节点调度了一个没有发出请求的Pod,或者当该节点上所有Pod的限制总和超过可用的机器容量时,该节点就被超额分配了。

在超额分配的环境中,节点上的 Pod 可能会尝试使用任何给定时间点都无法获得的更多计算资源。当这种情况发生时,节点必须优先考虑一个 Pod 而非另一个 Pod。用于做出此决定的机制称为服务质量 (QoS) 类。

Pod 被指定为三个 QoS 类之一,优先级递减

表 2. 服务质量类
优先级 类名 描述

1(最高)

Guaranteed(保证型)

如果所有资源都设置了限制(可选)和请求(不等于 0),并且它们相等,则该 Pod 被分类为Guaranteed(保证型)

2

Burstable(突发型)

如果所有资源都设置了请求(可选)和限制(不等于 0),并且它们不相等,则该 Pod 被分类为Burstable(突发型)

3(最低)

BestEffort(尽力型)

如果任何资源都没有设置请求和限制,则该 Pod 被分类为BestEffort(尽力型)

内存是一种不可压缩资源,因此在内存不足的情况下,优先级最低的容器将首先被终止。

  • Guaranteed(保证型)容器被认为是最高优先级,并且只有在它们超过其限制,或者系统处于内存压力且没有可以驱逐的更低优先级容器时,才会被终止。

  • 在系统内存压力下,Burstable(突发型)容器一旦超过其请求且不存在其他BestEffort(尽力型)容器,就更有可能被终止。

  • BestEffort(尽力型)容器的优先级最低。如果系统内存不足,这些容器中的进程将首先被终止。

了解如何在服务质量层级之间预留内存

您可以使用qos-reserved参数指定特定 QoS 级别中 Pod 预留的内存百分比。此功能尝试预留请求的资源,以防止较低 OoS 类的 Pod 使用较高 QoS 类的 Pod 请求的资源。

OpenShift Container Platform 使用qos-reserved参数如下:

  • 值为qos-reserved=memory=100%将阻止Burstable(突发型)BestEffort(尽力型)QoS 类消耗由较高 QoS 类请求的内存。这增加了在BestEffort(尽力型)Burstable(突发型)工作负载上引发 OOM 的风险,以换取提高Guaranteed(保证型)Burstable(突发型)工作负载的内存资源保证。

  • 值为qos-reserved=memory=50%将允许Burstable(突发型)BestEffort(尽力型)QoS 类消耗较高 QoS 类请求内存的一半。

  • 值为qos-reserved=memory=0%将允许Burstable(突发型)BestEffort(尽力型)QoS 类在可用情况下消耗高达节点可分配量的全部内存,但这增加了Guaranteed(保证型)工作负载无法访问请求的内存的风险。此条件实际上禁用了此功能。

了解交换内存和 QoS

您可以默认禁用节点上的交换分区以保留服务质量 (QOS) 保证。否则,节点上的物理资源可能会超额订阅,从而影响 Kubernetes 调度程序在 Pod 安置期间做出的资源保证。

例如,如果两个保证型 Pod 已达到其内存限制,则每个容器都可以开始使用交换内存。最终,如果没有足够的交换空间,由于系统超额订阅,Pod 中的进程可能会被终止。

未能禁用交换分区会导致节点无法识别它们正在经历MemoryPressure(内存压力),导致 Pod 未能获得其调度请求中声明的内存。结果,将更多 Pod 放置在节点上以进一步增加内存压力,最终增加您遇到系统内存不足 (OOM) 事件的风险。

如果启用交换分区,任何可用内存的资源不足处理驱逐阈值将无法按预期工作。利用资源不足处理允许在节点处于内存压力下时将 Pod 从节点驱逐,并在没有此类压力的备用节点上重新调度。

了解节点超额分配

在超额分配的环境中,正确配置节点以提供最佳系统行为非常重要。

节点启动时,它确保内存管理的内核可调标志设置正确。除非内核用尽物理内存,否则内核不应失败内存分配。

为了确保这种行为,OpenShift Container Platform 通过将vm.overcommit_memory参数设置为1来配置内核始终超额分配内存,从而覆盖默认的操作系统设置。

OpenShift Container Platform 还通过将vm.panic_on_oom参数设置为0来配置内核在内存不足时不出现恐慌。设置为 0 会指示内核在内存不足 (OOM) 条件下调用 oom_killer,后者会根据优先级终止进程。

您可以通过在节点上运行以下命令来查看当前设置:

$ sysctl -a |grep commit
示例输出
#...
vm.overcommit_memory = 0
#...
$ sysctl -a |grep panic
示例输出
#...
vm.panic_on_oom = 0
#...

上述标志应已在节点上设置,无需进一步操作。

您还可以对每个节点执行以下配置:

  • 使用 CPU CFS 配额禁用或强制执行 CPU 限制

  • 为系统进程预留资源

  • 在服务质量层级之间预留内存

使用 CPU CFS 配额禁用或强制执行 CPU 限制

节点默认使用 Linux 内核中的完全公平调度程序 (CFS) 配额支持来强制执行指定的 CPU 限制。

如果您禁用 CPU 限制强制执行,则必须了解其对节点的影响。

  • 如果容器具有 CPU 请求,则 Linux 内核中的 CFS 共享将继续强制执行该请求。

  • 如果容器没有 CPU 请求,但有 CPU 限制,则 CPU 请求默认为指定的 CPU 限制,并由 Linux 内核中的 CFS 共享强制执行。

  • 如果容器同时具有 CPU 请求和限制,则 Linux 内核中的 CFS 共享将强制执行 CPU 请求,而 CPU 限制对节点没有影响。

先决条件
  • 通过输入以下命令,获取与您要配置的节点类型的静态MachineConfigPool CRD 关联的标签:

    $ oc edit machineconfigpool <name>

    例如

    $ oc edit machineconfigpool worker
    示例输出
    apiVersion: machineconfiguration.openshift.io/v1
    kind: MachineConfigPool
    metadata:
      creationTimestamp: "2022-11-16T15:34:25Z"
      generation: 4
      labels:
        pools.operator.machineconfiguration.openshift.io/worker: "" (1)
      name: worker
    1 标签显示在“标签”下。

    如果标签不存在,请添加键值对,例如:

    $ oc label machineconfigpool worker custom-kubelet=small-pods
步骤
  1. 为您的配置更改创建一个自定义资源 (CR)。

    禁用 CPU 限制的示例配置:
    apiVersion: machineconfiguration.openshift.io/v1
    kind: KubeletConfig
    metadata:
      name: disable-cpu-units (1)
    spec:
      machineConfigPoolSelector:
        matchLabels:
          pools.operator.machineconfiguration.openshift.io/worker: "" (2)
      kubeletConfig:
        cpuCfsQuota: false (3)
    1 为CR分配一个名称。
    2 指定来自机器配置池的标签。
    3 cpuCfsQuota参数设置为false
  2. 运行以下命令以创建 CR:

    $ oc create -f <file_name>.yaml

为系统进程预留资源

为了提供更可靠的调度并最大限度地减少节点资源超额分配,每个节点都可以预留一部分资源供系统守护进程使用,这些守护进程需要在您的节点上运行才能使您的集群正常运行。特别是,建议您为内存等不可压缩资源预留资源。

步骤

要为非 Pod 进程明确预留资源,请通过指定可用于调度的资源来分配节点资源。有关更多详细信息,请参见为节点分配资源。

禁用节点的超额分配

启用后,可以在每个节点上禁用超额分配。

步骤

要在节点上禁用超额认购,请在该节点上运行以下命令:

$ sysctl -w vm.overcommit_memory=0

项目级限制

为了帮助控制超额认购,您可以设置每个项目的资源限制范围,指定内存和 CPU 限制以及超额认购无法超过的项目的默认值。

有关项目级资源限制的信息,请参阅其他资源。

或者,您可以为特定项目禁用超额认购。

禁用项目的超额认购

启用后,可以按项目禁用超额认购。例如,您可以允许基础设施组件独立于超额认购进行配置。

步骤
  1. 创建或编辑命名空间对象文件。

  2. 添加以下注释:

    apiVersion: v1
    kind: Namespace
    metadata:
      annotations:
        quota.openshift.io/cluster-resource-override-enabled: "false" (1)
    # ...
    1 将此注释设置为false 将为此命名空间禁用超额认购。

使用垃圾回收释放节点资源

了解并使用垃圾回收。

了解如何通过垃圾回收删除已终止的容器

容器垃圾回收通过使用逐出阈值来删除已终止的容器。

当为垃圾回收设置逐出阈值时,节点会尝试保留从 API 访问的任何 Pod 的任何容器。如果 Pod 已被删除,则容器也将被删除。只要 Pod 未被删除且未达到逐出阈值,容器就会被保留。如果节点处于磁盘压力下,它将删除容器,并且将无法再使用oc logs访问其日志。

  • eviction-soft - 软逐出阈值将逐出阈值与所需的管理员指定的宽限期配对。

  • eviction-hard - 硬逐出阈值没有宽限期,如果观察到,OpenShift Container Platform 将立即采取行动。

下表列出了逐出阈值:

表 3. 配置容器垃圾回收的变量
节点状态 逐出信号 描述

MemoryPressure

memory.available

节点上的可用内存。

DiskPressure

  • nodefs.available

  • nodefs.inodesFree

  • imagefs.available

  • imagefs.inodesFree

节点根文件系统、nodefs或镜像文件系统imagefs上的可用磁盘空间或 inode。

对于evictionHard,您必须指定所有这些参数。如果您没有指定所有参数,则只应用指定的参数,垃圾回收将无法正常工作。

如果节点在软逐出阈值之上和之下振荡,但没有超过其关联的宽限期,则相应的节点将不断在truefalse之间振荡。结果,调度程序可能会做出糟糕的调度决策。

为了防止这种振荡,请使用eviction-pressure-transition-period标志来控制 OpenShift Container Platform 必须等待多长时间才能从压力状态转换出来。在将状态切换回 false 之前,OpenShift Container Platform 不会在指定的期间内将满足的逐出阈值设置为指定的压力条件。

了解如何通过垃圾回收删除镜像

镜像垃圾回收删除任何正在运行的 Pod 未引用的镜像。

OpenShift Container Platform 根据**cAdvisor**报告的磁盘使用情况确定要从节点中删除哪些镜像。

镜像垃圾回收策略基于两个条件:

  • 触发镜像垃圾回收的磁盘使用率百分比(以整数表示)。默认值为85

  • 镜像垃圾回收尝试释放的磁盘使用率百分比(以整数表示)。默认值为80

对于镜像垃圾回收,您可以使用自定义资源修改以下任何变量:

表 4. 配置镜像垃圾回收的变量
设置 描述

imageMinimumGCAge

在垃圾回收删除镜像之前,未使用的镜像的最小期限。默认为2m

imageGCHighThresholdPercent

触发镜像垃圾回收的磁盘使用率百分比(以整数表示)。默认值为85

imageGCLowThresholdPercent

镜像垃圾回收尝试释放的磁盘使用率百分比(以整数表示)。默认值为80

在每次垃圾收集器运行中检索两个镜像列表:

  1. 当前至少在一个 Pod 中运行的镜像列表。

  2. 主机上可用的镜像列表。

随着新容器的运行,新的镜像会出现。所有镜像都标有时间戳。如果镜像正在运行(上面的第一个列表)或新检测到(上面的第二个列表),则它将标有当前时间。其余镜像已从之前的旋转中标记。然后按时间戳对所有镜像进行排序。

收集开始后,最旧的镜像将首先被删除,直到满足停止条件。

配置容器和镜像的垃圾回收

作为管理员,您可以通过为每个机器配置池创建一个kubeletConfig对象来配置 OpenShift Container Platform 如何执行垃圾回收。

OpenShift Container Platform 仅支持每个机器配置池一个kubeletConfig对象。

您可以配置以下任何组合:

  • 容器的软逐出

  • 容器的硬逐出

  • 镜像的逐出

容器垃圾回收删除已终止的容器。镜像垃圾回收删除任何正在运行的 Pod 未引用的镜像。

先决条件
  1. 通过输入以下命令,获取与您要配置的节点类型的静态MachineConfigPool CRD 关联的标签:

    $ oc edit machineconfigpool <name>

    例如

    $ oc edit machineconfigpool worker
    示例输出
    apiVersion: machineconfiguration.openshift.io/v1
    kind: MachineConfigPool
    metadata:
      creationTimestamp: "2022-11-16T15:34:25Z"
      generation: 4
      labels:
        pools.operator.machineconfiguration.openshift.io/worker: "" (1)
      name: worker
    #...
    1 标签显示在“标签”下。

    如果标签不存在,请添加键值对,例如:

    $ oc label machineconfigpool worker custom-kubelet=small-pods
步骤
  1. 为您的配置更改创建一个自定义资源 (CR)。

    如果只有一个文件系统,或者/var/lib/kubelet/var/lib/containers/位于同一个文件系统中,则具有最高值的设置会触发逐出,因为这些设置首先满足。文件系统触发逐出。

    容器垃圾回收 CR 的示例配置
    apiVersion: machineconfiguration.openshift.io/v1
    kind: KubeletConfig
    metadata:
      name: worker-kubeconfig (1)
    spec:
      machineConfigPoolSelector:
        matchLabels:
          pools.operator.machineconfiguration.openshift.io/worker: "" (2)
      kubeletConfig:
        evictionSoft: (3)
          memory.available: "500Mi" (4)
          nodefs.available: "10%"
          nodefs.inodesFree: "5%"
          imagefs.available: "15%"
          imagefs.inodesFree: "10%"
        evictionSoftGracePeriod:  (5)
          memory.available: "1m30s"
          nodefs.available: "1m30s"
          nodefs.inodesFree: "1m30s"
          imagefs.available: "1m30s"
          imagefs.inodesFree: "1m30s"
        evictionHard: (6)
          memory.available: "200Mi"
          nodefs.available: "5%"
          nodefs.inodesFree: "4%"
          imagefs.available: "10%"
          imagefs.inodesFree: "5%"
        evictionPressureTransitionPeriod: 0s (7)
        imageMinimumGCAge: 5m (8)
        imageGCHighThresholdPercent: 80 (9)
        imageGCLowThresholdPercent: 75 (10)
    #...
    1 对象的名称。
    2 指定来自机器配置池的标签。
    3 对于容器垃圾回收:逐出类型:evictionSoftevictionHard
    4 对于容器垃圾回收:基于特定逐出触发信号的逐出阈值。
    5 对于容器垃圾回收:软逐出的宽限期。此参数不适用于eviction-hard
    6 对于容器垃圾回收:基于特定逐出触发信号的逐出阈值。对于evictionHard,您必须指定所有这些参数。如果您没有指定所有参数,则只应用指定的参数,垃圾回收将无法正常工作。
    7 对于容器垃圾回收:在从逐出压力条件转换出来之前要等待的持续时间。
    8 对于镜像垃圾回收:在垃圾回收删除镜像之前,未使用的镜像的最小期限。
    9 对于镜像垃圾回收:触发镜像垃圾回收的磁盘使用率百分比(以整数表示)。
    10 对于镜像垃圾回收:镜像垃圾回收尝试释放的磁盘使用率百分比(以整数表示)。
  2. 运行以下命令以创建 CR:

    $ oc create -f <file_name>.yaml

    例如

    $ oc create -f gc-container.yaml
    示例输出
    kubeletconfig.machineconfiguration.openshift.io/gc-container created
验证
  1. 通过输入以下命令来验证垃圾回收是否处于活动状态。您在自定义资源中指定的机器配置池将显示UPDATING为'true`,直到更改完全实现。

    $ oc get machineconfigpool
    示例输出
    NAME     CONFIG                                   UPDATED   UPDATING
    master   rendered-master-546383f80705bd5aeaba93   True      False
    worker   rendered-worker-b4c51bb33ccaae6fc4a6a5   False     True

使用节点调优运算符

了解并使用节点调优运算符。

目的

节点调优操作符 (Node Tuning Operator) 通过协调 TuneD 守护进程来帮助您管理节点级别的调优,并使用性能配置文件控制器 (Performance Profile controller) 来实现低延迟性能。大多数高性能应用程序都需要某种程度的内核调优。节点调优操作符为节点级 sysctl 用户提供了统一的管理接口,并提供了更多灵活性来添加用户需求指定的自定义调优。

该操作符将 OpenShift Container Platform 的容器化 TuneD 守护进程作为 Kubernetes 守护进程集进行管理。它确保自定义调优规范以守护进程能够理解的格式传递给集群中运行的所有容器化 TuneD 守护进程。守护进程在集群中的所有节点上运行,每个节点一个。

当触发配置文件更改的事件发生,或者容器化 TuneD 守护进程通过接收和处理终止信号而被优雅地终止时,容器化 TuneD 守护进程应用的节点级设置将被回滚。

节点调优操作符使用性能配置文件控制器来实现自动调优,从而为 OpenShift Container Platform 应用程序实现低延迟性能。

集群管理员配置性能配置文件以定义节点级设置,例如:

  • 将内核更新到 kernel-rt。

  • 选择用于系统维护的 CPU。

  • 选择用于运行工作负载的 CPU。

节点调优操作符是 4.1 及更高版本 OpenShift Container Platform 标准安装的一部分。

在早期版本的 OpenShift Container Platform 中,使用性能附加组件操作符 (Performance Addon Operator) 来实现自动调优,从而为 OpenShift 应用程序实现低延迟性能。在 OpenShift Container Platform 4.11 及更高版本中,此功能是节点调优操作符的一部分。

访问示例节点调优操作符规范

使用此过程访问示例节点调优操作符规范。

步骤
  • 运行以下命令以访问示例节点调优操作符规范

    oc get tuned.tuned.openshift.io/default -o yaml -n openshift-cluster-node-tuning-operator

默认 CR 用于为 OpenShift Container Platform 平台提供标准的节点级调优,它只能修改以设置操作符管理状态。对默认 CR 的任何其他自定义更改都将被操作符覆盖。对于自定义调优,请创建您自己的 Tuned CR。新创建的 CR 将与默认 CR 合并,并根据节点或 Pod 标签和配置文件优先级将自定义调优应用于 OpenShift Container Platform 节点。

虽然在某些情况下,对 Pod 标签的支持可以作为自动交付所需调优的便捷方式,但不建议这样做,尤其是在大型集群中。默认 Tuned CR 不包含 Pod 标签匹配。如果创建具有 Pod 标签匹配的自定义配置文件,则该功能将在此时启用。Pod 标签功能将在未来版本的节点调优操作符中弃用。

自定义调优规范

操作符的自定义资源 (CR) 包含两个主要部分。第一部分,profile:,是 TuneD 配置文件及其名称的列表。第二部分,recommend:,定义了配置文件选择逻辑。

多个自定义调优规范可以作为操作符命名空间中的多个 CR 同时存在。操作符会检测新 CR 的存在或旧 CR 的删除。所有现有的自定义调优规范都将被合并,并且会更新容器化 TuneD 守护进程的相应对象。

管理状态

通过调整默认 Tuned CR 来设置操作符管理状态。默认情况下,操作符处于“已管理”状态,并且默认 Tuned CR 中不存在 spec.managementState 字段。操作符管理状态的有效值如下:

  • 已管理 (Managed):操作符将在更新配置资源时更新其操作数。

  • 未管理 (Unmanaged):操作符将忽略对配置资源的更改。

  • 已移除 (Removed):操作符将删除其操作数和操作符配置的资源。

配置文件数据

profile: 部分列出了 TuneD 配置文件及其名称。

profile:
- name: tuned_profile_1
  data: |
    # TuneD profile specification
    [main]
    summary=Description of tuned_profile_1 profile

    [sysctl]
    net.ipv4.ip_forward=1
    # ... other sysctl's or other TuneD daemon plugins supported by the containerized TuneD

# ...

- name: tuned_profile_n
  data: |
    # TuneD profile specification
    [main]
    summary=Description of tuned_profile_n profile

    # tuned_profile_n profile settings

推荐的配置文件

profile: 选择逻辑由 CR 的 recommend: 部分定义。recommend: 部分是一个项目列表,用于根据选择条件推荐配置文件。

recommend:
<recommend-item-1>
# ...
<recommend-item-n>

列表的各个项目

- machineConfigLabels: (1)
    <mcLabels> (2)
  match: (3)
    <match> (4)
  priority: <priority> (5)
  profile: <tuned_profile_name> (6)
  operand: (7)
    debug: <bool> (8)
    tunedConfig:
      reapply_sysctl: <bool> (9)
1 可选。
2 键/值 MachineConfig 标签的字典。键必须唯一。
3 如果省略,则假设配置文件匹配,除非具有更高优先级的配置文件首先匹配或设置了 machineConfigLabels
4 可选列表。
5 配置文件排序优先级。数字越小,优先级越高(0 是最高优先级)。
6 在匹配时应用的 TuneD 配置文件。例如 tuned_profile_1
7 可选的操作数配置。
8 为 TuneD 守护进程启用或禁用调试。选项为 true(启用)或 false(禁用)。默认为 false
9 为 TuneD 守护进程启用或禁用 reapply_sysctl 功能。选项为 true(启用)和 false(禁用)。

<match> 是一个可选列表,递归定义如下:

- label: <label_name> (1)
  value: <label_value> (2)
  type: <label_type> (3)
    <match> (4)
1 节点或 Pod 标签名称。
2 可选的节点或 Pod 标签值。如果省略,则 <label_name> 的存在足以匹配。
3 可选的对象类型(nodepod)。如果省略,则假定为 node
4 可选的 <match> 列表。

如果不省略 <match>,所有嵌套的 <match> 部分也必须计算为 true。否则,假定为 false,并且不会应用或推荐具有相应 <match> 部分的配置文件。因此,嵌套(子 <match> 部分)充当逻辑 AND 运算符。相反,如果 <match> 列表的任何项目匹配,则整个 <match> 列表计算为 true。因此,该列表充当逻辑 OR 运算符。

如果定义了 machineConfigLabels,则会为给定的 recommend: 列表项目启用基于机器配置池的匹配。<mcLabels> 指定机器配置的标签。机器配置会自动创建,以应用主机设置(例如内核引导参数)到配置文件 <tuned_profile_name>。这涉及查找所有机器配置池,其机器配置选择器与 <mcLabels> 匹配,并在分配了找到的机器配置池的所有节点上设置配置文件 <tuned_profile_name>。要定位同时具有主节点和工作节点角色的节点,必须使用主节点角色。

列表项 matchmachineConfigLabels 通过逻辑 OR 运算符连接。match 项目首先以短路方式进行评估。因此,如果它计算为 true,则不考虑 machineConfigLabels 项目。

使用基于机器配置池的匹配时,建议将具有相同硬件配置的节点分组到同一个机器配置池中。不遵循此做法可能会导致 TuneD 操作数为共享相同机器配置池的两个或多个节点计算冲突的内核参数。

示例:基于节点或 Pod 标签的匹配
- match:
  - label: tuned.openshift.io/elasticsearch
    match:
    - label: node-role.kubernetes.io/master
    - label: node-role.kubernetes.io/infra
    type: pod
  priority: 10
  profile: openshift-control-plane-es
- match:
  - label: node-role.kubernetes.io/master
  - label: node-role.kubernetes.io/infra
  priority: 20
  profile: openshift-control-plane
- priority: 30
  profile: openshift-node

上述 CR 会根据配置文件的优先级,转换为容器化 TuneD 守护进程的 recommend.conf 文件。优先级最高的配置文件 (10) 是 openshift-control-plane-es,因此它会被首先考虑。在给定节点上运行的容器化 TuneD 守护进程会检查同一节点上是否存在带有 tuned.openshift.io/elasticsearch 标签的 Pod。如果没有,则整个 <match> 部分将评估为 false。如果存在带有该标签的 Pod,则为了使 <match> 部分评估为 true,节点标签也需要是 node-role.kubernetes.io/masternode-role.kubernetes.io/infra

如果优先级为 10 的配置文件的标签匹配,则应用 openshift-control-plane-es 配置文件,并且不会考虑其他配置文件。如果节点/Pod 标签组合不匹配,则会考虑第二高的优先级配置文件 (openshift-control-plane)。如果容器化 TuneD Pod 在带有标签 node-role.kubernetes.io/masternode-role.kubernetes.io/infra 的节点上运行,则会应用此配置文件。

最后,配置文件 openshift-node 的优先级最低,为 30。它缺少 <match> 部分,因此始终匹配。如果在给定节点上没有其他更高优先级的配置文件匹配,它充当配置文件的兜底方案,设置 openshift-node 配置文件。

Decision workflow
示例:基于机器配置池的匹配
apiVersion: tuned.openshift.io/v1
kind: Tuned
metadata:
  name: openshift-node-custom
  namespace: openshift-cluster-node-tuning-operator
spec:
  profile:
  - data: |
      [main]
      summary=Custom OpenShift node profile with an additional kernel parameter
      include=openshift-node
      [bootloader]
      cmdline_openshift_node_custom=+skew_tick=1
    name: openshift-node-custom

  recommend:
  - machineConfigLabels:
      machineconfiguration.openshift.io/role: "worker-custom"
    priority: 20
    profile: openshift-node-custom

为了最大限度地减少节点重启次数,请使用机器配置池的节点选择器能够匹配的标签标记目标节点,然后创建上面的 Tuned CR,最后创建自定义机器配置池本身。

特定于云提供商的 TuneD 配置文件

通过此功能,所有特定于云提供商的节点都可以方便地分配一个专门为 OpenShift Container Platform 集群上的特定云提供商定制的 TuneD 配置文件。这可以在不添加额外的节点标签或将节点分组到机器配置池的情况下实现。

此功能利用 spec.providerID 节点对象的 <cloud-provider>://<cloud-provider-specific-id> 格式的值,并在 NTO 运算符容器中使用 <cloud-provider> 值写入文件 /var/lib/ocp-tuned/provider。然后,TuneD 使用此文件的内容加载 provider-<cloud-provider> 配置文件(如果存在此类配置文件)。

openshift-control-planeopenshift-node 配置文件都继承设置的 openshift 配置文件现在通过使用条件配置文件加载来使用此功能。NTO 和 TuneD 目前都不包含任何特定于云提供商的配置文件。但是,可以创建一个自定义配置文件 provider-<cloud-provider>,该配置文件将应用于所有特定于云提供商的集群节点。

示例 GCE 云提供商配置文件
apiVersion: tuned.openshift.io/v1
kind: Tuned
metadata:
  name: provider-gce
  namespace: openshift-cluster-node-tuning-operator
spec:
  profile:
  - data: |
      [main]
      summary=GCE Cloud provider-specific profile
      # Your tuning for GCE Cloud provider goes here.
    name: provider-gce

由于配置文件继承,provider-<cloud-provider> 配置文件中指定的任何设置都将被 openshift 配置文件及其子配置文件覆盖。

集群上设置的默认配置文件

以下是集群上设置的默认配置文件。

apiVersion: tuned.openshift.io/v1
kind: Tuned
metadata:
  name: default
  namespace: openshift-cluster-node-tuning-operator
spec:
  profile:
  - data: |
      [main]
      summary=Optimize systems running OpenShift (provider specific parent profile)
      include=-provider-${f:exec:cat:/var/lib/ocp-tuned/provider},openshift
    name: openshift
  recommend:
  - profile: openshift-control-plane
    priority: 30
    match:
    - label: node-role.kubernetes.io/master
    - label: node-role.kubernetes.io/infra
  - profile: openshift-node
    priority: 40

从 OpenShift Container Platform 4.9 开始,所有 OpenShift TuneD 配置文件都随 TuneD 包一起提供。您可以使用 oc exec 命令查看这些配置文件的内容。

$ oc exec $tuned_pod -n openshift-cluster-node-tuning-operator -- find /usr/lib/tuned/openshift{,-control-plane,-node} -name tuned.conf -exec grep -H ^ {} \;

受支持的 TuneD 守护进程插件

排除 [main] 部分,在使用 Tuned CR 的 profile: 部分中定义的自定义配置文件时,支持以下 TuneD 插件。

  • audio

  • cpu

  • disk

  • eeepc_she

  • modules

  • mounts

  • net

  • scheduler

  • scsi_host

  • selinux

  • sysctl

  • sysfs

  • usb

  • video

  • vm

  • bootloader

某些插件提供的一些动态调整功能不受支持。目前不支持以下 TuneD 插件:

  • script

  • systemd

TuneD引导加载程序插件仅支持Red Hat Enterprise Linux CoreOS (RHCOS)工作节点。

配置每个节点的最大 Pod 数

两个参数控制可以调度到节点上的最大 Pod 数:podsPerCoremaxPods。如果同时使用这两个选项,则较小的一个限制节点上的 Pod 数量。

例如,如果在具有 4 个处理器内核的节点上将 podsPerCore 设置为 10,则节点上允许的最大 Pod 数为 40。

先决条件
  1. 通过输入以下命令,获取与您要配置的节点类型的静态MachineConfigPool CRD 关联的标签:

    $ oc edit machineconfigpool <name>

    例如

    $ oc edit machineconfigpool worker
    示例输出
    apiVersion: machineconfiguration.openshift.io/v1
    kind: MachineConfigPool
    metadata:
      creationTimestamp: "2022-11-16T15:34:25Z"
      generation: 4
      labels:
        pools.operator.machineconfiguration.openshift.io/worker: "" (1)
      name: worker
    #...
    1 标签显示在“标签”下。

    如果标签不存在,请添加键值对,例如:

    $ oc label machineconfigpool worker custom-kubelet=small-pods
步骤
  1. 为您的配置更改创建一个自定义资源 (CR)。

    max-pods CR 的示例配置
    apiVersion: machineconfiguration.openshift.io/v1
    kind: KubeletConfig
    metadata:
      name: set-max-pods (1)
    spec:
      machineConfigPoolSelector:
        matchLabels:
          pools.operator.machineconfiguration.openshift.io/worker: "" (2)
      kubeletConfig:
        podsPerCore: 10 (3)
        maxPods: 250 (4)
    #...
    1 为CR分配一个名称。
    2 指定来自机器配置池的标签。
    3 根据节点上的处理器内核数指定节点可以运行的 Pod 数量。
    4 无论节点的属性如何,都将节点可以运行的 Pod 数量指定为固定值。

    podsPerCore 设置为 0 将禁用此限制。

    在上例中,podsPerCore 的默认值为 10maxPods 的默认值为 250。这意味着,除非节点具有 25 个或更多内核,否则默认情况下,podsPerCore 将是限制因素。

  2. 运行以下命令以创建 CR:

    $ oc create -f <file_name>.yaml
验证
  1. 列出 MachineConfigPool CRD 以查看是否应用了更改。如果更改被机器配置控制器接收,则 UPDATING 列将报告 True

    $ oc get machineconfigpools
    示例输出
    NAME     CONFIG                        UPDATED   UPDATING   DEGRADED
    master   master-9cc2c72f205e103bb534   False     False      False
    worker   worker-8cecd1236b33ee3f8a5e   False     True       False

    更改完成后,UPDATED 列将报告 True

    $ oc get machineconfigpools
    示例输出
    NAME     CONFIG                        UPDATED   UPDATING   DEGRADED
    master   master-9cc2c72f205e103bb534   False     True       False
    worker   worker-8cecd1236b33ee3f8a5e   True      False      False

使用静态 IP 地址进行机器扩展

将集群部署为使用静态 IP 地址运行节点后,您可以扩展机器或机器集的实例以使用这些静态 IP 地址之一。

扩展机器以使用静态 IP 地址

您可以扩展其他机器集以在集群上使用预定义的静态 IP 地址。对于此配置,您需要创建一个机器资源 YAML 文件,然后在此文件中定义静态 IP 地址。

先决条件
  • 您部署的集群至少运行一个配置了静态 IP 地址的节点。

步骤
  1. 创建一个机器资源 YAML 文件,并在 network 参数中定义静态 IP 地址网络信息。

    network 参数中定义了静态 IP 地址信息的机器资源 YAML 文件示例。
    apiVersion: machine.openshift.io/v1beta1
    kind: Machine
    metadata:
      creationTimestamp: null
      labels:
        machine.openshift.io/cluster-api-cluster: <infrastructure_id>
        machine.openshift.io/cluster-api-machine-role: <role>
        machine.openshift.io/cluster-api-machine-type: <role>
        machine.openshift.io/cluster-api-machineset: <infrastructure_id>-<role>
      name: <infrastructure_id>-<role>
      namespace: openshift-machine-api
    spec:
      lifecycleHooks: {}
      metadata: {}
      providerSpec:
        value:
          apiVersion: machine.openshift.io/v1beta1
          credentialsSecret:
            name: vsphere-cloud-credentials
          diskGiB: 120
          kind: VSphereMachineProviderSpec
          memoryMiB: 8192
          metadata:
            creationTimestamp: null
          network:
            devices:
            - gateway: 192.168.204.1 (1)
              ipAddrs:
              - 192.168.204.8/24 (2)
              nameservers: (3)
              - 192.168.204.1
              networkName: qe-segment-204
          numCPUs: 4
          numCoresPerSocket: 2
          snapshot: ""
          template: <vm_template_name>
          userDataSecret:
            name: worker-user-data
          workspace:
            datacenter: <vcenter_data_center_name>
            datastore: <vcenter_datastore_name>
            folder: <vcenter_vm_folder_path>
            resourcepool: <vsphere_resource_pool>
            server: <vcenter_server_ip>
    status: {}
    1 网络接口的默认网关的 IP 地址。
    2 列出安装程序传递给网络接口的 IPv4、IPv6 或两者 IP 地址。对于默认网络,两个 IP 族都必须使用相同的网络接口。
    3 列出 DNS 服务器。您可以定义最多 3 个 DNS 服务器。考虑定义多个 DNS 服务器,以便在其中一个 DNS 服务器无法访问时利用 DNS 解析。
    • 在您的终端中输入以下命令来创建machine自定义资源 (CR)

      $ oc create -f <file_name>.yaml

具有已配置静态 IP 地址的机器的机器集扩展

您可以使用机器集来扩展具有已配置静态 IP 地址的机器。

配置机器集以请求机器的静态 IP 地址后,机器控制器会在openshift-machine-api命名空间中创建一个IPAddressClaim资源。然后,外部控制器会创建一个IPAddress资源,并将任何静态 IP 地址绑定到IPAddressClaim资源。

您的组织可能使用多种类型的 IP 地址管理 (IPAM) 服务。如果您想在 OpenShift Container Platform 上启用特定的 IPAM 服务,您可能需要在 YAML 定义中手动创建IPAddressClaim资源,然后通过在您的oc CLI 中输入以下命令将静态 IP 地址绑定到此资源

$ oc create -f <ipaddressclaim_filename>

以下是IPAddressClaim资源的示例

kind: IPAddressClaim
metadata:
  finalizers:
  - machine.openshift.io/ip-claim-protection
  name: cluster-dev-9n5wg-worker-0-m7529-claim-0-0
  namespace: openshift-machine-api
spec:
  poolRef:
    apiGroup: ipamcontroller.example.io
    kind: IPPool
    name: static-ci-pool
status: {}

机器控制器将机器的状态更新为IPAddressClaimed,以指示静态 IP 地址已成功绑定到IPAddressClaim资源。对于包含多个IPAddressClaim资源(每个资源都包含一个绑定的静态 IP 地址)的机器,机器控制器也会应用相同的状态。然后,机器控制器创建一个虚拟机,并将静态 IP 地址应用于机器配置的providerSpec中列出的任何节点。

使用机器集扩展具有已配置静态 IP 地址的机器

您可以使用机器集来扩展具有已配置静态 IP 地址的机器。

步骤中的示例演示了使用控制器来扩展机器集中的机器。

先决条件
  • 您部署的集群至少运行一个配置了静态 IP 地址的节点。

步骤
  1. 通过在机器集的 YAML 文件的network.devices.addressesFromPools模式中指定 IP 池信息来配置机器集

    apiVersion: machine.openshift.io/v1beta1
    kind: MachineSet
    metadata:
      annotations:
        machine.openshift.io/memoryMb: "8192"
        machine.openshift.io/vCPU: "4"
      labels:
        machine.openshift.io/cluster-api-cluster: <infrastructure_id>
      name: <infrastructure_id>-<role>
      namespace: openshift-machine-api
    spec:
      replicas: 0
      selector:
        matchLabels:
          machine.openshift.io/cluster-api-cluster: <infrastructure_id>
          machine.openshift.io/cluster-api-machineset: <infrastructure_id>-<role>
      template:
        metadata:
          labels:
            ipam: "true"
            machine.openshift.io/cluster-api-cluster: <infrastructure_id>
            machine.openshift.io/cluster-api-machine-role: worker
            machine.openshift.io/cluster-api-machine-type: worker
            machine.openshift.io/cluster-api-machineset: <infrastructure_id>-<role>
        spec:
          lifecycleHooks: {}
          metadata: {}
          providerSpec:
            value:
              apiVersion: machine.openshift.io/v1beta1
              credentialsSecret:
                name: vsphere-cloud-credentials
              diskGiB: 120
              kind: VSphereMachineProviderSpec
              memoryMiB: 8192
              metadata: {}
              network:
                devices:
                - addressesFromPools: (1)
                  - group: ipamcontroller.example.io
                    name: static-ci-pool
                    resource: IPPool
                  nameservers:
                  - "192.168.204.1" (2)
                  networkName: qe-segment-204
              numCPUs: 4
              numCoresPerSocket: 2
              snapshot: ""
              template: rvanderp4-dev-9n5wg-rhcos-generated-region-generated-zone
              userDataSecret:
                name: worker-user-data
              workspace:
                datacenter: IBMCdatacenter
                datastore: /IBMCdatacenter/datastore/vsanDatastore
                folder: /IBMCdatacenter/vm/rvanderp4-dev-9n5wg
                resourcePool: /IBMCdatacenter/host/IBMCcluster//Resources
                server: vcenter.ibmc.devcluster.openshift.com
    1 指定一个 IP 池,其中列出了静态 IP 地址或静态 IP 地址范围。IP 池可以是自定义资源定义 (CRD) 的引用,也可以是IPAddressClaims资源处理器支持的资源。机器控制器访问机器集配置中列出的静态 IP 地址,然后将每个地址分配给每台机器。
    2 列出一个名称服务器。您必须为接收静态 IP 地址的节点指定一个名称服务器,因为动态主机配置协议 (DHCP) 网络配置不支持静态 IP 地址。
  2. 通过在您的oc CLI 中输入以下命令来扩展机器集

    $ oc scale --replicas=2 machineset <machineset> -n openshift-machine-api

    或者

    $ oc edit machineset <machineset> -n openshift-machine-api

    每扩展一台机器后,机器控制器都会创建一个IPAddressClaim资源。

  3. 可选:通过输入以下命令检查IPAddressClaim资源是否存在于openshift-machine-api命名空间中

    $ oc get ipaddressclaims.ipam.cluster.x-k8s.io -n openshift-machine-api
    列出openshift-machine-api命名空间中列出的两个 IP 池的示例oc CLI 输出
    NAME                                         POOL NAME        POOL KIND
    cluster-dev-9n5wg-worker-0-m7529-claim-0-0   static-ci-pool   IPPool
    cluster-dev-9n5wg-worker-0-wdqkt-claim-0-0   static-ci-pool   IPPool
  4. 通过输入以下命令来创建IPAddress资源

    $ oc create -f ipaddress.yaml

    以下示例显示了一个具有已定义网络配置信息和一个已定义静态 IP 地址的IPAddress资源

    apiVersion: ipam.cluster.x-k8s.io/v1alpha1
    kind: IPAddress
    metadata:
      name: cluster-dev-9n5wg-worker-0-m7529-ipaddress-0-0
      namespace: openshift-machine-api
    spec:
      address: 192.168.204.129
      claimRef: (1)
        name: cluster-dev-9n5wg-worker-0-m7529-claim-0-0
      gateway: 192.168.204.1
      poolRef: (2)
        apiGroup: ipamcontroller.example.io
        kind: IPPool
        name: static-ci-pool
      prefix: 23
    1 目标IPAddressClaim资源的名称。
    2 有关节点的静态 IP 地址或地址的详细信息。

    默认情况下,外部控制器会自动扫描机器集中的任何资源以查找可识别的地址池类型。当外部控制器在IPAddress资源中找到kind: IPPool时,控制器会将任何静态 IP 地址绑定到IPAddressClaim资源。

  5. 使用对IPAddress资源的引用更新IPAddressClaim状态

    $ oc --type=merge patch IPAddressClaim cluster-dev-9n5wg-worker-0-m7529-claim-0-0 -p='{"status":{"addressRef": {"name": "cluster-dev-9n5wg-worker-0-m7529-ipaddress-0-0"}}}' -n openshift-machine-api --subresource=status