Kubernetes 叢集安全至關重要,本文探討如何應用「國防深度」策略,建立多層次安全防護。除了驗證、授權、網路政策等基礎安全措施外,更涵蓋 Kubernetes 稽核、高用性設計和異常偵測等進階議題。透過稽核功能,管理員可以追蹤叢集活動,及早發現潛在威脅。高用性設計則確保服務即使在部分節點故障時仍能持續運作,提升系統穩定性。最後,文章也介紹了異常偵測工具 Falco,協助管理員主動識別並應對安全事件。

國防深度:強化 Kubernetes 叢集安全性

在網路安全領域中,「國防深度」(Defense in Depth)是一種透過多層次安全控制來保護重要資產的方法。在傳統或單一的 IT 環境中,我們可以列出多種安全控制措施,例如驗證、加密、授權、日誌記錄、入侵偵測、反病毒軟體、虛擬私人網路(VPN)和防火牆等。這些安全控制措施同樣適用於 Kubernetes 叢集。

多層次安全控制

在前面的章節中,我們已經討論了驗證、授權、准入控制器、Kubernetes 元件安全、組態安全、映像檔強化和 Kubernetes 工作負載等主題。這些措施共同構成了保護 Kubernetes 叢集的多層次安全控制。在本章中,我們將進一步探討與執行階段防禦相關的主題,包括 Kubernetes 稽核、高用性、金鑰管理、異常偵測和數位鑑識等。

本章重點

  • 介紹 Kubernetes 稽核
  • 在 Kubernetes 叢集中啟用高用性
  • 使用 Vault 管理金鑰
  • 使用 Falco 偵測異常活動
  • 使用 Sysdig Inspect 和 CRIU 進行數位鑑識

介紹 Kubernetes 稽核

Kubernetes 稽核功能在 1.11 版本中被引入,用於記錄叢集中的事件,例如建立佈署、修補 Pod 和刪除名稱空間等。透過稽核功能,Kubernetes 叢集管理員可以回答以下問題:

  • 發生了什麼事件?(例如,建立了什麼樣的 Pod)
  • 誰執行了該操作?(使用者或管理員)
  • 事件發生的時間?(事件的時間戳)
  • 事件發生的位置?(在哪個名稱空間中建立了 Pod)

從安全的角度來看,稽核功能可以幫助 DevOps 和安全團隊更好地進行異常偵測和預防。

Kubernetes 稽核政策

由於記錄叢集中的所有事件是不現實的,因此需要定義稽核政策來指定哪些事件應該被記錄以及記錄多少詳細資訊。下面是一個稽核政策的範例:

apiVersion: audit.k8s.io/v1
kind: Policy
omitStages:
  - "RequestReceived"
rules:
  - level: RequestResponse
    verbs: ["create", "update"]
    namespace: ["ns1", "ns2", "ns3"]
    resources:
      - group: ""
        resources: ["pods"]
  - level: Metadata
    resources:
      - group: ""
        resources: ["pods/log", "pods/status"]

稽核政策組態

稽核政策允許您透過指定 verbnamespaceresources 等欄位來組態細粒度的政策。其中,level 欄位定義了稽核事件的詳細程度。共有四個稽核級別:

  • None:不記錄符合稽核規則的事件
  • Metadata:記錄請求的元資料(例如使用者、時間戳、資源、動詞等)
  • Request:記錄元資料和請求主體(不適用於非資源 URL)
  • RequestResponse:記錄元資料、請求主體和回應主體(不適用於非資源請求)

稽核政策範例解說

apiVersion: audit.k8s.io/v1 # 必填
kind: Policy
# 略過 RequestReceived 階段的稽核事件產生,可在政策或規則層級設定
omitStages:
  - "RequestReceived"
rules:
  # 在 RequestResponse 級別記錄 Pod 的變更
  - level: RequestResponse
    verbs: ["create", "update"]
    namespace: ["ns1", "ns2", "ns3"]
    resources:
      - group: "" # 核心 API 群組
        resources: ["pods"] # 只檢查 pods 資源,不檢查子資源
  # 在 Metadata 級別記錄 pods/log 和 pods/status
  - level: Metadata
    resources:
      - group: ""
        resources: ["pods/log", "pods/status"]

#### 內容解密:

此 YAML 組態定義了一個 Kubernetes 稽核政策,用於指定哪些事件應該被記錄以及記錄多少詳細資訊。其中,omitStages欄位用於略過某些階段的稽核事件產生,而 rules欄位則定義了多個稽核規則。每個規則都指定了 levelverbsnamespaceresources 等欄位,以確定哪些事件應該被記錄以及如何記錄。

Kubernetes 稽核功能介紹

