前言
审计日志是kube-apiserver中比较常见的一种加固手段,通过对每一次请求的行为进行审计,从而达到加固集群的目的,同时,审计日志还能够帮助我们troubleshooting,因为每一次请求的内容都会被记录下来,如果请求的内容本身有问题,从而导致api返回5xx的错误,我们可以从审计日志中直接把报错信息抓出来给开发,帮助他们定位问题。
一、理论:kube-apiserver的审计日志
1.1 kube-apiserver.yaml 文件的五行修改
kube-apiserver.yaml 文件的五行修改
–audit-policy-file=/etc/kubernetes/simple-policy.yaml:审计日志policy文件的位置,如果我们的apiserver是容器启动的,那么我们可能需要再添加一个卷组和一个挂载点
–audit-log-path=/var/log/audit.log:审计日志存放的位置,我们同样需要一个volume和一个挂载点。
–audit-log-maxbackup=2:日志在retention之后保存几份
–audit-log-maxage=7:日志保留几天
–audit-log-maxsize=200:每个日志的大小,这里面是200m
需要注意的是,根据我们策略的不同,审计日志大小也会有所不同,简单来说说,粒度越洗,日志的量越大,所以我们一定要配置日志的retention
1.2 audit-policy.yaml文件的修改
审计功能被开启之后,所有的api调用都需要经过审计的流程,这样就会让我们的集群使用更多的内存。每个调用都会有三个阶段,RequestReceived,ResponseStarted,ResponseCompeted。
每个阶段都会有相应的规则。一个或者多个规则都会对应事件的某一个审计级别,审计级别有四个:
None:没有审计
Metadata:只有metadata,没有请求或者回应的内容
Request:请求的内容和metadata
RequestResponse:响应的内容和metadata
二、实践:编写策略文件,打印想要的审计日志
三个步骤:
步骤1:编写修改policy.yaml文件
步骤2:重启 apiserver ,这样修改的策略文件才会生效
步骤3:查看新日志
2.1 步骤1:编写修改policy.yaml文件
vim /etc/kubernetes/simple-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
两个错误:编辑 simple-policy.yaml 的时候
复制:一定要先输入 i,否则复制过来,apiVersion 变成了 piVersion
格式:rules应该和kind同一层级,- level 应该在rules下一层级(不能同一层级)
2.2 步骤2:重启 apiserver ,这样修改的策略文件才会生效
cd /etc/kubernetes/manifests
mkdir bak
cp kube-apiserver.yaml bak/kube-apiserver-bak.yaml
vi kube-apiserver.yaml
只要vi 修改了这个配置文件 kubectl get pod -o wide -n kube-system 里面的 apiserver就会重新应用, 如果 6443 refused 不要担心,docker ps | grep apiserver ,只需要等一下,等apiserver启动起来 6443 refused 就会消失
注意:不需要手动 kubectl apply -f kube-apiserver.yaml ,这样反而造成刚刚新建出来的这个处于Pending状态,使用 kubectl delete pod pod-name -n kube-system 删除掉这个处于Pending状态 (为什么可以使用 delete pod ,因为 apiserver.yaml 里面的 kind:Pod 类型 另外一个真实的 apiserver-xxx 也可以使用 delete pod 删除,只是删除会立马重建)
2.3 步骤3:查看新日志
tail -f /var/log/audit.log
问题:如果手动删除linux上的 rm -rf /var/log/audit.log ,audit.log 会变成一个目录
解决:将 vi kube-apiserver.yaml 将三个地方的 audio.log 变成 audio2.log (一个从来没有被使用过的名称就好了)就不会是目录了
2.4 编写策略文件和apiserver配置文件需要注意的三个点
编写 simple-policy.yaml 注意三个点
编写 kube-apiserver.yaml 注意三个点
simple-policy.yaml 注意三个点
1、审计时机和审计级别
审计时机:审计时机即记录事件的时机,分为四种类型
RequestReceived:接收到请求的时候,响应头发出之前,记录审计日志;
RequestStarted:响应头发出之后,响应消息体未发出之前,记录审计日志,一般用于长连接或耗时任务的场景;
ResponseComplete:响应消息体完成之后,记录审计日志;
Panic:出现panic的时候,记录审计日志。
审计级别:代表记录审计日志的完整程度,分为四种:
None:不记录审计日志,审计日志为空;
Metadata:记录请求的原子信息比如请求user、method、时间、资源类型等,但是不包括请求消息体和响应消息体;
Request:在Metadata基础上,加上请求消息体;
RequestResponse:在Metadata基础上,加上请求消息体和响应消息体,或者说,在Request的基础上,加上响应消息体。
2、从上到下:因为规则是从上到下进行匹配的,所以不需要记录的规则一般往上面放着,只要上面匹配了,就不会记录了
3、一般去掉静态pod和 查询类操作verb:[“list”,“get”] ,因为打印系统类日志或查询类日志,就导致日志太多了
kube-apiserver.yaml 注意三个点
1、采用 mkdir bak 新建一层目录保存 kube-apiserver-bak.yaml , 而不是同一级目录保存 kube-apiserver-bak.yaml (非必须,笔者自己的习惯)
2、vi kube-apiserver.yaml 然后 :wq 立马会生效
3、tail.log 变成了目录就重新搞一个 (注意 kube-apiserver.yaml 需要修改三个地方)
2.5 最后两个易错点
两个易错点:策略文件必须可读(chmod 777 audit-policy.yaml),审计日志文件自动创建不可删除
策略文件必须可读:策略文件audit-policy.yaml 必须可读 chmod 640 audit-policy.yaml 最好是是 chmod 777 audit-policy.yaml(scp),如果因为策略文件权限低造成 apiserver 起不来,使用 docker ps | grep apiserver 查看
审计日志文件自动创建不可删除:审计日志文件 audit.log 重启apiserver 就会被创建,一定不能手动删除,要不然会打印不了日志(因为日志文件已经被你删掉了)
【技巧】kubernetes查看日志的方式
方式1:如果是container容器,kubectl logs pod-name -n kube-system (注意一定是pod-name,就是xxx后缀的那种)(logs日志和exec进去的都是pod)
方式2:如果是服务的日志,使用 systemctl status kubelet
systemctl status docker
systemctl status firewalld
方式3:还有一种 -v 9
三、看懂审计日志和策略文件
3.1 看懂打印出来的audit.log日志
audit.log日志包括元数据(metadata)、请求内容(requestObject)和响应内容(responseObject)3个部分。其中元数据一定会存在,请求和响应内容是否存在取决于审计级别。元数据包含了请求的上下文信息,例如谁发起的请求,从哪里发起的,访问的 URI 等等,如下:
发生了什么? 干什么? requestUri + verb + objectRef (就这三个,没有 request)
谁发起的? user 下面有两个 username 和 group
从哪里发生? 查看 source 和 userAgent
结果是什么? responseStatus
什么时候发生的? stage字段是什么时候 level 是记录等级 两个 timestamp 是具体时间,需要加上 8 小时
3.2 看懂策略文件
1、rule是白名单,配置了规则rule才会被打印 (验证:如果none类型后面还配置了 metadata类型,就会打印日志;如果去掉后面的metadata类型,只保留前面的none类型的,不会打印任何日志)
2、rule规则中 最前面那个是 结果 select 输出结果,后面的是条件 where 条件 (验证:查看输出结果就知道)
3、每条rule规则中,多个条件是与的关系,任何一次操作同时满足这些条件才能打印指定类型日志
4、rules是数组,越前面优先级越高,一条日志走策略文件,先匹配到哪条就返回指定结果
5、omitStage 可以配置全局的,也可以配置在每条规则下 (验证:略)
6、annotations/reason解释为什么这一条会被选中
验证多个条件是与的关系
策略文件的每条rule规则中,多个条件是与的关系,任何一次操作同时满足这些条件才能打印指定类型日志
audit-policy.yaml策略文件中,条件可以最多包括四个,即
verbs 动作
user 用户
namespace 命名空间
resources 资源
verbs动词选项是:
查询:list get watch (区别:get 列出单个资源、list 列出资源类型的集合、watch 动态监控)
新建:create 创建
修改:update patch (区别:update 修改全部资源、patch 修改部分资源)
删除:delete
kubectl get pod ,因为具体到了pod-name为,就是会被策略文件识别为 list
kubectl get pod xxx ,因为具体到了pod-name为xxx,就是会被策略文件识别为 get
verbs动词其他还包括:
proxy 代理
redirect 重定向
use 调用
delete 删除
deletecollection 级联删除
验证优先级是从上到小的
验证(优先级是从上到小的):
kubectl create ns mao
策略文件:
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: None
verbs: ["create"]
- level: RequestResponse
users:
- kubernetes-admin
结果:不打印
解释:kubectl create ns mao 先匹配到了第一条,所以输出结果是None,就不打印日志
kubectl create ns mao
策略文件:
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: RequestResponse
users:
- kubernetes-admin
- level: None
verbs: ["create"]
结果:打印
解释:kubectl create ns mao 先匹配到了第一条,所以输出结果是RequestResponse,就打印日志
验证annotations/reason的解释作用
看 reason 字段, 表示为什么会匹配上
因为 userGroup 和
"requestURI": "/apis/batch/v1?timeout=32s",
"verb": "get",
{
"kind": "Event",
"apiVersion": "audit.k8s.io/v1",
"level": "RequestResponse",
"auditID": "406cf051-ba51-4d13-acdd-7f19f3746e29",
"stage": "ResponseComplete",
"requestURI": "/apis/batch/v1?timeout=32s",
"verb": "get",
"user": {
"username": "system:serviceaccount:kube-system:generic-garbage-collector",
"uid": "0446178d-04b9-11ed-a57e-000c291867b4",
"groups": ["system:serviceaccounts", "system:serviceaccounts:kube-system", "system:authenticated"]
},
"sourceIPs": ["192.168.100.151"],
"userAgent": "kube-controller-manager/v1.14.0 (linux/amd64) kubernetes/641856d/system:serviceaccount:kube-system:generic-garbage-collector",
"responseStatus": {
"metadata": {},
"code": 200
},
"responseObject": {
"kind": "APIResourceList",
"apiVersion": "v1",
"groupVersion": "batch/v1",
"resources": [{
"name": "jobs",
"singularName": "",
"namespaced": true,
"kind": "Job",
"verbs": ["create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"],
"categories": ["all"]
}, {
"name": "jobs/status",
"singularName": "",
"namespaced": true,
"kind": "Job",
"verbs": ["get", "patch", "update"]
}]
},
"requestReceivedTimestamp": "2022-07-16T07:20:24.959584Z",
"stageTimestamp": "2022-07-16T07:20:24.959723Z",
"annotations": {
"authorization.k8s.io/decision": "allow",
"authorization.k8s.io/reason": "RBAC: allowed by ClusterRoleBinding \"system:discovery\" of ClusterRole \"system:discovery\" to Group \"system:authenticated\""
}
}
“authorization.k8s.io/reason”: “RBAC: allowed by ClusterRoleBinding “system:discovery” of ClusterRole “system:discovery” to Group “system:authenticated””
解释:这次操作是用户 system:discovery 发起的,它已经取得了 system:authenticated 的权限
3.3 实践:审计日志仅打印kubernetes-admin相关的
如此编写策略文件,就可以了,如下:
## 最完美的过滤
apiVersion: audit.k8s.io/v1 # This is required.
kind: Policy
omitStages:
- "RequestReceived"
rules:
- level: RequestResponse
users:
- kubernetes-admin
问题:如何知道 users kubernetes-admin
回答:可以在 cat /root/.kube/config 里面看到,所以前端的请求都是这个
总结
静态Pod网关apiserver的audit审计日志,完成了。
天天打码,天天进步!