5.5. Compliance Operator 扫描

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

$ oc explain scansettings

或者

$ oc explain scansettingbindings

5.5.1. 运行合规性扫描

您可以使用互联网安全中心(CIS)配置集运行扫描。为方便起见,Compliance Operator 创建一个在启动时具有合理的默认值的 ScanSetting 对象。这个 ScanSetting 对象名为 default

注意

对于 all-in-one control plane 和 worker 节点,合规性扫描在 worker 和 control plane 节点上运行两次。合规性扫描可能会导致扫描结果不一致。您可以通过在 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
    Metadata:
      Creation Timestamp:  2022-10-10T14:07:29Z
      Generation:          1
      Managed Fields:
        API Version:  compliance.openshift.io/v1alpha1
        Fields Type:  FieldsV1
        fieldsV1:
          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-10T14:07:29Z
      Resource Version:  56111
      UID:               c21d1d14-3472-47d7-a450-b924287aec90
    Raw Result Storage:
      Node Selector:
        node-role.kubernetes.io/master:
      Pv Access Modes:
        ReadWriteOnce 1
      Rotation:  3 2
      Size:      1Gi 3
      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 4
      worker 5
    Scan Tolerations: 6
      Operator:           Exists
    Schedule:             0 1 * * * 7
    Show Not Applicable:  false
    Strict Node Scan:     true
    Events:               <none>

    1
    Compliance Operator 创建一个包含扫描结果的持久性卷(PV)。默认情况下,PV 将使用访问模式 ReadWriteOnce,因为 Compliance Operator 无法假定集群中配置的存储类。另外,多数集群中可以使用 ReadWriteOnce 访问模式。如果需要获取扫描结果,可以使用一个 helper pod 来完成此操作,该 pod 也绑定卷。使用 ReadWriteOnce 访问模式的卷只能由一个 pod 挂载,因此请记住删除帮助程序 pod。否则,Compliance Operator 将无法重复使用卷进行后续扫描。
    2
    Compliance Operator 在卷中保留三个后续扫描的结果,旧的扫描会被轮转。
    3
    Compliance Operator 将为扫描结果分配一个 GB 存储。
    4 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 2
    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 2
    通过将 autoUpdateRemediationsautoApplyRemediations 标记设置为 true,您可以轻松地创建无需额外步骤自动修复的 ScanSetting 对象。
  2. 创建一个 ScanSettingBinding 对,,它绑定到默认的 ScanSetting 对象,并使用 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 补救

5.5.2. 将结果服务器 pod 调度到 worker 节点上

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

这适用于那些不允许 control plane 节点挂载持久性卷的环境。

流程

  • 为 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

5.5.3. ScanSetting 自定义资源

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

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

重要

如果默认限值不足且 Operator 或扫描程序 Pod 被 Out Of Memory (OOM) 进程停止,则需要提高 Compliance Operator 或 scanner Pod 的内存限值。

5.5.4. 应用资源请求和限值

当 kubelet 作为 Pod 的一部分启动容器时,kubelet 会将该容器的请求和限值传递给容器运行时。在 Linux 中,容器运行时配置应用并强制实施您定义的限制的内核 cgroup。

CPU 限制定义容器可以使用的 CPU 时间。在每个调度间隔中,Linux 内核会检查是否超过这个限制。如果是这样,内核会在允许 cgroup 恢复执行前等待。

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

如果容器尝试分配超过这个限制的内存,Linux 内核的 out-of-memory 子系统会被激活,并通过停止容器中的一个进程来进行干预。Pod 或容器的内存限值也可以应用到由内存支持的卷的页面,如 emptyDir。

kubelet 将 tmpfs emptyDir 视为容器使用的内存进行跟踪,而不是视为本地临时存储。如果容器超过其内存请求,且在其中运行的节点变得缺少内存,则 Pod 的容器可能会被驱除。

重要

容器无法在超过 CPU 限制的情况下长时间运行。容器运行时不会停止 Pod 或容器超量使 CPU。要确定容器是否因为资源限值而无法调度或正在被终止,请参阅 Compliance Operator 故障排除

5.5.5. 使用容器资源请求调度 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:
  containers:
  - name: app
    image: images.my-company.example/app:v4
    resources:
      requests: 1
        memory: "64Mi"
        cpu: "250m"
      limits: 2
        memory: "128Mi"
        cpu: "500m"
  - name: log-aggregator
    image: images.my-company.example/log-aggregator:v6
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

1
容器请求 64 Mi 内存和 250 m CPU。
2
容器的限值是 128 Mi 内存和 500 m CPU。