Kubernetes 稽核功能提供了對叢集中物件操作的詳細記錄,能夠幫助管理員瞭解叢集的執行狀況和潛在的安全風險。稽核日誌可以記錄不同層級的事件,從簡單的 metadata 到完整的 RequestResponse 資訊。

稽核層級

Kubernetes 提供了多種稽核層級,以滿足不同的需求:

  • Metadata:記錄最基本的事件資訊,如使用者、時間戳記和被存取的物件等。
  • Request:除了 Metadata 的資訊外,還包括請求物件的詳細內容。
  • RequestResponse:最詳細的層級,包含請求和回應物件的完整資訊。

Metadata 層級稽核事件範例

{
  "kind": "Event",
  "apiVersion": "audit.k8s.io/v1",
  "level": "Metadata",
  "auditID": "05698e93-6ad7-4f4e-8ae9-046694bee469",
  "stage": "ResponseComplete",
  "requestURI": "/api/v1/namespaces/ns1/pods",
  "verb": "create",
  "user": {
    "username": "admin",
    "uid": "admin",
    "groups": [
      "system:masters",
      "system:authenticated"
    ]
  },
  "sourceIPs": [
    "98.207.36.92"
  ],
  "userAgent": "kubectl/v1.17.4 (darwin/amd64) kubernetes/8d8aa39",
  "objectRef": {
    "resource": "pods",
    "namespace": "ns1",
    "name": "pod-1",
    "apiVersion": "v1"
  },
  "responseStatus": {
    "metadata": {},
    "code": 201
  },
  "requestReceivedTimestamp": "2020-04-09T07:10:52.471720Z",
  "stageTimestamp": "2020-04-09T07:10:52.485551Z",
  "annotations": {
    "authorization.k8s.io/decision": "allow",
    "authorization.k8s.io/reason": ""
  }
}

Request 層級稽核事件範例

Request 層級的稽核事件會在 Metadata 的基礎上增加 requestObject 欄位,詳細記錄了請求物件的內容。

"requestObject": {
  "kind": "Pod",
  "apiVersion": "v1",
  "metadata": {
    "name": "pod-2",
    "namespace": "ns2",
    "creationTimestamp": null,
    ...
  },
  "spec": {
    "containers": [
      {
        "name": "echo",
        "image": "busybox",
        "command": [
          "sh",
          "-c",
          "echo 'this is echo' && sleep 1h"
        ],
        ...
        "imagePullPolicy": "Always"
      }
    ],
    ...
    "securityContext": {},
  }
}

RequestResponse 層級稽核事件範例

RequestResponse 是最詳細的稽核層級,除了包含 Request 的所有資訊外,還包括 responseObject,提供了回應物件的詳細資訊。

"responseObject": {
  ...
  "selfLink": "/api/v1/namespaces/ns3/pods/pod-3",
  "uid": "3fd18de1-7a31-11ea-9e8d-0a39f00d8287",
  "resourceVersion": "217243",
  "creationTimestamp": "2020-04-09T07:10:53Z",
  "tolerations": [
    {
      "key": "node.kubernetes.io/not-ready",
      "operator": "Exists",
      "effect": "NoExecute",
      "tolerationSeconds": 300
    },
    {
      "key": "node.kubernetes.io/unreachable",
      "operator": "Exists",
      "effect": "NoExecute",
      "tolerationSeconds": 300
    }
  ],
  ...
}

稽核層級選擇的重要性

選擇適當的稽核層級非常重要。較高的稽核層級(如 RequestResponse)能夠提供更深入的洞察,但也會消耗更多的儲存空間和處理時間。對於包含敏感資料的 Kubernetes 物件,如 Secret,設定過高的稽核層級可能會導致敏感資訊被記錄在稽核事件中,因此需要使用敏感資料遮蔽機制來避免這種情況。

組態稽核後端

要啟用 Kubernetes 稽核功能,需要在啟動 kube-apiserver 時透過 --audit-policy-file 引數指定稽核策略檔案。稽核後端可以組態為將稽核事件處理到不同的目的地。

日誌後端

日誌後端將稽核事件寫入 master 節點上的檔案。可以透過以下引陣列態日誌後端:

  • --log-audit-path:指定日誌檔案的路徑,用於啟用或停用日誌後端。
  • --audit-log-maxage:指定保留稽核記錄的最大天數。
  • --audit-log-maxbackup:指定 master 節點上保留的最大稽核檔案數量。
  • --audit-log-maxsize:指定稽核日誌檔案在輪替前的最大大小(以 MB 為單位)。

Webhook 後端

Webhook 後端將稽核事件傳送到註冊到 kube-apiserver 的遠端 Webhook。可以透過 --audit-webhook-config-file 引數指定 Webhook 組態檔案來啟用 Webhook 後端。

