本文已發布超過一年。較舊的文章可能包含過時的內容。請確認頁面中的資訊自發布以來未變得不正確。

OPA Gatekeeper:Kubernetes 的政策與治理

Open Policy Agent Gatekeeper 專案可用於協助執行政策並加強您 Kubernetes 環境中的治理。在本文中,我們將逐步介紹專案的目標、歷史和當前狀態。

以下是 Kubecon EU 2019 會議的錄音,是開始使用 Gatekeeper 的絕佳起點

動機

如果您的組織一直在營運 Kubernetes,您可能一直在尋找方法來控制終端使用者在叢集上可以執行的操作,以及確保叢集符合公司政策的方法。這些政策可能是為了滿足治理和法律要求,或為了執行最佳實務和組織慣例。使用 Kubernetes,您如何在不犧牲開發敏捷性和營運獨立性的情況下確保合規性?

例如,您可以執行如下政策:

  • 所有映像檔都必須來自核准的儲存庫
  • 所有 Ingress 主機名稱都必須是全域唯一的
  • 所有 Pod 都必須具有資源限制
  • 所有命名空間都必須具有列出聯絡點的標籤

Kubernetes 允許透過 准入控制器 Webhook 將政策決策與 API 伺服器分離,以在准入請求作為物件持久儲存在 Kubernetes 中之前攔截它們。Gatekeeper 的創建是為了讓使用者能夠透過組態(而非程式碼)自訂准入控制,並讓使用者了解叢集的狀態,而不僅僅是在准入時評估的單一物件。Gatekeeper 是 Kubernetes 的可自訂准入 Webhook,它執行由 Open Policy Agent (OPA) 執行的政策,OPA 是一個由 CNCF 託管的雲端原生環境的政策引擎。

演進

在我們深入探討 Gatekeeper 的當前狀態之前,讓我們先看看 Gatekeeper 專案是如何演進的。

  • Gatekeeper v1.0 - 使用 OPA 作為准入控制器,kube-mgmt Sidecar 執行基於 ConfigMap 的政策。它提供驗證和變更准入控制。由 Styra 捐贈。
  • Gatekeeper v2.0 - 使用 Kubernetes 政策控制器作為准入控制器,OPA 和 kube-mgmt Sidecar 執行基於 ConfigMap 的政策。它提供驗證和變更准入控制以及稽核功能。由 Microsoft 捐贈。
  • Gatekeeper v3.0 - 准入控制器與 OPA Constraint Framework 整合,以執行基於 CRD 的政策,並允許以宣告方式配置的政策可靠地共享。使用 kubebuilder 構建,它提供驗證和(最終將實作的)變更准入控制以及稽核功能。這使得能夠為 Rego 政策建立政策範本、以 CRD 形式建立政策,以及將稽核結果儲存在政策 CRD 上。這個專案是 Google、Microsoft、Red Hat 和 Styra 之間的合作。

Gatekeeper v3.0 功能

現在讓我們更仔細地看看 Gatekeeper 的當前狀態,以及您如何利用所有最新功能。假設有一個組織想要確保叢集中的所有物件都具有部門資訊,作為物件標籤的一部分。您如何使用 Gatekeeper 做到這一點?

驗證准入控制

一旦所有 Gatekeeper 組件都已 安裝 在您的叢集中,API 伺服器將觸發 Gatekeeper 准入 Webhook 來處理准入請求,每當叢集中的資源被建立、更新或刪除時。

在驗證過程中,Gatekeeper 充當 API 伺服器和 OPA 之間的橋樑。API 伺服器將執行由 OPA 執行的所有政策。

政策與約束

透過整合 OPA Constraint Framework,約束是一種宣告,其作者希望系統滿足一組給定的要求。每個約束都使用 Rego 編寫,Rego 是 OPA 使用的一種宣告式查詢語言,用於枚舉違反系統預期狀態的資料實例。所有約束都以邏輯 AND 方式評估。如果一個約束不滿足,則整個請求將被拒絕。

