Kubernetes 審計(Auditing)

人生的哲理發表於2024-06-25

目錄
  • 一.系統環境
  • 二.前言
  • 三.Kubernetes 審計簡介
  • 四.審計策略簡介
  • 五.啟用審計
    • 5.1 引入審計
    • 5.2 啟用審計
  • 六.審計策略
    • 6.1 記錄審計階段為:ResponseStarted,審計級別為Metadata,apiVersion為group: "" 的日誌
    • 6.2 只記錄audit名稱空間裡的日誌
    • 6.3 只記錄audit名稱空間的pods操作日誌
    • 6.4 只記錄audit名稱空間的pods,services,deployments操作日誌
    • 6.5 只記錄audit名稱空間的pods操作,審計級別為RequestResponse
    • 6.6 只記錄audit名稱空間下的tom使用者的pods操作,其他使用者操作不記錄
    • 6.7 rules規則是從上往下匹配的,第一條規則已經匹配了,第二條就不匹配了
    • 6.8 在 Metadata 級別為所有請求生成日誌
  • 七.總結

一.系統環境

本文主要基於Kubernetes1.22.2和Linux作業系統Ubuntu 18.04。

伺服器版本 docker軟體版本 Kubernetes(k8s)叢集版本 CPU架構
Ubuntu 18.04.5 LTS Docker version 20.10.14 v1.22.2 x86_64

Kubernetes叢集架構:k8scludes1作為master節點,k8scludes2,k8scludes3作為worker節點。

伺服器 作業系統版本 CPU架構 程序 功能描述
k8scludes1/192.168.110.128 Ubuntu 18.04.5 LTS x86_64 docker,kube-apiserver,etcd,kube-scheduler,kube-controller-manager,kubelet,kube-proxy,coredns,calico k8s master節點
k8scludes2/192.168.110.129 Ubuntu 18.04.5 LTS x86_64 docker,kubelet,kube-proxy,calico k8s worker節點
k8scludes3/192.168.110.130 Ubuntu 18.04.5 LTS x86_64 docker,kubelet,kube-proxy,calico k8s worker節點

二.前言

在當今的雲端計算時代,容器編排技術已成為企業部署和管理應用程式的關鍵組成部分。Kubernetes 作為最流行的容器編排平臺,提供了強大的功能來部署、管理和擴充套件容器化應用程式。然而,隨著應用程式的日益複雜和部署環境的擴大,確保 Kubernetes 叢集的安全性變得越來越重要。在這篇部落格中,我們將深入瞭解 Kubernetes 審計的概念,並探討如何在 Kubernetes 環境中實施審計策略。

使用Kubernetes 審計(Auditing)的前提是已經有一套可以正常執行的Kubernetes叢集,關於Kubernetes(k8s)叢集的安裝部署,可以檢視部落格《Ubuntu 安裝部署Kubernetes(k8s)叢集》https://www.cnblogs.com/renshengdezheli/p/17632858.html。

三.Kubernetes 審計簡介

Kubernetes 審計(Auditing) 功能提供了與安全相關的、按時間順序排列的記錄集, 記錄每個使用者、使用 Kubernetes API 的應用以及控制面自身引發的活動。

審計功能使得叢集管理員能夠回答以下問題:

  • 發生了什麼?
  • 什麼時候發生的?
  • 誰觸發的?
  • 活動發生在哪個(些)物件上?
  • 在哪觀察到的?
  • 它從哪觸發的?
  • 活動的後續處理行為是什麼?

審計記錄最初產生於 kube-apiserver 內部。每個請求在不同執行階段都會生成審計事件;這些審計事件會根據特定策略被預處理並寫入後端。 策略確定要記錄的內容和用來儲存記錄的後端,當前的後端支援日誌檔案webhook

每個請求都可被記錄其相關的階段(stage),階段(stage)可以理解為什麼時候記錄。。已定義的階段有:

  • RequestReceived - 此階段對應審計處理器接收到請求後, 並且在委託給其餘處理器之前生成的事件。
  • ResponseStarted - 在響應訊息的頭部傳送後,響應訊息體傳送前生成的事件。 只有長時間執行的請求(例如 watch)才會生成這個階段。
  • ResponseComplete - 當響應訊息體完成並且沒有更多資料需要傳輸的時候。
  • Panic - 當 panic 發生時生成。

審計日誌記錄功能會增加 API server 的記憶體消耗,因為需要為每個請求儲存審計所需的某些上下文。 記憶體消耗取決於審計日誌記錄的配置。

