8.5. 配置集群以将 pod 放置到过量使用的节点上

处于过量使用(overcommited)状态时,容器计算资源请求和限制的总和超过系统中可用的资源。例如,您可以在一个开发环境中使用过量使用功能,因为在这种环境中可以接受以牺牲保障性能来换取功能的情况。

容器可以指定计算资源的请求(request)和限值(limit)。请求用于调度容器,以提供最低服务保证。限值用于约束节点上可以消耗的计算资源数量。

调度程序会尝试优化集群中所有节点的计算资源使用。它将 pod 放置到特定的节点上,同时考虑 pod 的计算资源请求和节点的可用容量。

OpenShift Container Platform 管理员可以控制过量使用的程度,并管理节点上的容器密度。您可以使用 ClusterResourceOverride Operator 配置集群一级的过量使用,以覆盖开发人员容器上设置的请求和限值之间的比例。与节点过量使用项目内存以及 CPU 限值和默认值一同使用,您可以调整资源限值和请求,以达到所需的过量使用程度。

注意

在 OpenShift Container Platform 中,您必须启用集群级别的过量使用。节点过量使用功能会被默认启用。请参阅禁用节点过量使用

8.5.1. 资源请求和过量使用

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

限制的强制实施取决于计算资源类型。如果容器没有请求或限制,容器会调度到没有资源保障的节点。在实践中,容器可以在最低本地优先级适用的范围内消耗指定的资源。在资源较少的情况下,不指定资源请求的容器将获得最低的服务质量。

调度基于请求的资源,而配额和硬限制指的是资源限制,它们可以设置为高于请求的资源。请求和限制的差值决定了过量使用程度;例如,如果为容器赋予 1Gi 内存请求和 2Gi 内存限制,则根据 1Gi 请求将容器调度到节点上,但最多可使用 2Gi;因此过量使用为 200%。

8.5.2. 使用 Cluster Resource Override Operator 的集群级别的过量使用

Cluster Resource Override Operator 是一个准入 Webhook,可让您控制过量使用的程度,并在集群中的所有节点上管理容器密度。Operator 控制特定项目中节点可以如何超过定义的内存和 CPU 限值。

您必须使用 OpenShift Container Platform 控制台或 CLI 安装 Cluster Resource override Operator,如下所示。在安装过程中,您会创建一个 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。
注意

如果容器上没有设置限值,则 Cluster Resourceoverride Operator 覆盖无效。创建一个针对单独项目的带有默认限制的 LimitRange 对象,或在 Pod specs 中配置要应用的覆盖的限制。

配置后,可通过将以下标签应用到每个项目的命名空间对象来启用每个项目的覆盖:

apiVersion: v1
kind: Namespace
metadata:

# ...

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

# ...

Operator 监视 ClusterResourceOverride CR, 并确保 ClusterResourceOverride 准入 Webhook 被安装到与 Operator 相同的命名空间。

8.5.2.1. 使用 Web 控制台安装 Cluster Resource Override Operator

您可以使用 OpenShift Container Platform Web 控制台来安装 Cluster Resource Override Operator,以帮助控制集群中的过量使用。

先决条件

  • 如果容器上未设置限值,Cluster Resourceoverride Operator 将没有作用。您必须使用一个 LimitRange 对象为项目指定默认限值,或在 Pod spec 中配置要应用的覆盖的限制。

流程

使用 OpenShift Container Platform web 控制台安装 Cluster Resource Override Operator:

  1. 在 OpenShift Container Platform web 控制台中进入 HomeProjects

    1. 点击 Create Project
    2. 指定 clusterresourceoverride-operator 作为项目的名称。
    3. 点击 Create
  2. 进入 OperatorsOperatorHub

    1. 从可用 Operator 列表中选择 ClusterResourceOverride Operator,再点击 Install
    2. Install Operator 页面中,确保为 Installation Mode 选择了 A specific Namespace on the cluster
    3. 确保为 Installed Namespace 选择了 clusterresourceoverride-operator
    4. 指定更新频道批准策略
    5. 点击 Install
  3. Installed Operators 页面中,点 ClusterResourceOverride

    1. ClusterResourceOverride Operator 详情页面中,点 Create ClusterResourceOverride
    2. Create 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
      可选。指定在 1-100 之间覆盖容器 CPU 限值的百分比(如果使用的话)。默认值为 25。
      4
      可选。如果使用,请指定覆盖容器内存限值的百分比。以 100% 扩展 1Gi RAM, 等于 1 个 CPU 内核。这会在覆盖 CPU 请求前进行处理(如果已配置)。默认值为 200。
    3. 点击 Create
  4. 通过检查集群自定义资源的状态来检查准入 Webhook 的当前状态:

    1. ClusterResourceOverride Operator 页面中,点击 cluster
    2. ClusterResourceOverride Details 页中,点 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。

8.5.2.2. 使用 CLI 安装 Cluster Resource Override Operator

您可以使用 OpenShift Container Platform CLI 来安装 Cluster Resource Override Operator,以帮助控制集群中的过量使用。

