云原生|kubernetes|apiserver审计日志的开启

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: 云原生|kubernetes|apiserver审计日志的开启

前言:

kubernetes集群的apiserver服务的审计日志通常是不开启的,如果是新安装的kubernetes集群的话。

审计日志是kube-apiserver中比较常见的一种加固手段,通过对每一次请求的行为进行审计,从而达到加固集群的目的,同时,审计日志还能够帮助我们troubleshooting,因为每一次请求的内容都会被记录下来,如果请求的内容本身有问题,从而导致api返回5xx的错误,我们可以从审计日志中直接把报错信息抓出来给开发,帮助他们定位问题。

但有一点特别需要注意,如果审计策略是不恰当的,什么都记录的,可能会造成集群的内存资源浪费(审计日志会占用很多内存的)审计日志记录功能会增加 API server 的内存消耗,因为需要为每个请求存储审计所需的某些上下文。 内存消耗取决于审计日志记录的配置。

审计记录最初产生于 kube-apiserver 内部。每个请求在不同执行阶段都会生成审计事件;这些审计事件会根据特定策略 被预处理并写入后端。策略确定要记录的内容和用来存储记录的后端。 当前的后端支持日志文件和 webhook。

一,

如何正确的开启apiserver的审计日志?

首先,我们需要一个审计策略文件,该文件是yaml格式的,此文件内容定义的是要抓取审计哪些内容。

同样的,日志审计功能在官方的文档里有详细的说明:审计 | Kubernetes

什么时候记录?

每个请求都可被记录其相关的阶段(stage)。已定义的阶段有:

  • RequestReceived - 此阶段对应审计处理器接收到请求后,并且在委托给 其余处理器之前生成的事件。
  • ResponseStarted - 在响应消息的头部发送后,响应消息体发送前生成的事件。 只有长时间运行的请求(例如 watch)才会生成这个阶段。
  • ResponseComplete - 当响应消息体完成并且没有更多数据需要传输的时候。
  • Panic - 当 panic 发生时生成。

记录哪些内容?

审计策略定义了关于应记录哪些事件以及应包含哪些数据的规则。 审计策略对象结构定义在 audit.k8s.io API 组 。处理事件时,将按顺序与规则列表进行比较。第一个匹配规则设置事件的 审计级别(Audit Level)。已定义的审计级别有:

  • None - 符合这条规则的日志将不会记录。
  • Metadata - 记录请求的元数据(请求的用户、时间戳、资源、动词等等), 但是不记录请求或者响应的消息体。
  • Request - 记录事件的元数据和请求的消息体,但是不记录响应的消息体。 这不适用于非资源类型的请求。
  • RequestResponse - 记录事件的元数据,请求和响应的消息体。这不适用于非资源类型的请求。

下面是一个比较标准的审计策略定义:

apiVersion: audit.k8s.io/v1beta1 # This is required.
kind: Policy
#不要为RequestReceived阶段中的所有请求生成审核事件。
omitStages:
- "RequestReceived"
rules:
# 以下请求被手动确定为高容量和低风险,因此请取消这些请求。
- level: None
  users: ["system:kube-proxy"]
  verbs: ["watch"]
  resources:
    - group: "" # core
      resources: ["endpoints", "services"]
- level: None
  users: ["system:unsecured"]
  namespaces: ["kube-system"]
  verbs: ["get"]
  resources:
    - group: "" # core
      resources: ["configmaps"]
- level: None
  users: ["kubelet"] # legacy kubelet identity
  verbs: ["get"]
  resources:
    - group: "" # core
      resources: ["nodes"]
- level: None
  userGroups: ["system:nodes"]
  verbs: ["get"]
  resources:
    - group: "" # core
      resources: ["nodes"]
- level: None
  users:
    - system:kube-controller-manager
    - system:kube-scheduler
    - system:serviceaccount:kube-system:endpoint-controller
  verbs: ["get", "update"]
  namespaces: ["kube-system"]
  resources:
    - group: "" # core
      resources: ["endpoints"]
