Modifica risorse

Questa pagina mostra come modificare le risorse utilizzando Policy Controller. È utile per impostare valori predefiniti. Ad esempio, potresti voler inserire un'etichetta per tutte le risorse in uno spazio dei nomi specifico o impostare come predefinito il valore di imagePullPolicy di un pod su Always se non è già impostato.

Abilita mutazione

Console

Per abilitare la mutazione, completa i seguenti passaggi:

  1. Nella console Google Cloud , vai alla pagina Policy nella sezione Posture Management.

    Vai alle norme

  2. Nella scheda Impostazioni, seleziona Modifica nella colonna Modifica configurazione della tabella dei cluster.
  3. Espandi il menu Modifica la configurazione di Policy Controller.
  4. Seleziona la casella di controllo Abilita webhook di modifica.
  5. Seleziona Salva modifiche.

gcloud

Per abilitare la mutazione, esegui questo comando:

gcloud container fleet policycontroller update \
    --memberships=MEMBERSHIP_NAME \
    --mutation

Sostituisci MEMBERSHIP_NAME con il nome dell'appartenenza del cluster registrato per abilitare la mutazione. Puoi specificare più abbonamenti separati da una virgola.

Definizioni

  • mutator:una risorsa Kubernetes che consente di configurare il comportamento di mutazione di Policy Controller.
  • system: 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 è dove 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 attuale non avrebbe senso se venisse applicato a una risorsa Namespace. Per questo motivo, questo campo è obbligatorio in modo che Policy Controller sappia per quali schemi è pertinente questo mutatore. 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 contenitore. Tieni presente che gli unici tipi di elenchi che possono essere attraversati dal campo location sono gli elenchi di tipo mappa e deve essere specificato il campo chiave per la mappa. Gli elenchi di tipo mappa sono una struttura Kubernetes. Per ulteriori dettagli, consulta la documentazione di Kubernetes.

spec.parameters.assign.value è il valore da assegnare a location. Questo campo non è tipizzato e può accettare qualsiasi valore, anche se 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 le offerte di lavoro

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 Jobs, i job esistenti non vengono modificati a meno che non vengano modificati. La modifica di un job attiva una richiesta al webhook di modifica e ne causa la mutazione.

Flusso di esecuzione

Forse il concetto più importante da comprendere sugli webhook di mutazione di Kubernetes è la loro norma 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 il criterio di pull dell'immagine per tutti i container ora ha un nuovo container da mutare.

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 richiama automaticamente per evitare richieste HTTP aggiuntive. Ciò significa che l'inserimento di sidecar e il pull delle immagini hanno il risultato previsto.

La routine di mutazione di Policy Controller continuerà a richiamarsi finché la risorsa non "converge", il che significa che ulteriori iterazioni non hanno alcun effetto.

Sintassi della località

La sintassi della posizione utilizza l'accesso con il 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 ("). Questo è necessario 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" si trasforma in Use " to escape and \" to escape.

Alcuni esempi per la risorsa v1/Pod:

  • spec.priority riferimenti spec.priority
  • spec.containers[name: "foo"].volumeMounts[mountPath: "/my/mount"].readOnly fa riferimento al campo readOnly del montaggio /my/mount del container foo.
  • spec.containers[name: *].volumeMounts[mountPath: "/my/mount"].readOnly fa riferimento al campo readOnly del montaggio /my/mount di tutti i container.

Se fai riferimento a una località che al momento non esiste in una risorsa, questa viene creata per impostazione predefinita. Questo comportamento può essere configurato tramite il test dei percorsi.

Test del percorso

Come possiamo eseguire l'impostazione predefinita, evitando di modificare un valore già esistente? Forse vogliamo impostare /secure-mount come di sola lettura per tutti i contenitori, 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 contenitore 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

Al momento 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 particolari.

Ha lo schema seguente:

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 dei metadati esistenti. In caso contrario, sarebbe possibile scrivere un sistema di mutatori che ricorsivamente si ripeterebbero 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 può fare molto, 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 webhook di ammissione Kubernetes, questo consiglio è valido anche in questo caso.

La sintassi di mutazione di Policy Controller è progettata per semplificare la conformità ai problemi operativi relativi agli webhook di mutazione, inclusa l'idempotenza.

Scrivere mutatori

Atomicità

La best practice consiste nel rendere ogni mutatore il più autosufficiente possibile. Poiché Kubernetes è coerente alla fine, un mutatore non deve fare affidamento sul riconoscimento di un secondo mutatore per svolgere correttamente il proprio lavoro. Ad esempio, quando aggiungi un sidecar, aggiungi l'intero sidecar, non costruirlo pezzo per pezzo 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 norme vengono rifiutate e le violazioni preesistenti vengono rilevate durante il controllo.

Recupero di emergenza

La mutazione viene implementata come webhook di mutazione Kubernetes. Può essere arrestato allo stesso modo dell'webhook di convalida, ma la risorsa pertinente è un MutatingWebhookConfiguration chiamato gatekeeper-mutating-webhook-configuration.

Passaggi successivi