驗證性准入策略
Kubernetes v1.30 [穩定]
本頁面提供了驗證准入策略的概述。
什麼是驗證准入策略?
驗證准入策略提供了一種宣告式的、程序內的替代方案,用於驗證准入 webhook。
驗證准入策略使用通用表示式語言 (CEL) 來宣告策略的驗證規則。驗證准入策略是高度可配置的,使策略作者能夠定義可引數化並根據叢集管理員的需求限定資源範圍的策略。
構成策略的資源
策略通常由三個資源組成
ValidatingAdmissionPolicy
描述了策略的抽象邏輯(例如:“此策略確保某個特定標籤設定為特定值”)。引數資源向 ValidatingAdmissionPolicy 提供資訊,使其成為一個具體的語句(例如“
owner
標籤必須設定為以.company.com
結尾的值”)。原生型別(如 ConfigMap)或 CRD 定義了引數資源的模式。ValidatingAdmissionPolicy
物件指定了它們期望的引數資源的 Kind。ValidatingAdmissionPolicyBinding
將上述資源連結在一起並提供作用域。如果你只希望Pods
設定owner
標籤,則可以在繫結中指定此限制。
至少必須定義一個 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
當嘗試建立一個副本數不滿足驗證表示式的 Deployment 時,將返回包含訊息的錯誤
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
定義的失敗僅在 failurePolicy
設定為 Fail
(或未指定)時根據這些動作強制執行,否則失敗將被忽略。
有關驗證失敗審計註解的更多詳細資訊,請參閱審計註解:驗證失敗。
引數資源
引數資源允許策略配置與其定義分離。策略可以定義 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"
parameterNotFoundAction: Deny
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"
parameterNotFoundAction: Deny
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
訪問許可權。
paramRef
paramRef
欄位指定了策略使用的引數資源。它具有以下欄位
name:引數資源的名稱。
namespace:引數資源的名稱空間。
selector:一個標籤選擇器,用於匹配多個引數資源。
parameterNotFoundAction:(必需)控制未找到指定引數時的行為。
- 允許值:
Allow
:未找到匹配引數被視為繫結成功驗證。Deny
:未找到匹配引數受策略的failurePolicy
約束。
- 允許值:
name
或 selector
必須設定一個,但不能同時設定兩者。
注意
paramRef
中的 parameterNotFoundAction
欄位是**必需**的。它指定當沒有找到與 paramRef
匹配的引數時要執行的操作。如果未指定,則策略繫結可能被視為無效並將被忽略或可能導致意外行為。
Allow
:如果設定為Allow
並且未找到引數,則繫結將引數缺失視為成功驗證,並且策略被認為已透過。Deny
:如果設定為Deny
並且未找到引數,則繫結將強制執行策略的failurePolicy
。如果failurePolicy
為Fail
,則請求將被拒絕。
請確保根據引數缺失時的預期行為設定 parameterNotFoundAction
。
使用 parameterNotFoundAction
處理缺失引數
當使用帶有選擇器的 paramRef
時,可能沒有引數與選擇器匹配。parameterNotFoundAction
欄位決定了在這種情況下繫結的行為。
示例
apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: example-binding
spec:
policyName: example-policy
paramRef:
selector:
matchLabels:
environment: test
parameterNotFoundAction: Allow
validationActions:
- Deny
故障策略
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 欄位的整數和字串情況 |
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”列表對映中只出現一次 |
閱讀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,並且註解將不包含。
請注意,審計註解鍵以 ValidatingAdmissionPolicy
的名稱和 /
為字首。如果另一個准入控制器(例如准入 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 個副本的 Deployment 時,將收到以下訊息。
$ 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
,則以下建立 Deployment 的嘗試將被拒絕。
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
免於准入驗證的 API 種類
某些 API 種類免於准入時間驗證檢查。例如,你不能建立阻止更改 ValidatingAdmissionPolicyBindings 的 ValidatingAdmissionPolicy。
免除的 API 種類列表是
- ValidatingAdmissionPolicies
- ValidatingAdmissionPolicyBindings
- MutatingAdmissionPolicies
- MutatingAdmissionPolicyBindings
- TokenReviews
- LocalSubjectAccessReviews
- SelfSubjectAccessReviews
- SelfSubjectReviews