×

建议使用ScanSettingScanSettingBinding API来运行合规性扫描。有关这些API对象的更多信息,请运行

$ oc explain scansettings

$ oc explain scansettingbindings

运行合规性扫描

您可以使用互联网安全中心 (CIS) 配置文件运行扫描。为方便起见,合规性运算符在启动时会创建一个具有合理默认值的ScanSetting对象。此ScanSetting对象的名称为default

对于一体化控制平面和工作节点,合规性扫描会在工作节点和控制平面节点上运行两次。合规性扫描可能会生成不一致的扫描结果。您可以通过仅在ScanSetting对象中定义单个角色来避免不一致的结果。

步骤
  1. 通过运行以下命令检查ScanSetting对象

    $ oc describe scansettings default -n openshift-compliance
    示例输出
    Name:                  default
    Namespace:             openshift-compliance
    Labels:                <none>
    Annotations:           <none>
    API Version:           compliance.openshift.io/v1alpha1
    Kind:                  ScanSetting
    Max Retry On Timeout:  3
    Metadata:
      Creation Timestamp:  2024-07-16T14:56:42Z
      Generation:          2
      Resource Version:    91655682
      UID:                 50358cf1-57a8-4f69-ac50-5c7a5938e402
    Raw Result Storage:
      Node Selector:
        node-role.kubernetes.io/master:
      Pv Access Modes:
        ReadWriteOnce (1)
      Rotation:            3 (2)
      Size:                1Gi (3)
      Storage Class Name:  standard (4)
      Tolerations:
        Effect:              NoSchedule
        Key:                 node-role.kubernetes.io/master
        Operator:            Exists
        Effect:              NoExecute
        Key:                 node.kubernetes.io/not-ready
        Operator:            Exists
        Toleration Seconds:  300
        Effect:              NoExecute
        Key:                 node.kubernetes.io/unreachable
        Operator:            Exists
        Toleration Seconds:  300
        Effect:              NoSchedule
        Key:                 node.kubernetes.io/memory-pressure
        Operator:            Exists
    Roles:
      master (5)
      worker (5)
    Scan Tolerations: (6)
      Operator:           Exists
    Schedule:             0 1 * * * (7)
    Show Not Applicable:  false
    Strict Node Scan:     true
    Suspend:              false
    Timeout:              30m
    Events:               <none>
    1 合规性运算符会创建一个持久卷 (PV),其中包含扫描结果。默认情况下,PV 将使用访问模式ReadWriteOnce,因为合规性运算符无法对集群上配置的存储类进行任何假设。此外,大多数集群上都提供ReadWriteOnce访问模式。如果您需要获取扫描结果,可以使用辅助 Pod,该 Pod 也会绑定卷。使用ReadWriteOnce访问模式的卷一次只能由一个 Pod 挂载,因此务必记住删除辅助 Pod。否则,合规性运算符将无法重用该卷进行后续扫描。
    2 合规性运算符会在卷中保留三个后续扫描的结果;较旧的扫描将被轮换。
    3 合规性运算符将为扫描结果分配 1 GB 的存储空间。
    4 scansetting.rawResultStorage.storageClassName 字段指定在创建用于存储原始结果的 PersistentVolumeClaim 对象时使用的 storageClassName 值。默认值为 null,这将尝试使用集群中配置的默认存储类。如果没有指定默认类,则必须设置一个默认类。
    5 如果扫描设置使用任何扫描集群节点的配置文件,请扫描这些节点角色。
    6 默认扫描设置对象扫描所有节点。
    7 默认扫描设置对象每天01:00运行扫描。

    作为默认扫描设置的替代方案,您可以使用 default-auto-apply,它具有以下设置

    Name:                      default-auto-apply
    Namespace:                 openshift-compliance
    Labels:                    <none>
    Annotations:               <none>
    API Version:               compliance.openshift.io/v1alpha1
    Auto Apply Remediations:   true (1)
    Auto Update Remediations:  true (1)
    Kind:                      ScanSetting
    Metadata:
      Creation Timestamp:  2022-10-18T20:21:00Z
      Generation:          1
      Managed Fields:
        API Version:  compliance.openshift.io/v1alpha1
        Fields Type:  FieldsV1
        fieldsV1:
          f:autoApplyRemediations:
          f:autoUpdateRemediations:
          f:rawResultStorage:
            .:
            f:nodeSelector:
              .:
              f:node-role.kubernetes.io/master:
            f:pvAccessModes:
            f:rotation:
            f:size:
            f:tolerations:
          f:roles:
          f:scanTolerations:
          f:schedule:
          f:showNotApplicable:
          f:strictNodeScan:
        Manager:         compliance-operator
        Operation:       Update
        Time:            2022-10-18T20:21:00Z
      Resource Version:  38840
      UID:               8cb0967d-05e0-4d7a-ac1c-08a7f7e89e84
    Raw Result Storage:
      Node Selector:
        node-role.kubernetes.io/master:
      Pv Access Modes:
        ReadWriteOnce
      Rotation:  3
      Size:      1Gi
      Tolerations:
        Effect:              NoSchedule
        Key:                 node-role.kubernetes.io/master
        Operator:            Exists
        Effect:              NoExecute
        Key:                 node.kubernetes.io/not-ready
        Operator:            Exists
        Toleration Seconds:  300
        Effect:              NoExecute
        Key:                 node.kubernetes.io/unreachable
        Operator:            Exists
        Toleration Seconds:  300
        Effect:              NoSchedule
        Key:                 node.kubernetes.io/memory-pressure
        Operator:            Exists
    Roles:
      master
      worker
    Scan Tolerations:
      Operator:           Exists
    Schedule:             0 1 * * *
    Show Not Applicable:  false
    Strict Node Scan:     true
    Events:               <none>
    1 autoUpdateRemediationsautoApplyRemediations 标志设置为 true,您可以轻松创建自动修复的 ScanSetting 对象,无需额外步骤。
  2. 创建一个绑定到默认 ScanSetting 对象的 ScanSettingBinding 对象,并使用 ciscis-node 配置文件扫描集群。例如

    apiVersion: compliance.openshift.io/v1alpha1
    kind: ScanSettingBinding
    metadata:
      name: cis-compliance
      namespace: openshift-compliance
    profiles:
      - name: ocp4-cis-node
        kind: Profile
        apiGroup: compliance.openshift.io/v1alpha1
      - name: ocp4-cis
        kind: Profile
        apiGroup: compliance.openshift.io/v1alpha1
    settingsRef:
      name: default
      kind: ScanSetting
      apiGroup: compliance.openshift.io/v1alpha1
  3. 运行以下命令创建 ScanSettingBinding 对象:

    $ oc create -f <file-name>.yaml -n openshift-compliance

    在此过程的这一点上,ScanSettingBinding 对象将被协调,并基于 BindingBound 设置。Compliance Operator 创建一个 ComplianceSuite 对象和相关的 ComplianceScan 对象。

  4. 运行以下命令跟踪合规性扫描进度:

    $ oc get compliancescan -w -n openshift-compliance

    扫描将经过扫描阶段,最终在完成时达到 DONE 阶段。在大多数情况下,扫描结果为 NON-COMPLIANT。您可以查看扫描结果并开始应用修复程序以使集群符合规范。有关更多信息,请参阅 *管理 Compliance Operator 修复*。