Webhook 組態範例
apiVersion: v1
kind: Config
clusters:
- name: falco
  cluster:
    server: http://$FALCO_SERVICE_CLUSTERIP:8765/k8s_audit
contexts:
- context:
    cluster: falco
    user: ""
  name: default-context
current-context: default-context
preferences: {}
users: []

此組態範例中,Webhook 後端將稽核事件傳送到 Falco 服務的遠端端點。

在 Kubernetes 叢集中啟用高用性

高用性是指使用者能夠存取服務或系統的能力。系統的高用性確保了系統的約定可用時間。例如,如果只有一個例項來服務,而該例項宕機了,使用者就無法再存取該服務。具有高用性的服務由多個例項提供。當一個例項宕機時,備使用案例項或備份例項仍可提供服務。下圖描述了具有和不具有高用性的服務:

此圖示展示了服務在不同可用性組態下的運作狀態。在 Kubernetes 叢集中,通常會有不止一個工作節點。叢集的高用性得以保證,即使一個工作節點宕機,也會有其他工作節點來承載工作負載。然而,高用性不僅僅是在叢集中執行多個節點。在本文中,我們將從工作負載、Kubernetes 元件和雲端基礎設施三個層面來探討 Kubernetes 叢集中的高用性。

啟用 Kubernetes 工作負載的高用性

對於 Kubernetes 工作負載,如 Deployment 和 StatefulSet,您可以在規範中指定 replicas 欄位,以確定有多少複製的 Pod 正在為微服務執行。控制器將確保在叢集中的不同工作節點上執行指定數量的 Pod。DaemonSet 是一種特殊的工作負載;控制器將確保在叢集中的每個節點上執行一個 Pod,假設您的 Kubernetes 叢集有多個節點。因此,在 Deployment 或 StatefulSet 中指定多個副本,或使用 DaemonSet,將確保您的工作負載具有高用性。為了確保工作負載的高用性,也需要確保 Kubernetes 元件的高用性。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: example-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: example
  template:
    metadata:
      labels:
        app: example
    spec:
      containers:
      - name: example-container
        image: example-image
        ports:
        - containerPort: 80

內容解密:

此 YAML 組態檔案定義了一個名為 example-deployment 的 Deployment 物件。其中,replicas: 3 指定了需要執行 3 個副本。selectortemplate 部分定義瞭如何選擇和建立 Pod。containers 部分則定義了容器相關的組態,包括使用的映像檔和開放的連線埠。

啟用 Kubernetes 元件的高用性

高用性同樣適用於 Kubernetes 元件。讓我們回顧一些關鍵的 Kubernetes 元件:

  • kube-apiserver:Kubernetes API 伺服器(kube-apiserver)是一個控制平面元件,用於驗證和組態 Pod、服務和控制器等物件的資料。它使用 REST 請求與這些物件互動。
  • etcdetcd 是一個高可用性的鍵值儲存,用於儲存組態、狀態和後設資料等資料。其監視功能使 Kubernetes 能夠監聽組態的更新並相應地進行更改。
  • kube-schedulerkube-scheduler 是 Kubernetes 的預設排程器。它監視新建立的 Pod 並將它們分配給節點。
  • kube-controller-manager:Kubernetes 控制器管理器是核心控制器的組合,它監視狀態更新並相應地對叢集進行更改。

如果 kube-apiserver 宕機,則基本上您的叢集就宕機了,因為使用者或其他 Kubernetes 元件依賴於與 kube-apiserver 的通訊來執行任務。如果 etcd 宕機,則叢集和物件的狀態都無法被存取。kube-schedulerkube-controller-manager 也很重要,以確保工作負載在叢集中正常執行。所有這些元件都在主節點上執行,為了確保這些元件的高用性,一種直接的方法是為您的 Kubernetes 叢集啟動多個主節點,無論是透過 kops 還是 kubeadm

$ kubectl get pods -n kube-system
...
etcd-manager-events-ip-172-20-109-109.ec2.internal 1/1 Running 0 4h15m
etcd-manager-events-ip-172-20-43-65.ec2.internal 1/1 Running 0 4h16m
etcd-manager-events-ip-172-20-67-151.ec2.internal 1/1 Running 0 4h16m
...

內容解密:

此命令用於取得 kube-system 名稱空間中的 Pod 狀態。輸出顯示了多個 etcd-manager Pod 和其他 Kubernetes 元件的 Pod,它們都在不同的主節點上執行。這確保了即使某個主節點宕機,其他節點上的元件仍可繼續提供服務,從而實作高用性。

雲端基礎設施的高用性

無論您的 Kubernetes 叢集是在公有雲還是在私有資料中心執行,基礎設施都是支援 Kubernetes 叢集可用性的根本。接下來,我們將以雲端供應商為例,討論雲端基礎設施的高用性。