ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Kube-Bench 实战:Kubernetes 安全基线检查与合规审计指南

2026/9/11 9:43:53 拓冰建站 浏览量
Kube-Bench 实战:Kubernetes 安全基线检查与合规审计指南 Kubernetes 集群跑起来之后安全这块迟早要面对。尤其是做容器化落地的团队经常会收到安全部门或者甲方来的清单要求提供集群的安全基线情况。这时候 Kube-Bench 就是绕不开的一个工具。它是一个基于 CIS Kubernetes Benchmark 的自动化检查工具用来帮你快速评估集群的配置是否符合行业公认的安全基线标准。这篇文章我会结合自己的实际使用经验把 Kube-Bench 从原理、部署、运行到结果解读、问题排查完整讲一遍。内容主要面向正在使用 Kubernetes、需要做安全合规但还没系统了解过 Kube-Bench 的运维、开发和架构同学。无论你是刚接触安全审计还是已经跑过一轮 Kube-Bench 但对排查整改还拿不准这篇文章都值得看一下。1. 项目整体思路拆解为什么安全审计要先抓基线1.1 基线检查在 Kubernetes 安全体系里的位置很多团队对 Kubernetes 安全的第一反应是装一个服务网格、上 RBAC、配网络策略这些当然都重要但都属于“建设侧”的事情。安全审计里还有一个“检查侧”的工作——你需要知道当前集群到底有多少配置是不合规的这就是基线检查要做的事。Kube-Bench 这类工具存在的核心价值是把一套业界公认的、经过大量实践验证的安全配置标准变成可以自动执行的检查脚本。它对照 CIS Kubernetes Benchmark 的几百条检查项逐个检测你的集群组件配置、文件权限、API Server 参数、etcd 设置、kubelet 行为等是否符合推荐值。我见过不少团队在接到安全整改任务后第一反应是到处翻文档、看配置折腾半天也没有一个全局视角。而跑一遍 Kube-Bench 只需要几分钟输出结果会告诉你哪一项没过、风险是什么、应该怎么改这样一个审计闭环才有办法真正落地。1.2 Kube-Bench 的设计逻辑和检查范围Kube-Bench 本身是一个 Go 语言写的二进制程序由 Aqua Security 开源目前是 CNCF 项目的一部分。它的工作逻辑很简单加载一套 YAML 格式的检查定义文件里面描述了每个检查项对应的组件、配置路径、期望值和判定方式然后对当前节点执行检查最后输出 PASS / FAIL / WARN / INFO 的结果。从检查范围来看Kube-Bench 覆盖了主节点和工作节点的核心组件包括控制平面组件、etcd、CNI 插件配置、kubelet、kubectl 文件权限等。它支持多种 Kubernetes 版本不同版本对应不同的 CIS Benchmark 版本所以在正式使用前搞清楚版本对应关系非常重要这点我会在后面的章节详细展开。我自己用下来最大的感受是Kube-Bench 不只是一个检查工具它更像是一份“可以执行的体检清单”。有了它你不需要把 CIS 文档从头到尾背下来也能知道集群的薄弱点在哪里。2. 核心细节解析部署方式和检查项的关键环节2.1 Kube-Bench 的三种部署方式对比Kube-Bench 官方支持多种运行方式包括直接下载二进制运行、通过容器运行、通过 Kubernetes Job 运行。我在这三种方式上都实际用过这里直接说结论。二进制方式适合一次性、临时的检查或者在没有 Kubernetes 集群的环境中做静态评估。容器方式适合在主节点上快速执行不用关心二进制依赖。而 Kubernetes Job 方式是我个人最推荐的因为它能以 Kubernetes 原生的方式管理检查任务检查结束后可以通过 Pod 日志获取结果也方便留存记录。运行方式优点缺点适用场景直接运行二进制独立性强、依赖少需要手动管理版本和配置临时检查、无法访问集群时Docker run环境隔离好、随时清理需要 Docker 环境、权限映射要小心主节点快速检查Kubernetes Job原生集成、输出易管理创建 Job 时需要注意权限和节点选择定期巡检、审计留痕2.2 以二进制方式运行 Kube-Bench 的完整步骤二进制方式的优势在于快一条命令就能跑完。但这里有三个特别容易踩坑的地方我一个个说。第一个坑是版本选择。Kube-Bench 的检查规则是按 Kubernetes 版本分目录存放的比如cfg/1.24/、cfg/1.28/这种结构。如果你拿默认配置去检查一个 1.30 的集群会出现大量误报因为默认配置可能还停留在旧版本。所以运行之前一定要确认集群版本和 Kube-Bench 版本是否匹配。第二个坑是容器内运行时的挂载路径。如果你用docker run的方式需要把宿主机的很多路径挂载进容器比如/etc/kubernetes、/var/lib/etcd、/var/lib/kubelet、/etc/systemd等。漏挂任何一个目录对应检查项就会因为没有权限读取配置而显示 WARN 而不是 PASS排查起来很容易被误导。第三个坑是 etcd 检查经常出现假 FAIL。如果 etcd 是以静态 Pod 方式管理的静态 Pod 的定义文件路径通常是/etc/kubernetes/manifests/etcd.yamlKube-Bench 会尝试解析这个文件里的启动参数。但有时候 etcd 的证书路径、数据目录并没有显式写在启动参数里而是通过环境变量注入的这就会导致 Kube-Bench 判 FAIL。注意运行 kube-bench 一定要用 root 权限因为它需要读取/etc/kubernetes下的敏感文件以及 kubelet 的配置文件。用普通用户跑的话一大半检查项会因为权限不足而出现 WARN。2.3 以 Kubernetes Job 方式运行 Kube-Bench以 Job 方式运行核心思路是把 Kube-Bench 封装成一个容器任务调度到指定节点上执行检查。这样做的好处是集群管理员可以在任意一台有 kubectl 权限的机器上提交检查不需要 SSH 到每台节点。这里给出一个比较稳妥的 Job 定义保留了关键配置apiVersion: batch/v1 kind: Job metadata: name: kube-bench-master namespace: kube-system spec: template: spec: hostPID: true nodeSelector: node-role.kubernetes.io/control-plane: tolerations: - key: node-role.kubernetes.io/control-plane operator: Exists effect: NoSchedule containers: - name: kube-bench image: aquasec/kube-bench:latest command: [kube-bench] args: [run, --targetsmaster, --scoredtrue, --verbose] volumeMounts: - name: etc-kubernetes mountPath: /etc/kubernetes readOnly: true - 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: lib-systemd mountPath: /lib/systemd readOnly: true - name: usr-bin mountPath: /usr/local/mount-from-host/bin readOnly: true - name: etc-cni-netd mountPath: /etc/cni/net.d readOnly: true securityContext: privileged: true restartPolicy: Never hostNetwork: true volumes: - name: etc-kubernetes hostPath: path: /etc/kubernetes - 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: lib-systemd hostPath: path: /lib/systemd - name: usr-bin hostPath: path: /usr/bin - name: etc-cni-netd hostPath: path: /etc/cni/net.d注意几个关键点hostPID: true是为了让容器能查看宿主机进程特权模式是必需的否则无法读取部分挂载文件nodeSelector指定控制平面节点。实际使用中我发现工作节点和控制平面节点最好分开跑因为两者的检查项范围不一样。提交完 Job 之后查看黑日志命令是kubectl -n kube-system logs job/kube-bench-master日志输出会直接显示各个检查项的结果和本地运行的效果完全一致。3. 实操过程与核心环节实现从结果解读到整改闭环3.1 理解检查结果的四种状态Kube-Bench 的输出结果分为 PASS、FAIL、WARN、INFO 四种。我刚接触的时候以为只要关注 FAIL 就行后来发现这种想法容易漏掉重要信息。PASS 表示检查项通过了FAIL 表示检查项未通过是重点整改对象WARN 表示检查项无法确认通常是因为权限不足、文件缺失或者检查依赖的项目不在当前环境INFO 表示这个检查项只是信息展示不参与合规评分。我建议拿到报告后先把 FAIL 项全部列出来然后逐条查看 WARN 的原因。很多 WARN 并不是真的没问题而是因为 Kube-Bench 无法读取到配置本质上还是存在风险。3.2 实战解读几个高频 FAIL 项的整改思路这里我挑几个实际运行中最常出现的 FAIL 项结合我的处理经验讲一下。第一个是检查项1.2.6要求 API Server 的--authorization-mode不能包含AlwaysAllow。很多集群用的部署工具默认就是RBAC所以这项目前很少见。但有些内部自建集群为了省事直接用了AlwaysAllow这种情况必须改。修改方式是在 kube-apiserver 的启动参数里改成--authorization-modeRBAC改完后 API Server 会自动滚动重启。第二个是1.4.1要求 kubelet 启用 RBAC 授权。这个在配置 kubelet 时容易漏掉常见表现是 kubelet 配置文件里没有authorization段。整改时需要在 kubelet 配置文件中添加authorization: mode: Webhook然后重启 kubelet。这里要注意改完 kubelet 配置后原先依赖匿名访问的组件可能会受影响比如部分监控组件或者旧版本的 dashboard需要同步调整 RBAC。第三个是4.2.6要求 kubelet 的--protect-kernel-defaults参数设置为 true。这个参数的作用是让 kubelet 在启动时检查宿主机内核参数是否符合安全要求。很多部署工具默认没有开启因为一旦开启后某些内核参数不满足会导致 kubelet 拒绝启动。建议在整改前先确认所有节点内核参数满足要求再开启这个选项。从我的经验看这些高频 FAIL 项往往不是技术难点而是部署阶段遗留的配置问题。整改的时候最忌讳的是只改一个检查项、重启完就完事一定要想清楚这个参数改了之后会不会影响其他组件。3.3 定制检查范围只跑需要的章节或检查项Kube-Bench 支持用参数控制检查范围这在排查问题时非常方便。比如你只改了 API Server 的配置想确认这部分是否通过不需要重新跑全部检查可以指定章节kube-bench run --check1.2这个命令只检查控制平面中编号为 1.2 的章节输出结果更清晰也不会被其他不相关的 WARN 干扰。如果只想看某个具体检查项比如1.2.6kube-bench run --check1.2.6如果希望输出内容中包含具体的整改建议可以加--verbose参数kube-bench run --check1.2 --verbose实际用下来结合--check和--verbose在整改阶段效率特别高。改一个配置跑一个小范围的检查立刻就能看到结果不需要等完整报告跑完。3.4 输出结果的保存与后续使用Kube-Bench 输出默认是直接打印到终端同时也支持 JSON、YAML、JUnit 等格式。做审计留痕的时候建议输出 JSON 格式方便后续汇总到监控系统或者生成报告。kube-bench run --json kube-bench-result.jsonJUnit 格式适合接入 CI/CD 或者 Jenkins 之类的平台可以在流水线里直接展示检查结果。我之前帮一个团队做容器安全平台接入时就是通过解析 JSON 输出把 FAIL 项自动推送到了工单系统实现了安全检查和问题跟踪的联动。4. 常见问题与排查技巧实录4.1 版本不匹配导致的批量误报这个问题出现的频率最高。Kube-Bench 的检查规则是按 Kubernetes 版本区分的如果你用的是默认配置检查新版本集群会出现大量 FAIL 或 WARN而这些项其实在目标版本里根本不存在或者规则已变化。排查方法很简单先确认集群版本再检查 Kube-Bench 版本对应的配置目录。运行kubectl version --short kube-bench version如果版本相差太大建议用官方容器镜像它会根据集群版本自动选择合适的配置。如果你用的是自定义编译的 Kube-Bench务必同步更新配置目录。4.2 容器运行环境下 WARN 泛滥的问题在容器里运行 Kube-Bench常见的现象是几十个检查项全是 WARN几乎看不到 PASS 和 FAIL。这大概率是挂载目录不全导致的。Kube-Bench 容器默认以非 root 用户运行如果挂载了宿主机目录但权限不够就会表现为 WARN。我的经验是先在宿主机上看一下目录属主然后用--as-root参数运行docker run --rm -v /etc/kubernetes:/etc/kubernetes -v /var/lib/kubelet:/var/lib/kubelet aquasec/kube-bench:latest run --targetsmaster --as-root如果你是用 Kubernetes Job 跑的这类问题往往表现为 Job 一直 Running 但不结束因为容器卡在权限检查或者读文件失败上。这时候先看 Event 和日志再确认挂载是否正常。4.3 自建集群和托管集群的差异用过托管集群的同学应该深有体会比如在 EKS 或者 AKS 上跑 Kube-Bench控制平面的部分检查项你根本没法操作因为你没有节点访问权限。这种情况下 Kube-Bench 只能检查工作节点的部分控制平面部分会直接报 WARN 或者无法读取。这不是 Kube-Bench 的问题而是托管集群的安全责任边界决定的。对于托管集群我建议重点关注工作节点和 kubelet 层面的检查项控制平面部分直接参考云厂商提供的合规白皮书。4.4 常见问题速查表现象可能原因排查思路大量项显示 WARN权限不足或挂载目录不全确认 root 权限检查挂载目录完整检查结果与集群版本不匹配Kube-Bench 配置版本过旧更新配置目录或使用最新容器镜像Job 一直不结束容器无法读取宿主机配置查看 Pod 事件确认挂载是否正常FAIL 项修改后仍然 FAIL修改的配置文件没有被实际加载确认组件重启成功检查参数是否生效etcd 检查项全部 FAIL静态 Pod 参数通过环境变量注入手动检查 etcd 启动参数忽略误报5. 从检查到治理让 Kube-Bench 接入日常运维5.1 定时巡检与告警Kube-Bench 一次检查只能反映当前时刻的状态而集群配置是会变的。今天整改完的项过两周一个新组件部署可能又把配置改回去了。所以安全基线检查一定要做成定时任务。用 Kubernetes CronJob 包装 Kube-Bench 是最自然的做法。调度周期可以根据团队实际情况来定一般建议至少一周一次。如果集群变更比较频繁可以缩短到每三天一次。CronJob 跑完之后检查结果记录在 Pod 日志里同时通过脚本把 FAIL 数量推送到监控平台。我自己实践过用 Prometheus 的 PushGateway 接收 Kube-Bench 的 JSON 输出解析出 FAIL、WARN 数量后生成指标在 Grafana 里展示趋势图。这样安全状态的演进就变得非常直观整改了一个漏洞对应曲线就降下来了。提示定时巡检最关键的不是你有没有跑而是你有没有对结果做出响应。建议给 FAIL 项设置一个阈值超过阈值就告警到应急响应群要不然巡检结果没人看等于白搭。5.2 上线检查与变更流程结合除了定时巡检Kube-Bench 还有一个很有价值的场景就是相结合在版本升级或者节点上线流程里。新节点加入集群之前先跑一遍针对工作节点的检查确认基础配置没问题再允许流量接入。这样做的逻辑很简单新节点如果不合规未来排查问题时又多了一个变量。与其等到出了问题再回查不如在入口处就卡一道。有一个注意点新节点刚初始化完马上跑 Kube-Bench部分检查项可能会因为服务还没完全启动而显示 WARN最好等节点 Ready 之后再执行检查。5.3 Kube-Bench 的配置自定义虽然 Kube-Bench 自带了一套比较完整的检查规则但实际使用中你会发现有些检查项并不适用于你的环境。比如有些内部集群对 etcd 有单独的配置管理方式Kube-Bench 默认的检查逻辑会有大量误报这时候可以对配置做定制。Kube-Bench 的配置目录结构是cfg/{version}/每个版本目录下有独立的 YAML 文件定义检查项。你可以复制一份配置修改其中的检查项逻辑然后用--config参数指定自定义配置路径。kube-bench run --config /path/to/my-config.yaml需要注意的是自定义配置意味着你需要自己维护一套规则文件未来 Kube-Bench 升级时需要做同步。如果不是特殊情况建议尽量使用官方默认配置通过结果解析层面做过滤而不是直接修改检查规则。5.4 安全基线的延伸和策略引擎联动Kube-Bench 定位是基线检查工具它检查的是“集群组件配置”是否合规而不是“部署到集群里的工作负载”是否合规。如果想把安全能力延伸到应用层就需要和 OPA Gatekeeper、Kyverno 这类策略引擎配合使用。举个例子Kube-Bench 能告诉你 kubelet 的匿名访问是否关闭但不能阻止开发人员部署一个带特权模式的 Pod。后者需要策略引擎在准入控制阶段拦截。Kube-Bench 解决的是基础设施层面的问题策略引擎解决的是工作负载层面的问题两者是互补关系不能互相替代。我在实际项目里一般这样配合Kube-Bench 负责定期确认集群“地基”是否稳固策略引擎负责运行时强制约束。把这两层结合起来安全合规的覆盖面才完整。最后分享几个实操细节做 Kube-Bench 审计这段时间我自己总结了几条经验算是用时间换来的教训。第一拿到 FAIL 项不要急着改先判断是不是误报。尤其是 etcd 相关项和 kubelet 相关项错误率不低。确认是真实问题后再进行整改。第二每次整改完只跑对应的检查章节就行不要每次都全量检查。用--check1.2这种参数效率明显更高输出也更容易对比。第三检查报告一定要留档。不仅是给安全部门或者客户看更重要的是你自己团队的积累。把报告按日期归档后面做趋势分析、衡量安全投入效果都有依据。第四如果集群规模比较大建议在每一类节点上各抽一台代表节点做检查没必要每台都跑。因为基线检查看的是配置模板同一类节点大概率使用的是同一个部署模板配置是基本一致的。当然如果你团队管理混乱节点配置经常有人手动乱改那每台都跑一下会更安心。Kube-Bench 这个工具本身不复杂真正考验人的是对检查结果的理解和整改节奏的把控。希望这篇文章能帮你少走一些弯路把安全基线检查这个事真正落地。