从合规到免疫:基于 Kube-bench 构建 Kubernetes 集群的安全基石

本文面向负责 Kubernetes 集群安全与合规性的中高级工程师与架构师。我们将从 CIS Benchmark 的基本原理出发,深入剖析 Kube-bench 的工作机制与实现细节,并最终探讨如何将其从一个简单的检查工具,演进为融入 CI/CD 流程的自动化合规与免疫体系。我们不只谈论“是什么”,更聚焦于“为什么”以及在真实生产环境中“如何做”,并分析其中的关键技术权衡。

现象与问题背景

在 Kubernetes 成为云原生事实标准的今天,其复杂性也带来了巨大的安全挑战。早期野蛮生长的阶段,为了业务快速上线,开发者可能被授予 `cluster-admin` 权限,网络策略缺失,大量配置采用默认值。这种“能跑就行”的状态,为攻击者留下了广阔的攻击面。当企业发展到一定规模,尤其是金融、电商、医疗等强监管行业,来自外部审计(如 PCI-DSS, SOX, GDPR)和内部安全团队的压力,迫使我们必须正视集群的合规性问题。

此时,团队面临的核心问题是:如何将一份长达数百页、理论化的安全标准文档(如 CIS Kubernetes Benchmark),转化为一个可度量、可重复、可自动化的工程实践?手动逐项核对上百个配置项在动辄成百上千个节点的集群中是完全不可行的。配置漂移(Configuration Drift)——即集群在日积月累的变更中逐渐偏离其初始安全基线——是另一个巨大挑战。我们需要一个工具,一个锚点,来持续地度量和校准集群的安全状态。这正是 Kube-bench 这类工具存在的价值。

关键原理拆解

在深入工具之前,我们必须回归本源,理解其背后的安全公理。这部分内容,我将以一位计算机科学教授的视角来阐述。

  • CIS Benchmark 的本质:共识驱动的防御矩阵

    CIS (Center for Internet Security) Benchmark 并非某个天才的灵光一现,而是一个由全球安全专家、厂商、学者和用户社区共同维护的共识性最佳实践集合。它本质上是一个结构化的防御矩阵,覆盖了 Kubernetes 的所有关键组件。其指导思想源于两大经典安全原则:

    1. 攻击面收缩 (Attack Surface Reduction): 大量检查项,如“确保 `–anonymous-auth` 设置为 false”(CIS 1.1.1),其目的就是关闭不必要的访问入口,减少系统暴露给潜在攻击者的“面积”。每一个开放的端口、一个启用的非必要特性,都是攻击面的一部分。
    2. 纵深防御 (Defense in Depth): CIS Benchmark 不会只依赖单一层面的防护。它会对控制平面(API Server, Controller Manager, Scheduler, etcd)、工作节点(Kubelet, Kube-proxy)以及 Pod 安全策略等多个层面进行检查。即使某一层防御被突破,其他层的安全配置也能起到阻断或延缓攻击的作用。
  • 最小权限原则 (Principle of Least Privilege)

    这是计算机安全最古老也最核心的原则之一。CIS Benchmark 中超过三分之一的检查项都与此相关。例如,对 `/etc/kubernetes/pki` 目录下证书和密钥文件的权限检查(要求 `640` 或 `600`),对 Kubelet 的 `client-ca` 文件的配置要求,以及对 Service Account 的严格管理,都是为了确保系统中的每个组件、每个用户、每个进程只拥有完成其任务所必需的最小权限。这极大地增加了攻击者在获得初步立足点后,进行横向移动(Lateral Movement)的难度。

  • 安全配置的原子性与幂等性

    现代基础设施即代码(IaC)的核心思想是幂等性。安全配置的检查与修复也应遵循此道。Kube-bench 这类工具的价值在于,它提供了一种幂等的“检查”操作。无论你运行多少次,对于一个确定的集群状态,它的输出都是相同的。这使得我们可以将安全合规检查纳入自动化流程,持续对集群状态进行断言(Assertion),一旦发现偏离(Drift),就能立刻告警或触发自动修复流程。这正是从“一次性加固”迈向“持续免疫”的理论基础。

系统架构总览

Kube-bench 本身并不是一个复杂的分布式系统,它的巧妙之处在于其部署和执行模型。它通常作为一个 Kubernetes `Job` 或 `Pod` 在集群内部运行,通过精心设计的 `volumeMounts` 和安全上下文(Security Context)来获取检查所需的信息。