在定義約束之前,您需要建立一個約束範本,允許人們宣告新的約束。每個範本都描述了執行約束的 Rego 邏輯和約束的結構描述,其中包括 CRD 的結構描述和可以傳遞到約束的參數,很像函式的引數。

例如,這是一個約束範本 CRD,它要求在任意物件上存在某些標籤。

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8srequiredlabels
spec:
  crd:
    spec:
      names:
        kind: K8sRequiredLabels
        listKind: K8sRequiredLabelsList
        plural: k8srequiredlabels
        singular: k8srequiredlabels
      validation:
        # Schema for the `parameters` field
        openAPIV3Schema:
          properties:
            labels:
              type: array
              items: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8srequiredlabels

        deny[{"msg": msg, "details": {"missing_labels": missing}}] {
          provided := {label | input.review.object.metadata.labels[label]}
          required := {label | label := input.parameters.labels[_]}
          missing := required - provided
          count(missing) > 0
          msg := sprintf("you must provide labels: %v", [missing])
        }        

一旦約束範本已部署在叢集中,管理員現在可以建立由約束範本定義的個別約束 CRD。例如,這是一個約束 CRD,它要求在所有命名空間上存在 hr 標籤。

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: ns-must-have-hr
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Namespace"]
  parameters:
    labels: ["hr"]

同樣地,可以從同一個約束範本輕鬆建立另一個約束 CRD,它要求在所有命名空間上存在 finance 標籤。

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: ns-must-have-finance
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Namespace"]
  parameters:
    labels: ["finance"]

如您所見,透過約束框架,我們可以透過約束範本可靠地共享 Rego,使用 match 欄位定義執行範圍,並為約束提供使用者定義的參數,以針對每個約束建立自訂行為。

稽核

稽核功能可以定期評估針對叢集中執行的約束複製的資源,以偵測預先存在的不當組態。Gatekeeper 將稽核結果儲存為列在相關約束狀態欄位中的 violations

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: ns-must-have-hr
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Namespace"]
  parameters:
    labels: ["hr"]
status:
  auditTimestamp: "2019-08-06T01:46:13Z"
  byPod:
  - enforced: true
    id: gatekeeper-controller-manager-0
  violations:
  - enforcementAction: deny
    kind: Namespace
    message: 'you must provide labels: {"hr"}'
    name: default
  - enforcementAction: deny
    kind: Namespace
    message: 'you must provide labels: {"hr"}'
    name: gatekeeper-system
  - enforcementAction: deny
    kind: Namespace
    message: 'you must provide labels: {"hr"}'
    name: kube-public
  - enforcementAction: deny
    kind: Namespace
    message: 'you must provide labels: {"hr"}'
    name: kube-system

資料複寫

稽核需要將 Kubernetes 資源複寫到 OPA,然後才能根據執行的約束對其進行評估。需要存取叢集中物件(而非正在評估的物件)的約束也需要資料複寫。例如,強制執行 Ingress 主機名稱唯一性的約束必須能夠存取叢集中的所有其他 Ingress。

若要組態要複寫的 Kubernetes 資料,請使用要複寫到 OPA 的資源建立同步組態資源。例如,以下組態將所有命名空間和 Pod 資源複寫到 OPA。

apiVersion: config.gatekeeper.sh/v1alpha1
kind: Config
metadata:
  name: config
  namespace: "gatekeeper-system"
spec:
  sync:
    syncOnly:
      - group: ""
        version: "v1"
        kind: "Namespace"
      - group: ""
        version: "v1"
        kind: "Pod"

未來規劃

Gatekeeper 專案背後的社群將專注於提供變更准入控制以支援變更案例(例如:在建立新資源時自動使用部門資訊註解物件)、支援外部資料,將叢集外部的內容注入到准入決策中、支援 Dry Run,以在執行政策之前查看政策對叢集中現有資源的影響,以及更多稽核功能。

如果您有興趣了解更多關於此專案的資訊,請查看 Gatekeeper 儲存庫。如果您有興趣協助定義 Gatekeeper 的方向,請加入 OPA Slack 上的 #kubernetes-policy 頻道,並加入我們的 每週會議,討論開發、問題、使用案例等。