先决条件

  • 如果容器上未设置限值,Cluster Resourceoverride Operator 将没有作用。您必须使用一个 LimitRange 对象为项目指定默认限值,或在 Pod spec 中配置要应用的覆盖的限制。

流程

使用 CLI 安装 Cluster Resource Override Operator:

  1. 为 Cluster Resource Override Operator 创建命名空间:

    1. 为 Cluster Resource Override Operator 创建一个 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. 创建一个 Operator 组:

    1. 为 Cluster Resource Override Operator 创建一个 OperatorGroup 对象 YAML 文件(如 cro-og.yaml):

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

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

      例如:

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

    1. 为 Cluster Resourceoverride Operator 创建一个 Subscription 对象 YAML 文件(如 cro-sub.yaml):

      apiVersion: operators.coreos.com/v1alpha1
      kind: Subscription
      metadata:
        name: clusterresourceoverride
        namespace: clusterresourceoverride-operator
      spec:
        channel: "4.12"
        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. 为 Cluster Resourceoverride Operator 创建 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
      可选。指定在 1-100 之间覆盖容器 CPU 限值的百分比(如果使用的话)。默认值为 25。
      4
      可选。如果使用,请指定覆盖容器内存限值的百分比。以 100% 扩展 1Gi 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。

8.5.2.3. 配置集群级别的过量使用

Cluster Resource Override Operator 需要一个 ClusterResourceOverride 自定义资源 (CR),以及您希望 Operator 来控制过量使用的每个项目的标识。

先决条件

  • 如果容器上未设置限值,Cluster Resourceoverride Operator 将没有作用。您必须使用一个 LimitRange 对象为项目指定默认限值,或在 Pod spec 中配置要应用的覆盖的限制。

流程

修改集群级别的过量使用:

  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
    可选。指定在 1-100 之间覆盖容器 CPU 限值的百分比(如果使用的话)。默认值为 25。
    3
    可选。如果使用,请指定覆盖容器内存限值的百分比。以 100% 扩展 1Gi RAM, 等于 1 个 CPU 内核。这会在覆盖 CPU 请求前进行处理(如果已配置)。默认值为 200。
  2. 确保在每个您希望 Cluster Resourceoverride Operator 来控制过量使用的项目中都添加了以下标识:

    apiVersion: v1
    kind: Namespace
    metadata:
    
    # ...
    
      labels:
        clusterresourceoverrides.admission.autoscaling.openshift.io/enabled: "true" 1
    
    # ...
    1
    把这个标识添加到每个项目。

8.5.3. 节点级别的过量使用

您可以使用各种方法来控制特定节点上的过量使用,如服务质量 (QOS) 保障、CPU 限值或保留资源。您还可以为特定节点和特定项目禁用过量使用功能。

8.5.3.1. 了解计算资源和容器

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

8.5.3.1.1. 了解容器 CPU 请求

容器可以保证获得其请求的 CPU 量,还可额外消耗节点上提供的超额 CPU,但不会超过容器指定的限制。如果多个容器试图使用超额 CPU,则会根据每个容器请求的 CPU 数量来分配 CPU 时间。

例如,如果一个容器请求了 500m CPU 时间,另一个容器请求了 250m CPU 时间,那么该节点上提供的额外 CPU 时间以 2:1 比例在这两个容器之间分配。如果容器指定了一个限制,它将被限速,无法使用超过指定限制的 CPU。使用 Linux 内核中的 CFS 共享支持强制实施 CPU 请求。默认情况下,使用 Linux 内核中的 CFS 配额支持以 100ms 测量间隔强制实施 CPU 限制,但这可以禁用。

8.5.3.1.2. 了解容器内存请求

容器可以保证获得其请求的内存量。容器可以使用高于请求量的内存,但一旦超过请求量,就有可能在节点上遇到内存不足情形时被终止。如果容器使用的内存少于请求量,它不会被终止,除非系统任务或守护进程需要的内存量超过了节点资源保留考虑在内的内存量。如果容器指定了内存限制,则超过限制数量时会立即被终止。

8.5.3.2. 了解过量使用和服务质量类

当节点上调度了没有发出请求的 pod,或者节点上所有 pod 的限制总和超过了机器可用容量时,该节点处于过量使用状态。

在过量使用环境中,节点上的 pod 可能会在任意给定时间点尝试使用超过可用量的计算资源。发生这种情况时,节点必须为 pod 赋予不同的优先级。有助于做出此决策的工具称为服务质量 (QoS) 类。

pod 被指定为三个 QoS 类中的一个,带有降序排列:

表 8.19. 服务质量类

优先级类名称描述

1(最高)

Guaranteed

如果为所有资源设置了限制和可选请求(不等于 0)并且它们相等,则 pod 被归类为 Guaranteed

2

Burstable

如果为所有资源设置了请求和可选限制(不等于 0)并且它们不相等,则 pod 被归类为 Burstable

3(最低)

BestEffort