- level: None
  users: ["system:apiserver"]
  verbs: ["get"]
  resources:
    - group: "" # core
      resources: ["namespaces"]
#不要记录这些只读URL。
- level: None
  nonResourceURLs:
    - /healthz*
    - /version
    - /swagger*
#不要记录事件请求。
- level: None
  resources:
    - group: "" # core
      resources: ["events"]
# 机密、配置映射和令牌审查可以包含敏感和二进制数据,
# 因此,只能在元数据级别进行日志记录。
- level: Metadata
  resources:
    - group: "" # core
      resources: ["secrets", "configmaps"]
    - group: authentication.k8s.io
      resources: ["tokenreviews"]
- level: Request
  verbs: ["get", "list", "watch"]
  resources:
    - group: "" # core
    - group: "admissionregistration.k8s.io"
    - group: "apps"
    - group: "authentication.k8s.io"
    - group: "authorization.k8s.io"
    - group: "autoscaling"
    - group: "batch"
    - group: "certificates.k8s.io"
    - group: "extensions"
    - group: "networking.k8s.io"
    - group: "policy"
    - group: "rbac.authorization.k8s.io"
    - group: "settings.k8s.io"
    - group: "storage.k8s.io"
# 已知API的默认级别。
- level: RequestResponse
  resources:
    - group: "" # core
    - group: "admissionregistration.k8s.io"
    - group: "apps"
    - group: "authentication.k8s.io"
    - group: "authorization.k8s.io"
    - group: "autoscaling"
    - group: "batch"
    - group: "certificates.k8s.io"
    - group: "extensions"
    - group: "networking.k8s.io"
    - group: "policy"
    - group: "rbac.authorization.k8s.io"
    - group: "settings.k8s.io"
    - group: "storage.k8s.io"
    - group: "autoscaling.alibabacloud.com"
# 所有其他请求的默认级别。
- level: Metadata

假设这个文件存放路径为:/etc/kubernetes/logpolicy/sample-policy.yaml ,那么现在需要在apiserver的配置文件内启用日志审计功能:

 cat /etc/kubernetes/manifests/kube-apiserver.yaml 
apiVersion: v1
kind: Pod
metadata:
  annotations:
    kubeadm.kubernetes.io/kube-apiserver.advertise-address.endpoint: 192.168.123.11:6443
  creationTimestamp: null
  labels:
    component: kube-apiserver
    tier: control-plane
  name: kube-apiserver
  namespace: kube-system