Kubernetes 審計是一種監控和記錄 Kubernetes 叢集中資源操作的方法,用於確保叢集的安全性和符合性。透過審計,管理員可以跟蹤對叢集資源的訪問和修改,以便在發生安全事件時進行調查和響應。Kubernetes 提供了審計日誌記錄的框架,允許管理員自定義審計策略,以確定哪些資源操作應該被記錄。

四.審計策略簡介

審計策略定義了關於應記錄哪些事件以及應包含哪些資料的規則。 審計策略物件結構定義在 audit.k8s.io API 組。 處理事件時,將按順序與規則列表進行比較。第一個匹配規則設定事件的審計級別(Audit Level),審計級別(Audit Level)可以理解為記錄什麼? 已定義的審計級別有:

  • None - 符合這條規則的日誌將不會記錄。
  • Metadata - 記錄請求的後設資料(請求的使用者、時間戳、資源、動詞等等), 但是不記錄請求或者響應的訊息體。
  • Request - 記錄事件的後設資料和請求的訊息體,但是不記錄響應的訊息體。 這不適用於非資源型別的請求。
  • RequestResponse - 記錄事件的後設資料,請求和響應的訊息體。這不適用於非資源型別的請求。

你可以使用 --audit-policy-file 標誌將包含策略的檔案傳遞給 kube-apiserver。 如果不設定該標誌,則不記錄事件。 注意 rules 欄位必須在審計策略檔案中提供。沒有(0)規則的策略將被視為非法配置。

審計策略定義了哪些資源操作應該被審計以及審計記錄的格式。在 Kubernetes 中,審計策略透過 Admission Controllers 實現,可以透過 Webhook 的方式進行整合。審計策略可以根據資源的型別、操作的型別和使用者身份等資訊進行過濾,以滿足不同場景下的審計需求。

五.啟用審計

5.1 引入審計

本次使用etcd2機器作為kubernetes叢集的客戶端,kctom是kubeconfig檔案,etcd2機器使用kctom連線kubernetes叢集,現在使用者tom沒有許可權,需要先授權。kubeconfig檔案在部落格《Kubernetes(k8s)訪問控制:身份認證》裡已經詳細介紹過了,這裡不再贅述。

[root@etcd2 ~]# ls kc* -lh
-rw------- 1 root root 5.5K 5月   5 17:46 kctom

[root@etcd2 ~]# kubectl get node --kubeconfig=kctom
Error from server (Forbidden): nodes is forbidden: User "tom" cannot list resource "nodes" in API group "" at the cluster scope

去kubernetes叢集給tom使用者授予cluster-admin許可權,也可以授予部分許可權。關於授權的詳細資訊,請檢視部落格《Kubernetes(k8s)訪問控制:許可權管理之RBAC授權/鑑權》。

root@k8scludes1:~# kubectl create clusterrolebinding crbindtom --clusterrole=cluster-admin --user=tom
clusterrolebinding.rbac.authorization.k8s.io/crbindtom created

授予cluster-admin許可權之後,客戶端就具有許可權了。

[root@etcd2 ~]# kubectl get node --kubeconfig=kctom
NAME         STATUS   ROLES                  AGE   VERSION
k8scludes1   Ready    control-plane,master   66d   v1.22.2
k8scludes2   Ready    <none>                 65d   v1.22.2
k8scludes3   Ready    <none>                 65d   v1.22.2

編輯pod配置檔案,表示使用nginx映象建立pod。

root@k8scludes1:~# vim pod.yaml 

root@k8scludes1:~# cat pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: podtest
  name: podtest
spec:
  #當需要關閉容器時,立即殺死容器而不等待預設的30秒優雅停機時長。
  terminationGracePeriodSeconds: 0
  containers:
  - image: hub.c.163.com/library/nginx:latest
    #imagePullPolicy: IfNotPresent:表示如果本地已經存在該映象,則不重新下載;否則從遠端 Docker Hub 下載該映象
    imagePullPolicy: IfNotPresent
    name: podtest
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

在admissioncontr名稱空間建立一個pod。

root@k8scludes1:~# kubectl apply -f pod.yaml 
pod/podtest created

在客戶端etcd2機器可以看到這個pod。

[root@etcd2 ~]# kubectl get pod --kubeconfig=kctom -n admissioncontr
NAME      READY   STATUS    RESTARTS   AGE
podtest   1/1     Running   0          34s

在客戶端刪除pod。

[root@etcd2 ~]# kubectl delete pod podtest --kubeconfig=kctom -n admissioncontr
pod "podtest" deleted

kubectl get ev (檢視事件),可以看到pod被刪除掉了,但是看不到pod被誰刪除掉了!