设置自定义结果存储大小

虽然诸如 ComplianceCheckResult 之类的自定义资源表示跨所有扫描节点的一个检查的聚合结果,但查看扫描程序生成的原始结果可能很有用。原始结果以 ARF 格式生成,并且可能很大(每个节点几十兆字节),因此将它们存储在由 etcd 键值存储支持的 Kubernetes 资源中是不切实际的。相反,每次扫描都会创建一个持久卷 (PV),默认为 1GB 大小。根据您的环境,您可能需要相应地增加 PV 大小。这可以通过在 ScanSettingComplianceScan 资源中公开的 rawResultStorage.size 属性来完成。

相关的参数是 rawResultStorage.rotation,它控制在旋转较旧的扫描之前在 PV 中保留多少次扫描。默认值为 3,将旋转策略设置为 0 将禁用旋转。鉴于默认旋转策略和每次原始 ARF 扫描报告约 100MB 的估计值,您可以计算适合您环境的正确 PV 大小。

使用自定义结果存储值

由于 OpenShift Container Platform 可以部署在各种公有云或裸机环境中,因此 Compliance Operator 无法确定可用的存储配置。默认情况下,Compliance Operator 将尝试使用集群的默认存储类创建用于存储结果的 PV,但是可以使用 rawResultStorage.StorageClassName 属性配置自定义存储类。