我们可以将 Kube-bench 的工作流程描绘如下:

  1. 部署与启动: 用户通过 `kubectl apply` 创建一个 `Job` 资源。Kubernetes 调度器将 Kube-bench Pod 调度到某个节点上运行。为了全面扫描,通常会使用 `DaemonSet` 或针对不同节点类型(Master/Worker)的多个 `Job`。
  2. 环境自检测: Pod 启动后,Kube-bench 进程首先会检测自己运行在什么类型的节点上(Master 还是 Worker)。它通过检查特定文件(如 `/etc/kubernetes/manifests/kube-apiserver.yaml`)是否存在来做出判断。
  3. 加载基准定义: Kube-bench 内置了多个版本的 CIS Benchmark 定义,这些定义以 YAML 格式存储。它会根据用户指定的版本(或自动检测的 Kubernetes 版本)加载相应的检查项集合。
  4. 执行检查: 这是核心环节。对于每个检查项,Kube-bench 会:
    • 读取配置文件: 通过挂载的 `hostPath` volume,直接读取宿主机上的 Kubernetes 组件配置文件,如 `/etc/kubernetes/manifests/kube-apiserver.yaml` 或 `/var/lib/kubelet/config.yaml`。
    • 检查运行时进程: 通过 `hostPID: true` 获取宿主机的 PID 命名空间,从而能够执行 `ps -ef` 等命令,检查 API Server、Kubelet 等关键进程的启动参数是否符合安全要求。
    • 检查文件权限: 直接在挂载的宿主机文件系统上执行 `stat` 等命令,检查证书、密钥等敏感文件的权限设置。
  5. 生成报告: 将每个检查项的实际状态与 CIS Benchmark 的期望状态进行比对,最终生成一份详细的报告,标记出 `[PASS]`, `[FAIL]`, `[WARN]` 和 `[INFO]` 的结果,并输出到标准输出。

从这个流程可以看出,Kube-bench 的实现强依赖于 Pod 对宿主机资源的访问权限。这本身是一种安全上的“特权升级”,但为了实现安全扫描这一更高目标,这种设计是一种必要的、经过深思熟虑的权衡。

核心模块设计与实现

现在,让我们切换到极客工程师的视角,直接看代码和配置。理论讲得再多,不如一份能直接运行的 `job.yaml` 来得实在。

1. 运行 Kube-bench 的 Job Manifest

下面是一个典型的用于扫描 Master 节点的 Kube-bench `Job` 定义。这里面的每一个配置都不是随便写的,都对应着我们上面提到的原理。


apiVersion: batch/v1
kind: Job
metadata:
  name: kube-bench-master
spec:
  template:
    spec:
      hostPID: true
      nodeSelector:
        node-role.kubernetes.io/master: ""
      tolerations:
      - key: "node-role.kubernetes.io/master"
        operator: "Exists"
        effect: "NoSchedule"
      containers:
        - name: kube-bench
          image: aquasec/kube-bench:latest
          command: ["kube-bench", "master", "--version", "1.23", "--json"]
          volumeMounts:
            - name: var-lib-etcd
              mountPath: /var/lib/etcd
              readOnly: true
            - name: var-lib-kubelet
              mountPath: /var/lib/kubelet
              readOnly: true
            - name: etc-systemd
              mountPath: /etc/systemd
              readOnly: true
            - name: etc-kubernetes
              mountPath: /etc/kubernetes
              readOnly: true
            - name: usr-bin
              mountPath: /usr/local/mount-from-host/bin
              readOnly: true
      restartPolicy: Never
      volumes:
        - name: var-lib-etcd
          hostPath:
            path: "/var/lib/etcd"
        - name: var-lib-kubelet
          hostPath:
            path: "/var/lib/kubelet"
        - name: etc-systemd
          hostPath:
            path: "/etc/systemd"
        - name: etc-kubernetes
          hostPath:
            path: "/etc/kubernetes"
        - name: usr-bin
          hostPath:
            path: "/usr/bin"