spec:
  containers:
  - command:
    - kube-apiserver
    - --advertise-address=192.168.123.11
    - --allow-privileged=true
    - --authorization-mode=Node,RBAC
    - --client-ca-file=/etc/kubernetes/pki/ca.crt
    - --enable-admission-plugins=NodeRestriction
    - --audit-policy-file=/etc/kubernetes/logpolicy/sample-policy.yaml #add 这个是绝对路径指定审计策略文件
    - --audit-log-path=/var/log/kubernetes/audit-logs/audit.log#add 这个是绝对路径
    - --audit-log-maxsize=7#add 单位为M,最多7M大小,超出就另生成一个新日志
    - --audit-log-maxbackup=2#add 最多有两个7M的日志文件
    - --enable-bootstrap-token-auth=true
    - --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt
    - --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt
    - --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key
    - --etcd-servers=https://127.0.0.1:2379
    - --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt
    - --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key
    - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
    - --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt
    - --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key
    - --requestheader-allowed-names=front-proxy-client
    - --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt
    - --requestheader-extra-headers-prefix=X-Remote-Extra-
    - --requestheader-group-headers=X-Remote-Group
    - --requestheader-username-headers=X-Remote-User
    - --secure-port=6443
    - --service-account-issuer=https://kubernetes.default.svc.cluster.local
    - --service-account-key-file=/etc/kubernetes/pki/sa.pub
    - --service-account-signing-key-file=/etc/kubernetes/pki/sa.key
    - --service-cluster-ip-range=10.96.0.0/12
    - --tls-cert-file=/etc/kubernetes/pki/apiserver.crt
    - --tls-private-key-file=/etc/kubernetes/pki/apiserver.key
    image: registry.aliyuncs.com/google_containers/kube-apiserver:v1.23.15
    imagePullPolicy: IfNotPresent
    livenessProbe:
      failureThreshold: 8
      httpGet:
        host: 192.168.123.11
        path: /livez
        port: 6443
        scheme: HTTPS
      initialDelaySeconds: 10
      periodSeconds: 10
      timeoutSeconds: 15
    name: kube-apiserver
    readinessProbe:
      failureThreshold: 3
      httpGet:
        host: 192.168.123.11
        path: /readyz
        port: 6443
        scheme: HTTPS
      periodSeconds: 1
      timeoutSeconds: 15
    resources:
      requests:
        cpu: 250m
    startupProbe:
      failureThreshold: 24
      httpGet:
        host: 192.168.123.11
        path: /livez
        port: 6443
        scheme: HTTPS
      initialDelaySeconds: 10
      periodSeconds: 10
      timeoutSeconds: 15
    volumeMounts:
    - mountPath: /etc/ssl/certs
      name: ca-certs
      readOnly: true
    - mountPath: /etc/kubernetes/logpolicy/sample-policy.yaml#add
      name: audit-policy#add
      readOnly: true#add
    - mountPath: /var/log/kubernetes/audit-logs#add
      name: audit-logs#add
      readOnly: false#add 这个不能是true,否则apiserver启动不了
    - mountPath: /etc/pki
      name: etc-pki
      readOnly: true
    - mountPath: /etc/kubernetes/pki
      name: k8s-certs
      readOnly: true
  hostNetwork: true
  priorityClassName: system-node-critical
  securityContext:
    seccompProfile:
      type: RuntimeDefault
  volumes:
  - hostPath:
      path: /etc/ssl/certs
      type: DirectoryOrCreate
    name: ca-certs
  - hostPath:
      path: /etc/pki
      type: DirectoryOrCreate
    name: etc-pki
  - hostPath:
      path: /etc/kubernetes/pki
      type: DirectoryOrCreate
    name: k8s-certs
  - hostPath:#add
      path: /etc/kubernetes/logpolicy/sample-policy.yaml#add
      type: File#add 这个地方必须是这个type
    name: audit-policy#add
  - hostPath:#add
      path: /var/log/kubernetes/audit-logs#add 这个路径不需要手动建立,会自动建立的
      type: DirectoryOrCreate#add 这个地方必须是这个type
    name: audit-logs#add
status: {}

二,

验证审计策略

此命令生成相关日志

kubectl get configmaps -n kube-system

利用jq命令检索,可以发现没有相关日志生成:

cat audit.log |grep configmaps|grep get |jq

为什么没有相关审计日志呢?由于上面的审计策略里有这个:

- level: None
  users: ["system:unsecured"]
  namespaces: ["kube-system"]
  verbs: ["get"]
  resources:
    - group: "" # core
      resources: ["configmaps"]

查询list就可以查到了:

