【K8S 运维实战】16-事件与审计

事件与审计:K8s 事件流与审计日志

一句话定位:出事了怎么知道"谁在什么时候做了什么"?Event + Audit Log 双通道给你完整的时间线和责任链。

写在前面

有次生产事故让我印象极深:运维同学在半夜清理资源,不小心执行了 kubectl delete namespace production------还好集群有准入控制器拦截。事后我们想看看到底是谁执行的、从哪台机器、用的什么凭据,结果发现审计日志根本没开。

如果那次操作真的执行成功,而我们连"谁干的"都查不出来------这不叫事故,这叫灾难。

K8s 的可观测性有三根支柱:Metrics(指标) 告诉你"出事了",Logs(日志) 告诉你"为什么出事",Events + Audit Logs(事件+审计) 告诉你"什么时候、谁、做了什么"。这篇文章专门讲第三根容易被忽视的支柱。

读完你能带走:

  • K8s Event 机制的原理和使用
  • Audit Log 的配置策略和存储方案
  • 事件导出 + 审计日志采集的完整管道
  • 高危操作告警规则(删除 ns / 修改 rbac / 创建特权 pod)
  • 审计日志分析查询方法

核心问题

出事了怎么知道"谁在什么时候做了什么"?

K8s 里有两套"记录簿"回答这个问题:

  • Event:K8s 自身产生的状态变更通知(如 Pod 调度成功、Liveness Probe 失败)
  • Audit Log:API Server 记录的所有 API 请求(谁、什么时候、调了什么 API、结果如何)

一、原理剖析

1.1 K8s Event 机制

复制代码
K8s Event 生命周期

┌─────────────────────────────────────────────────────────────────┐
│                                                                  │
│  1. 事件触发                                                      │
│     Scheduler 将 Pod 调度到 Node-3                                │
│                    │                                              │
│  2. 控制器/组件创建 Event 对象                                      │
│     scheduler 创建一个 Event:                                     │
│     ┌─────────────────────────────────────────────┐              │
│     │ apiVersion: v1                               │              │
│     │ kind: Event                                  │              │
│     │ metadata:                                    │              │
│     │   namespace: production                      │              │
│     │   name: nginx-7d4f8.17a3f5d8e               │              │
│     │ involvedObject:                              │              │
│     │   kind: Pod                                  │              │
│     │   name: nginx-7d4f8                          │              │
│     │   namespace: production                      │              │
│     │ reason: Scheduled                            │              │
│     │ message: Successfully assigned pod to node-3 │              │
│     │ type: Normal                                 │              │
│     │ source:                                      │              │
│     │   component: default-scheduler               │              │
│     │ firstTimestamp: 2024-07-18T10:00:00Z        │              │
│     │ lastTimestamp: 2024-07-18T10:00:00Z         │              │
│     │ count: 1                                     │              │
│     └─────────────────────────────────────────────┘              │
│                    │                                              │
│  3. 存储到 etcd                                                   │
│     Event 作为 API 资源存储,但不支持 CRUD(只能 Create/Get/List)   │
│                    │                                              │
│  4. 默认保留 1 小时                                               │
│     etcd 中 Event 默认 TTL = 1h(由 kube-apiserver 控制)          │
│     过期后自动清理                                                 │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Event 的关键字段:

字段 含义 示例值
type 事件类型 Normal / Warning
reason 事件原因(机器可读) Scheduled, Failed, Unhealthy
message 事件描述(人类可读) Liveness probe failed: ...
source.component 产生事件的组件 kubelet, default-scheduler
involvedObject 事件关联的资源 Pod / Node / Deployment
firstTimestamp 首次发生时间 2024-07-18T10:00:00Z
lastTimestamp 最后发生时间 2024-07-18T10:05:00Z
count 发生次数 12

一个关键认知:Event 是瞬时的、有 TTL 的。Pod 被删除后,其 Event 也会很快过期消失。因此必须将 Event 导出到外部存储。

1.2 Audit Log 机制

