0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

k8s の audit 設定をちゃんと理解する

Last updated at Posted at 2025-02-17

タイトル

k8s の audit 設定をちゃんと理解する

目的

  • api-server に設定する audit 機能を理解する

手段

  • マニュアルベースで手を動かす

ざっくり理解する

k8s の audit 設定をちゃんと理解する.png

  • 必要な設定内容
    • kube-apiserver に audit 関連のオプション設定追加
    • kube-apiserver に audti 設定ファイルとロギング用をマウント
    • audit 用の設定ファイル作成(yaml)

環境

  • killercode 環境を活用

audit 機能とは?

audit 機能は k8s クラスター内の一連アクション監査ログを提供します。(いわゆる監査ログ)
kube-apiserver 内で処理されるリクエストを各ステージごとにロギングします。各ステージは以下の通りです。

  • RequestReceived : audit handler はリクエストを受けたら可能な限り早くイベントを生成するステージ
  • ResponseStarted : response header が送信され、response body が送信される前のステージ
  • ResponseComplete : response body 送信が完了したステージ
  • Panic : panic 発生時のステージ(エラーの様なイメージ)

また、どのような監査ログ(ログレベル)を記録するか設定ファイルで定義します。

  • None : イベントを記録しません
  • Metadata : リクエストのメタデータ(リクエストしたユーザ、タイムスタンプ、リソース、動作など)を記録します。リクエストやレスポンスのボディは記録しません
  • Request : イベントのメタデータとリクエストボディを記録します。レスポンスボディは記録しません
  • RequestResponse : イベントのメタデータ・リクエストとレスポンスのボディを記録します

audit 機能の設定方法

autdit 機能は kube-apiserver.yaml を用いて有効化します。必要設定は以下の通りです。

  1. --audit-policy-file : audit 設定ファイル
  2. --audit-log-path : audit ログ保存パス
  3. --audit-log-maxage : audit ログの最大保持日数を指定
  4. --audit-log-maxbackup : audit ログの最大保持ファイル数を指定
  5. --audit-log-maxsize : audit ログがローテーションされるまでの最大ファイルサイズを指定(1ファイルの最大サイズ)
controlplane $ diff kube-apiserver.yaml /root/kube-apiserver.yaml 
43,46d42
<     - --audit-log-maxsize=7
<     - --audit-log-maxbackup=2
<     - --audit-log-path=/etc/kubernetes/audit-logs/audit.log
<     - --audit-policy-file=/etc/kubernetes/audit-policy/policy.yaml
# kube-apiserver.yaml にフラグを追加します

98,103d93
<     - mountPath: /etc/kubernetes/audit-policy/policy.yaml
<       name: audit
<       readOnly: true
# kube-apiserver に監査ログ用の設定ファイルを readonly でマウントします
<     - mountPath: /etc/kubernetes/audit-logs
<       name: audit-log
<       readOnly: false
# kube-apiserver に監査ログ保存ディレクトリをマウントします

131,138d120
<   - name: audit
<     hostPath:
<       path: /etc/kubernetes/audit-policy/policy.yaml
<       type: File
<   - name: audit-log
<     hostPath:
<       path: /etc/kubernetes/audit-logs/
<       type: DirectoryOrCreate
# 監査ログ設定ファイルとログディレクトリのボリュームを作成します

動作確認方法

動作確認方法は以下の通りです。

controlplane $ stat /etc/kubernetes/audit-logs/audit.log 
  File: /etc/kubernetes/audit-logs/audit.log
  Size: 984661          Blocks: 1928       IO Block: 4096   regular file
Device: fc01h/64513d    Inode: 1327002     Links: 1
Access: (0600/-rw-------)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2025-02-10 10:21:18.846192987 +0000
Modify: 2025-02-10 10:23:35.235664013 +0000
Change: 2025-02-10 10:23:35.235664013 +0000
 Birth: -
# ログファイルの書き込み有無を確認
controlplane $ cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep audit-policy-file=/etc/kubernetes/audit-policy/policy.yaml
    - --audit-policy-file=/etc/kubernetes/audit-policy/policy.yaml
controlplane $ 
controlplane $ cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep audit-log-path=/etc/kubernetes/audit-logs/audit.log
    - --audit-log-path=/etc/kubernetes/audit-logs/audit.log
controlplane $ 
controlplane $ cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep audit-log-maxsize=7
    - --audit-log-maxsize=7
controlplane $ 
controlplane $ cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep audit-log-maxbackup=2
    - --audit-log-maxbackup=2
# kube-apiserver.yaml 内の設定値を確認

audit 用の yaml ファイルを作成する

まずは、Pods 関連のみロギングする。

controlplane $ cat policy.yaml
# /etc/kubernetes/audit/policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:

# log Secret resources audits, level Metadata
- level: Metadata
  resources:
  - group: ""
    resources: ["pods"]
