編寫自訂限制範本

本頁面說明如何編寫自訂限制範本,並在找不到符合需求的預先編寫限制範本時,使用該範本擴充 Policy Controller

本頁內容適用於 IT 管理員和營運人員,他們希望確保雲端平台中執行的所有資源都符合機構的法規遵循規定,因此提供並維護自動化功能來稽核或強制執行,以及使用宣告式設定的範本。如要進一步瞭解 Google Cloud 內容中提及的常見角色和範例工作,請參閱常見的 GKE Enterprise 使用者角色和工作

Policy Controller 政策是使用 OPA 限制架構說明,並以 Rego 編寫而成。政策可以評估 Kubernetes 物件的任何欄位。

使用 Rego 編寫政策需要專業技能。因此,系統預設會安裝常見限制範本程式庫。建立限制時,您可能會叫用這些限制範本。如有特殊需求,可以建立自己的限制範本。

您可以使用限制範本,將政策的邏輯與特定需求分開,以便重複使用及委派。您可以透過第三方開發的限制範本 (例如開放原始碼專案、軟體供應商或法規專家),建立限制。

事前準備

限制範本範例

以下是限制範本範例,會拒絕名稱與限制建立者提供的值相符的所有資源。本頁面其餘部分將討論範本內容,並重點說明重要概念。

如果您使用 Config Sync 和階層式存放區,建議在 cluster/ 目錄中建立限制。

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8sdenyname
spec:
  crd:
    spec:
      names:
        kind: K8sDenyName
      validation:
        # Schema for the `parameters` field
        openAPIV3Schema:
          properties:
            invalidName:
              type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sdenynames
        violation[{"msg": msg}] {
          input.review.object.metadata.name == input.parameters.invalidName
          msg := sprintf("The name %v is not allowed", [input.parameters.invalidName])
        }

限制範例

以下是您可能導入的限制範例,可拒絕所有名為 policy-violation 的資源:

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sDenyName
metadata:
  name: no-policy-violation
spec:
  parameters:
    invalidName: "policy-violation"

限制範本的組成部分

限制範本有兩個重要部分:

  • 您希望使用者建立的限制條件結構定義。限制範本的結構定義會儲存在 crd 欄位中。

  • 評估限制條件時執行的 Rego 原始碼。範本的 Rego 原始碼會儲存在 targets 欄位中。

結構定義 (crd 欄位)

CRD 欄位是建立 Kubernetes 自訂資源定義的藍圖,可定義 Kubernetes API 伺服器的限制資源。您只需要填寫下列欄位。

欄位 說明
spec.crd.spec.names.kind 限制的種類。這個欄位的值必須等於 metadata.name (小寫)。
spec.crd.spec.validation.openAPIV3Schema

限制資源的 spec.parameters 欄位結構定義 (Policy Controller 會自動定義其餘限制的結構定義)。遵循與一般 CRD 資源相同的慣例。

在限制範本前加上 K8s 名稱是慣例,可避免與其他類型的限制範本發生衝突,例如以 Google Cloud 資源為目標的 Forseti 範本。

Rego 原始碼 (targets 欄位)

下列各節將提供 Rego 原始碼的詳細資訊。

位置

Rego 原始碼會儲存在 spec.targets 欄位中,其中 targets 是以下列格式表示的物件陣列:

{"target": "admission.k8s.gatekeeper.sh","rego": REGO_SOURCE_CODE, "libs": LIST_OF_REGO_LIBRARIES}
  • target:告知 Policy Controller 我們要查看的系統 (在本例中為 Kubernetes);targets 中只能有一個項目。
  • rego:限制的原始碼。
  • libs:Rego 程式碼的選用程式庫清單,可供限制範本使用,目的是為了方便使用共用程式庫,但不在本文範圍內。

原始碼

以下是上述限制的 Rego 原始碼:

package k8sdenynames

violation[{"msg": msg}] {
   input.review.object.metadata.name == input.parameters.invalidName
   msg := sprintf("The name %v is not allowed", [input.parameters.invalidName])
}