复制代码
K8s Audit Log 请求处理流程

  kubectl delete pod nginx-7d4f8
         │
         ▼
  ┌──────────────────────┐
  │   API Server         │
  │                      │
  │  1. 认证(AuthN)       │ → 提取用户信息
  │     ├─ 证书           │     → username: admin
  │     ├─ Token          │     → groups: system:masters
  │     └─ OIDC           │     → userAgent: kubectl/v1.28
  │                      │
  │  2. 鉴权(AuthZ)       │ → 检查权限
  │     └─ RBAC 检查      │     → "admin 有 delete pods 权限? YES"
  │                      │
  │  3. 准入控制          │ → Webhook 校验
  │     └─ ValidatingWebhook │ → "允许删除?" 
  │                      │
  │  4. 审计日志记录       │ ★ 在这里记录!               │
  │     ┌────────────────┐│
  │     │ 审计事件:       ││
  │     │  level: Request ││
  │     │  stage: Response││     ┌──────────────────────┐ │
  │     │  verb: delete   ││────▶│ 审计日志后端:         │ │
  │     │  user: admin    ││     │ - 文件(/var/log/     │ │
  │     │  sourceIP: ...  ││     │   audit.log)         │ │
  │     │  objectRef:     ││     │ - Webhook            │ │
  │     │   resource: pods││     │ - 日志文件            │ │
  │     │   namespace:    ││     └──────────────────────┘ │
  │     │     production  ││                              │
  │     │  responseStatus:││                              │
  │     │     code: 200   ││                              │
  │     └────────────────┘│                              │
  └──────────────────────┘

审计策略的四个级别(Profile Level):

复制代码
审计级别对比:

┌────────────────┬──────────────────────┬──────────────────────┐
│  Level         │  记录内容              │  适用场景            │
├────────────────┼──────────────────────┼──────────────────────┤
│ None           │ 不记录                │  关闭审计(不推荐)   │
├────────────────┼──────────────────────┼──────────────────────┤
│ Metadata       │ 请求元数据             │  生产环境默认级别     │
│                │ (用户/时间/资源/状态码)  │  审计全量 API 调用    │
├────────────────┼──────────────────────┼──────────────────────┤
│ Request        │ 元数据 + 请求体         │  排查配置变更问题     │
│                │                        │  安全分析             │
├────────────────┼──────────────────────┼──────────────────────┤
│ RequestResponse│ 元数据 + 请求体 + 响应体 │  完整取证             │
│                │                        │  注意:可能包含 Secret  │
│                │                        │  数据量大 10-100x      │
└────────────────┴──────────────────────┴──────────────────────┘

1.3 Event 和 Audit Log 的分工

复制代码
                    Event                    Audit Log
                   ──────                    ─────────
记录什么?      K8s 内部状态变更通知        API Server 接收的所有请求
谁产生?        控制器/Scheduler/Kubelet    API Server
记录粒度?      高(具体"发生了什么")       中("谁调了什么 API")
典型内容?     "Liveness probe failed"    "admin deleted pod X"
持久化?        默认 1 小时 TTL             根据配置(文件/Webhook/Log)
用途?          排查 Pod/Node 异常          安全审计 + 变更追踪
                     │                              │
                     └──────────┬───────────────────┘
                                │
                     ┌──────────▼──────────┐
                     │   组合使用            │
                     │  Event = "发生了"     │
                     │  Audit = "谁做的"     │
                     │  两者结合 = 完整故事   │
                     └─────────────────────┘

二、实战操作

2.1 部署 kubernetes-event-exporter

bash 复制代码
kubectl create namespace monitoring

# 安装 event-exporter
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update

event-exporter-values.yaml

yaml 复制代码
# ============================================
# kubernetes-event-exporter 配置
# ============================================

replicaCount: 1

image:
  repository: bitnami/kubernetes-event-exporter
  tag: 1.7.0

