本頁面說明如何編寫自訂限制範本,並在找不到符合需求的預先編寫限制範本時,使用該範本擴充 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 |
限制資源的 |
在限制範本前加上 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 |
|
name |
資源名稱。如果使用者依賴 API 伺服器在 CREATE 要求中產生名稱,這個欄位可能會空白。 |
namespace |
資源命名空間 (叢集範圍內的資源未提供)。 |
operation |
要求的作業 (例如 CREATE 或 UPDATE),稽核期間無法使用。 |
userInfo |
要求者的資訊,稽核期間無法使用。 格式如下:
|
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
欄位。
範本擷取完畢後,您就可以按照「建立限制」一文所述,為範本套用限制。
移除限制範本
如要移除限制範本,請完成下列步驟:
確認要保留的限制條件未使用限制範本:
kubectl get TEMPLATE_NAME
如果限制範本的名稱與叢集中的其他物件發生命名衝突,請改用下列指令:
kubectl get TEMPLATE_NAME.constraints.gatekeeper.sh
移除限制範本:
kubectl delete constrainttemplate CONSTRAINT_TEMPLATE_NAME
移除限制範本後,您就無法再建立參照該範本的限制。
後續步驟
- 進一步瞭解 Policy Controller。
- 查看限制範本庫參考說明文件。
- 瞭解如何使用限制取代 PodSecurityPolicies。