如果您的集群未指定默认存储类,则必须设置此属性。

配置 ScanSetting 自定义资源以使用标准存储类并创建大小为 10GB 并保留最后 10 个结果的持久卷

ScanSetting CR 示例
apiVersion: compliance.openshift.io/v1alpha1
kind: ScanSetting
metadata:
  name: default
  namespace: openshift-compliance
rawResultStorage:
  storageClassName: standard
  rotation: 10
  size: 10Gi
roles:
- worker
- master
scanTolerations:
- effect: NoSchedule
  key: node-role.kubernetes.io/master
  operator: Exists
schedule: '0 1 * * *'

在工作节点上调度结果服务器 Pod

结果服务器 Pod 挂载存储原始资产报告格式 (ARF) 扫描结果的持久卷 (PV)。nodeSelectortolerations 属性使您可以配置结果服务器 Pod 的位置。

这对不允许控制平面节点挂载持久卷的环境很有帮助。

步骤
  • 为 Compliance Operator 创建 ScanSetting 自定义资源 (CR)

    1. 定义 ScanSetting CR 并保存 YAML 文件,例如 rs-workers.yaml

      apiVersion: compliance.openshift.io/v1alpha1
      kind: ScanSetting
      metadata:
        name: rs-on-workers
        namespace: openshift-compliance
      rawResultStorage:
        nodeSelector:
          node-role.kubernetes.io/worker: "" (1)
        pvAccessModes:
        - ReadWriteOnce
        rotation: 3
        size: 1Gi
        tolerations:
        - operator: Exists (2)
      roles:
      - worker
      - master
      scanTolerations:
        - operator: Exists
      schedule: 0 1 * * *
      1 Compliance Operator 使用此节点以 ARF 格式存储扫描结果。
      2 结果服务器 Pod 容忍所有污点。
    2. 要创建 ScanSetting CR,请运行以下命令:

      $ oc create -f rs-workers.yaml
验证
  • 要验证是否已创建 ScanSetting 对象,请运行以下命令:

    $ oc get scansettings rs-on-workers -n openshift-compliance -o yaml
    示例输出
    apiVersion: compliance.openshift.io/v1alpha1
    kind: ScanSetting
    metadata:
      creationTimestamp: "2021-11-19T19:36:36Z"
      generation: 1
      name: rs-on-workers
      namespace: openshift-compliance
      resourceVersion: "48305"
      uid: 43fdfc5f-15a7-445a-8bbc-0e4a160cd46e
    rawResultStorage:
      nodeSelector:
        node-role.kubernetes.io/worker: ""
      pvAccessModes:
      - ReadWriteOnce
      rotation: 3
      size: 1Gi
      tolerations:
      - operator: Exists
    roles:
    - worker
    - master
    scanTolerations:
    - operator: Exists
    schedule: 0 1 * * *
    strictNodeScan: true

ScanSetting 自定义资源

ScanSetting 自定义资源现在允许您通过扫描限制属性覆盖扫描程序 Pod 的默认 CPU 和内存限制。Compliance Operator 将为扫描程序容器使用 500Mi 内存、100m CPU 的默认值,为 api-resource-collector 容器使用 200Mi 内存和 100m CPU 的默认值。要设置 Operator 的内存限制,请修改通过 OLM 安装的 Subscription 对象或 Operator 部署本身。

要增加 Compliance Operator 的默认 CPU 和内存限制,请参阅 *增加 Compliance Operator 资源限制*。

如果默认限制不足并且 Operator 或扫描程序 Pod 被内存不足 (OOM) 进程结束,则需要增加 Compliance Operator 或扫描程序 Pod 的内存限制。

配置托管控制平面管理集群

如果您正在托管自己的托管控制平面或 Hypershift 环境,并希望从管理集群扫描托管集群,则需要设置目标托管集群的名称和前缀命名空间。您可以通过创建 TailoredProfile 来实现此目的。

此过程仅适用于管理自己托管控制平面环境的用户。

在托管控制平面管理集群中,仅支持 ocp4-cisocp4-pci-dss 配置文件。

先决条件
  • Compliance Operator 安装在管理集群中。