config:
  logLevel: info
  logFormat: json
  metricsNamePrefix: ""

  receivers:
    # 接收器1: 文件输出
    - name: "dump"
      file:
        path: "/data/events.json"
        # 文件轮转
        maxBytes: 104857600   # 100MB
        maxBackups: 10

    # 接收器2: Loki(日志系统)
    - name: "loki"
      loki:
        url: "http://loki.loki.svc.cluster.local:3100/loki/api/v1/push"
        tenantID: "events"
        labels:
          cluster: "prod-k8s-1"
        batchSize: 1048576
        batchWait: 5s

    # 接收器3: Elasticsearch(可选)
    # - name: "elasticsearch"
    #   elasticsearch:
    #     hosts:
    #       - "http://elasticsearch-master.logging:9200"
    #     index: "k8s-events"
    #     indexFormat: "k8s-events-{2006-01-02}"

    # 接收器4: Webhook(关键事件推送)
    - name: "webhook"
      webhook:
        endpoint: "http://alert-webhook.monitoring.svc/events"
        headers:
          X-Event-Source: "k8s-event-exporter"
        layout:
          text: |
            [{{ .Type | ToUpper }}] {{ .Reason }}: {{ .Message }}
            Object: {{ .InvolvedObject.Kind }}/{{ .InvolvedObject.Name }}
            Namespace: {{ .InvolvedObject.Namespace }}
            Time: {{ .LastTimestamp }}

  # ── 路由规则(控制哪些 Event 发到哪些接收器) ──
  route:
    routes:
      # 规则1: 所有 Warning 事件 → Loki + Webhook
      - match:
          - type: Warning
        receiver: "dump"
        drop:
          - type: Normal

      # 规则2: 高危 Warning → Webhook 立即告警
      - match:
          - type: Warning
            reason: "(Failed|BackOff|Unhealthy|FailedScheduling|FailedMount|OOMKilling|NodeNotReady)"
            regexp: true
        receiver: "webhook"

      # 规则3: 特定资源的事件 → 额外关注
      - match:
          - involvedObject:
              kind: "(Node|PersistentVolume)"
              regexp: true
        receiver: "dump"

rbac:
  create: true

serviceAccount:
  create: true
  name: event-exporter

# 持久化事件文件
persistence:
  enabled: true
  size: 20Gi
  storageClass: ssd-sc

resources:
  requests:
    cpu: 100m
    memory: 128Mi
  limits:
    cpu: 500m
    memory: 512Mi
bash 复制代码
helm upgrade --install event-exporter bitnami/kubernetes-event-exporter \
  --namespace monitoring \
  --values event-exporter-values.yaml \
  --wait

2.2 配置审计策略

审计策略通过 --audit-policy-file 参数传给 kube-apiserver。

audit-policy.yaml (生产级审计策略):

yaml 复制代码
# ============================================
# K8s 审计策略 - 生产级配置
# 版本基线: K8s 1.30
# ============================================

apiVersion: audit.k8s.io/v1
kind: Policy

