kubernetes 审计与日志 详解

本文介绍了如何在Kubernetes中配置APIServer的审计日志,包括日志内容、阶段、资源访问控制和示例政策。通过`audit-policy`,可以定制哪些操作被记录,以及如何收集、呈现和管理审计日志,如使用filebeat、ELK堆栈或webhook技术。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

开头语

写在前面:如有问题,以你为准,

目前24年应届生,各位大佬轻喷,部分资料与图片来自网络

内容较长,页面右上角目录方便跳转

基本

介绍

在Kubernetes集群中,API Server的审计日志记录了哪些用户、哪些服务请求操作集群资源,并且可以编写不同规则 控制忽略、存储的操作日志。

审计日志采用SON格式输出,每条日志都包含丰富的元数据,例如请求的URL、HTTP方法、客户端来源等,你可以使 用监控服务来分析API流量,以检测趋势或河能存在的安全隐患。

这些可能服务会访问API Server:

  1. 管理节点(controller--manager、.scheduler)
  2. 工作节点(kubelet、.kube-proxy)
  3. 集群服务(CoreDNS、Calico、HPA等)
  4. kubectl、.APl、Dashboard

事件 阶段

yaml 解析

https://kubernetes.io/zh-cn/docs/tasks/debug/debug-cluster/audit/

audit-policy

修改配置后是需要删除apiserver容器,等待自动pod自动进行创建

apiVersion: audit.k8s.io/v1 # 这是必填项。

kind: Policy

# 不要在 RequestReceived 阶段为任何请求生成审计事件。

omitStages:

  - "RequestReceived"

rules:

  # 在日志中用 RequestResponse 级别记录 Pod 变化。

  - level: RequestResponse

    resources:

    - group: ""

      # 资源 "pods" 不匹配对任何 Pod 子资源的请求,

      # 这与 RBAC 策略一致。

      resources: ["pods"]

  # 在日志中按 Metadata 级别记录 "pods/log"、"pods/status" 请求

  - level: Metadata

    resources:

    - group: ""

      resources: ["pods/log", "pods/status"]



  # 不要在日志中记录对名为 "controller-leader" 的 configmap 的请求。

  - level: None

    resources:

    - group: ""

      resources: ["configmaps"]

      resourceNames: ["controller-leader"]



  # 不要在日志中记录由 "system:kube-proxy" 发出的对端点或服务的监测请求。

  - level: None

    users: ["system:kube-proxy"]

    verbs: ["watch"]

    resources:

    - group: "" # core API 组

      resources: ["endpoints", "services"]



  # 不要在日志中记录对某些非资源 URL 路径的已认证请求。

  - level: None

    userGroups: ["system:authenticated"]

    nonResourceURLs:

    - "/api*" # 通配符匹配。

    - "/version"



  # 在日志中记录 kube-system 中 configmap 变更的请求消息体。

  - level: Request

    resources:

    - group: "" # core API 组

      resources: ["configmaps"]

    # 这个规则仅适用于 "kube-system" 名字空间中的资源。

    # 空字符串 "" 可用于选择非名字空间作用域的资源。

    namespaces: ["kube-system"]



  # 在日志中用 Metadata 级别记录所有其他名字空间中的 configmap 和 secret 变更。

  - level: Metadata

    resources:

    - group: "" # core API 组

      resources: ["secrets", "configmaps"]



  # 在日志中以 Request 级别记录所有其他 core 和 extensions 组中的资源操作。

  - level: Request

    resources:

    - group: "" # core API 组

    - group: "extensions" # 不应包括在内的组版本。



  # 一个抓取所有的规则,将在日志中以 Metadata 级别记录所有其他请求。

  - level: Metadata

    # 符合此规则的 watch 等长时间运行的请求将不会

    # 在 RequestReceived 阶段生成审计事件。

    omitStages:

      - "RequestReceived"

示例

除了命名空间 pod 资源相关操作,其他都不记录

apiVersion: audit.k8s.io/v1

kind: Policy

rules:

- level: Metadata

  # namespaces: ["default"] # 执行命名空间

  verbs: ["create","delete"] # 指定相关操作

  resources: # 执行资源

  - group: ""

    resources: ["pods"]

    # resourceNames: ["controller-leader"] 指定资源名

- level: None

[root@master audit]# ps -ef | grep apiserver

root      831053  831034  0 10:27 ?      

root     2791437 2791419 71 21:09 ?        00:00:08 kube-apiserver --advertise-address=

[root@master audit]# kill -9 2791437

[root@master audit]# kubectl get pod -A

[root@master ~]# kubectl delete  pod web1666

pod "web1666" deleted

[root@master audit]# tail -f /var/log/audit/k8s_audit.log

{

  "kind": "Event",

  "apiVersion": "audit.k8s.io/v1",

  "level": "Metadata",

  "auditID": "c52213b1-0bd6-4790-80ae-7c5aeb159ab9",

  "stage": "ResponseComplete",

  "requestURI": "/api/v1/namespaces/default/pods/web1666",

  "verb": "delete",

  "user": {

    "username": "system:node:node1",

    "groups": [

      "system:nodes",

      "system:authenticated"

    ]

  },

  "sourceIPs": [

    "192.168.100.51"

  ],

  "userAgent": "kubelet/v1.28.1 (linux/amd64) kubernetes/8dc49c4",

  "objectRef": {

    "resource": "pods",

    "namespace": "default",

    "name": "web1666",

    "apiVersion": "v1"

  },

  "responseStatus": {

    "metadata": {},

    "code": 200

  },

  "requestReceivedTimestamp": "2023-11-21T02:11:53.435596Z",

  "stageTimestamp": "2023-11-21T02:11:53.444542Z",

  "annotations": {

    "authorization.k8s.io/decision": "allow",

    "authorization.k8s.io/reason": ""

  }

}

