Kubernetes 审计日志功能

审计日志可以记录所有对 apiserver 接口的调用,让我们能够非常清晰的知道集群到底发生了什么事情,通过记录的日志可以查到所发生的事件、操作的用户和时间。

1

审计日志的策略

一、日志记录阶段

kube-apiserver 是负责接收及相应用户请求的一个组件,每一个请求都会有几个阶段,每个阶段都有对应的日志,当前支持的阶段有:

  • RequestReceived - apiserver 在接收到请求后且在将该请求下发之前会生成对应的审计日志。

  • ResponseStarted - 在响应 header 发送后并在响应 body 发送前生成日志。这个阶段仅为长时间运行的请求生成(例如 watch)。

  • ResponseComplete - 当响应 body 发送完并且不再发送数据。

  • Panic - 当有 panic 发生时生成。

也就是说对 apiserver 的每一个请求理论上会有三个阶段的审计日志生成。

二、日志记录级别

当前支持的日志记录级别有:

  • None - 不记录日志。

  • Metadata - 只记录 Request 的一些 metadata (例如 user, timestamp, resource, verb 等),但不记录 Request 或 Response 的body。

  • Request - 记录 Request 的 metadata 和 body。

  • RequestResponse - 最全记录方式,会记录所有的 metadata、Request 和 Response 的 body。

三、日志记录策略

在记录日志的时候尽量只记录所需要的信息,不需要的日志尽可能不记录,避免造成系统资源的浪费。

  • 一个请求不要重复记录,每个请求有三个阶段,只记录其中需要的阶段

  • 不要记录所有的资源,不要记录一个资源的所有子资源

  • 系统的请求不需要记录,kubelet、kube-proxy、kube-scheduler、kube-controller-manager 等对 kube-apiserver 的请求不需要记录

  • 对一些认证信息(secerts、configmaps、token 等)的 body 不记录

K8s 审计日志的一个示例:

$ wget https://github.com/kubernetes-sigs/kind/releases/download/v0.5.1/kind-darwin-amd64

$ chmod +x kind-darwin-amd64

$ mv kind-darwin-amd64 /usr/local/bin/kind

使用 kind 部署 Kubernetes 集群:

{

"kind": "EventList",

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

"Items": [

{

"Level": "Request",

"AuditID": "793e7ae2-5ca7-4ad3-a632-19708d2f8265",

"Stage": "RequestReceived",

"RequestURI": "/api/v1/namespaces/default/pods/test-pre-sf-de7cc-0",

"Verb": "get",

"User": {

"Username": "system:unsecured",

"UID": "",

"Groups": [

"system:masters",

"system:authenticated"

],

"Extra": null

},

"ImpersonatedUser": null,

"SourceIPs": [

"192.168.1.11"

],

"UserAgent": "kube-scheduler/v1.12.2 (linux/amd64) kubernetes/73f3294/scheduler",

"ObjectRef": {

"Resource": "pods",

"Namespace": "default",

"Name": "test-pre-sf-de7cc-0",

"UID": "",

"APIGroup": "",

"APIVersion": "v1",

"ResourceVersion": "",

"Subresource": ""

},

"ResponseStatus": null,

"RequestObject": null,

"ResponseObject": null,

"RequestReceivedTimestamp": "2019-01-11T06:51:43.528703Z",

"StageTimestamp": "2019-01-11T06:51:43.528703Z",

"Annotations": null

}

]

}

2

启用审计日志

审计日志支持两种收集方式:保存为日志文件和调用自定义的 webhook,在 v1.13 后还支持动态的 webhook。

一、将审计日志以 json 格式保存到本地文件

apiserver 配置文件的 KUBE_API_ARGS 中需要添加如下参数:

--audit-policy-file=/etc/kubernetes/audit-policy.yaml --audit-log-path=/var/log/kube-audit --audit-log-format=json

日志保存到本地后再通过 fluentd 等其他组件进行收集。

还有其他几个选项可以指定保留审计日志文件的最大天数、文件的最大数量、文件的大小等。

二、将审计日志打到后端指定的 webhook

--audit-policy-file=/etc/kubernetes/audit-policy.yaml --audit-webhook-config-file=/etc/kubernetes/audit-webhook-kubeconfig