# 默认:不记录任何审计事件(显式规则才记录)
rules:

  # ──────────────────────────────────────────
  # Level: None(不记录)
  # ──────────────────────────────────────────
  # 排除系统组件的健康检查和状态轮询(噪音太大)
  - level: None
    users: ["system:kube-proxy", "system:kube-scheduler"]
    verbs: ["watch"]
    resources:
      - group: ""
        resources: ["endpoints", "services", "services/status"]

  - level: None
    users: ["system:apiserver", "system:kube-controller-manager"]
    verbs: ["get", "list", "watch"]
    resources:
      - group: ""
        resources: ["endpoints", "configmaps"]

  - level: None
    userGroups: ["system:nodes"]
    verbs: ["get", "list", "watch"]
    resources:
      - group: ""
        resources: ["nodes", "nodes/status", "pods", "pods/status"]

  - level: None
    nonResourceURLs:
      - "/healthz*"
      - "/readyz*"
      - "/livez*"
      - "/version"
      - "/metrics"

  # ──────────────────────────────────────────
  # Level: Metadata(默认审计级别)
  # ──────────────────────────────────────────
  # 大部分请求只记录元数据(用户、时间、操作、资源、状态码)
  - level: Metadata
    omitStages:
      - RequestReceived   # 不记录收到的原始请求时间,减少噪音

  # ──────────────────────────────────────────
  # Level: Request(关键操作记录请求体)
  # ──────────────────────────────────────────
  # 高危 Namespace 操作
  - level: Request
    verbs: ["create", "update", "patch", "delete"]
    resources:
      - group: ""
        resources: ["namespaces"]
    omitStages:
      - RequestReceived

  # 安全敏感操作
  - level: Request
    verbs: ["create", "update", "patch", "delete"]
    resources:
      - group: "rbac.authorization.k8s.io"
        resources: ["clusterroles", "clusterrolebindings",
                     "roles", "rolebindings"]
    omitStages:
      - RequestReceived

  # Secret/ConfigMap 操作
  - level: Request
    verbs: ["create", "update", "patch", "delete"]
    resources:
      - group: ""
        resources: ["secrets", "configmaps"]
    omitStages:
      - RequestReceived

  # NetworkPolicy 变更
  - level: Request
    verbs: ["create", "update", "patch", "delete"]
    resources:
      - group: "networking.k8s.io"
        resources: ["networkpolicies"]
    omitStages:
      - RequestReceived

  # PodSecurityPolicy / ValidatingWebhook 变更
  - level: Request
    verbs: ["create", "update", "patch", "delete"]
    resources:
      - group: "admissionregistration.k8s.io"
        resources: ["validatingwebhookconfigurations",
                     "mutatingwebhookconfigurations"]
    omitStages:
      - RequestReceived

  # Pod Exec / Attach / PortForward(安全审计重点)
  - level: RequestResponse
    verbs: ["create"]
    resources:
      - group: ""
        resources: ["pods/exec", "pods/attach", "pods/portforward"]
    omitStages:
      - RequestReceived

  # ──────────────────────────────────────────
  # Level: RequestResponse(完整记录)
  # ──────────────────────────────────────────
  # ServiceAccount Token 创建
  - level: RequestResponse
    verbs: ["create"]
    resources:
      - group: ""
        resources: ["serviceaccounts/token"]
    omitStages:
      - RequestReceived

  # 特权 Pod 创建(完整审计)
  - level: RequestResponse
    verbs: ["create", "update"]
    resources:
      - group: ""
        resources: ["pods"]
    namespaces: ["kube-system", "production"]
    omitStages:
      - RequestReceived

2.3 Kube-apiserver 审计配置

在 kubeadm 部署的集群中,编辑 kube-apiserver 的 manifest:

yaml 复制代码
# /etc/kubernetes/manifests/kube-apiserver.yaml
spec:
  containers:
    - name: kube-apiserver
      command:
        - kube-apiserver
        # 审计策略文件
        - --audit-policy-file=/etc/kubernetes/audit/audit-policy.yaml
        # 审计日志文件(主)
        - --audit-log-path=/var/log/kubernetes/audit.log
        - --audit-log-maxage=30       # 保留 30 天
        - --audit-log-maxbackup=10    # 最多 10 个备份文件
        - --audit-log-maxsize=100     # 每个文件最大 100MB
        - --audit-log-format=json     # JSON 格式
        # Webhook 后端(实时推送)
        - --audit-webhook-config-file=/etc/kubernetes/audit/webhook-config.yaml
        - --audit-webhook-mode=batch  # batch 模式减少 API 调用
        - --audit-webhook-batch-max-size=400
        - --audit-webhook-batch-max-wait=30s
      volumeMounts:
        - name: audit-policy
          mountPath: /etc/kubernetes/audit
          readOnly: true
        - name: audit-log
          mountPath: /var/log/kubernetes
  volumes:
    - name: audit-policy
      hostPath:
        path: /etc/kubernetes/audit
        type: DirectoryOrCreate
    - name: audit-log
      hostPath:
        path: /var/log/kubernetes
        type: DirectoryOrCreate

Webhook 配置(推送到 Loki 或 SIEM)

yaml 复制代码
# /etc/kubernetes/audit/webhook-config.yaml
apiVersion: v1
kind: Config
clusters:
  - name: audit-sink
    cluster:
      server: http://audit-sink.monitoring.svc:8080/audit
contexts:
  - context:
      cluster: audit-sink
      user: ""
    name: default-context
current-context: default-context

2.4 部署 Audit Sink(接收 Webhook 并导入 Loki)

yaml 复制代码
# audit-sink-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: audit-sink
  namespace: monitoring
