Questa pagina mostra come modificare le risorse utilizzando
Policy Controller. Questa funzionalità è utile per eseguire operazioni come l'impostazione dei valori predefiniti. Ad esempio, potresti voler inserire un'etichetta per tutte le risorse in uno spazio dei nomi specifico o impostare imagePullPolicy di un pod su Always se non è già impostato.
Attivare la mutazione
Console
Per attivare la mutazione:
- Nella Google Cloud console, vai alla pagina Policy nella sezione Posture Management.
- Nella scheda Impostazioni, nella tabella dei cluster, seleziona Modifica edit nella colonna Modifica configurazione.
- Espandi il menu Modifica configurazione di Policy Controller.
- Seleziona la casella di controllo Attiva webhook di mutazione.
- Seleziona Salva modifiche.
gcloud
Per attivare la mutazione, esegui il seguente comando:
gcloud container fleet policycontroller update \
--memberships=MEMBERSHIP_NAME \
--mutation
Sostituisci MEMBERSHIP_NAME con il nome dell'appartenenza del cluster registrato su cui attivare la mutazione. Puoi specificare più appartenenze separate da una virgola.
Definizioni
- Mutatore: una risorsa Kubernetes che consente di configurare il comportamento di mutazione di Policy Controller.
- Sistema: una disposizione di più mutatori
Esempio di mutazione
L'esempio seguente mostra un mutatore che imposta imagePullPolicy per tutti i container in tutti i pod su 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"
In questo esempio, sono presenti i campi dei metadati Kubernetes standard (apiVersion, kind, metadata.name), ma spec è il punto in cui viene configurato il comportamento del mutatore.
spec.applyTo associa il mutatore alle risorse specificate. Poiché stiamo modificando campi specifici in un oggetto, stiamo definendo implicitamente lo schema dell'oggetto. Ad esempio, il mutatore corrente non avrebbe senso se fosse applicato a una risorsa Namespace. Per questo motivo, questo campo è obbligatorio in modo che Policy Controller sappia per quali schemi è pertinente questo mutatore.
I GroupVersionKinds mancanti in questo elenco non vengono modificati.
spec.location indica il campo da modificare. In questo caso, utilizziamo un glob (*) per indicare che vogliamo modificare tutte le voci nell'elenco dei container. Tieni presente che gli unici tipi di elenchi che potrebbero essere attraversati dal campo location sono gli elenchi di tipo mappa e il campo chiave per la mappa deve essere specificato. Gli elenchi di tipo mappa sono una struttura Kubernetes. Ulteriori dettagli su
di essi sono disponibili nella documentazione di Kubernetes.
spec.parameters.assign.value è il valore da assegnare a location.
Questo campo non è tipizzato e può accettare qualsiasi valore, ma tieni presente che Kubernetes convalida comunque la richiesta dopo la mutazione, quindi l'inserimento di valori con uno schema errato per l'oggetto modificato comporta il rifiuto della richiesta.
Utilizzare i mutatori per i job
Se stai configurando un job o un CronJob, devi specificare la versione e il gruppo separatamente, come mostrato nell'esempio seguente:
applyTo:
- groups: ["batch"]
kind: ["Job"]
versions: ["v1"]
Quando utilizzi un mutatore per i job, i job esistenti non vengono modificati a meno che non vengano modificati. La modifica di un job attiva una richiesta al webhook di mutazione e ne provoca la mutazione.
Flusso di esecuzione
Forse il concetto più importante da comprendere sui webhook di mutazione di Kubernetes è la loro policy di reinvocazione, perché l'output di un mutatore potrebbe modificare il comportamento di un altro mutatore. Ad esempio, se aggiungi un nuovo container sidecar, un mutatore che imposta la policy di pull delle immagini per tutti i container ora ha un nuovo container da modificare.
In pratica, ciò significa che per una determinata richiesta il webhook di mutazione di Policy Controller potrebbe essere chiamato più di una volta.
Per ridurre la latenza, Policy Controller si reinvoca per evitare richieste HTTP aggiuntive. Ciò significa che l'inserimento di sidecar e la policy di pull delle immagini hanno il risultato previsto.
La routine di mutazione di Policy Controller continuerà a reinvocarsi finché la risorsa non "converge", il che significa che le iterazioni aggiuntive non hanno ulteriori effetti.
Sintassi della località
La sintassi della località utilizza l'accesso con punto (.) per attraversare i campi. Nel caso
di elenchi con chiavi, gli utenti possono fare riferimento a singoli oggetti in un elenco utilizzando la sintassi
[<key>: <value>] o a tutti gli oggetti nell'elenco utilizzando [<key>: *].
I valori e i campi possono essere racchiusi tra virgolette singole (') o doppie ("). Questa operazione è necessaria quando contengono caratteri speciali, come punti o spazi.
Nei valori tra virgolette, i caratteri speciali possono essere sottoposti a escape anteponendo \. "Use \" to escape and \\\" to escape" diventa Use " to escape and \" to escape.
Alcuni esempi per la risorsa v1/Pod:
spec.priorityfa riferimento aspec.priorityspec.containers[name: "foo"].volumeMounts[mountPath: "/my/mount"].readOnlyfa riferimento al camporeadOnlydel montaggio/my/mountdelfoocontainer.spec.containers[name: *].volumeMounts[mountPath: "/my/mount"].readOnlyfa riferimento al camporeadOnlydel montaggio/my/mountdi tutti i container.
Se fai riferimento a una località che non esiste attualmente in una risorsa, questa viene creata per impostazione predefinita. Questo comportamento può essere configurato tramite il test del percorso.
Test del percorso
Come possiamo eseguire l'impostazione predefinita, evitando di modificare un valore già esistente? Forse vogliamo impostare /secure-mount su sola lettura per tutti i container, ma non vogliamo creare un /secure-mount se non ne esiste già uno. Possiamo eseguire una di queste operazioni tramite il test del percorso.
Ecco un esempio che evita di modificare imagePullPolicy se è già impostato:
# 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"
Ecco un altro esempio che evita di creare un container sidecar vuoto se non esiste già:
# 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"
Se necessario, è possibile specificare più test del percorso.
subPath deve essere un prefisso di (o uguale a) location.
Gli unici valori validi per condition sono MustExist e MustNotExist.
Corrispondenza
I mutatori consentono anche la corrispondenza, utilizzando gli stessi criteri dei vincoli.
Mutatori
Attualmente esistono due tipi di mutatori: Assign e AssignMetadata.
Assegna
Assign può modificare qualsiasi valore al di fuori del campo metadata di una risorsa.
Poiché tutti i GroupVersionKinds hanno uno schema univoco, devono essere associati a un insieme di GroupVersionKinds specifici.
Ha il seguente schema:
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 può aggiungere nuove etichette di metadati. Non può modificare il valore delle etichette di metadati esistenti. In caso contrario, sarebbe possibile scrivere un sistema di mutatori che si ripeterebbe all'infinito, causando il timeout delle richieste.
Poiché tutte le risorse condividono lo stesso schema metadata, non è necessario specificare a quale risorsa si applica un AssignMetadata.
Inoltre, poiché AssignMetadata non è autorizzato a eseguire molte operazioni, il suo schema è un po' più semplice.
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
Best practice
Avvertenze di Kubernetes
La documentazione di Kubernetes elenca alcune considerazioni importanti sull' utilizzo dei webhook di mutazione. Poiché Policy Controller funziona come un webhook di ammissione di Kubernetes, questi suggerimenti si applicano anche in questo caso.
La sintassi di mutazione di Policy Controller è progettata per semplificare il rispetto delle problematiche operative relative ai webhook di mutazione, inclusa l'idempotenza.
Scrivere mutatori
Atomicità
È consigliabile rendere ogni mutatore il più autosufficiente possibile. Poiché Kubernetes è coerente alla fine, un mutatore non deve fare affidamento sul fatto che un secondo mutatore sia stato riconosciuto per svolgere correttamente il proprio lavoro. Ad esempio, quando aggiungi un sidecar, aggiungi l'intero sidecar, non costruirlo gradualmente utilizzando più mutatori.
Convalida
Se esiste una condizione che vuoi applicare, è consigliabile che il mutatore abbia un vincolo corrispondente. In questo modo, le richieste che violano le regole vengono rifiutate e le violazioni preesistenti vengono rilevate nell'audit.
Ripristino di emergenza
La mutazione viene implementata come webhook di mutazione di Kubernetes. Può essere interrotta in
modo analogo a webhook di convalida,
ma la risorsa pertinente è un MutatingWebhookConfiguration denominato
gatekeeper-mutating-webhook-configuration.
Passaggi successivi
- Per spiegazioni ed esempi sulla mutazione di Gatekeeper, consulta la documentazione open source