webhook 配置文件实际上是一个 kubeconfig,apiserver 会将审计日志发送 到指定的 webhook 后,webhook 接收到日志后可以再分发到 kafka 或其他组件进行收集。

audit-webhook-kubeconfig 示例:

apiVersion: v1

clusters:

- cluster:

server: http://127.0.0.1:8081/audit/webhook

name: metric

contexts:

- context:

cluster: metric

user: ""

name: default-context

current-context: default-context

kind: Config

preferences: {}

users: []

前面提到过,apiserver 的每一个请求会记录三个阶段的审计日志,但是在实际中并不是需要所有的审计日志,官方也说明了启用审计日志会增加 apiserver 对内存的使用量。

audit-policy.yaml 配置示例:

apiVersion: audit.k8s.io/v1

kind: Policy

# ResponseStarted 阶段不记录

omitStages:

- "ResponseStarted"

rules:

# 记录用户对 pod 和 statefulset 的操作

- level: RequestResponse

resources:

- group: ""

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

- group: "apps"

resources: ["statefulsets","statefulsets/scale"]

# kube-controller-manager、kube-scheduler 等已经认证过身份的请求不需要记录

- level: None

userGroups: ["system:authenticated"]

nonResourceURLs:

- "/api*"

- "/version"

# 对 config、secret、token 等认证信息不记录请求体和返回体

- level: Metadata

resources:

- group: "" # core API group

resources: ["secrets", "configmaps"]

官方提供两个参考示例:

  • Use fluentd to collect and distribute audit events from log file

  • Use logstash to collect and distribute audit events from webhook backend

三、subresource 说明

kubernetes 每个资源对象都有 subresource,通过调用 master 的 api 可以获取 kubernetes 中所有的 resource 以及对应的 subresource,比如 pod 有 logs、exec 等 subresource。

获取所有 resource( 1.10 之后使用):

$ curl  127.0.0.1:8080/openapi/v2

参考:

https://kubernetes.io/docs/concepts/overview/kubernetes-api/

3

webhook 的一个简单示例

package main

import (

"encoding/json"

"io/ioutil"

"log"

"net/http"

"github.com/emicklei/go-restful"

"github.com/gosoon/glog"

"k8s.io/apiserver/pkg/apis/audit"

)

func main() {

// NewContainer creates a new Container using a new ServeMux and default router (CurlyRouter)

container := restful.NewContainer()

ws := new(restful.WebService)

ws.Path("/audit").

Consumes(restful.MIME_JSON).

Produces(restful.MIME_JSON)

ws.Route(ws.POST("/webhook").To(AuditWebhook))

//WebService ws2被添加到container2中

container.Add(ws)

server := &http.Server{

Addr:    ":8081",

Handler: container,

}

//go consumer()

log.Fatal(server.ListenAndServe())

}

func AuditWebhook(req *restful.Request, resp *restful.Response) {

body, err := ioutil.ReadAll(req.Request.Body)

if err != nil {

glog.Errorf("read body err is: %v", err)

}

var eventList audit.EventList

err = json.Unmarshal(body, &eventList)

if err != nil {

glog.Errorf("unmarshal failed with:%v,body is :\n", err, string(body))

return

}

for _, event := range eventList.Items {

jsonBytes, err := json.Marshal(event)

if err != nil {

glog.Infof("marshal failed with:%v,event is \n %+v", err, event)

}

// 消费日志

asyncProducer(string(jsonBytes))

}

resp.AddHeader("Content-Type", "application/json")

resp.WriteEntity("success")

}

完整代码请参考: 

https://github.com/gosoon/k8s-audit-webhook

本文主要介绍了 Kubernetes 的日志审计功能,安全问题是不可忽视的,Kubernetes 虽然被很多公司用作私有云,但日志审计仍然不可或缺。

作者:tianfeiyu

原文:http://rrd.me/fKges

END

免费领集群

动手做实验

华为云开年采购季·云原生专场特惠 四大福利 来袭

1、Kubernetes集群免费领

2、容器平台软件免费领

3、开发者集群套餐低至4.5折

4、更多优惠套餐低至 2 折

点击下方 阅读原文 识别二维码

即可领取 免费 集群动手实验

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章