很多集群在安全建设时都会开启审计日志,但真正遇到问题时才发现,要么日志里信息不全,要么海量日志根本无从下手。Kubernetes 审计日志的价值不在于“记录了”,而在于能否从记录中快速定位到“谁在什么时间对什么资源做了什么”,并把异常行为转化成告警。这篇文章从审计策略配置讲起,结合日志解析与告警接入,帮你把原始审计日志变成可用的调查线索。
审计日志到底在记录什么
Kubernetes 审计日志由 kube-apiserver 生成,记录了所有对 API 服务器的请求。每一个审计事件都包含四个核心问题的答案:谁发起的请求(用户、服务账号或匿名)、执行了什么操作(get、create、patch、delete)、发生在什么时间(纳秒级时间戳)、针对什么资源(Pod、Secret、ConfigMap 等)。
理解审计日志的作用范围很重要。它覆盖的是所有经过 API 服务器的请求,包括 kubectl 命令、控制器管理器、调度器、kubelet 以及通过 ServiceAccount 运行的业务组件。但如果你需要追踪 etcd 层面的直接访问,审计日志并不覆盖——etcd 的访问需要依赖 etcd 自身的日志和 TLS 客户端证书审计。这也是很多人在排查时容易混淆的地方:审计日志追踪的是“谁通过 API 服务器做了什么”,而不是“谁直接连上了 etcd”。
配置审计策略:从最小可用到精确覆盖
审计策略是一个 YAML 文件,通过 kube-apiserver 的 --audit-policy-file 参数加载。策略的核心是规则列表,每条规则定义了匹配的资源范围和记录级别。
最基础的策略可以记录所有请求的 Metadata 级别:
apiVersion: audit.k8s.io/v1
kind: Policy
omitStages:
- "RequestReceived"
rules:
- level: Metadata这个策略足以回答“谁在什么时候对什么资源做了什么”,但不会记录请求体(requestObject)和响应体(responseObject)。对于安全调查来说,这往往不够——比如你想知道一次 Secret 读取请求具体返回了什么内容,Metadata 级别就无能为力了。
实际部署时,建议按资源敏感度分级配置。参考官方文档推荐的策略结构,可以这样组织:
apiVersion: audit.k8s.io/v1
kind: Policy
omitStages:
- "RequestReceived"
rules:
# 对 Secret 和 ConfigMap 的读写记录完整请求和响应
- level: RequestResponse
resources:
- group: ""
resources: ["secrets", "configmaps"]
# 对 RBAC 配置的变更记录完整请求
- level: RequestResponse
resources:
- group: "rbac.authorization.k8s.io"
resources: ["roles", "rolebindings", "clusterroles", "clusterrolebindings"]
# 对 Pod 的 exec、attach、portforward 等子资源记录完整请求
- level: RequestResponse
resources:
- group: ""
resources: ["pods/exec", "pods/attach", "pods/portforward"]
# 所有写入操作记录 Request 级别
- level: Request
verbs: ["create", "update", "patch", "delete"]
# 默认记录 Metadata
- level: Metadata这里有个关键配置值得单独说明:omitStages。审计事件有多个阶段,其中 RequestReceived 阶段发生在鉴权之前,包含的信息与 ResponseComplete 阶段基本重复,但日志量会翻倍。官方文档和社区实践都建议在策略顶层全局省略该阶段,而不是在每条规则中重复设置。
配置完成后,需要在 kube-apiserver 启动参数中启用审计日志后端。常用的后端是日志文件,通过 --audit-log-path 指定路径,--audit-log-maxsize 和 --audit-log-maxbackup 控制轮转。如果是托管集群(如 GKE、EKS),控制面的审计日志通常由云平台直接导出,你只需要配置策略即可。