[root@etcd2 ~]# kubectl get ev --kubeconfig=kctom -n admissioncontr -o wide
LAST SEEN   TYPE     REASON    OBJECT        SUBOBJECT                  SOURCE                MESSAGE                                                                            FIRST SEEN   COUNT   NAME
3m37s       Normal   Pulled    pod/podtest   spec.containers{podtest}   kubelet, k8scludes3   Container image "hub.c.163.com/library/nginx:latest" already present on machine   3m37s        1       podtest.16fab43e14342a3f
3m37s       Normal   Created   pod/podtest   spec.containers{podtest}   kubelet, k8scludes3   Created container podtest                                                          3m37s        1       podtest.16fab43e1db484f4
3m36s       Normal   Started   pod/podtest   spec.containers{podtest}   kubelet, k8scludes3   Started container podtest                                                          3m36s        1       podtest.16fab43e3315ada7
2m47s       Normal   Killing   pod/podtest   spec.containers{podtest}   kubelet, k8scludes3   Stopping container podtest                                                         2m47s        1       podtest.16fab449c468f9af

我們的k8s叢集會被各種使用者連線使用,我們想知道連線k8s叢集的各個使用者做了什麼操作?應該怎麼辦?透過審計解決!

5.2 啟用審計

建立audit目錄存放yaml檔案。

root@k8scludes1:~# mkdir audit

root@k8scludes1:~# cd audit/

root@k8scludes1:~/audit# pwd
/root/audit

建立名稱空間audit。

root@k8scludes1:~/audit# kubectl create ns audit
namespace/audit created

切換到名稱空間audit。

root@k8scludes1:~/audit# kubens audit
Context "kubernetes-admin@kubernetes" modified.
Active namespace is "audit".

root@k8scludes1:~/audit# kubectl get pod 
No resources found in audit namespace.

kubernetes預設並沒有啟用審計,需要啟用審計功能。指定審計策略檔案的路徑:--audit-policy-file=/etc/kubernetes/audit/audit-policy.yaml

root@k8scludes1:~# vim /etc/kubernetes/manifests/kube-apiserver.yaml 

root@k8scludes1:~# grep audit-policy-file /etc/kubernetes/manifests/kube-apiserver.yaml
    - --audit-policy-file=/etc/kubernetes/audit/audit-policy.yaml

建立審計策略檔案,檔案內容可以先為空。

root@k8scludes1:~# mkdir /etc/kubernetes/audit/

root@k8scludes1:~# cd /etc/kubernetes/audit/

root@k8scludes1:/etc/kubernetes/audit# touch audit-policy.yaml

root@k8scludes1:/etc/kubernetes/audit# ls /etc/kubernetes/audit/audit-policy.yaml
/etc/kubernetes/audit/audit-policy.yaml

指定審計日誌存放的路徑:--audit-log-path=/var/log/kubernetes/audit/audit.log 。審計日誌格式為JSONlines 格式

root@k8scludes1:/etc/kubernetes/audit# vim /etc/kubernetes/manifests/kube-apiserver.yaml

root@k8scludes1:/etc/kubernetes/audit# grep audit-log-path /etc/kubernetes/manifests/kube-apiserver.yaml
    - --audit-log-path=/var/log/kubernetes/audit/audit.log

建立審計日誌檔案。

root@k8scludes1:/etc/kubernetes/audit# mkdir -p /var/log/kubernetes/audit/

root@k8scludes1:/etc/kubernetes/audit# touch /var/log/kubernetes/audit/audit.log

root@k8scludes1:/etc/kubernetes/audit# ls /var/log/kubernetes/audit/audit.log
/var/log/kubernetes/audit/audit.log

審計日誌引數如下:

  • --audit-log-path 指定用來寫入審計事件的日誌檔案路徑。不指定此標誌會禁用日誌後端。- 意味著標準化
  • --audit-log-maxage 定義保留舊審計日誌檔案的最大天數
  • --audit-log-maxbackup 定義要保留的審計日誌檔案的最大數量
  • --audit-log-maxsize 定義審計日誌檔案輪轉之前的最大大小(兆位元組)

配置審計日誌的引數。

root@k8scludes1:/etc/kubernetes/audit# vim /etc/kubernetes/manifests/kube-apiserver.yaml

root@k8scludes1:/etc/kubernetes/audit# grep audit /etc/kubernetes/manifests/kube-apiserver.yaml
    - --audit-policy-file=/etc/kubernetes/audit/audit-policy.yaml
    - --audit-log-path=/var/log/kubernetes/audit/audit.log
    - --audit-log-maxage=365
    - --audit-log-maxbackup=730
    - --audit-log-maxsize=250