如果没有为任何资源设置请求和限制,则 pod 被归类为 BestEffort

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

  • Guaranteed 容器优先级最高,并且保证只有在它们超过限制或者系统遇到内存压力且没有优先级更低的容器可被驱除时,才会被终止。
  • 在遇到系统内存压力时,Burstable 容器如果超过其请求量并且不存在其他 BestEffort 容器,则有较大的可能会被终止。
  • BestEffort 容器被视为优先级最低。系统内存不足时,这些容器中的进程最先被终止。
8.5.3.2.1. 了解如何为不同的服务质量层级保留内存

您可以使用 qos-reserved 参数指定在特定 QoS 级别上 pod 要保留的内存百分比。此功能尝试保留请求的资源,阻止较低 QoS 类中的 pod 使用较高 QoS 类中 pod 所请求的资源。

OpenShift Container Platform 按照如下所示使用 qos-reserved 参数:

  • 值为 qos-reserved=memory=100% 时,阻止 BurstableBestEffort QoS 类消耗较高 QoS 类所请求的内存。这会增加 BestEffortBurstable 工作负载上为了提高 GuaranteedBurstable 工作负载的内存资源保障而遭遇 OOM 的风险。
  • 值为 qos-reserved=memory=50% 时,允许 BurstableBestEffort QoS 类消耗较高 QoS 类所请求的内存的一半。
  • 值为 qos-reserved=memory=0% 时,允许 BurstableBestEffort QoS 类最多消耗节点的所有可分配数量(若可用),但会增加 Guaranteed 工作负载不能访问所请求内存的风险。此条件等同于禁用这项功能。

8.5.3.3. 了解交换内存和 QoS

您可以在节点上默认禁用交换,以便保持服务质量 (QoS) 保障。否则,节点上的物理资源会超额订阅,从而影响 Kubernetes 调度程序在 pod 放置过程中所做的资源保障。

例如,如果两个有保障 pod 达到其内存限制,各个容器可以开始使用交换内存。最终,如果没有足够的交换空间,pod 中的进程可能会因为系统被超额订阅而被终止。

如果不禁用交换,会导致节点无法意识到它们正在经历 MemoryPressure,从而造成 pod 无法获得它们在调度请求中索取的内存。这样节点上就会放置更多 pod,进一步增大内存压力,最终增加遭遇系统内存不足 (OOM) 事件的风险。

重要

如果启用了交换,则对于可用内存的资源不足处理驱除阈值将无法正常发挥作用。利用资源不足处理,允许在遇到内存压力时从节点中驱除 pod,并且重新调度到没有此类压力的备选节点上。

8.5.3.4. 了解节点过量使用

在过量使用的环境中,务必要正确配置节点,以提供最佳的系统行为。

当节点启动时,它会确保为内存管理正确设置内核可微调标识。除非物理内存不足,否则内核应该永不会在内存分配时失败。

为确保这一行为,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 限制
  • 为系统进程保留资源
  • 为不同的服务质量等级保留内存

8.5.3.5. 使用 CPU CFS 配额禁用或强制实施 CPU 限制

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

如果禁用了 CPU 限制强制实施,了解其对节点的影响非常重要:

  • 如果容器有 CPU 请求,则请求仍由 Linux 内核中的 CFS 共享来实施。
  • 如果容器没有 CPU 请求,但没有 CPU 限制,则 CPU 请求默认为指定的 CPU 限值,并由 Linux 内核中的 CFS 共享强制。
  • 如果容器同时具有 CPU 请求和限制,则 CPU 请求由 Linux 内核中的 CFS 共享强制实施,且 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
    标签会出现在 Labels 下。
    提示

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

    $ 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

8.5.3.6. 为系统进程保留资源

为提供更可靠的调度并且最大程度减少节点资源过量使用,每个节点都可以保留一部分资源供系统守护进程使用(节点上必须运行这些守护进程才能使集群正常工作)。特别是,建议您为内存等不可压缩的资源保留资源。

流程

要明确为非 pod 进程保留资源,请通过指定可用于调度的资源来分配节点资源。如需了解更多详细信息,请参阅“为节点分配资源”。

8.5.3.7. 禁用节点过量使用

启用之后,可以在每个节点上禁用过量使用。

流程

要在节点中禁用过量使用,请在该节点上运行以下命令:

$ sysctl -w vm.overcommit_memory=0

8.5.4. 项目级别限值

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

如需有关项目级别资源限值的信息,请参阅附加资源。

另外,您可以为特定项目禁用过量使用。

8.5.4.1. 禁用项目过量使用

启用之后,可以按项目禁用过量使用。例如,您可以允许独立于过量使用配置基础架构组件。

流程

在某个项目中禁用过量使用:

  1. 编辑命名空间对象以添加以下注解:

    apiVersion: v1
    kind: Namespace
    metadata:
      annotations:
        quota.openshift.io/cluster-resource-override-enabled: "false" 1
    # ...
    1
    将此注解设置为 false 可禁用这个命名空间的过量使用。

8.5.5. 其他资源