spec:
  replicas: 2
  selector:
    matchLabels:
      app: audit-sink
  template:
    metadata:
      labels:
        app: audit-sink
    spec:
      containers:
        - name: audit-sink
          image: nginx:alpine
          ports:
            - containerPort: 8080
          volumeMounts:
            - name: audit-log
              mountPath: /var/log/audit
          # 生产环境使用专门的审计接收服务,
          # 如 fluentd / vector / logstash 导入 Loki
      volumes:
        - name: audit-log
          emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
  name: audit-sink
  namespace: monitoring
spec:
  selector:
    app: audit-sink
  ports:
    - port: 8080
      targetPort: 8080

2.5 高危操作告警规则

yaml 复制代码
# audit-alerts.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: audit-alert-rules
  namespace: monitoring
  labels:
    role: alert-rules
data:
  audit-alerts.yaml: |
    groups:
      - name: audit-security-alerts
        rules:
          # ── P0 告警 ──
          - alert: NamespaceDeleted
            expr: |
              count(
                count_over_time(
                  {app="audit-sink"} 
                  | json 
                  | verb="delete" 
                  | objectRef_resource="namespaces"
                  [5m]
                )
              ) > 0
            for: 1m
            labels:
              severity: P0
            annotations:
              summary: "Namespace 被删除"
              description: "检查审计日志确认操作人和原因"

          - alert: ClusterRoleCreated
            expr: |
              count(
                count_over_time(
                  {app="audit-sink"}
                  | json
                  | verb="create"
                  | objectRef_resource="clusterroles"
                  [5m]
                )
              ) > 0
            for: 1m
            labels:
              severity: P0
            annotations:
              summary: "新的 ClusterRole 被创建"
              description: "检查是否是预期操作"

          # ── P1 告警 ──
          - alert: PrivilegedPodCreated
            expr: |
              count(
                count_over_time(
                  {app="audit-sink"}
                  | json
                  | verb="create"
                  | objectRef_resource="pods"
                  | responseStatus_code="201"
                  [10m]
                )
              ) > 0
            for: 1m
            labels:
              severity: P1
            annotations:
              summary: "检测到特权 Pod 创建"
              description: "验证该 Pod 的 securityContext 配置"

          - alert: SecretAccessedByNonSystem
            expr: |
              count(
                count_over_time(
                  {app="audit-sink"}
                  | json
                  | objectRef_resource="secrets"
                  | user!~"system:.*"
                  | verb=~"get|list|watch"
                  [10m]
                )
              ) > 10
            for: 5m
            labels:
              severity: P1
            annotations:
              summary: "非系统用户大量读取 Secret"

          - alert: RBACBindingModified
            expr: |
              count(
                count_over_time(
                  {app="audit-sink"}
                  | json
                  | objectRef_resource=~"clusterrolebindings|rolebindings"
                  | verb=~"create|update|delete"
                  [5m]
                )
              ) > 0
            for: 1m
            labels:
              severity: P1
            annotations:
              summary: "RBAC 绑定被修改"

          - alert: PodExecDetected
            expr: |
              count(
                count_over_time(
                  {app="audit-sink"}
                  | json
                  | objectRef_subresource="exec"
                  | verb="create"
                  [5m]
                )
              ) > 0
            for: 1m
            labels:
              severity: P1
            annotations:
              summary: "检测到 kubectl exec 操作"
              description: "用户 {{ $labels.user }} 在 {{ $labels.objectRef_namespace }}/{{ $labels.objectRef_name }} 上执行了 exec"

          # ── P2 告警 ──
          - alert: AuditLogVolumeDropped
            expr: |
              rate({app="audit-sink"} [10m]) < 0.1
            for: 30m
            labels:
              severity: P2
            annotations:
              summary: "审计日志接收量异常下降"
              description: "审计采集管道可能中断"

三、踩坑与排查

3.1 坑一:审计日志把磁盘打满

现象 :Master 节点 / 分区使用率 100%,kube-apiserver 无法写入,集群不可控。

原因 :审计策略配置了 RequestResponse 级别但没有限制大小,大 Deploy 的 YAML 全写进审计日志。一个包含 500 行 YAML 的 kubectl apply 能产生 50KB+ 的审计日志。

排查