如果你的叢集控制面以 Pod 的形式執行 kube-apiserver,需要透過 hostPath 資料捲來訪問策略檔案和日誌檔案所在的目錄,這樣審計記錄才會持久儲存下來。

現在/etc/kubernetes/audit/audit-policy.yaml和/var/log/kubernetes/audit/audit.log在宿主機裡是存在的,但是kube-apiserver是以pod的方式執行的,pod裡並不存在這兩個檔案,需要透過hostPath 資料捲進行對映。

/etc/kubernetes/manifests/kube-apiserver.yaml所有的修改如下截圖:

image-20240621110718241

注意:/var/log/kubernetes/audit/的readOnly為false,否則不能寫入日誌!

image-20240621110746808

自此,成功啟用審計了,下面開始配置審計策略。

六.審計策略

6.1 記錄審計階段為:ResponseStarted,審計級別為Metadata,apiVersion為group: "" 的日誌

先不用重啟kubelet,因為審計策略檔案還沒寫好。

現在編寫審計策略檔案,該審計策略表示什麼都不記錄。

root@k8scludes1:~# vim /etc/kubernetes/audit/audit-policy.yaml

root@k8scludes1:~# cat /etc/kubernetes/audit/audit-policy.yaml
apiVersion: audit.k8s.io/v1 # This is required.
kind: Policy
# Don't generate audit events for all requests in RequestReceived stage.
omitStages:
  - "ResponseStarted"
rules:
  - level: None
    resources:
    - group: ""

重啟kubelet使配置生效。

root@k8scludes1:~# systemctl restart kubelet

root@k8scludes1:~# kubectl get node
NAME         STATUS   ROLES                  AGE   VERSION
k8scludes1   Ready    control-plane,master   66d   v1.22.2
k8scludes2   Ready    <none>                 66d   v1.22.2
k8scludes3   Ready    <none>                 66d   v1.22.2

在客戶端etcd2機器執行命令:kubectl get ev --kubeconfig=kctom -n admissioncontr -o wide。

[root@etcd2 ~]# kubectl get ev --kubeconfig=kctom -n admissioncontr -o wide
No resources found in admissioncontr namespace.

檢視審計日誌,沒有任何日誌記錄。

root@k8scludes1:~# cat /var/log/kubernetes/audit/audit.log 

審計級別修改為Metadata,表示記錄請求的後設資料(請求的使用者、時間戳、資源、動詞等等), 但是不記錄請求或者響應的訊息體。

root@k8scludes1:~# vim /etc/kubernetes/audit/audit-policy.yaml

root@k8scludes1:~# cat /etc/kubernetes/audit/audit-policy.yaml
apiVersion: audit.k8s.io/v1 # This is required.
kind: Policy
# Don't generate audit events for all requests in RequestReceived stage.
omitStages:
  - "ResponseStarted"
rules:
  - level: Metadata
    resources:
    - group: ""

重啟kubelet使配置生效。

root@k8scludes1:~# systemctl daemon-reload ; systemctl restart kubelet

在客戶端etcd2機器執行命令:kubectl get ev --kubeconfig=kctom -n admissioncontr -o wide 。

[root@etcd2 ~]# kubectl get ev --kubeconfig=kctom -n admissioncontr -o wide
No resources found in admissioncontr namespace.

檢視審計日誌,發現還是沒有日誌產生,看來重啟kubelet還不行,現在重啟機器。

root@k8scludes1:~# cat /var/log/kubernetes/audit/audit.log

現在直接重啟k8scludes1機器,k8s worker節點不用重啟。

root@k8scludes1:~# reboot

重啟k8scludes1機器之後,現在/var/log/kubernetes/audit/audit.log裡有很多資料,先刪除資料,然後客戶端執行命令,檢視審計日誌。

root@k8scludes1:~# cat /var/log/kubernetes/audit/audit.log | wc -l
3317

清空日誌。

root@k8scludes1:~# >/var/log/kubernetes/audit/audit.log

客戶端執行kubectl get ev --kubeconfig=kctom -n admissioncontr -o wide命令。

[root@etcd2 ~]# kubectl get ev --kubeconfig=kctom -n admissioncontr -o wide
No resources found in admissioncontr namespace.

現在不停的產生日誌。

root@k8scludes1:~# cat /var/log/kubernetes/audit/audit.log | wc -l
32

這是最新的日誌。

