Modifica risorse

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

Attivare la mutazione

Console

Per attivare la mutazione, completa i seguenti passaggi:

  1. Nella console Google Cloud , vai alla pagina Criteri di GKE Enterprise nella sezione Gestione della postura.

    Vai a Norme

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

gcloud Policy Controller

Per abilitare 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 per attivare la mutazione. Puoi specificare più iscrizioni separate da una virgola.

gcloud ConfigManagement

La mutazione deve essere attivata impostando spec.policyController.mutation.enabled su true nella risorsa config-management:

apiVersion: configmanagement.gke.io/v1
kind: ConfigManagement
metadata:
  name: config-management
spec:
  policyController:
    enabled: true
     mutation:
      enabled: true 

Se utilizzi il comando gcloud CLI, devi utilizzare la versione alpha per attivare la mutazione, come mostrato nell'esempio seguente:

  # apply-spec.yaml

  applySpecVersion: 1
  spec:
    policyController:
      enabled: true
      mutationEnabled: true

Dopo aver creato il file apply-spec.yaml, esegui il seguente comando per applicare la configurazione:

  gcloud alpha container fleet config-management apply \
      --membership=MEMBERSHIP_NAME \
      --config=CONFIG_YAML_PATH \
      --project=PROJECT_ID

Sostituisci quanto segue:

  • MEMBERSHIP_NAME: il nome dell'appartenenza al cluster registrato con le impostazioni del controller dei criteri che vuoi utilizzare
  • CONFIG_YAML_PATH: il percorso del file apply-spec.yaml
  • PROJECT_ID: il tuo ID progetto

Definizioni

  • mutator: una risorsa Kubernetes che consente di configurare il comportamento della mutazione di Policy Controller.
  • system: un'organizzazione di più mutator

Esempio di mutazione

L'esempio seguente mostra un mutatore che imposta imagePullPolicy su Always per tutti i container di tutti i pod:

# 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 in spec è configurato il comportamento del modificatore.

spec.applyTo lega 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 applicato a una risorsa Namespace. Per questo motivo, questo campo è obbligatorio affinché Policy Controller sappia per quali schemi è pertinente questo mutatore. GroupVersionKinds mancanti in questo elenco non vengono sottoposti a mutazione.

spec.location ci indica quale campo modificare. In questo caso, utilizziamo un glob (*) per indicare che vogliamo modificare tutte le voci nell'elenco del contenitore. Tieni presente che gli unici tipi di elenchi che possono essere attraversati dal campo location sono gli elenchi di tipo mappa e che il campo chiave per la mappa deve essere specificato. Gli elenchi di tipo mappa sono un costrutto Kubernetes. Puoi trovare maggiori dettagli nella documentazione di Kubernetes.

spec.parameters.assign.value è il valore da assegnare a location. Questo campo non è tipizzato e può assumere qualsiasi valore, ma tieni presente che Kubernetes convalida comunque la richiesta dopo la mutazione, pertanto 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 modifica e ne causa la modifica.

Flusso di esecuzione

Forse il concetto più importante da comprendere sui webhook di mutazione Kubernetes è il loro regolamento di richiamo, perché l'output di un mutator potrebbe cambiare il comportamento di un altro mutator. Ad esempio, se aggiungi un nuovo container sidecar, un mutatore che imposta il criterio di estrazione delle immagini per tutti i container ora ha un nuovo container da modificare.

In pratica, ciò significa che per qualsiasi richiesta, il webhook di mutazione di Policy Controller potrebbe essere chiamato più volte.

Per ridurre la latenza, Policy Controller si richiama di nuovo per evitare richieste HTTP aggiuntive. Ciò significa che il criterio di inserimento di sidecar e di estrazione delle immagini ha il risultato previsto.

La routine di mutazione di Policy Controller continuerà a riavviarsi fino a quando la risorsa non "converge", il che significa che le iterazioni aggiuntive non hanno alcun ulteriore effetto.

Sintassi della località

La sintassi della posizione utilizza l'accessore punto (.) per attraversare i campi. Nel caso degli elenchi con chiave, 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 inseriti con un carattere di escape anteponendoli a \. "Use \" to escape and \\\" to escape" diventa 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 contenitore 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 non esiste attualmente in una risorsa, questa viene creata per impostazione predefinita. Questo comportamento può essere configurato tramite il testing dei percorsi.

Test del percorso

Come possiamo eseguire l'impostazione predefinita, evitando di modificare un valore già esistente? Ad esempio, potremmo voler impostare /secure-mount su di sola lettura per tutti i contenitori, ma non vogliamo creare un /secure-mount se non esiste già. Possiamo eseguire entrambe queste operazioni tramite i test di percorso.

Ecco un esempio che evita la mutazione di 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 di 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 mutator: 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 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 dei metadati. Non può modificare il valore delle etichette dei metadati esistenti. In caso contrario, sarebbe possibile scrivere un sistema di mutatori che si rechi in modo ricorsivo a un numero infinito di volte, 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

Limitazioni di Kubernetes

La documentazione di Kubernetes elenca alcune considerazioni importanti sull'utilizzo degli webhook di mutazione. Poiché Policy Controller funziona come webhook di ammissione Kubernetes, questo consiglio si applica qui.

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

Scrivi i mutatori

Atomicità

È buona prassi rendere ogni mutator il più autonomo possibile. Poiché Kubernetes è eventualmente coerente, un mutator non deve fare affidamento sul riconoscimento di un secondo mutator per svolgere correttamente il proprio compito. Ad esempio, quando aggiungi un sidecar, aggiungi l'intero sidecar, non costruiscilo a pezzi utilizzando più mutator.

Convalida

Se vuoi applicare una condizione, è buona norma che il mutatore abbia una limitazione di corrispondenza. In questo modo, le richieste in violazione vengono rifiutate e le violazioni preesistenti vengono rilevate durante il controllo.

Ripristino di emergenza

La mutazione è implementata come webhook di modifica Kubernetes. Può essere interrotto nello stesso modo del webhook di convalida, ma la risorsa pertinente è un MutatingWebhookConfiguration chiamato gatekeeper-mutating-webhook-configuration.

Passaggi successivi