[root@k8s-master audit-logs]# cat audit.log |grep configmaps|grep list |jq
{
  "kind": "Event",
  "apiVersion": "audit.k8s.io/v1",
  "level": "Metadata",
  "auditID": "39290452-13a5-4547-a1f3-8bd214ad88b4",
  "stage": "ResponseComplete",
  "requestURI": "/api/v1/configmaps?limit=500",
  "verb": "list",
  "user": {
    "username": "kubernetes-admin",
    "groups": [
      "system:masters",
      "system:authenticated"
    ]
  },
  "sourceIPs": [
    "192.168.123.11"
  ],
  "userAgent": "kubectl/v1.23.15 (linux/amd64) kubernetes/b84cb8a",
  "objectRef": {
    "resource": "configmaps",
    "apiVersion": "v1"
  },
  "responseStatus": {
    "metadata": {},
    "code": 200
  },
  "requestReceivedTimestamp": "2023-01-08T15:13:38.086276Z",
  "stageTimestamp": "2023-01-08T15:13:38.092581Z",
  "annotations": {
    "authorization.k8s.io/decision": "allow",
    "authorization.k8s.io/reason": ""
  }
}
{
  "kind": "Event",
  "apiVersion": "audit.k8s.io/v1",
  "level": "Metadata",
  "auditID": "ae5f5d3a-9f26-46be-bfa8-f0889a0321c4",
  "stage": "ResponseComplete",
  "requestURI": "/api/v1/namespaces/default/configmaps?limit=500",
  "verb": "list",
  "user": {
    "username": "kubernetes-admin",
    "groups": [
      "system:masters",
      "system:authenticated"
    ]
  },
  "sourceIPs": [
    "192.168.123.11"
  ],
  "userAgent": "kubectl/v1.23.15 (linux/amd64) kubernetes/b84cb8a",
  "objectRef": {
    "resource": "configmaps",
    "namespace": "default",
    "apiVersion": "v1"
  },
  "responseStatus": {
    "metadata": {},
    "code": 200
  },
  "requestReceivedTimestamp": "2023-01-08T15:14:01.133134Z",
  "stageTimestamp": "2023-01-08T15:14:01.137090Z",
  "annotations": {
    "authorization.k8s.io/decision": "allow",
    "authorization.k8s.io/reason": ""
  }
}

三,

审计后端

审计后端实现将审计事件导出到外部存储。Kube-apiserver 默认提供两个后端:

  • Log 后端,将事件写入到文件系统
  • Webhook 后端,将事件发送到外部 HTTP API

很明显,本文是使用的Log后端,仅仅将事件写入文件系统,基于此日志文件,可以将日志推送到filebeat内,构成一个完整的日志系统。

审计策略小结:

1、rule是白名单,配置了规则rule才会被打印 (验证:如果none类型后面还配置了 metadata类型,不会打印日志;如果去掉后面的metadata类型,只保留前面的none类型的,不会打印任何日志;如果metadata类型在none类型的前面,将会打印日志)

例如这样的打印日志:

apiVersion: audit.k8s.io/v1beta1
kind: Policy
rules:
- level: Metadata
  resources:
    - group: "" # core
      resources: ["secrets", "configmaps"]
    - group: authentication.k8s.io
      resources: ["tokenreviews"]
- level: None
- level: None
  userGroups: ["system:kube-controller-manager"]
  nonResourceURLs:
  - "/api*" # 通配符匹配。
  - "/version"
- level: None
  resources:
    - group: "" # core
      resources: ["events"]

把metadata和none位置替换后,将不会打印日志:

apiVersion: audit.k8s.io/v1beta1
kind: Policy
rules:
- level: None
- level: None
  userGroups: ["system:kube-controller-manager"]
  nonResourceURLs:
  - "/api*" # 通配符匹配。
  - "/version"
- level: None
  resources:
    - group: "" # core
      resources: ["events"]
- level: Metadata
  resources:
    - group: "" # core
      resources: ["secrets", "configmaps"]
    - group: authentication.k8s.io
      resources: ["tokenreviews"]

 