bash 复制代码
# 1. 检查审计日志文件大小
ls -lh /var/log/kubernetes/audit.log*
du -sh /var/log/kubernetes/

# 2. 分析日志增长速率
tail -f /var/log/kubernetes/audit.log | pv -l > /dev/null

# 3. 找到日志量最大的操作
cat /var/log/kubernetes/audit.log | jq -r '.objectRef.resource' | sort | uniq -c | sort -rn | head -10

解决方案

bash 复制代码
# 1. 立即清理过期日志文件(K8s 1.30 的自动轮转需要确认)
find /var/log/kubernetes/ -name "audit.log.*" -mtime +7 -delete

# 2. 缩小日志上限
# audit-log-maxsize: 50    # 从 100MB 降到 50MB
# audit-log-maxbackup: 5   # 从 10 降到 5

# 3. 审计策略中增加排除规则
# 排除 Deployment/StatefulSet 的更新(请求体太大)
- level: Metadata
  verbs: ["update", "patch"]
  resources:
    - group: "apps"
      resources: ["deployments", "statefulsets", "daemonsets"]

3.2 坑二:Event 丢失

现象 :Pod 创建失败后,kubectl describe pod 显示的 Event 只有最近几条,看不到最早的和关键的 Warning。

原因

  • Event 默认 TTL 只有 1 小时,过期被 etcd 清理
  • 同一 Event 的压缩(count 累加),旧时间戳被覆盖

解决方案

bash 复制代码
# 1. 调整 Event TTL(大集群建议 4h+)
# kube-apiserver 参数:
# --event-ttl=4h

# 2. 确认 event-exporter 正常工作
kubectl logs -n monitoring deployment/event-exporter | tail -20

# 3. 检查 Loki 中的 Event 是否完整
# 查询最近 24 小时的 Warning Event
curl -G 'http://loki.loki:3100/loki/api/v1/query_range' \
  --data-urlencode 'query={app="event-exporter", type="Warning"}' \
  --data-urlencode 'start='$(date -d '24 hours ago' +%s)'000000000' \
  --data-urlencode 'end='$(date +%s)'000000000' \
  --data-urlencode 'limit=100' | jq

3.3 坑三:审计日志噪音太大,查不到关键事件

现象 :一天审计日志 200GB,99% 是 kubelet/node 的心跳和 watches。用 grep | jq 分析慢到无法接受。

原因:审计策略默认级别设得太高,或没有排除高频低价值操作。

排查和优化

bash 复制代码
# 1. 统计各类型操作的分布
cat audit.log | jq -r '.verb + " " + .objectRef.resource' | sort | uniq -c | sort -rn | head -20

# 典型的高噪音操作:
#  3000000 watch pods         ← 系统的 Watch 连接,全无价值
#  1500000 get nodes/status   ← kubelet 心跳
#   500000 list endpoints     ← kube-proxy 定期同步

# 2. 优化审计策略,排除这些操作

优化后的审计策略规则:

yaml 复制代码
# 在 Policy 最前面加入排除规则:
rules:
  # 排除高频无价值操作
  - level: None
    users: ["system:kube-proxy", "system:kube-scheduler",
            "system:apiserver"]
    verbs: ["watch", "get", "list"]
    resources:
      - group: ""
        resources: ["endpoints", "services", "services/status"]
  - level: None
    userGroups: ["system:nodes"]
    verbs: ["watch", "get"]
    resources:
      - group: ""
        resources: ["nodes/status", "pods/status"]

四、最佳实践