步骤
  1. 运行以下命令获取要扫描的托管集群的 namenamespace

    $ oc get hostedcluster -A
    示例输出
    NAMESPACE       NAME                   VERSION   KUBECONFIG                              PROGRESS    AVAILABLE   PROGRESSING   MESSAGE
    local-cluster   79136a1bdb84b3c13217   4.13.5    79136a1bdb84b3c13217-admin-kubeconfig   Completed   True        False         The hosted control plane is available
  2. 在管理集群中,创建一个扩展扫描配置文件的 TailoredProfile 并定义要扫描的托管集群的名称和命名空间

    management-tailoredprofile.yaml 示例
    apiVersion: compliance.openshift.io/v1alpha1
    kind: TailoredProfile
    metadata:
      name: hypershift-cisk57aw88gry
      namespace: openshift-compliance
    spec:
      description: This profile test required rules
      extends: ocp4-cis (1)
      title: Management namespace profile
      setValues:
      - name: ocp4-hypershift-cluster
        rationale: This value is used for HyperShift version detection
        value: 79136a1bdb84b3c13217 (2)
      - name: ocp4-hypershift-namespace-prefix
        rationale: This value is used for HyperShift control plane namespace detection
        value: local-cluster (3)
    1 变量。在托管控制平面管理集群中,仅支持 ocp4-cisocp4-pci-dss 配置文件。
    2 value 是上一步输出中的 NAME
    3 value 是上一步输出中的 NAMESPACE
  3. 创建 TailoredProfile

    $ oc create -n openshift-compliance -f mgmt-tp.yaml

应用资源请求和限制

当 kubelet 启动 Pod 中的容器时,kubelet 会将该容器的内存和 CPU 请求和限制传递给容器运行时。在 Linux 中,容器运行时会配置应用并强制执行您定义的限制的内核 cgroups。

CPU 限制定义容器可以使用多少 CPU 时间。在每个调度间隔期间,Linux 内核都会检查是否超过此限制。如果是,则内核会在允许 cgroup 恢复执行之前等待。

如果多个不同的容器 (cgroups) 想要在竞争系统上运行,则具有较大 CPU 请求的工作负载分配的 CPU 时间多于具有较小请求的工作负载。内存请求在 Pod 调度期间使用。在使用 cgroups v2 的节点上,容器运行时可能会使用内存请求作为提示来设置 memory.minmemory.low 值。

如果容器尝试分配超过此限制的内存,则 Linux 内核内存不足子系统会激活并通过停止尝试分配内存的容器中的一个进程来进行干预。Pod 或容器的内存限制也可能适用于内存支持卷(例如 emptyDir)中的页面。

kubelet 将 tmpfs emptyDir 卷视为容器内存使用情况的一部分,而不是本地临时存储。如果容器超过其内存请求,并且其运行所在的节点整体内存不足,则 Pod 的容器可能会被驱逐。

容器可能不会长时间超过其 CPU 限制。容器运行时不会因过度 CPU 使用而停止 Pod 或容器。要确定容器是否因资源限制而无法调度或被终止,请参阅《排查 Compliance Operator 问题》。

调度具有容器资源请求的 Pod

创建 Pod 时,调度器会选择一个节点供 Pod 运行。每个节点的每种资源类型(CPU 和内存)都有最大容量,它可以为 Pod 提供这些资源。调度器确保已调度容器的资源请求总和小于每个资源类型的节点容量。

即使节点上的内存或 CPU 资源使用率非常低,如果容量检查失败,无法防止节点资源短缺,调度器仍然可能拒绝将 Pod 放置到节点上。

对于每个容器,您可以指定以下资源限制和请求

spec.containers[].resources.limits.cpu
spec.containers[].resources.limits.memory
spec.containers[].resources.limits.hugepages-<size>
spec.containers[].resources.requests.cpu
spec.containers[].resources.requests.memory
spec.containers[].resources.requests.hugepages-<size>

虽然您只能为单个容器指定请求和限制,但考虑 Pod 的整体资源请求和限制也很有用。对于特定资源,容器资源请求或限制是 Pod 中每个容器的该类型资源请求或限制之和。

容器资源请求和限制示例
apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  securityContext:
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: app
    image: images.my-company.example/app:v4
    resources:
      requests: (1)
        memory: "64Mi"
        cpu: "250m"
      limits: (2)
        memory: "128Mi"
        cpu: "500m"
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop: [ALL]
  - name: log-aggregator
    image: images.my-company.example/log-aggregator:v6
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop: [ALL]
1 容器请求 64 Mi 内存和 250 m CPU。
2 容器的限制是 128 Mi 内存和 500 m CPU。