审计日志

开启

审计日志支持写入本地文件和Vebhook (发送到外部HTTP API) 两种方式。

启用审计日志功能:

vi /etc/kubernetes/manifests/kube-apiserver.yaml

---audit-policy-file=/etc/kubernetes/audit/audit-policy.yaml

--audit-log-path=/var/log/audit/k8s_audit.log

---audit-log-maxage=30

---audit-log-maxbackup=10

---audit-log-maxsize=100

注:使用hostpath数据卷将宿主机/etc/kubernetes/,audit目录挂载到容器中

mkdir /etc/kubernetes/audit

touch /var/log/audit/k8s_audit.log

 apiserver.yaml 需要修改内容

      volumeMounts:

      - mountPath: /etc/kubernetes/audit

      name: audit

      readOnly: true

    - mountPath: /var/log/audit/k8s_audit.log

      name: audit-log-file



  volumes:           

  - hostPath:

      path: /etc/kubernetes/audit

      type: DirectoryOrCreate

    name: audit

  - hostPath:

      path: /var/log/audit/k8s_audit.log

      type: File

    name: audit-log-file

解析

yum -y install jq

日志内容

[root@master kubernetes]# tail -1 /var/log/audit/k8s_audit.log  | jq

{

  "kind": "Event",

  "apiVersion": "audit.k8s.io/v1",

  "level": "Metadata",

  "auditID": "95279099-833a-4a79-b942-9cd5da761cc6",

  "stage": "ResponseComplete", # 在那个阶段处理

  "requestURI": "/healthz",

  "verb": "get",

  "user": {

    "username": "system:serviceaccount:calico-system:calico-kube-controllers",

    "uid": "47d3e62f-edcf-4938-b988-ae0b14e40666",

    "groups": [

      "system:serviceaccounts",

      "system:serviceaccounts:calico-system",

      "system:authenticated"

    ],

    "extra": {

      "authentication.kubernetes.io/pod-name": [

        "calico-kube-controllers-6b7b9c649d-xllqh"

      ],

      "authentication.kubernetes.io/pod-uid": [

        "fbf6ee10-fd48-4e64-bd03-31995dedbe6a"

      ]

    }

  },

  "sourceIPs": [

    "10.244.219.105"

  ],

  "userAgent": "kube-controllers/v0.0.0 (linux/amd64) kubernetes/$Format",

  "responseStatus": {

    "metadata": {},

    "code": 200

  },

  "requestReceivedTimestamp": "2023-11-20T09:06:54.725743Z",

  "stageTimestamp": "2023-11-20T09:06:54.727333Z",

  "annotations": {

    "authorization.k8s.io/decision": "allow",

    "authorization.k8s.io/reason": "RBAC: allowed by ClusterRoleBinding \"system:public-info-viewer\" of ClusterRole \"system:public-info-viewer\" to Group \"system:authenticated\""

  }

}

内容解析

  1. 事件基本信息
    1. kind: 表示事件的类型,这里是 "Event"。
    2. apiVersion: 表示 Kubernetes 审计 API 的版本,这里是 "audit.k8s.io/v1"。
    3. level: 表示事件的级别,这里是 "Metadata"。
    4. auditID: 事件的唯一标识符。
    5. stage: 表示事件发生的阶段,这里是 "ResponseComplete",表示 API 请求的响应已经完成。
  2. 请求信息
    1. requestURI: 表示请求的 URI,这里是 "/healthz"。
    2. verb: 表示请求的动作,这里是 "get",表示是一个 GET 请求。
    3. user: 提供有关执行请求的用户的详细信息,包括用户名、UID、用户组等。
    4. sourceIPs: 表示请求的来源 IP 地址。
    5. userAgent: 表示发起请求的用户代理信息,这里是 "kube-controllers/v0.0.0 (linux/amd64) kubernetes/$Format"。
  3. 响应信息
    1. responseStatus: 提供有关响应的信息,包括响应代码和元数据。这里是一个成功的响应,HTTP 状态码为 200。
    2. 时间戳:
    3. requestReceivedTimestamp: 表示请求接收的时间戳。
    4. stageTimestamp: 表示事件阶段的时间戳。
  4. 注释信息
  5. annotations: 提供与事件相关的注释信息,这里包括授权决策的一些详细信息。
  6. authorization.k8s.io/decision: 授权决策,这里是 "allow",表示允许请求。
  7. authorization.k8s.io/reason: 授权决策的原因,这里是 "RBAC: allowed by ClusterRoleBinding...",表示通过 ClusterRoleBinding 的 RBAC 规则允许。

示例

[root@master ~]# docker run -d  --name web1666 nginx:1.17.1

[root@master kubernetes]# cat  /var/log/audit/k8s_audit.log  | grep web1666 | jq

日志收集与呈现方案

审计日志文件 + filebeat

审计日志文件 + ELK

审计webhook + logstash

审计webhook + falco

K8S 日志为什么以 stdout 和 stderr 的方式输出

文件描述符                     作用                                  例子(c语言)

0     (stdin)                 标准输入                           fscanf(stdin,"%s",str);

1     (stdout)               标准输出                           fprintf(stdout,"%s\n","hello");

2      (stderror)              标准错误输出                    fprintf(stderr,"%s\n","error");

1. 简单方便,可以直接使用语言自带的标准库,打印出信息(比如c语言的printf, fprintf函数)作为日志的输入源,不用额外的再建立一个文件。

2. 易管理,可以将容器的标准输出stdout, stderr重定向到log-file.log。 比如将上面的test.c文件编译后,执行  ./a.out >> a.log  2>&1,就会将标准输出存放到a.log里

nginx 导出日志到logs

使用 volumes 中的 emptyDir: {}

yaml 如图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值