root@k8scludes1:~# tail -1 /var/log/kubernetes/audit/audit.log
{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"Metadata","auditID":"72736d33-508f-4279-89a5-d95aea7b98c5","stage":"ResponseComplete","requestURI":"/api/v1/namespaces/ingress-nginx/configmaps/ingress-controller-leader","verb":"update","user":{"username":"system:serviceaccount:ingress-nginx:ingress-nginx","uid":"70a36f2c-225f-450d-849e-2432db224f40","groups":["system:serviceaccounts","system:serviceaccounts:ingress-nginx","system:authenticated"],"extra":{"authentication.kubernetes.io/pod-name":["ingress-nginx-controller-684bbc4b45-jmpxk"],"authentication.kubernetes.io/pod-uid":["308fdf30-854b-49f7-b041-4e5d770c0667"]}},"sourceIPs":["192.168.110.130"],"userAgent":"nginx-ingress-controller/v1.0.0 (linux/amd64) ingress-nginx/041eb167c7bfccb1d1653f194924b0c5fd885e10","objectRef":{"resource":"configmaps","namespace":"ingress-nginx","name":"ingress-controller-leader","uid":"db625974-8e33-4bd6-a2e2-1816301af942","apiVersion":"v1","resourceVersion":"2739119"},"responseStatus":{"metadata":{},"code":200},"requestReceivedTimestamp":"2022-06-22T13:03:36.751232Z","stageTimestamp":"2022-06-22T13:03:36.759442Z","annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":"RBAC: allowed by RoleBinding \"ingress-nginx/ingress-nginx\" of Role \"ingress-nginx\" to ServiceAccount \"ingress-nginx/ingress-nginx\"","mutation.webhook.admission.k8s.io/round_0_index_1":"{\"configuration\":\"gatekeeper-mutating-webhook-configuration\",\"webhook\":\"mutation.gatekeeper.sh\",\"mutated\":false}"}}

客戶端不執行命令就產生了太多審計日誌了,需要修改審計策略。

root@k8scludes1:~# cat /var/log/kubernetes/audit/audit.log | wc -l
1174

6.2 只記錄audit名稱空間裡的日誌

修改審計策略,現在配置只記錄某個名稱空間裡的審計日誌,namespaces: ["audit"]表示只記錄audit名稱空間裡的日誌。

root@k8scludes1:~# vim /etc/kubernetes/audit/audit-policy.yaml 

root@k8scludes1:~# cat /etc/kubernetes/audit/audit-policy.yaml
apiVersion: audit.k8s.io/v1 # This is required.
kind: Policy
# Don't generate audit events for all requests in RequestReceived stage.
omitStages:
  - "ResponseStarted"
rules:
  - level: Metadata
    resources:
    - group: ""
    namespaces: ["audit"]

重啟kubelet使其生效,但是審計策略沒有生效,重啟機器。

root@k8scludes1:~# systemctl restart kubelet

重啟k8s master節點。

root@k8scludes1:~# reboot

root@k8scludes1:~# kubectl get node
NAME         STATUS   ROLES                  AGE   VERSION
k8scludes1   Ready    control-plane,master   66d   v1.22.2
k8scludes2   Ready    <none>                 66d   v1.22.2
k8scludes3   Ready    <none>                 66d   v1.22.2

重啟k8s master節點之後,清空日誌。

root@k8scludes1:~# >/var/log/kubernetes/audit/audit.log

客戶端執行kubectl get pod --kubeconfig=kctom -n default -o wide。

[root@etcd2 ~]# kubectl get pod --kubeconfig=kctom  -n default -o wide
No resources found in default namespace.

客戶端執行 kubectl get pod --kubeconfig=kctom -n audit -o wide。

[root@etcd2 ~]# kubectl get pod --kubeconfig=kctom  -n audit -o wide
No resources found in audit namespace.

檢視審計日誌,只記錄了audit名稱空間的操作,default名稱空間的操作沒有記錄。

root@k8scludes1:~# tail -2 /var/log/kubernetes/audit/audit.log
{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"Metadata","auditID":"08b8fca7-8390-4f59-8a21-6ff3541fd2a2","stage":"RequestReceived","requestURI":"/api/v1/namespaces/audit/pods?limit=500","verb":"list","user":{"username":"tom","groups":["normalusertom","system:authenticated"]},"sourceIPs":["192.168.110.131"],"userAgent":"kubectl/v1.23.1 (linux/amd64) kubernetes/86ec240","objectRef":{"resource":"pods","namespace":"audit","apiVersion":"v1"},"requestReceivedTimestamp":"2022-06-22T13:26:08.732751Z","stageTimestamp":"2022-06-22T13:26:08.732751Z"}
{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"Metadata","auditID":"08b8fca7-8390-4f59-8a21-6ff3541fd2a2","stage":"ResponseComplete","requestURI":"/api/v1/namespaces/audit/pods?limit=500","verb":"list","user":{"username":"tom","groups":["normalusertom","system:authenticated"]},"sourceIPs":["192.168.110.131"],"userAgent":"kubectl/v1.23.1 (linux/amd64) kubernetes/86ec240","objectRef":{"resource":"pods","namespace":"audit","apiVersion":"v1"},"responseStatus":{"metadata":{},"code":200},"requestReceivedTimestamp":"2022-06-22T13:26:08.732751Z","stageTimestamp":"2022-06-22T13:26:08.741665Z","annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":"RBAC: allowed by ClusterRoleBinding \"crbindtom\" of ClusterRole \"cluster-admin\" to User \"tom\""}}