controlplane $ tail -f audit.log |grep pods
{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"Metadata","auditID":"7f926292-edc9-48d0-8975-595ffb966675","stage":"RequestReceived","requestURI":"/api/v1/pods?fieldSelector=spec.nodeName%3Dcontrolplane\u0026resourceVersion=2545","verb":"list","user":{"username":"system:node:controlplane","groups":["system:nodes","system:authenticated"]},"sourceIPs":["172.30.1.2"],"userAgent":"kubelet/v1.31.0 (linux/amd64) kubernetes/9edcffc","objectRef":{"resource":"pods","apiVersion":"v1"},"requestReceivedTimestamp":"2025-02-13T11:20:35.906449Z","stageTimestamp":"2025-02-13T11:20:35.906449Z"}
{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"Metadata","auditID":"7f926292-edc9-48d0-8975-595ffb966675","stage":"ResponseComplete","requestURI":"/api/v1/pods?fieldSelector=spec.nodeName%3Dcontrolplane\u0026resourceVersion=2545","verb":"list","user":{"username":"system:node:controlplane","groups":["system:nodes","system:authenticated"]},"sourceIPs":["172.30.1.2"],"userAgent":"kubelet/v1.31.0 (linux/amd64) kubernetes/9edcffc","objectRef":{"resource":"pods","apiVersion":"v1"},"responseStatus":{"metadata":{},"code":200},"requestReceivedTimestamp":"2025-02-13T11:20:35.906449Z","stageTimestamp":"2025-02-13T11:20:35.908974Z","annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":""}}
# Pod関連ログのみロギングされている。

次に、ログレベルを MetadataRequestResponse に変更する。kube-apiserverをリスタート(Pod再作成)させるために kube-apiserver.yaml を編集して、kube-apiserverをリスタートさせるのが手間ですね。コマンドで実行したいです。

controlplane $ cat policy.yaml
# /etc/kubernetes/audit/policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:

# log Secret resources audits, level Metadata
- level: RequestResponse
  resources:
  - group: ""
    resources: ["pods"]
# level を変更済み
controlplane $ tail -f audit.log |grep RequestResponse
{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"RequestResponse","auditID":"af23f5d2-c145-413d-a48a-09bb54425274","stage":"ResponseStarted","requestURI":"/api/v1/pods?allowWatchBookmarks=true\u0026resourceVersion=2962\u0026timeout=7m12s\u0026timeoutSeconds=432\u0026watch=true","verb":"watch","user":{"username":"system:kube-controller-manager","groups":["system:authenticated"]},"sourceIPs":["172.30.1.2"],"userAgent":"kube-controller-manager/v1.31.0 (linux/amd64) kubernetes/9edcffc/shared-informers","objectRef":{"resource":"pods","apiVersion":"v1"},"responseStatus":{"metadata":{},"code":200},"requestReceivedTimestamp":"2025-02-13T11:25:28.542419Z","stageTimestamp":"2025-02-13T11:25:28.542797Z","annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":"RBAC: allowed by ClusterRoleBinding \"system:kube-controller-manager\" of ClusterRole \"system:kube-controller-manager\" to User \"system:kube-controller-manager\""}}
# "RequestResponse" レベルのログがロギングされている

続いて、namespace でロギング対象を制限してみます。

controlplane $ cat policy.yaml
# /etc/kubernetes/audit/policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:

# log Secret resources audits, level Metadata
- level: RequestResponse
  resources:
  - group: ""
    resources: ["pods"]
  namespaces: ["test"]
controlplane $ tail -f audit.log |grep test
{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"RequestResponse","auditID":"b13d607d-60f5-4640-9ada-8b222029b59f","stage":"RequestReceived","requestURI":"/api/v1/namespaces/test/pods?fieldManager=kubectl-run","verb":"create","user":{"username":"kubernetes-admin","groups":["kubeadm:cluster-admins","system:authenticated"]},"sourceIPs":["172.30.1.2"],"userAgent":"kubectl/v1.31.0 (linux/amd64) kubernetes/9edcffc","objectRef":{"resource":"pods","namespace":"test","apiVersion":"v1"},"requestReceivedTimestamp":"2025-02-13T11:42:39.035337Z","stageTimestamp":"2025-02-13T11:42:39.035337Z"}
# test namespace のみロギングされる。

続いて、omitSatges 設定とロギング設定をバッティングさせてみます。想定では、ロギングされない動作になると思います。

controlplane $ cat ../audit-policy/policy.yaml
# /etc/kubernetes/audit/policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:

omitStages:
  - "RequestResponse"
# log Secret resources audits, level Metadata
- level: RequestResponse
  resources:
  - group: ""
    resources: ["pods"]
  namespaces: ["test"]
# 結果的に、kube-apiserver は起動しませんでした。policy.yaml ファイルに不備があるためでしょう。

namespaces を "" 指定した場合の動作を確認します。"" はnamespace に所属しないオブジェクトを対象にするようです。

controlplane $ cat ../audit-policy/policy.yaml
# /etc/kubernetes/audit/policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:

# log Secret resources audits, level Metadata
- level: RequestResponse
  resources:
  - group: ""
    resources: ["pods"]
  namespaces: [""]
controlplane $ k run -n test nginx2 --image=nginx
pod/nginx2 created
# test に nginx2 を作成