关键配置剖析:

  • hostPID: true: 这是“天眼”的开关。没有它,Pod 里的 `ps` 命令只能看到容器自己的进程,无法检查宿主机上 API Server 的启动参数。这是 Kube-bench 能够工作的基石。
  • nodeSelectortolerations: 这确保了用于扫描 Master 的 Pod 一定会被调度到 Master 节点上。同理,扫描 Worker 节点的 Job 需要选择 Worker 节点。
  • volumeMountsvolumes: 这就是 Kube-bench 的“触手”。它将宿主机的关键目录(如 `/etc/kubernetes`, `/var/lib/kubelet`)以只读方式挂载到容器内部。注意 `readOnly: true`,这是最小权限原则的体现,我们只需要读取信息,绝不应给予写入权限。
  • command: 我们指定了扫描对象 `master`,以及对应的 CIS Benchmark 版本 `1.23`。输出为 `–json` 格式,这对于后续的自动化解析和告警至关重要。纯文本日志是给运维人员看的,JSON 才是给机器读的。

2. 解读扫描报告

当 Job 运行结束后,你可以通过 `kubectl logs` 查看 Pod 的输出。一份 JSON 格式的报告片段可能如下所示:


{
  "id": "1.1",
  "version": "1.23",
  "text": "Master Node Security Configuration",
  "tests": [
    {
      "section": "1.1.1",
      "desc": "Ensure that the --anonymous-auth argument is set to false (Automated)",
      "results": [
        {
          "test_number": "1.1.1",
          "test_desc": "Ensure that the --anonymous-auth argument is set to false (Automated)",
          "status": "FAIL",
          "actual_value": "missing",
          "expected_result": "The --anonymous-auth argument should be set to false."
        }
      ]
    }
  ]
}

这份报告清晰地告诉你:检查项 `1.1.1`(禁止匿名认证)失败了(`”status”: “FAIL”`),因为在 API Server 的启动参数中,`–anonymous-auth` 这个参数根本就没设置 (`”actual_value”: “missing”`)。这提供了直接的、可操作的修复线索。

3. 定制化扫描:不是所有规则都适用

在真实世界中,生搬硬套 CIS Benchmark 往往会出问题。比如,你的集群可能使用了特定的 CNI 插件,导致某些网络相关的检查项天然就不适用。或者,出于业务兼容性考虑,你不得不临时接受某个较低风险的配置。此时,就需要定制化扫描。

Kube-bench 支持通过配置文件来覆盖默认行为。例如,创建一个 `config.yaml`:


---
CHECKS:
  - id: 1.1.1
    controls:
    - id: 1.1.1
      skip: "Business requirement for legacy monitoring"
  - id: 4.2.6
    controls:
    - id: 4.2.6
      skip: "Using Cilium CNI, which manages this differently"

然后通过 `ConfigMap` 将这个文件挂载到 Kube-bench Pod 中,并在启动命令中通过 `–config` 参数指定它。这使得合规性检查从一个僵化的“一刀切”过程,变为了一个可灵活管理的、适应企业自身情况的动态过程。

对抗层:性能、安全与可用性的权衡

实施 Kube-bench 和 CIS 基准加固,绝非一个纯粹的技术任务,它充满了各种权衡(Trade-off)。作为架构师,你必须清晰地认识到这些。

  • 安全性 vs. 可用性: 这是最经典的冲突。例如,CIS 建议严格限制 Pod 对宿主机端口的访问。但如果你部署的监控 Agent(如 Node Exporter)就需要绑定宿主机的特定端口,那么完全遵循该建议将导致监控系统瘫痪。此时的决策不是“yes/no”,而是风险评估:这个 Agent 是否可信?其暴露的端口是否有认证?我们能否通过网络策略将其访问限制在可信的监控服务器IP范围内?
  • 扫描频率 vs. 系统开销: Kube-bench 本身的资源消耗不大,但频繁地(比如每分钟)在所有节点上运行 `DaemonSet` 形式的扫描,依然会产生不必要的 CPU 和 I/O 抖动。通常,每日或每周一次的例行扫描,结合在基础设施变更(如通过 Terraform/Ansible 变更了 Kubelet 配置)后触发一次性扫描,是比较均衡的策略。即“定期巡检 + 变更触发”。
  • 自动化修复 vs. 人工介入: 看到 `FAIL` 就自动修改配置文件并重启组件听起来很酷,但也是极其危险的。错误的自动修复可能导致整个集群雪崩。一个成熟的策略是“自动化告警,半自动化修复”。例如,扫描发现问题后,自动在Jira或工单系统中创建一个带有详细修复建议的 Ticket,由工程师确认后再执行。对于权限设置这类无服务中断风险的修复,可以考虑完全自动化。
  • lí>原生工具 vs. 商业平台: Kube-bench 是一个优秀的开源“引擎”,但它不提供历史趋势分析、多集群统一视图、RBAC权限管理等企业级功能。当集群规模和团队规模扩大时,就需要考虑基于 Kube-bench 这类引擎的商业安全平台。这里的权衡是成本与效率:投入人力自建上层管理平台,还是直接采购商业方案?这取决于公司的技术实力、预算和安全需求的紧迫性。

