本頁面說明如何使用 Policy Controller 變動資源。這項功能適合用來設定預設值等。舉例來說,您可能想為特定命名空間中的所有資源插入標籤,或在 Pod 的 imagePullPolicy 未設定時,將其預設為 Always。
啟用變異
控制台
如要啟用變異功能,請完成下列步驟:
- 在 Google Cloud 控制台的「防護機制管理」部分,前往「政策」頁面。
- 在「Settings」(設定) 分頁的叢集資料表中,選取「Edit configuration」(編輯設定) 欄中的「Edit」(編輯) edit。
- 展開「編輯 Policy Controller 設定」選單。
- 勾選「啟用異動 Webhook」核取方塊。
- 選取「儲存變更」。
gcloud
執行下列指令,啟用變異功能:
gcloud container fleet policycontroller update \
--memberships=MEMBERSHIP_NAME \
--mutation
將 MEMBERSHIP_NAME 替換為已註冊叢集的成員資格名稱,以便啟用變異功能。您可以指定多個成員資格,並以半形逗號分隔。
定義
- mutator:Kubernetes 資源,可協助設定 Policy Controller 的變更行為。
- 系統:多個變異器的排列
異動範例
以下範例顯示的變動器會將所有 Pod 中所有容器的 imagePullPolicy 設為 Always:
# set-image-pull-policy.yaml
apiVersion: mutations.gatekeeper.sh/v1alpha1
kind: Assign
metadata:
name: always-pull-image
spec:
applyTo:
- groups: [""]
kinds: ["Pod"]
versions: ["v1"]
location: "spec.containers[name: *].imagePullPolicy"
parameters:
assign:
value: "Always"
在這個範例中,有標準 Kubernetes 中繼資料欄位 (apiVersion、kind、metadata.name),但 spec 是設定變動器行為的位置。
spec.applyTo 會將變動器繫結至指定資源。由於我們正在變更物件中的特定欄位,因此會隱含定義該物件的結構定義。舉例來說,如果將目前的變異器套用至 Namespace 資源,就沒有任何意義。因此,這個欄位為必填,Policy Controller 才能知道這個變動器與哪些結構定義相關。這份清單中缺少的GroupVersionKinds不會變動。
spec.location 會指出要修改的欄位。在本例中,我們使用 glob (*) 表示要修改容器清單中的所有項目。請注意,location 欄位可能周遊的清單類型只有地圖類型清單,且必須指定地圖的鍵欄位。對應類型清單是 Kubernetes 建構。如要進一步瞭解這些物件,請參閱 Kubernetes 說明文件。
spec.parameters.assign.value 是要指派給 location 的值。這個欄位不限類型,可接受任何值,但請注意,Kubernetes 仍會驗證變更後的要求,因此如果插入的值與要修改的物件結構定義不正確,要求就會遭到拒絕。
使用工作異動器
如果您要設定 Job 或 CronJob,則必須分別指定版本和群組,如以下範例所示:
applyTo:
- groups: ["batch"]
kind: ["Job"]
versions: ["v1"]
如果對工作使用異動器,現有工作除非經過修改,否則不會異動。修改工作會觸發對變更 Webhook 的要求,並導致工作變更。
執行流程
關於 Kubernetes 變更 Webhook,最重要的概念或許是重新叫用政策,因為某個變更器的輸出內容可能會改變另一個變更器的行為。舉例來說,如果您新增邊車容器,設定所有容器映像檔提取政策的變動器,現在就會有新的容器可變動。
實際上,這表示對於任何指定的要求,Policy Controller 的變動 Webhook 可能會呼叫多次。
為縮短延遲時間,Policy Controller 會重新叫用自身,避免產生額外的 HTTP 要求。這表示加入邊車容器和映像檔提取政策的結果符合預期。
Policy Controller 的變動常式會持續重新叫用,直到資源「收斂」為止,也就是說,額外的疊代不會再產生任何效果。
位置語法
位置語法會使用點 (.) 存取子來周遊欄位。如果是鍵控清單,使用者可以使用 [<key>: <value>] 語法參照清單中的個別物件,或使用 [<key>: *] 參照清單中的所有物件。
值和欄位可以使用單引號 (') 或雙引號 (") 括住。如果名稱含有特殊字元 (例如點或空格),就必須這麼做。
在引號值中,特殊字元可以加上 \ 前置字元來逸出。"Use \" to escape and \\\" to escape" 變成 Use " to escape and \" to escape。
v1/Pod 資源範例:
spec.priority參考資料spec.priorityspec.containers[name: "foo"].volumeMounts[mountPath: "/my/mount"].readOnly參照foo容器/my/mount掛接的readOnly欄位。spec.containers[name: *].volumeMounts[mountPath: "/my/mount"].readOnly參照所有容器/my/mount掛接的readOnly欄位。
如果您參照的位置目前不存在於資源上,系統預設會建立該位置。這項行為可透過路徑測試進行設定。
路徑測試
如何執行預設作業,避免修改現有值?假設我們想將所有容器的 /secure-mount 設為唯讀,但不想在 /secure-mount 不存在時建立。這兩項工作都可以透過路徑測試完成。
以下範例可避免在 imagePullPolicy 已設定的情況下變更:
# set-image-pull-policy.yaml
apiVersion: mutations.gatekeeper.sh/v1alpha1
kind: Assign
metadata:
name: always-pull-image
spec:
applyTo:
- groups: [""]
kinds: ["Pod"]
versions: ["v1"]
location: "spec.containers[name: *].imagePullPolicy"
parameters:
assign:
value: "Always"
pathTests:
- subPath: "spec.containers[name: *].imagePullPolicy"
condition: "MustNotExist"
以下是另一個範例,可避免在 sidecar 容器不存在時建立空白容器:
# set-image-pull-policy.yaml
apiVersion: mutations.gatekeeper.sh/v1alpha1
kind: Assign
metadata:
name: always-pull-image
spec:
applyTo:
- groups: [""]
kinds: ["Pod"]
versions: ["v1"]
location: 'spec.containers[name: "sidecar"].imagePullPolicy'
parameters:
assign:
value: "Always"
pathTests:
- subPath: 'spec.containers[name: "sidecar"]'
condition: "MustExist"
如有需要,可以指定多個路徑測試。
subPath「必須」是 location 的前置字串 (或與其相同)。
condition 的有效值只有 MustExist 和 MustNotExist。
比對
Mutator 也允許比對,使用與限制相同的條件。
Mutator
目前有兩種異動器:Assign 和 AssignMetadata。
指派
Assign 可以變更資源 metadata 欄位以外的任何值。由於所有 GroupVersionKinds 都有專屬結構定義,因此必須繫結至一組特定 GroupVersionKinds。
結構定義如下:
apiVersion: mutations.gatekeeper.sh/v1alpha1
kind: Assign
metadata:
name: always-pull-image
spec:
applyTo:
- groups: [""]
kinds: ["Pod"]
versions: ["v1"]
match:
kinds: # redundant because of `applyTo`, but left in for consistency
- apiGroups: ["*"]
kinds: ["*"]
namespaces: ["my-namespace"]
scope: "Namespaced" # or "Cluster"
excludedNamespaces: ["some-other-ns"]
labelSelector:
matchLabels:
mutate: "yes"
matchExpressions:
- key: "my-label"
operator: "In" # or, "NotIn", "Exists", or "DoesNotExist"
values: ["my-value"]
namespaceSelector:
matchLabels:
mutate: "yes"
matchExpressions:
- key: "my-label"
operator: "In" # or, "NotIn", "Exists", or "DoesNotExist"
values: ["my-value"]
location: "spec.containers[name: *].imagePullPolicy"
parameters:
pathTests:
- subPath: 'spec.containers[name: "sidecar"]' # must be a prefix of `location`
condition: "MustExist" # or "MustNotExist"
- subPath: "spec.containers[name: *].imagePullPolicy"
condition: "MustNotExist"
assign:
value: "Always" # any type can go here, not just a string
AssignMetadata
AssignMetadata可以新增中繼資料標籤。無法變更現有中繼資料標籤的值。否則,可能會寫出無限遞迴的變異器系統,導致要求逾時。
由於所有資源都共用相同的 metadata 結構定義,因此您不需要指定 AssignMetadata 套用至哪項資源。
此外,由於 AssignMetadata 的功能較少,因此其結構定義也較簡單。
apiVersion: mutations.gatekeeper.sh/v1alpha1
kind: AssignMetadata
metadata:
name: set-team-name
spec:
match:
kinds:
- apiGroups: ["*"]
kinds: ["*"]
namespaces: ["my-namespace"]
scope: "Namespaced" # or "Cluster"
excludedNamespaces: ["some-other-ns"]
labelSelector:
matchLabels:
mutate: "yes"
matchExpressions:
- key: "my-label"
operator: "In" # or, "NotIn", "Exists", or "DoesNotExist"
values: ["my-value"]
namespaceSelector:
matchLabels:
mutate: "yes"
matchExpressions:
- key: "my-label"
operator: "In" # or, "NotIn", "Exists", or "DoesNotExist"
values: ["my-value"]
location: "metadata.labels.team" # must start with `metadata.labels`
parameters:
assign:
value: "Always" # any type can go here, not just a string
最佳做法
Kubernetes 注意事項
Kubernetes 說明文件列出了使用變更 Webhook 的一些重要注意事項。Policy Controller 的運作方式與 Kubernetes 准入 Webhook 相同,因此該建議也適用於此。
Policy Controller 的變更語法旨在簡化變更 Webhook 的作業考量,包括冪等性。
寫入變異器
完整性
最佳做法是盡可能讓每個變動器自給自足。由於 Kubernetes 最終會保持一致,因此一個變動器不應依賴第二個變動器來正確執行工作。舉例來說,新增 sidecar 時,請新增整個 sidecar,不要使用多個變異器逐步建構。
驗證
如果您想強制執行某個條件,建議讓變動器具有相符的限制。確保違規要求遭到拒絕,並在稽核時偵測到既有的違規行為。
緊急復原
異動是以 Kubernetes 異動 Webhook 的形式實作。停止方式與驗證用 Webhook 相同,但相關資源是名為 gatekeeper-mutating-webhook-configuration 的 MutatingWebhookConfiguration。
後續步驟
- 如需 Gatekeeper 變異說明和範例,請參閱開放原始碼說明文件。