解析审计日志:从 JSON 到调查线索
审计日志默认以 JSON 格式逐行输出。每条记录的关键字段包括:
user.username/user.groups:发起请求的身份信息verb:操作类型objectRef.resource/objectRef.namespace/objectRef.name:目标资源requestReceivedTimestamp/stageTimestamp:时间信息requestObject/responseObject:请求和响应体(取决于记录级别)responseStatus.code:HTTP 状态码sourceIPs:来源 IP
用 jq 可以快速提取关键信息。比如排查 RBAC 权限变更:
cat /var/log/kubernetes/audit.log |
jq -r 'select(.objectRef.apiGroup == "rbac.authorization.k8s.io" and (.verb == "create" or .verb == "update" or .verb == "patch" or .verb == "delete")) | [.requestReceivedTimestamp, .user.username, .verb, .objectRef.resource, .objectRef.name] | @tsv'排查 Secret 访问:
cat /var/log/kubernetes/audit.log |
jq -r 'select(.objectRef.resource == "secrets") | [.requestReceivedTimestamp, .user.username, .verb, .objectRef.namespace, .objectRef.name, .responseStatus.code] | @tsv'解析日志时有一个容易忽略的点:requestObject 字段只在 Request 及以上级别才会出现,responseObject 只在 RequestResponse 级别出现。如果你发现日志里没有请求体,先检查策略级别是否配置正确。
构建告警规则:从日志到通知
日志本身不会主动告诉你“出事了”,需要把解析后的数据接入告警系统。常见的路径有两种:通过 Fluent Bit 或 Logstash 将审计日志采集到 Elasticsearch/Loki,再用 SIEM 或告警规则引擎做检测;或者通过 Webhook 后端直接对接告警平台。
无论采用哪种管道,告警规则的核心是识别异常模式。以下几类事件优先级最高:
匿名访问。如果集群禁用了匿名认证(--anonymous-auth=false),但日志中出现 user.username: "system:anonymous",说明有请求绕过了认证,必须立即告警。
RBAC 权限变更。对 ClusterRoleBinding 或 RoleBinding 的 create、update、patch、delete 操作是最典型的权限提升路径。攻击者入侵后通常会通过修改绑定关系给自己授予高权限。这类告警需要关联 requestObject 字段,查看被授予权限的主体是谁。
Secret 批量读取。单个 Secret 读取可能是正常业务,但短时间内大量读取不同 Secret,或者由非预期身份读取,就需要关注。可以设置阈值规则:同一用户在一分钟内读取超过 N 个 Secret 触发告警。
对敏感资源的 exec 操作。pods/exec 的调用意味着有人在 Pod 内执行命令,如果发生在生产环境且不是预期的调试行为,需要立即调查。
大量 403/401 响应。连续失败的鉴权请求可能意味着攻击者在尝试未授权操作,也可能是凭证泄露后的探测行为。
配置告警时要注意误报控制。比如 RBAC 变更告警,合法的集群初始化或权限回收操作也会触发。建议先以“通知”级别运行一段时间,积累基线数据后再调整阈值和抑制规则。

验证审计配置是否生效
配置完成后不能直接不管,需要验证策略确实在按预期工作。验证分两步:
第一步,确认审计日志在产生。创建一个测试事件,比如读取一个 Secret:
kubectl get secret my-secret -n default然后检查审计日志中是否出现了对应记录,且级别符合预期:
tail -n 50 /var/log/kubernetes/audit.log | jq 'select(.objectRef.resource == "secrets" and .objectRef.name == "my-secret")'确认 level 字段是 RequestResponse,requestObject 和 responseObject 都存在。
第二步,验证告警链路。手动构造一个应该触发告警的行为,比如创建一个 ClusterRoleBinding(测试完记得删除),确认告警通知到达。这一步要特别注意,不要在非测试环境执行可能影响集群状态的操作。
常见误报与排查思路
告警配置上线后,误报是不可避免的。几个高频误报场景值得提前了解:
系统组件引发的“正常”操作。kube-controller-manager、kube-scheduler 等服务账号会频繁读写资源,它们的操作也会进入审计日志。如果告警规则没有排除系统组件,会产生大量噪音。建议在规则中过滤 user.username 以 system: 开头的账号,除非你有理由怀疑控制面组件被攻陷。
控制器对 Secret 的频繁读取。很多控制器(如 ingress-controller)会持续读取 Secret 来更新证书。如果告警规则只按“读取次数”设阈值,很容易误报。需要结合读取方身份和资源名称做白名单。
kubectl 调试操作。开发人员在排查问题时执行 kubectl exec 是很常见的。如果团队没有统一的调试流程,exec 告警会频繁触发。建议在告警规则中区分环境(生产 vs 测试),或者要求生产环境的 exec 必须通过审批流程。
时间同步问题。审计日志的时间戳来自 API 服务器,如果集群节点时间不同步,会导致告警时间线混乱。排查问题时先确认所有节点 NTP 同步正常。
把审计日志纳入日常安全运营
审计日志不是配置完就结束的。要想让它真正发挥作用,需要把它纳入日常的安全运营流程。建议至少做到以下几点:
- 建立审计日志的归档策略,保留周期根据合规要求确定,一般不少于 180 天
- 定期(比如每月)复盘告警规则,根据实际触发情况调整阈值和过滤条件
- 将审计日志与事件响应流程打通,确保告警触发后有明确的调查路径和责任人
- 关注 Kubernetes 官方文档和安全公告,及时更新审计策略以覆盖新的攻击面
审计日志的价值在于它记录了集群中每一次身份验证和授权决策的完整轨迹。当安全事件发生时,这些记录是还原攻击路径、确认影响范围最直接的证据。配置好审计策略、解析好日志格式、建立有效的告警规则,这三步走完,你的集群才算真正具备了可观测的安全能力。
- it2021
- it2021.com
- Kubernetes
- tag
- Webhook
- 安全运营





重庆 重庆 1F
之前只开 Metadata,难怪查不到请求体