controlplane $ tail -f ../audit-logs/audit.log |grep nginx2
# nginx2 pod 関連葉ロギングされません

最後のサンプル設定を読み解きます。

apiVersion: audit.k8s.io/v1 # This is required.
kind: Policy
# Don't generate audit events for all requests in RequestReceived stage.
omitStages:
  - "RequestReceived"
# audit ポリシーは設定を上から適用するため、最初にomitStages で設定すれば、当該ステージのログはロギングされない
rules:
  # Log pod changes at RequestResponse level
  - level: RequestResponse
    resources:
    - group: ""
      # Resource "pods" doesn't match requests to any subresource of pods,
      # which is consistent with the RBAC policy.
      resources: ["pods"]
  # Log "pods/log", "pods/status" at Metadata level
  - level: Metadata
    resources:
    - group: ""
      resources: ["pods/log", "pods/status"]
      # ロギング対象を pod 内のログやステータスに限定している
  # Don't log requests to a configmap called "controller-leader"
  - level: None
    resources:
    - group: ""
      resources: ["configmaps"]
      resourceNames: ["controller-leader"]
      # ロギング対象をリソース名で限定しています
  # Don't log watch requests by the "system:kube-proxy" on endpoints or services
  - level: None
    users: ["system:kube-proxy"]
    verbs: ["watch"]
    # ロギング対象を操作内容で限定しています
    resources:
    - group: "" # core API group
      resources: ["endpoints", "services"]
      # 複数オブジェクト存在する場合はカンマで区切って指定します
  # Don't log authenticated requests to certain non-resource URL paths.
  - level: None
    userGroups: ["system:authenticated"]
    nonResourceURLs:
    - "/api*" # Wildcard matching.
    - "/version"

  # Log the request body of configmap changes in kube-system.
  - level: Request
    resources:
    - group: "" # core API group
      resources: ["configmaps"]
    # This rule only applies to resources in the "kube-system" namespace.
    # The empty string "" can be used to select non-namespaced resources.
    namespaces: ["kube-system"]
    # namespace でロギング対象を限定しています
  # Log configmap and secret changes in all other namespaces at the Metadata level.
  - level: Metadata
    resources:
    - group: "" # core API group
      resources: ["secrets", "configmaps"]

  # Log all other resources in core and extensions at the Request level.
  - level: Request
    resources:
    - group: "" # core API group
    - group: "extensions" # Version of group should NOT be included.

  # A catch-all rule to log all other requests at the Metadata level.
  - level: Metadata
    # Long-running requests like watches that fall under this rule will not
    # generate an audit event in RequestReceived.
    omitStages:
      - "RequestReceived"
  # 最後のルールはその他ルールに該当しない全てのリクエストを対象とします。
  # 基本、None にしたり、上記のように Metadata のみロギングするなど設定します。

audit log 出力時の deployment は group に apps を指定するべきか確認する。

controlplane $ cat ../audit-policy/policy.yaml
# /etc/kubernetes/audit/policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:

# log Secret resources audits, level Metadata
- level: RequestResponse
  resources:
  - group: "apps"
    resources: ["deployments"]
  namespaces: ["test"]
controlplane $ tail -f ../audit-logs/audit.log |grep dep
{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"RequestResponse","auditID":"8bdfc262-1d6d-42b6-97c9-8d77defb9045","stage":"RequestReceived","requestURI":"/apis/apps/v1/namespaces/test/deployments/nginx-deploy","verb":"get","user":{"username":"system:serviceaccount:kube-system:generic-garbage-collector","uid":"6fd135c6-2b99-483d-a01e-c5272aa913f2","groups":["system:serviceaccounts","system:serviceaccounts:kube-system","system:authenticated"],"extra":{"authentication.kubernetes.io/credential-id":["JTI=5da5661c-6262-4c8b-9554-22bcdad8008d"]}},"sourceIPs":["172.30.1.2"],"userAgent":"kube-controller-manager/v1.31.0 (linux/amd64) kubernetes/9edcffc/system:serviceaccount:kube-system:generic-garbage-collector","objectRef":{"resource":"deployments","namespace":"test","name":"nginx-deploy","apiGroup":"apps","apiVersion":"v1"},"requestReceivedTimestamp":"2025-02-13T12:09:19.131306Z","stageTimestamp":"2025-02-13T12:09:19.131306Z"}

group に "apps" を指定すべきかどうかは kubectl resources コマンドの APIVERSION 列を確認すれば良いです。

controlplane $ kubectl api-resources |grep -e dep -e NAME 
NAME                                SHORTNAMES   APIVERSION                        NAMESPACED   KIND
deployments                         deploy       apps/v1                           true         Deployment
# deplyments リソースは `apps/v1` ですので、group に apps を指定する必要があります
controlplane $ kubectl api-resources |grep -e pod -e NAME 
NAME                                SHORTNAMES   APIVERSION                        NAMESPACED   KIND
pods                                po           v1                                true         Pod
# pods リソースh `v1` ですので、group は空で問題ありません

あとがき

ログレベルの書き方に注意が必要ですね。例えば、namespace 単位での設定方法など、設定単位を整理する必要がありそうです。

ソース

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?