6.3 只記錄audit名稱空間的pods操作日誌

修改審計策略,該審計策略表示只記錄audit名稱空間的pods操作。

root@k8scludes1:~# vim /etc/kubernetes/audit/audit-policy.yaml 

root@k8scludes1:~# cat /etc/kubernetes/audit/audit-policy.yaml
apiVersion: audit.k8s.io/v1 # This is required.
kind: Policy
# Don't generate audit events for all requests in RequestReceived stage.
omitStages:
  - "ResponseStarted"
rules:
  - level: Metadata
    resources:
    - group: ""
      resources: ["pods"]
    namespaces: ["audit"]

重啟機器使審計策略生效。

root@k8scludes1:~# reboot

重啟之後,清空日誌。

root@k8scludes1:~# >/var/log/kubernetes/audit/audit.log 

在客戶端執行kubectl get pod --kubeconfig=kctom -n audit -o wide。

[root@etcd2 ~]# kubectl get pod --kubeconfig=kctom  -n audit -o wide
No resources found in audit namespace.

在客戶端執行 kubectl get svc --kubeconfig=kctom -n audit -o wide 。

[root@etcd2 ~]# kubectl get svc --kubeconfig=kctom  -n audit -o wide
No resources found in audit namespace.

檢視日誌,發現只記錄了audit名稱空間的pod操作,svc操作沒有記錄。

root@k8scludes1:~# cat /var/log/kubernetes/audit/audit.log
{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"Metadata","auditID":"4748e76d-e9cb-46de-af28-d467171ca105","stage":"RequestReceived","requestURI":"/api/v1/namespaces/audit/pods?limit=500","verb":"list","user":{"username":"tom","groups":["normalusertom","system:authenticated"]},"sourceIPs":["192.168.110.131"],"userAgent":"kubectl/v1.23.1 (linux/amd64) kubernetes/86ec240","objectRef":{"resource":"pods","namespace":"audit","apiVersion":"v1"},"requestReceivedTimestamp":"2022-06-23T00:24:45.351036Z","stageTimestamp":"2022-06-23T00:24:45.351036Z"}
{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"Metadata","auditID":"4748e76d-e9cb-46de-af28-d467171ca105","stage":"ResponseComplete","requestURI":"/api/v1/namespaces/audit/pods?limit=500","verb":"list","user":{"username":"tom","groups":["normalusertom","system:authenticated"]},"sourceIPs":["192.168.110.131"],"userAgent":"kubectl/v1.23.1 (linux/amd64) kubernetes/86ec240","objectRef":{"resource":"pods","namespace":"audit","apiVersion":"v1"},"responseStatus":{"metadata":{},"code":200},"requestReceivedTimestamp":"2022-06-23T00:24:45.351036Z","stageTimestamp":"2022-06-23T00:24:45.434147Z","annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":"RBAC: allowed by ClusterRoleBinding \"clusterrolebinding1\" of ClusterRole \"clusterole1\" to User \"tom\""}}

6.4 只記錄audit名稱空間的pods,services,deployments操作日誌

編輯審計策略檔案,表示只記錄audit名稱空間的pods,services,deployments操作,因為deployments的apiVersion的父級為apps,所以需要group: "apps" 。

root@k8scludes1:~# vim /etc/kubernetes/audit/audit-policy.yaml 

root@k8scludes1:~# cat /etc/kubernetes/audit/audit-policy.yaml
apiVersion: audit.k8s.io/v1 # This is required.
kind: Policy
# Don't generate audit events for all requests in RequestReceived stage.
omitStages:
  - "ResponseStarted"
rules:
  - level: Metadata
    resources:
    - group: ""
      resources: ["pods","services"]
    - group: "apps"
      resources: ["deployments"]
    namespaces: ["audit"]

6.5 只記錄audit名稱空間的pods操作,審計級別為RequestResponse

編輯審計策略檔案,表示只記錄audit名稱空間的pods操作,審計級別為RequestResponse,記錄事件的後設資料,請求和響應的訊息體。

