前言
審計日志是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審計日志,完成了。
天天打碼,天天進步!