注意事項:

  • OPA (Rego 的執行階段) 需要 package k8sdenynames。該值會遭到忽略。
  • Policy Controller 會叫用 Rego 規則,查看是否有任何違規事項,這項規則稱為「violation」。如果這項規則有相符項目,即表示發生限制違規事件。
  • violation 規則的簽章為 violation[{"msg": "violation message for the user"}],其中 "msg" 的值是傳回給使用者的違規訊息。
  • 提供給限制的參數會顯示在關鍵字 input.parameters 下方。
  • request-under-test 儲存在關鍵字 input.review 下。

關鍵字 input.review 具有下列欄位。

欄位 說明
uid 這項要求的專屬 ID,稽核期間無法使用。
kind

object-under-test的種類資訊。格式如下:

  • kind:資源種類
  • group:資源群組
  • version:資源版本
name 資源名稱。如果使用者依賴 API 伺服器在 CREATE 要求中產生名稱,這個欄位可能會空白。
namespace 資源命名空間 (叢集範圍內的資源未提供)。
operation 要求的作業 (例如 CREATE 或 UPDATE),稽核期間無法使用。
userInfo

要求者的資訊,稽核期間無法使用。 格式如下:

  • username:提出要求的使用者
  • uid:使用者的 UID
  • groups:使用者所屬的群組清單
  • extra:Kubernetes 提供的任何額外使用者資訊
object 使用者嘗試修改或建立的物件。
oldObject 物件的原始狀態,僅適用於 UPDATE 作業。
dryRun 這項要求是否是透過 kubectl --dry-run 叫用; 稽核期間無法使用。

編寫參照限制範本

參照限制範本可讓使用者根據其他物件限制某個物件。舉例來說,您可能會想「在已知有相符的 Ingress 存在之前,不允許建立 Pod」。另一個例子可能是「不允許兩個服務使用相同的主機名稱」。

Policy Controller 會監控 API 伺服器中使用者提供的一組資源,讓您編寫參照限制。資源修改後,Policy Controller 會在本地快取資源,方便 Rego 原始碼參照。Policy Controller 會透過 data.inventory 關鍵字提供這個快取。

叢集範圍內的資源會快取在下列位置:

data.inventory.cluster["GROUP_VERSION"]["KIND"]["NAME"]

舉例來說,名為 my-favorite-node 的節點可能位於

data.inventory.cluster["v1"]["Node"]["my-favorite-node"]

命名空間範圍內的資源會快取在這裡:

data.inventory.namespace["NAMESPACE"]["GROUP_VERSION"]["KIND"]["NAME"]

舉例來說,命名空間 shipping-prod 中名為 production-variables 的 ConfigMap 可能位於

data.inventory.namespace["shipping-prod"]["v1"]["ConfigMap"]["production-variables"]

物件的完整內容會儲存在這個快取位置,您可以在 Rego 原始碼中參照這些內容。

進一步瞭解 Rego

上述資訊說明 Policy Controller 的獨特功能,可讓您輕鬆在 Rego 中編寫 Kubernetes 資源的限制。本指南不會提供有關如何使用 Rego 編寫程式碼的完整教學課程。不過,Open Policy Agent 的文件提供 Rego 語言本身的語法和功能資訊。

安裝限制範本

建立限制範本後,請使用 kubectl apply 套用,Policy Controller 會負責擷取範本。請務必檢查限制範本的 status 欄位,確認例項化時沒有發生錯誤。成功擷取後,status 欄位應會顯示 created: true,且 status 欄位中註記的 observedGeneration 應等於 metadata.generation 欄位。

範本擷取完畢後,您就可以按照「建立限制」一文所述,為範本套用限制。

移除限制範本

如要移除限制範本,請完成下列步驟:

  1. 確認要保留的限制條件未使用限制範本:

    kubectl get TEMPLATE_NAME
    

    如果限制範本的名稱與叢集中的其他物件發生命名衝突,請改用下列指令:

    kubectl get TEMPLATE_NAME.constraints.gatekeeper.sh
    
  2. 移除限制範本:

    kubectl delete constrainttemplate CONSTRAINT_TEMPLATE_NAME
    

移除限制範本後,您就無法再建立參照該範本的限制。

後續步驟