root@k8scludes1:~# vim /etc/kubernetes/audit/audit-policy.yaml

root@k8scludes1:~# cat /etc/kubernetes/audit/audit-policy.yaml
apiVersion: audit.k8s.io/v1 # This is required.
kind: Policy
# Don't generate audit events for all requests in RequestReceived stage.
omitStages:
  - "ResponseStarted"
rules:
  - level: RequestResponse
    resources:
    - group: ""
      resources: ["pods"]
    namespaces: ["audit"]

重啟機器使審計策略生效。

root@k8scludes1:~# reboot

建立一個pod。

root@k8scludes1:~# kubectl apply -f pod.yaml 
pod/podtest created

root@k8scludes1:~# kubectl get pod
NAME      READY   STATUS    RESTARTS   AGE
podtest   1/1     Running   0          5s

清空審計日誌。

root@k8scludes1:~# >/var/log/kubernetes/audit/audit.log 

客戶端執行kubectl get pod --kubeconfig=kctom -n audit -o wide 。

[root@etcd2 ~]# kubectl get pod --kubeconfig=kctom  -n audit -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
podtest   1/1     Running   0          48s   10.244.1.97   k8scludes3   <none>           <none>

檢視審計日誌,記錄的內容很豐富,後設資料,請求和響應的訊息體都顯示出來了。

root@k8scludes1:~# cat /var/log/kubernetes/audit/audit.log
{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"RequestResponse","auditID":"d6836f9b-4918-49f2-80dc-ad02e246949b","stage":"RequestReceived","requestURI":"/api/v1/namespaces/audit/pods?limit=500","verb":"list","user":{"username":"tom","groups":["normalusertom","system:authenticated"]},"sourceIPs":["192.168.110.131"],"userAgent":"kubectl/v1.23.1 (linux/amd64) kubernetes/86ec240","objectRef":{"resource":"pods","namespace":"audit","apiVersion":"v1"},"requestReceivedTimestamp":"2022-06-23T00:43:30.782241Z","stageTimestamp":"2022-06-23T00:43:30.782241Z"}
......
23T00:42:46Z","fieldsType":"FieldsV1","fieldsV1":{"f:status":{"f:conditions":{".":{},"k:{\"type\":\"ContainersReady\"}":{".":{},"f:lastProbeTime":{},"f:lastTransitionTime":{},"f:status":{},"f:type":{}},"k:{\"type\":\"Initialized\"}":{".":{},"f:lastProbeTime":{},"f:lastTransitionTime":{},"f:status":{},"f:type":{}},"k:{\"type\":\"PodScheduled\"}":{".":{},"f:lastProbeTime":{},"f:lastTransitionTime":{},"f:status":{},"f:type":{}},"k:{\"type\":\"Ready\"}":{".":{},"f:lastProbeTime":{},"f:lastTransitionTime":{},"f:status":{},"f:type":{}}},"f:containerStatuses":{},"f:hostIP":{},"f:phase":{},"f:podIP":{},"f:podIPs":{".":{},"k:{\"ip\":\"10.244.1.97\"}":{".":{},"f:ip":{}}},"f:startTime":{}}},"subresource":"status"}]}}}]},"requestReceivedTimestamp":"2022-06-23T00:43:30.782241Z","stageTimestamp":"2022-06-23T00:43:30.785883Z","annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":"RBAC: allowed by ClusterRoleBinding \"clusterrolebinding1\" of ClusterRole \"clusterole1\" to User \"tom\""}}

6.6 只記錄audit名稱空間下的tom使用者的pods操作,其他使用者操作不記錄

編輯審計策略檔案,設定審計策略:只記錄audit名稱空間下的tom使用者的pods操作,其他使用者的操作不記錄。

root@k8scludes1:~# vim /etc/kubernetes/audit/audit-policy.yaml 

root@k8scludes1:~# cat /etc/kubernetes/audit/audit-policy.yaml
apiVersion: audit.k8s.io/v1 # This is required.
kind: Policy
# Don't generate audit events for all requests in RequestReceived stage.
omitStages:
  - "ResponseStarted"
rules:
  - level: Metadata
    users: ["tom"]
    resources:
    - group: ""
      resources: ["pods"]
    namespaces: ["audit"]

重啟機器使審計策略生效。

root@k8scludes1:~# reboot 

清空日誌。

root@k8scludes1:~# >/var/log/kubernetes/audit/audit.log 

使用管理員使用者檢視pod。

root@k8scludes1:~# kubectl get pod -n audit
NAME      READY   STATUS    RESTARTS   AGE
podtest   1/1     Running   0          29m