架构演进与落地路径

在企业中落地基于 Kube-bench 的安全合规体系,不应该是一蹴而就的“大爆炸”式变革,而应遵循一个分阶段、逐步演进的路径。

  1. 第一阶段:基线评估与意识建立 (Baseline Assessment & Awareness)

    在所有集群中手动运行一次 Kube-bench。不要怕,第一次的报告通常会是满江红。这个阶段的目标不是修复所有问题,而是建立一个安全基线,并让所有相关团队(开发、运维、安全)对当前集群的安全状况有一个量化的、残酷的认知。这份报告是后续争取资源、推动改进最有力的武器。

  2. 第二阶段:优先修复与策略定制 (Prioritization & Customization)

    与安全团队一起,对所有 `FAIL` 的项目进行风险评级。优先处理那些高风险、易于修复的问题,例如关闭匿名认证、保护 etcd 数据、加固 API Server 权限等。对于暂时无法修复或不适用的检查项,使用 Kube-bench 的定制化配置功能将其明确地标记为 `skip`,并记录下原因和风险接受说明。目标是让报告的“噪音”降下来,只保留真正需要关注的问题。

  3. 第三阶段:自动化与持续监控 (Automation & Continuous Monitoring)

    将 Kube-bench 封装为 `CronJob`,实现每日或每周的定期扫描。将 JSON 输出结果推送到日志聚合系统(如 ELK/Loki)或监控系统(如 Prometheus)。配置告警规则,当失败项的数量增加,或某个高危项由 `PASS` 变为 `FAIL` 时,立即发送告警。此时,安全合规性已经从一个项目,转变为一个持续运营的指标。

  4. 第四阶段:左移与流程集成 (Shift-Left & CI/CD Integration)

    安全的最高境界是“内生安全”。将 Kube-bench 的检查集成到你的基础设施即代码(IaC)的 CI/CD 流水线中。例如,当有工程师提交一个修改 Kubelet 配置的 Terraform 模块时,CI 流水线在一个临时搭建的测试环境中应用该变更,然后运行 Kube-bench 进行扫描。只有当扫描通过时,该变更才被允许合并到主干。这从源头上阻止了不安全的配置流入生产环境,实现了真正的“安全左移”。

  5. 第五阶段:生态扩展与纵深防御 (Ecosystem Expansion & Defense in Depth)

    Kube-bench 主要关注静态配置。一个完整的安全体系还需要其他工具的配合。在稳固了配置安全基线后,应逐步引入容器镜像扫描(如 Trivy、Clair)、运行时安全检测(如 Falco、Sysdig)、网络策略管理(如 Cilium、Calico)等工具,构建一个覆盖从开发、部署到运行全生命周期的纵深防御体系。Kube-bench 在其中扮演的,是那个最坚实、最底层的安全基石。

总而言之,Kube-bench 不仅仅是一个工具,它是一种方法论的工程实现。通过它,我们可以将抽象的安全标准,转化为可执行的代码、可度量的指标和可自动化的流程,最终在复杂动态的 Kubernetes 环境中,构建起一套持续演进的、具备自我修复能力的“免疫系统”。

延伸阅读与相关资源

  • 想系统性规划股票、期货、外汇或数字币等多资产的交易系统建设,可以参考我们的
    交易系统整体解决方案
  • 如果你正在评估撮合引擎、风控系统、清结算、账户体系等模块的落地方式,可以浏览
    产品与服务
    中关于交易系统搭建与定制开发的介绍。
  • 需要针对现有架构做评估、重构或从零规划,可以通过
    联系我们
    和架构顾问沟通细节,获取定制化的技术方案建议。
滚动至顶部