天天看點

Kubernetes_靜态Pod網關apiserver的audit審計日志

作者:毛奇志

前言

審計日志是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_靜态Pod網關apiserver的audit審計日志

【技巧】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 等等,如下:

Kubernetes_靜态Pod網關apiserver的audit審計日志

發生了什麼? 幹什麼? 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

Kubernetes_靜态Pod網關apiserver的audit審計日志

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,就列印日志

Kubernetes_靜态Pod網關apiserver的audit審計日志

驗證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 的權限

Kubernetes_靜态Pod網關apiserver的audit審計日志

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審計日志,完成了。

天天打碼,天天進步!

繼續閱讀