使用tom使用者在客戶端檢視pod 。

[root@etcd2 ~]# kubectl get pod --kubeconfig=kctom  -n audit -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
podtest   1/1     Running   0          29m   10.244.1.97   k8scludes3   <none>           <none>

檢視日誌,可以發現只記錄了tom使用者的pod查詢操作。

root@k8scludes1:~# cat /var/log/kubernetes/audit/audit.log
{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"Metadata","auditID":"a70f1b39-3c54-4ed8-ab45-9cbb7b4688ef","stage":"RequestReceived","requestURI":"/api/v1/namespaces/audit/pods?limit=500","verb":"list","user":{"username":"tom","groups":["normalusertom","system:authenticated"]},"sourceIPs":["192.168.110.131"],"userAgent":"kubectl/v1.23.1 (linux/amd64) kubernetes/86ec240","objectRef":{"resource":"pods","namespace":"audit","apiVersion":"v1"},"requestReceivedTimestamp":"2022-06-23T01:12:24.103036Z","stageTimestamp":"2022-06-23T01:12:24.103036Z"}
{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"Metadata","auditID":"a70f1b39-3c54-4ed8-ab45-9cbb7b4688ef","stage":"ResponseComplete","requestURI":"/api/v1/namespaces/audit/pods?limit=500","verb":"list","user":{"username":"tom","groups":["normalusertom","system:authenticated"]},"sourceIPs":["192.168.110.131"],"userAgent":"kubectl/v1.23.1 (linux/amd64) kubernetes/86ec240","objectRef":{"resource":"pods","namespace":"audit","apiVersion":"v1"},"responseStatus":{"metadata":{},"code":200},"requestReceivedTimestamp":"2022-06-23T01:12:24.103036Z","stageTimestamp":"2022-06-23T01:12:24.107872Z","annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":"RBAC: allowed by ClusterRoleBinding \"crbindtom\" of ClusterRole \"cluster-admin\" to User \"tom\""}}

6.7 rules規則是從上往下匹配的,第一條規則已經匹配了,第二條就不匹配了

編輯審計策略檔案,有兩條策略,一條是:apiVersion為group: ""的操作不記錄日誌,另外一條是:只記錄audit名稱空間下tom使用者的pod操作。

root@k8scludes1:~# vim /etc/kubernetes/audit/audit-policy.yaml

root@k8scludes1:~# cat /etc/kubernetes/audit/audit-policy.yaml
apiVersion: audit.k8s.io/v1 # This is required.
kind: Policy
# Don't generate audit events for all requests in RequestReceived stage.
omitStages:
  - "ResponseStarted"
rules:
  #apiVersion為group: ""的操作不記錄日誌
  - level: None
    resources:
    - group: ""
  #只記錄audit名稱空間下tom使用者的pod操作
  - level: Metadata
    users: ["tom"]
    resources:
    - group: ""
      resources: ["pods"]
    namespaces: ["audit"]

重啟機器使配置生效。

root@k8scludes1:~# reboot 

清空日誌。

root@k8scludes1:~# >/var/log/kubernetes/audit/audit.log 

使用管理員使用者查詢audit名稱空間的pod。

root@k8scludes1:~# kubectl get pod -n audit
NAME      READY   STATUS    RESTARTS   AGE
podtest   1/1     Running   0          37m

使用tom使用者在客戶端機器etcd2上查詢audit名稱空間的pod。

[root@etcd2 ~]# kubectl get pod --kubeconfig=kctom  -n audit -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
podtest   1/1     Running   0          37m   10.244.1.97   k8scludes3   <none>           <none>

檢視審計日誌,可以發現在客戶端使用tom使用者查詢pod和使用管理員使用者檢視pod都沒有生成審計日誌,rules規則是從上往下匹配的,第一條規則已經匹配了,第二條就不匹配了。

root@k8scludes1:~# cat /var/log/kubernetes/audit/audit.log

6.8 在 Metadata 級別為所有請求生成日誌

編輯審計策略檔案,在 Metadata 級別為所有請求生成日誌。

root@k8scludes1:~# vim /etc/kubernetes/audit/audit-policy.yaml 

root@k8scludes1:~# cat /etc/kubernetes/audit/audit-policy.yaml
apiVersion: audit.k8s.io/v1beta1
kind: Policy
rules:
- level: Metadata

七.總結

在 Kubernetes 1.22.2 環境中實施審計策略可以幫助管理員監控和記錄叢集中的資源操作,確保叢集的安全性和符合性。透過啟用審計 Admission Controller 和配置相應的審計策略,我們可以靈活地控制審計記錄的格式和範圍。

相關文章