Kubernetes 审计提供了一组与安全相关的、按时间排序的记录,用于记录集群中的操作序列。集群会审计由用户、使用 Kubernetes API 的应用程序以及控制平面本身所产生的活动。
审计允许集群管理员回答以下问题:
审计记录的生命周期始于 kube-apiserver 组件。每个请求在其执行的每个阶段都会生成一个审计事件,该事件随后会根据特定的策略进行预处理,并写入后端。策略决定了记录什么内容,后端则负责持久化这些记录。当前的后端实现包括日志文件和 Webhook。
每个请求都可以记录一个相关联的阶段。定义的阶段如下:
RequestReceived - 当审计处理程序接收到请求并将其委派给后续处理程序链之前,生成的事件所属的阶段。ResponseStarted - 在发送响应头之后,但在发送响应体之前。此阶段仅针对长连接请求(例如 watch)生成。ResponseComplete - 响应体已发送完毕,不会再有字节发送。Panic - 发生宕机(panic)时生成的事件。审计日志功能会增加 API 服务器的内存消耗,因为每个请求都需要存储一些审计所需的上下文信息。内存消耗取决于审计日志的配置。
审计策略定义了关于应该记录哪些事件以及它们应该包含哪些数据的规则。审计策略对象的结构在 audit.k8s.io API 组中定义。当处理一个事件时,它会按顺序与规则列表进行比较。第一个匹配的规则决定了事件的审计级别。定义的审计级别如下:
None - 不记录匹配此规则的事件。Metadata - 记录事件的元数据(请求用户、时间戳、资源、动词等),但不记录请求体或响应体。Request - 记录事件的元数据和请求体,但不记录响应体。这不适用于非资源请求。RequestResponse - 记录事件的元数据、请求体和响应体。这不适用于非资源请求。你可以通过 --audit-policy-file 标志将策略文件传递给 kube-apiserver。如果省略此标志,则不会记录任何事件。请注意,审计策略文件中必须提供 rules 字段。没有规则(0 条)的策略被视为非法。
以下是审计策略文件的示例:
apiVersion: audit.k8s.io/v1 # This is required.
kind: Policy
# Don't generate audit events for all requests in RequestReceived stage.
omitStages:
- "RequestReceived"
rules:
# Log pod changes at RequestResponse level
- level: RequestResponse
resources:
- group: ""
# Resource "pods" doesn't match requests to any subresource of pods,
# which is consistent with the RBAC policy.
resources: ["pods"]
# Log "pods/log", "pods/status" at Metadata level
- level: Metadata
resources:
- group: ""
resources: ["pods/log", "pods/status"]
# Don't log requests to a configmap called "controller-leader"
- level: None
resources:
- group: ""
resources: ["configmaps"]
resourceNames: ["controller-leader"]
# Don't log watch requests by the "system:kube-proxy" on endpoints or services
- level: None
users: ["system:kube-proxy"]
verbs: ["watch"]
resources:
- group: "" # core API group
resources: ["endpoints", "services"]
# Don't log authenticated requests to certain non-resource URL paths.
- level: None
userGroups: ["system:authenticated"]
nonResourceURLs:
- "/api*" # Wildcard matching.
- "/version"
# Log the request body of configmap changes in kube-system.
- level: Request
resources:
- group: "" # core API group
resources: ["configmaps"]
# This rule only applies to resources in the "kube-system" namespace.
# The empty string "" can be used to select non-namespaced resources.
namespaces: ["kube-system"]
# Log configmap and secret changes in all other namespaces at the Metadata level.
- level: Metadata
resources:
- group: "" # core API group
resources: ["secrets", "configmaps"]
# Log all other resources in core and extensions at the Request level.
- level: Request
resources:
- group: "" # core API group
- group: "extensions" # Version of group should NOT be included.
# A catch-all rule to log all other requests at the Metadata level.
- level: Metadata
# Long-running requests like watches that fall under this rule will not
# generate an audit event in RequestReceived.
omitStages:
- "RequestReceived"
你可以使用最小化的审计策略文件,在 Metadata 级别记录所有请求:
# Log all requests at the Metadata level.
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
如果你正在构建自己的审计配置,可以使用 Google Container-Optimized OS 的审计配置文件作为起点。你可以查看 configure-helper.sh 脚本,该脚本会生成一个审计策略文件。直接查看该脚本,你可以看到大部分的审计策略文件内容。
你也可以参考 Policy 配置参考了解定义字段的详细信息。
审计后端将审计事件持久化到外部存储中。kube-apiserver 开箱即用提供了两种后端:
在所有情况下,审计事件都遵循 Kubernetes API 在 audit.k8s.io API 组中定义的结构。
对于补丁(patch)请求,请求体是一个包含补丁操作的 JSON 数组,而不是包含对应 Kubernetes API 对象的 JSON 对象。例如,以下请求体是对 /apis/batch/v1/namespaces/some-namespace/jobs/some-job-name 的有效补丁请求:
[
{
"op": "replace",
"path": "/spec/parallelism",
"value": 0
},
{
"op": "remove",
"path": "/spec/template/spec/containers/0/terminationMessagePolicy"
}
]
日志后端以 JSONlines 格式将审计事件写入文件。你可以使用以下 kube-apiserver 标志配置日志审计后端:
--audit-log-path 指定日志后端用于写入审计事件的日志文件路径。未指定此标志将禁用日志后端。- 表示标准输出。--audit-log-maxage 定义保留旧审计日志文件的最大天数。--audit-log-maxbackup 定义要保留的审计日志文件的最大数量。--audit-log-maxsize 定义审计日志文件在轮转前的最大大小(以 MB 为单位)。如果你的集群控制平面将 kube-apiserver 作为 Pod 运行,请记住将 hostPath 挂载到策略文件和日志文件的位置,以便审计记录能够持久化。例如:
- --audit-policy-file=/etc/kubernetes/audit-policy.yaml
- --audit-log-path=/var/log/kubernetes/audit/audit.log
然后挂载卷:
...
volumeMounts:
- mountPath: /etc/kubernetes/audit-policy.yaml
name: audit
readOnly: true
- mountPath: /var/log/kubernetes/audit/
name: audit-log
readOnly: false
最后配置 hostPath:
...
volumes:
- name: audit
hostPath:
path: /etc/kubernetes/audit-policy.yaml
type: File
- name: audit-log
hostPath:
path: /var/log/kubernetes/audit/
type: DirectoryOrCreate
Webhook 审计后端将审计事件发送到远程 Web API,该 API 被假定为 Kubernetes API 的一种形式,包括身份验证机制。你可以使用以下 kube-apiserver 标志配置 Webhook 审计后端:
--audit-webhook-config-file 指定 Webhook 配置文件的路径。Webhook 配置实际上是一种特殊的 kubeconfig。--audit-webhook-initial-backoff 指定第一次请求失败后重试前的等待时间。后续请求将以指数退避的方式进行重试。Webhook 配置文件使用 kubeconfig 格式来指定服务的远程地址以及用于连接该服务的凭据。
log 和 webhook 后端都支持批处理。下面是每个后端特有的可用标志列表。默认情况下,webhook 后端的批处理和限流是启用的,而 log 后端的批处理和限流是禁用的。
--audit-webhook-mode 定义缓冲策略。取值如下之一:batch - 缓冲事件并异步进行批处理。这是 webhook 后端的默认模式。blocking - 在处理每个独立事件时阻塞 API 服务器响应。blocking-strict - 与 blocking 相同,但在 RequestReceived 阶段进行审计日志记录时如果发生故障,整个对 kube-apiserver 的请求将失败。以下标志仅在 batch 模式下使用:
--audit-webhook-batch-buffer-size 定义进行批处理前要缓冲的事件数量。如果传入事件的速率超过了缓冲区,事件将被丢弃。默认值为 10000。--audit-webhook-batch-max-size 定义一个批次中包含的最大事件数。默认值为 400。--audit-webhook-batch-max-wait 定义在强制对队列中的事件进行批处理之前等待的最长时间。默认值为 30 秒。--audit-webhook-batch-throttle-enable 定义是否启用批处理限流。默认启用限流。--audit-webhook-batch-throttle-qps 定义每秒生成的最大平均批次数量。默认值为 10。--audit-webhook-batch-throttle-burst 定义如果之前未充分利用允许的 QPS,则可以同时生成的最大批次数量。默认值为 15。--audit-log-mode 定义缓冲策略。取值如下之一:batch - 缓冲事件并异步进行批处理。不建议为 log 后端使用批处理。blocking - 在处理每个独立事件时阻塞 API 服务器响应。这是 log 后端的默认模式。blocking-strict - 与 blocking 相同,但在 RequestReceived 阶段进行审计日志记录时如果发生故障,整个对 kube-apiserver 的请求将失败。以下标志仅在 batch 模式下使用(批处理对于 log 后端默认是禁用的,且当批处理禁用时,所有与批处理相关的标志都会被忽略):
--audit-log-batch-buffer-size 定义进行批处理前要缓冲的事件数量。如果传入事件的速率超过了缓冲区,事件将被丢弃。--audit-log-batch-max-size 定义一个批次中包含的最大事件数。--audit-log-batch-max-wait 定义在强制对队列中的事件进行批处理之前等待的最长时间。--audit-log-batch-throttle-enable 定义是否启用批处理限流。--audit-log-batch-throttle-qps 定义每秒生成的最大平均批次数量。--audit-log-batch-throttle-burst 定义如果之前未充分利用允许的 QPS,则可以同时生成的最大批次数量。参数应根据 API 服务器的负载进行设置。
例如,如果 kube-apiserver 每秒接收 100 个请求,并且每个请求仅在 ResponseStarted 和 ResponseComplete 阶段被审计,那么你需要考虑每秒生成 ≅200 个审计事件。假设一个批次最多有 100 个事件,你应该将限流级别至少设置为每秒 2 个查询。假设后端最多需要 5 秒才能写入事件,你应该将缓冲区大小设置为足以容纳 5 秒的事件;即:10 个批次,或 1000 个事件。
不过在大多数情况下,默认参数应该足够了,你不需要担心手动设置它们。你可以查看 kube-apiserver 暴露的以下 Prometheus 指标以及日志,以监控审计子系统的状态。
apiserver_audit_event_total 指标包含导出的审计事件总数。apiserver_audit_error_total 指标包含因导出期间出错而丢弃的事件总数。log 和 webhook 后端都支持限制记录的事件大小。例如,以下是 log 后端可用的标志列表:
audit-log-truncate-enabled 是否启用事件和批处理截断。audit-log-truncate-max-batch-size 发送到底层后端的批处理最大字节数。audit-log-truncate-max-event-size 发送到底层后端的审计事件最大字节数。默认情况下,webhook 和 log 中的截断都是禁用的,集群管理员应设置 audit-log-truncate-enabled 或 audit-webhook-truncate-enabled 来启用此功能。
Event 和 Policy 资源类型的信息。