Event 管理清单

  • 必做:部署 kubernetes-event-exporter,将 Event 导出到 Loki/ES
  • 必做:Warning 级别 Event 实时告警(通过 Webhook/Loki Ruler)
  • 推荐 :Event TTL 调整为 4-8 小时(通过 --event-ttl
  • 推荐 :根据 reason 字段过滤关注的事件类型(BackOff, FailedMount 等)
  • 可选:历史 Event 保留 30 天用于趋势分析

审计策略清单

  • 默认级别用 Metadata ------ 记录所有 API 调用的元数据,成本低、覆盖全
  • 关键操作升级到 Request ------ 删除 ns、修改 RBAC、访问 Secret → 记录请求体
  • 高危操作用 RequestResponse ------ Pod Exec、ServiceAccount Token 创建 → 完整记录
  • 系统组件操作降级到 None ------ kubelet 心跳、kube-proxy sync、scheduler watch → 不记录
  • 审计日志持久化 ------ 文件 + Webhook 双写,文件定期归档到对象存储
  • 敏感数据脱敏 ------ RequestResponse 级别注意 Secret/Token 等敏感字段可能出现在审计日志中

审计日志分析工具链

bash 复制代码
# 1. 查找某个用户的所有操作
cat audit.log | jq 'select(.user.username == "admin")'

# 2. 查找某个时间段的错误请求
cat audit.log | jq 'select(.responseStatus.code >= 400)'

# 3. 查找对特定资源的操作
cat audit.log | jq 'select(.objectRef.resource == "secrets" and .verb == "get")'

# 4. 按用户统计操作类型(Top 操作者)
cat audit.log | jq -r '.user.username' | sort | uniq -c | sort -rn | head -10

# 5. 查找失败的 kubectl exec 操作
cat audit.log | jq 'select(.objectRef.subresource == "exec" and .responseStatus.code >= 400)'

# 6. 查找非预期来源 IP 的请求
cat audit.log | jq 'select(.sourceIPs[] | startswith("10.0.") | not)'

# 7. 生产级: 用 Loki 的 LogQL 分析审计日志(需将审计日志导入 Loki)
# 查找最近 24 小时内所有 delete 操作
{app="audit-sink"} | json | verb="delete" | line_format "{{.user_username}} deleted {{.objectRef_resource}}/{{.objectRef_name}} in {{.objectRef_namespace}}"

五、小结

这三样东西的关系很好记:

复制代码
Metrics: 身体检查报告(血压、心率、体温) → 出问题了
Logs:    病历(头疼、发烧、咳嗽) → 为什么出问题
Events + Audit: 监控录像(谁进来的、碰了什么) → 谁干的、什么时候干的

如果你只配了 Prometheus 和 Loki,还缺最后一块拼图。花半天时间把 Event 导出和审计日志配好,出事故时就不会手忙脚乱地问"到底是谁干的"。

一句话总结: Event 告诉你 Pod 发生了什么,Audit Log 告诉你谁对集群做了什么,两者结合就是完整的"时间线+责任链"。


思考题

  1. Audit Policy 的 omitStages 可以排除 RequestReceived 阶段。排除和不排除有什么实际影响?什么时候应该保留?
  2. 如果你的 K8s 集群是云厂商托管(如 EKS/ACK/GKE),审计日志的采集和自建集群有什么不同?云厂商通常提供什么方案?
  3. Event 和 Audit Log 之间有没有关联关系?比如,如何从一个 Audit 事件("张三创建了 Pod Y")找到对应的 K8s Event("Pod Y 调度成功")?

延伸阅读

相关推荐
我头发多我先学1 小时前
linux系统编程:初识进程
linux·运维·服务器
云飞云共享云桌面1 小时前
SolidWorks—天津智能装备工厂1台高配主机共享给10个研发用
运维·服务器·自动化·汽车·制造
回眸不遇1 小时前
将 Docker虚拟磁盘文件ext.vhdx迁移出C盘 ,更换到D盘
c语言·docker·容器
苍狗T2 小时前
LVS相关知识总结
linux·运维·服务器·lvs
雨辰AI2 小时前
K8s人大金仓主从高可用搭建|容器化集群自动同步+故障切换(生产完整版)
云原生·容器·kubernetes
各类产品分享3 小时前
什么是AR智慧运维系统,主要能解决什么问题
运维·ar·ar智慧运维解决方案
RisunJan3 小时前
Linux命令-skill(发送信号给进程)
linux·运维·服务器
潘正翔3 小时前
k8s基础_kubeadm搭建k8s集群
linux·运维·docker·云原生·容器·kubernetes
Echo flower3 小时前
Docker 容器中 Puppeteer 僵尸进程排查与修复
运维·docker·容器·puppeteer
骊城英雄3 小时前
彩笔运维勇闯机器学习--逻辑回归
运维·机器学习·逻辑回归