本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。

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 sidecars 強制執行基於 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 邏輯和約束的 schema,其中包括 CRD 的 schema 和可以傳遞給約束的引數,很像函式的引數。

例如,這是一個約束模板 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,使用匹配欄位定義強制範圍,並向約束提供使用者定義的引數,為每個約束建立自定義行為。

審計

審計功能允許定期評估複製的資源與叢集中強制執行的約束,以檢測預先存在的錯誤配置。Gatekeeper 將審計結果儲存為相關約束的 status 欄位中列出的 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 資料,請建立一個 sync config 資源,其中包含要複製到 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 專案的社群將專注於提供修改准入控制以支援修改場景(例如:在建立新資源時自動為物件新增部門資訊)、支援外部資料以將叢集外部的上下文注入到准入決策中、支援試執行以在強制執行策略之前檢視策略對叢集中現有資源的影響,以及更多審計功能。

如果您有興趣瞭解更多關於該專案的資訊,請檢視 Gatekeeper 倉庫。如果您有興趣幫助定義 Gatekeeper 的方向,請加入 OPA Slack 上的 #kubernetes-policy 頻道,並參加我們的每週會議,討論開發、問題、用例等。