驗證准入策略
Kubernetes v1.30 [穩定]
本頁面概述了驗證准入策略。
什麼是驗證准入策略?
驗證准入策略提供了一種宣告式、在程序中進行的替代方案,以取代驗證准入 Webhook。
驗證准入策略使用通用表達式語言 (CEL) 來宣告策略的驗證規則。驗證准入策略具有高度可配置性,使策略作者能夠定義可參數化並根據叢集管理員的需求將範圍限定於資源的策略。
構成策略的資源
一個策略通常由三個資源組成
ValidatingAdmissionPolicy
描述了策略的抽象邏輯(想想:「此策略確保將特定標籤設定為特定值」)。ValidatingAdmissionPolicyBinding
將上述資源連結在一起並提供範圍界定。如果您只想要求為Pod
設定owner
標籤,則繫結是您指定此限制的位置。參數資源向 ValidatingAdmissionPolicy 提供資訊,使其成為具體陳述(想想:「
owner
標籤必須設定為以.company.com
結尾的內容」)。ConfigMap 或 CRD 等原生類型定義了參數資源的結構描述。ValidatingAdmissionPolicy
物件指定它們期望其參數資源的 Kind 是什麼。
至少必須定義 ValidatingAdmissionPolicy
和對應的 ValidatingAdmissionPolicyBinding
,策略才能生效。
如果 ValidatingAdmissionPolicy
不需要透過參數進行配置,只需將 ValidatingAdmissionPolicy
中的 spec.paramKind
保持未指定即可。
開始使用驗證准入策略
驗證准入策略是叢集控制平面的一部分。您應謹慎編寫和部署它們。以下說明如何快速試驗驗證准入策略。
建立 ValidatingAdmissionPolicy
以下是 ValidatingAdmissionPolicy 的範例。
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: "demo-policy.example.com"
spec:
failurePolicy: Fail
matchConstraints:
resourceRules:
- apiGroups: ["apps"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["deployments"]
validations:
- expression: "object.spec.replicas <= 5"
spec.validations
包含 CEL 表達式,這些表達式使用通用表達式語言 (CEL)來驗證請求。如果表達式評估為 false,則根據 spec.failurePolicy
欄位強制執行驗證檢查。
注意
您可以在CEL Playground中快速測試 CEL 表達式。若要設定驗證准入策略以在叢集中使用,則需要繫結。以下是 ValidatingAdmissionPolicyBinding 的範例。
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: "demo-binding-test.example.com"
spec:
policyName: "demo-policy.example.com"
validationActions: [Deny]
matchResources:
namespaceSelector:
matchLabels:
environment: test
當嘗試建立副本集設定不滿足驗證表達式的部署時,將傳回包含訊息的錯誤
ValidatingAdmissionPolicy 'demo-policy.example.com' with binding 'demo-binding-test.example.com' denied request: failed expression: object.spec.replicas <= 5
以上提供了一個在未設定參數的情況下使用 ValidatingAdmissionPolicy 的簡單範例。
驗證動作
每個 ValidatingAdmissionPolicyBinding
都必須指定一個或多個 validationActions
,以宣告如何強制執行策略的 validations
。
支援的 validationActions
為
Deny
:驗證失敗會導致請求被拒絕。Warn
:驗證失敗會以警告的形式報告給請求用戶端。Audit
:驗證失敗會包含在 API 請求的稽核事件中。
例如,若要同時警告用戶端驗證失敗並稽核驗證失敗,請使用
validationActions: [Warn, Audit]
Deny
和 Warn
不可一起使用,因為此組合不必要地重複了 API 回應主體和 HTTP 警告標頭中的驗證失敗。
評估為 false 的 validation
始終根據這些動作強制執行。只有在 failurePolicy
設定為 Fail
(或未指定)時,才根據這些動作強制執行 failurePolicy
定義的失敗,否則將忽略這些失敗。
有關驗證失敗稽核註解的更多詳細資訊,請參閱稽核註解:驗證失敗。
參數資源
參數資源允許策略配置與其定義分離。策略可以定義 paramKind,概述參數資源的 GVK,然後策略繫結通過名稱(通過 policyName)將策略與特定的參數資源通過 paramRef 綁定。
如果需要參數配置,以下是一個帶有參數配置的 ValidatingAdmissionPolicy 範例。
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: "replicalimit-policy.example.com"
spec:
failurePolicy: Fail
paramKind:
apiVersion: rules.example.com/v1
kind: ReplicaLimit
matchConstraints:
resourceRules:
- apiGroups: ["apps"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["deployments"]
validations:
- expression: "object.spec.replicas <= params.maxReplicas"
reason: Invalid
ValidatingAdmissionPolicy 的 spec.paramKind
欄位指定用於參數化此策略的資源種類。在此範例中,它由 ReplicaLimit 自訂資源配置。請注意此範例中 CEL 表達式如何通過 CEL params 變數引用參數,例如 params.maxReplicas
。spec.matchConstraints
指定此策略旨在驗證哪些資源。請注意,原生類型(例如 ConfigMap
)也可以用作參數參考。
spec.validations
欄位包含 CEL 表達式。如果表達式評估為 false,則根據 spec.failurePolicy
欄位強制執行驗證檢查。
驗證許可策略作者負責提供 ReplicaLimit 參數 CRD。
若要配置驗證許可策略以在叢集中使用,則需要建立繫結和參數資源。以下是一個 ValidatingAdmissionPolicyBinding 的範例,該範例使用集群範圍參數 - 相同的參數將用於驗證每個符合繫結的資源請求
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: "replicalimit-binding-test.example.com"
spec:
policyName: "replicalimit-policy.example.com"
validationActions: [Deny]
paramRef:
name: "replica-limit-test.example.com"
namespace: "default"
matchResources:
namespaceSelector:
matchLabels:
environment: test
請注意,此繫結將參數應用於 test
環境中的所有資源的策略。
參數資源可能如下所示
apiVersion: rules.example.com/v1
kind: ReplicaLimit
metadata:
name: "replica-limit-test.example.com"
namespace: "default"
maxReplicas: 3
此策略參數資源將部署限制為最多 3 個副本。
一個許可策略可能有多個繫結。若要繫結所有其他環境以將 maxReplicas 限制設定為 100,請建立另一個 ValidatingAdmissionPolicyBinding
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: "replicalimit-binding-nontest"
spec:
policyName: "replicalimit-policy.example.com"
validationActions: [Deny]
paramRef:
name: "replica-limit-prod.example.com"
namespace: "default"
matchResources:
namespaceSelector:
matchExpressions:
- key: environment
operator: NotIn
values:
- test
請注意,此繫結將不同的參數應用於不在 test
環境中的資源。
並具有參數資源
apiVersion: rules.example.com/v1
kind: ReplicaLimit
metadata:
name: "replica-limit-prod.example.com"
maxReplicas: 100
對於每個許可請求,API 伺服器評估符合請求的每個(策略、繫結、參數)組合的 CEL 表達式。為了允許請求,它必須通過所有評估。
如果多個繫結符合請求,則將針對每個繫結評估策略,並且它們都必須通過評估才能將策略視為通過。
如果多個參數符合單個繫結,則將針對每個參數評估策略規則,並且它們也必須全部通過才能將繫結視為通過。繫結可能具有重疊的匹配條件。針對每個匹配的繫結-參數組合評估策略。如果多個繫結符合策略,或者符合多個參數的單個繫結,則甚至可以多次評估策略。
如果未繫結參數資源,則不會設定表示參數資源的 params 物件,因此對於需要參數資源的策略,新增檢查以確保已繫結一個參數資源會很有用。如果未指定策略的 paramKind
或繫結的 paramRef
,則不會繫結參數資源,並且 params
將為 null。
對於需要參數配置的使用案例,我們建議在 spec.validations[0].expression
中新增參數檢查
- expression: "params != null"
message: "params missing but required to bind to this policy"
選用參數
能夠將選用參數作為參數資源的一部分,並且僅在存在時驗證它們可能會很方便。CEL 提供了 has()
,用於檢查傳遞給它的鍵是否存在。CEL 也實作了布林短路。如果邏輯 OR 的前半部分評估為 true,則它不會評估後半部分(因為整個 OR 的結果無論如何都將為 true)。
結合兩者,我們可以提供一種驗證選用參數的方法
!has(params.optionalNumber) || (params.optionalNumber >= 5 && params.optionalNumber <= 10)
在這裡,我們首先使用 !has(params.optionalNumber)
檢查選用參數是否存在。
- 如果尚未定義
optionalNumber
,則表達式會短路,因為!has(params.optionalNumber)
將評估為 true。 - 如果已定義
optionalNumber
,則將評估 CEL 表達式的後半部分,並且將檢查 optionalNumber 以確保它包含介於 5 到 10(含)之間的值。
每個命名空間的參數
作為 ValidatingAdmissionPolicy 及其 ValidatingAdmissionPolicyBinding 的作者,您可以選擇指定集群範圍或每個命名空間的參數。如果您為繫結的 paramRef
指定了 namespace
,則控制平面只會在該命名空間中搜尋參數。
但是,如果在 ValidatingAdmissionPolicyBinding 中未指定 namespace
,則 API 伺服器可以在請求針對的命名空間中搜尋相關參數。例如,如果您發出請求以修改 default
命名空間中的 ConfigMap,並且存在沒有設定 namespace
的相關 ValidatingAdmissionPolicyBinding,則 API 伺服器會在 default
中尋找參數物件。此設計允許取決於正在操作的資源的命名空間的策略配置,以實現更精細的控制。
參數選擇器
除了通過 name
在繫結中指定參數之外,您還可以選擇指定標籤選擇器,以便選擇所有策略 paramKind
的資源,以及符合標籤選擇器的參數的 namespace
(如果適用)以進行評估。有關標籤選擇器如何匹配資源的更多資訊,請參閱選擇器。
如果發現多個參數符合條件,則會針對找到的每個參數評估策略規則,並且結果將進行 AND 運算。
如果提供了 namespace
,則只有所提供命名空間中 paramKind
的物件才有資格被選取。否則,當 namespace
為空且 paramKind
具有命名空間作用域時,將使用許可請求中使用的 namespace
。
授權檢查
我們引入了參數資源的授權檢查。使用者應具有對 ValidatingAdmissionPolicy
中的 paramKind
和 ValidatingAdmissionPolicyBinding
中的 paramRef
引用的資源的 read
存取權。
請注意,如果 paramKind
中的資源通過 restmapper 解析失敗,則需要對群組的所有資源進行 read
存取。
失敗策略
failurePolicy
定義了如何處理來自許可策略的錯誤配置和評估為錯誤的 CEL 表達式。允許的值為 Ignore
或 Fail
。
Ignore
表示呼叫 ValidatingAdmissionPolicy 時發生錯誤將被忽略,並且 API 請求被允許繼續。Fail
表示呼叫 ValidatingAdmissionPolicy 時發生錯誤會導致許可失敗,並且 API 請求將被拒絕。
請注意,failurePolicy
是在 ValidatingAdmissionPolicy
內部定義的
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
spec:
...
failurePolicy: Ignore # The default is "Fail"
validations:
- expression: "object.spec.xyz == params.x"
驗證表達式
spec.validations[i].expression
表示將由 CEL 評估的表達式。若要瞭解更多資訊,請參閱 CEL 語言規範。CEL 表達式可以存取許可請求/回應的內容,這些內容組織成 CEL 變數以及其他一些有用的變數
- ’object’ - 來自傳入請求的物件。對於 DELETE 請求,該值為 null。
- ’oldObject’ - 現有的物件。對於 CREATE 請求,該值為 null。
- ’request’ - 許可請求的屬性。
- ’params’ - 由正在評估的策略繫結引用的參數資源。如果未指定
ParamKind
,則該值為 null。 namespaceObject
- 傳入物件所屬的命名空間(作為 Kubernetes 資源)。如果傳入物件具有集群作用域,則該值為 null。authorizer
- CEL 授權器。可用於對請求的主體(已驗證身分的使用者)執行授權檢查。有關更多詳細資訊,請參閱 Kubernetes CEL 程式庫文件中的 AuthzSelectors 和 Authz。authorizer.requestResource
- 使用請求資源(群組、資源、(子資源)、命名空間、名稱)配置的授權檢查的快捷方式。
apiVersion
、kind
、metadata.name
和 metadata.generateName
始終可以從物件的根目錄存取。無法存取其他中繼資料屬性。
對列表類型為 'set' 或 'map' 的陣列進行等式運算會忽略元素順序,即 [1, 2] == [2, 1]。對具有 x-kubernetes-list-type 的陣列進行串連會使用列表類型的語意
- 'set':
X + Y
執行聯集,其中保留X
中所有元素的陣列位置,並且附加Y
中不相交的元素,並保留其部分順序。 - 'map':
X + Y
執行合併,其中保留X
中所有鍵的陣列位置,但當X
和Y
的鍵集相交時,值會被Y
中的值覆寫。Y
中具有不相交鍵的元素會被附加,並保留其部分順序。
驗證表達式範例
表達式 | 目的 |
---|---|
object.minReplicas <= object.replicas && object.replicas <= object.maxReplicas | 驗證定義副本的三個欄位是否已適當排序 |
'Available' in object.stateCounts | 驗證在對應中是否存在具有 'Available' 鍵的條目 |
(size(object.list1) == 0) != (size(object.list2) == 0) | 驗證兩個清單中只有一個是非空的,但不能同時為非空 |
!('MY_KEY' in object.map1) || object['MY_KEY'].matches('^[a-zA-Z]*$') | 如果對應中存在特定鍵,則驗證該鍵的對應值 |
object.envars.filter(e, e.name == 'MY_ENV').all(e, e.value.matches('^[a-zA-Z]*$') | 驗證鍵欄位 'name' 為 'MY_ENV' 的 listMap 條目的 'value' 欄位 |
has(object.expired) && object.created + object.ttl < object.expired | 驗證 'expired' 日期是否在 'create' 日期加上 'ttl' 持續時間之後 |
object.health.startsWith('ok') | 驗證 'health' 字串欄位是否具有字首 'ok' |
object.widgets.exists(w, w.key == 'x' && w.foo < 10) | 驗證具有鍵 'x' 的 listMap 項目中的 'foo' 屬性是否小於 10 |
type(object) == string ? object == '100%' : object == 1000 | 驗證 int-or-string 欄位的 int 和字串案例 |
object.metadata.name.startsWith(object.prefix) | 驗證物件的名稱是否具有另一個欄位值的前綴 |
object.set1.all(e, !(e in object.set2)) | 驗證兩個 listSet 是否不相交 |
size(object.names) == size(object.details) && object.names.all(n, n in object.details) | 驗證 'details' 對應是否由 'names' listSet 中的項目鍵控 |
size(object.clusters.filter(c, c.name == object.primary)) == 1 | 驗證 'primary' 屬性在 'clusters' listMap 中是否只有一個出現次數 |
閱讀 CEL 上支援的評估,以取得有關 CEL 規則的更多資訊。
spec.validation[i].reason
表示驗證失敗原因的機器可讀描述。如果這是清單中第一個失敗的驗證,則此原因以及對應的 HTTP 回應碼將用於對用戶端的 HTTP 回應中。目前支援的原因為:Unauthorized
、Forbidden
、Invalid
、RequestEntityTooLarge
。如果未設定,則在對用戶端的回應中使用 StatusReasonInvalid
。
匹配請求:matchConditions
如果您需要精細的請求篩選,則可以為 ValidatingAdmissionPolicy
定義匹配條件。如果您發現匹配規則、objectSelectors
和 namespaceSelectors
仍然無法提供您想要的篩選,這些條件會很有用。匹配條件是 CEL 表達式。所有匹配條件都必須評估為 true,才能評估資源。
以下範例說明了匹配條件的一些不同用途
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: "demo-policy.example.com"
spec:
failurePolicy: Fail
matchConstraints:
resourceRules:
- apiGroups: ["*"]
apiVersions: ["*"]
operations: ["CREATE", "UPDATE"]
resources: ["*"]
matchConditions:
- name: 'exclude-leases' # Each match condition must have a unique name
expression: '!(request.resource.group == "coordination.k8s.io" && request.resource.resource == "leases")' # Match non-lease resources.
- name: 'exclude-kubelet-requests'
expression: '!("system:nodes" in request.userInfo.groups)' # Match requests made by non-node users.
- name: 'rbac' # Skip RBAC requests.
expression: 'request.resource.group != "rbac.authorization.k8s.io"'
validations:
- expression: "!object.metadata.name.contains('demo') || object.metadata.namespace == 'demo'"
匹配條件可以存取與驗證表達式相同的 CEL 變數。
如果評估匹配條件時發生錯誤,則不會評估策略。是否拒絕請求取決於以下因素
- 如果任何匹配條件評估為
false
(無論其他錯誤如何),API 伺服器都會跳過該策略。 - 否則
- 對於
failurePolicy: Fail
,拒絕請求(不評估策略)。 - 對於
failurePolicy: Ignore
,繼續處理請求,但跳過該策略。
- 對於
稽核註解
auditAnnotations
可用於在 API 請求的稽核事件中包含稽核註解。
例如,以下是一個帶有稽核註解的許可策略
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: "demo-policy.example.com"
spec:
failurePolicy: Fail
matchConstraints:
resourceRules:
- apiGroups: ["apps"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["deployments"]
validations:
- expression: "object.spec.replicas > 50"
messageExpression: "'Deployment spec.replicas set to ' + string(object.spec.replicas)"
auditAnnotations:
- key: "high-replica-count"
valueExpression: "'Deployment spec.replicas set to ' + string(object.spec.replicas)"
當使用此許可策略驗證 API 請求時,產生的稽核事件將如下所示
# the audit event recorded
{
"kind": "Event",
"apiVersion": "audit.k8s.io/v1",
"annotations": {
"demo-policy.example.com/high-replica-count": "Deployment spec.replicas set to 128"
# other annotations
...
}
# other fields
...
}
在此範例中,只有當 Deployment 的 spec.replicas
大於 50 時,才會包含註解,否則 CEL 表達式評估為 null,並且不會包含註解。
請注意,稽核註解鍵以 ValidatingAdmissionWebhook
的名稱和 /
為字首。如果另一個許可控制器(例如許可 Webhook)使用完全相同的稽核註解鍵,則稽核事件中將包含第一個包含稽核註解的許可控制器的值,並且所有其他值都將被忽略。
訊息表達式
若要在策略拒絕請求時傳回更友善的訊息,我們可以使用 CEL 表達式與 spec.validations[i].messageExpression
組合訊息。與驗證表達式類似,訊息表達式可以存取 object
、oldObject
、request
、params
和 namespaceObject
。與驗證不同,訊息表達式必須評估為字串。
例如,為了在策略引用參數時更好地告知使用者拒絕原因,我們可以進行以下驗證
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: "deploy-replica-policy.example.com"
spec:
paramKind:
apiVersion: rules.example.com/v1
kind: ReplicaLimit
matchConstraints:
resourceRules:
- apiGroups: ["apps"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["deployments"]
validations:
- expression: "object.spec.replicas <= params.maxReplicas"
messageExpression: "'object.spec.replicas must be no greater than ' + string(params.maxReplicas)"
reason: Invalid
在建立將副本限制為 3 的參數物件並設定繫結後,當我們嘗試建立具有 5 個副本的部署時,我們將收到以下訊息。
$ kubectl create deploy --image=nginx nginx --replicas=5
error: failed to create deployment: deployments.apps "nginx" is forbidden: ValidatingAdmissionPolicy 'deploy-replica-policy.example.com' with binding 'demo-binding-test.example.com' denied request: object.spec.replicas must be no greater than 3
這比「副本過多」的靜態訊息更具資訊性。
如果同時定義了訊息表達式和 spec.validations[i].message
中定義的靜態訊息,則訊息表達式優先於靜態訊息。但是,如果訊息表達式評估失敗,則將改為使用靜態訊息。此外,如果訊息表達式評估為多行字串,則評估結果將被捨棄,並且如果存在靜態訊息,則將使用該訊息。請注意,靜態訊息會針對多行字串進行驗證。
類型檢查
當建立或更新策略定義時,驗證過程會剖析其包含的表達式,並報告任何語法錯誤,如果發現任何錯誤,則拒絕該定義。之後,會針對 spec.matchConstraints
的匹配類型檢查引用的變數是否存在類型錯誤,包括遺失欄位和類型混淆。類型檢查的結果可以從 status.typeChecking
檢索。status.typeChecking
的存在表示類型檢查已完成,而空的 status.typeChecking
表示未偵測到任何錯誤。
例如,給定以下策略定義
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: "deploy-replica-policy.example.com"
spec:
matchConstraints:
resourceRules:
- apiGroups: ["apps"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["deployments"]
validations:
- expression: "object.replicas > 1" # should be "object.spec.replicas > 1"
message: "must be replicated"
reason: Invalid
狀態將產生以下資訊
status:
typeChecking:
expressionWarnings:
- fieldRef: spec.validations[0].expression
warning: |-
apps/v1, Kind=Deployment: ERROR: <input>:1:7: undefined field 'replicas'
| object.replicas > 1
| ......^
如果在 spec.matchConstraints
中匹配了多個資源,則將檢查所有匹配的資源。例如,以下策略定義
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: "replica-policy.example.com"
spec:
matchConstraints:
resourceRules:
- apiGroups: ["apps"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["deployments","replicasets"]
validations:
- expression: "object.replicas > 1" # should be "object.spec.replicas > 1"
message: "must be replicated"
reason: Invalid
將在警告訊息中包含多個類型和每個類型的類型檢查結果。
status:
typeChecking:
expressionWarnings:
- fieldRef: spec.validations[0].expression
warning: |-
apps/v1, Kind=Deployment: ERROR: <input>:1:7: undefined field 'replicas'
| object.replicas > 1
| ......^
apps/v1, Kind=ReplicaSet: ERROR: <input>:1:7: undefined field 'replicas'
| object.replicas > 1
| ......^
類型檢查具有以下限制
- 沒有萬用字元匹配。如果
spec.matchConstraints.resourceRules
在apiGroups
、apiVersions
或resources
中的任何一個包含"*"
,則不會檢查"*"
匹配的類型。 - 匹配類型的數量限制為 10 個。這是為了防止手動指定過多類型的策略消耗過多的運算資源。依群組、版本,然後是資源的升序排列,第 11 個組合及以後的組合將被忽略。
- 類型檢查不會以任何方式影響策略行為。即使類型檢查偵測到錯誤,策略仍將繼續評估。如果在評估期間發生錯誤,失敗策略將決定其結果。
- 類型檢查不適用於 CRD,包括匹配的 CRD 類型和 paramKind 的參考。對 CRD 的支援將在未來版本中推出。
變數組合
如果表達式變得太複雜,或者表達式的一部分可重複使用且評估的運算成本很高,則可以將表達式的一部分提取到變數中。變數是一個具名的表達式,稍後可以在其他表達式的 variables
中引用。
spec:
variables:
- name: foo
expression: "'foo' in object.spec.metadata.labels ? object.spec.metadata.labels['foo'] : 'default'"
validations:
- expression: variables.foo == 'bar'
變數在第一次被引用時會延遲評估。評估期間發生的任何錯誤都將在引用表達式的評估期間報告。結果和潛在錯誤都會被記憶,並且每個只計入執行時間成本一次。
變數的順序很重要,因為變數可以引用在其之前定義的其他變數。此順序可防止循環參考。
以下是一個更複雜的範例,強制執行映像檔倉庫名稱與其命名空間中定義的環境相符。
# This policy enforces that all containers of a deployment has the image repo match the environment label of its namespace.
# Except for "exempt" deployments, or any containers that do not belong to the "example.com" organization (e.g. common sidecars).
# For example, if the namespace has a label of {"environment": "staging"}, all container images must be either staging.example.com/*
# or do not contain "example.com" at all, unless the deployment has {"exempt": "true"} label.
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: "image-matches-namespace-environment.policy.example.com"
spec:
failurePolicy: Fail
matchConstraints:
resourceRules:
- apiGroups: ["apps"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["deployments"]
variables:
- name: environment
expression: "'environment' in namespaceObject.metadata.labels ? namespaceObject.metadata.labels['environment'] : 'prod'"
- name: exempt
expression: "'exempt' in object.metadata.labels && object.metadata.labels['exempt'] == 'true'"
- name: containers
expression: "object.spec.template.spec.containers"
- name: containersToCheck
expression: "variables.containers.filter(c, c.image.contains('example.com/'))"
validations:
- expression: "variables.exempt || variables.containersToCheck.all(c, c.image.startsWith(variables.environment + '.'))"
messageExpression: "'only ' + variables.environment + ' images are allowed in namespace ' + namespaceObject.metadata.name"
由於策略已繫結到標記為 environment: prod
的命名空間 default
,因此以下建立部署的嘗試將被拒絕。
kubectl create deploy --image=dev.example.com/nginx invalid
錯誤訊息與此類似。
error: failed to create deployment: deployments.apps "invalid" is forbidden: ValidatingAdmissionPolicy 'image-matches-namespace-environment.policy.example.com' with binding 'demo-binding-test.example.com' denied request: only prod images are allowed in namespace default