2、rule规则中 最前面那个是 结果 select 输出结果,后面的是条件 where 条件 (验证:查看输出结果就知道)
3、每条rule规则中,多个条件是与的关系,任何一次操作同时满足这些条件才能打印指定类型日志
4、rules是数组,越前面优先级越高,一条日志走策略文件,先匹配到哪条就返回指定结果
5、omitStage 可以配置全局的,也可以配置在每条规则下 (验证:略)

 

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
3天前
|
Kubernetes API Docker
跟着iLogtail学习容器运行时与K8s下日志采集方案
iLogtail 作为开源可观测数据采集器,对 Kubernetes 环境下日志采集有着非常好的支持,本文跟随 iLogtail 的脚步,了解容器运行时与 K8s 下日志数据采集原理。
|
14天前
|
Kubernetes Cloud Native 开发者
云原生入门:从Docker到Kubernetes的旅程
【9月更文挑战第16天】 本文将带你进入云原生的世界,从理解Docker容器的基础开始,逐步深入到Kubernetes集群管理。我们将通过简单的代码示例和实际操作,探索这两个关键技术如何协同工作,以实现更高效、灵活的应用程序部署和管理。无论你是云原生新手还是希望深化理解,这篇文章都将为你提供清晰的指导和实用的知识。
51 11
|
6天前
|
Kubernetes 负载均衡 Cloud Native
探索云原生技术:Kubernetes的魔法
【9月更文挑战第24天】 在数字化浪潮中,云原生技术如同现代航海的罗盘,指引着企业航向灵活、高效的未来。本文将深入剖析云原生世界的璀璨明星——Kubernetes,揭秘其如何在容器化的基础上,实现复杂应用的自动化部署、扩展和管理。从概念到实践,我们将一同领略Kubernetes如何简化运维、提高资源利用率,并推动微服务架构的发展。通过实际的代码示例,我们将手把手教你如何在云上构建和运行第一个Kubernetes集群,让理论与实践相结合,开启云原生之旅。
|
12天前
|
Kubernetes Cloud Native Linux
云原生入门:Kubernetes的简易部署与应用
【8月更文挑战第49天】在云原生的世界里,Kubernetes(K8s)是一颗璀璨的星。本文将带你走进K8s的世界,从安装到简单应用,轻松驾驭这个强大的容器编排工具。让我们一起探索云原生的奥秘,解锁新技能!
|
13天前
|
Kubernetes 负载均衡 监控
深入云原生技术:Kubernetes集群部署与管理
【9月更文挑战第17天】在数字化转型的浪潮中,云原生技术以其灵活性和可扩展性成为企业新宠。本文将引导读者探索云原生的核心组件——Kubernetes,通过实际案例分析其部署与管理流程,旨在帮助技术从业者和企业决策者理解如何利用Kubernetes提升应用的可用性和性能。从基础概念到操作实践,我们将一同见证云原生技术的变革力量。
|
24天前
|
Kubernetes 监控 Cloud Native
云原生入门:Kubernetes 集群部署与管理
【8月更文挑战第38天】在数字化浪潮中,云原生技术如同翱翔的雄鹰,引领着企业飞向灵活高效的未来。本文将带你一探究竟,从Kubernetes的基础概念到实际操作,深入浅出地介绍如何在云端构建和管理你的容器化应用。我们将一步步搭建起一个小型的Kubernetes集群,并通过代码示例和图解,让你轻松掌握云原生世界的钥匙。让我们一起开启这趟技术之旅,探索云原生的秘密花园,找到那把打开创新之门的金钥匙。
|
12天前
|
Kubernetes Cloud Native Java
探索未来编程新纪元:Quarkus带你秒建高性能Kubernetes原生Java应用,云原生时代的技术狂欢!
Quarkus 是专为 Kubernetes 设计的全栈云原生 Java 框架,凭借其轻量级、快速启动及高效执行特性,在 Java 社区脱颖而出。通过编译时优化与原生镜像支持,Quarkus 提升了应用性能,同时保持了 Java 的熟悉度与灵活性。本文将指导你从创建项目、编写 REST 控制器到构建与部署 Kubernetes 原生镜像的全过程,让你快速上手 Quarkus,体验高效开发与部署的乐趣。
13 0
|
27天前
|
运维 Kubernetes 监控
Loki+Promtail+Grafana监控K8s日志
综上,Loki+Promtail+Grafana 监控组合对于在 K8s 环境中优化日志管理至关重要,它不仅提供了强大且易于扩展的日志收集与汇总工具,还有可视化这些日志的能力。通过有效地使用这套工具,可以显著地提高对应用的运维监控能力和故障诊断效率。
64 0
|
2月前
|
Kubernetes Ubuntu Windows
【Azure K8S | AKS】分享从AKS集群的Node中查看日志的方法(/var/log)
【Azure K8S | AKS】分享从AKS集群的Node中查看日志的方法(/var/log)
|
18天前
|
Java
日志框架log4j打印异常堆栈信息携带traceId,方便接口异常排查
日常项目运行日志,异常栈打印是不带traceId,导致排查问题查找异常栈很麻烦。
下一篇
无影云桌面