Scrivere un modello di vincolo personalizzato

Questa pagina mostra come scrivere un modello di vincolo personalizzato e utilizzarlo per estendere Policy Controller se non riesci a trovare un modello di vincolo predefinito adatto alle tue esigenze.

I criteri del controller dei criteri vengono descritti utilizzando il framework dei vincoli OPA e sono scritti in Rego. Un criterio può valutare qualsiasi campo di un oggetto Kubernetes.

Scrivere criteri con Rego è una competenza specializzata. Per questo motivo, una libreria di modelli di vincolo comuni è installata per impostazione predefinita. Quando crei i vincoli, probabilmente puoi invocare questi modelli di vincolo. Se hai esigenze specifiche, puoi creare modelli di vincolo personalizzati.

I modelli di vincolo consentono di separare la logica di un criterio dai requisiti specifici, per il riutilizzo e la delega. Puoi creare vincoli utilizzando modelli di vincolo sviluppati da terze parti, come progetti open source, fornitori di software o esperti di normative.

Prima di iniziare

Esempio di modello di vincolo

Di seguito è riportato un modello di vincolo di esempio che nega tutte le risorse il cui nome corrisponde a un valore fornito dall'autore del vincolo. Il resto della pagina descrive i contenuti del modello, evidenziando i concetti importanti lungo il percorso.

Se utilizzi un repository strutturato, ti consigliamo di creare i vincoli nella directory cluster/.

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8sdenyname
spec:
  crd:
    spec:
      names:
        kind: K8sDenyName
      validation:
        # Schema for the `parameters` field
        openAPIV3Schema:
          properties:
            invalidName:
              type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sdenynames
        violation[{"msg": msg}] {
          input.review.object.metadata.name == input.parameters.invalidName
          msg := sprintf("The name %v is not allowed", [input.parameters.invalidName])
        }

Vincolo di esempio

Di seguito è riportato un vincolo di esempio che potresti implementare per rifiutare tutte le risorse denominate policy-violation:

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sDenyName
metadata:
  name: no-policy-violation
spec:
  parameters:
    invalidName: "policy-violation"

Parti di un modello di vincolo

I modelli di vincolo sono costituiti da due elementi importanti:

  • Lo schema del vincolo che vuoi che gli utenti creino. Lo schema di un modello di vincolo è archiviato nel campo crd.

  • Il codice sorgente Rego che viene eseguito quando viene valutato il vincolo. Il codice sorgente Rego per un modello viene memorizzato nel campo targets.

Schema (campo crd)

Il campo CRD è un progetto per creare la definizione di risorsa personalizzata Kubernetes che definisce la risorsa di vincolo per il server API Kubernetes. Devi completare solo i seguenti campi.

Campo Descrizione
spec.crd.spec.names.kind Il tipo di vincolo. Quando si utilizza le lettere minuscole, il valore di questo campo deve essere uguale a metadata.name.
spec.crd.spec.validation.openAPIV3Schema

Lo schema per il campo spec.parameters della risorsa vincolo (Anthos Config Management definisce automaticamente il resto dello schema di vincolo). Segue le stesse convenzioni di una normale risorsa CRD.

Prefisso del modello di vincolo è il nome K8s; è una convenzione che ti consente di evitare conflitti con altri tipi di modelli di vincolo, come i modelli Forseti che hanno come target le risorse Google Cloud.

Codice sorgente Rego (targets campo)

Le seguenti sezioni forniscono ulteriori informazioni sul codice sorgente Rego.

Località

Il codice sorgente Rego è archiviato nel campo spec.targets, dove targets è un array di oggetti del seguente formato:

{"target": "admission.k8s.gatekeeper.sh","rego": REGO_SOURCE_CODE, "libs": LIST_OF_REGO_LIBRARIES}
  • target: indica ad Anthos Config Management il sistema che stiamo esaminando (in questo caso Kubernetes); è consentita una sola voce in targets.
  • rego: il codice sorgente del vincolo.
  • libs: un elenco facoltativo di librerie di codice Rego che viene reso disponibile al modello di vincolo. Ha lo scopo di semplificare l'utilizzo delle librerie condivise e non rientra nell'ambito di questo documento.

Codice sorgente

Di seguito è riportato il codice sorgente Rego per il vincolo precedente:

package k8sdenynames

violation[{"msg": msg}] {
   input.review.object.metadata.name == input.parameters.invalidName
   msg := sprintf("The name %v is not allowed", [input.parameters.invalidName])
}

Tieni presente quanto segue:

  • package k8sdenynames è richiesto da OPA (Rego's runtime). Il valore viene ignorato.
  • La regola Rego richiamata dal controller dei criteri per verificare se ci sono violazioni sono chiamate violation. Se questa regola ha corrispondenze, si è verificata una violazione del vincolo.
  • La regola violation ha la firma violation[{"msg": "violation message for the user"}], dove il valore di "msg" è il messaggio di violazione che viene restituito all'utente.
  • I parametri forniti al vincolo sono resi disponibili nella parola chiave input.parameters.
  • Il request-under-test è memorizzato nella parola chiave input.review.

La parola chiave input.review ha i seguenti campi.

Campo Descrizione
uid L'ID univoco per questa richiesta specifica; non è disponibile durante l'audit.
kind

Le informazioni relative al tipo object-under-test. Ha il seguente formato:

  • kind: tipo di risorsa
  • group: il gruppo di risorse
  • version: la versione della risorsa
name Il nome della risorsa. Potrebbe essere vuoto se l'utente si affida al server API per generare il nome su una richiesta CREATE.
namespace Lo spazio dei nomi della risorsa (non fornito per le risorse con ambito cluster).
operation L'operazione richiesta (ad esempio, CREATE o UPDATE) non è disponibile durante l'audit.
userInfo

Le informazioni dell'utente richiedente non sono disponibili durante l'audit. Ha il seguente formato:

  • username: l'utente che ha effettuato la richiesta
  • uid: UID dell'utente
  • groups: un elenco di gruppi di cui l'utente è membro
  • extra: qualsiasi informazione aggiuntiva fornita da Kubernetes
object L'oggetto che l'utente sta tentando di modificare o creare.
oldObject Lo stato originale dell'oggetto ed è disponibile solo sulle operazioni di AGGIORNAMENTO.
dryRun Indica se la richiesta è stata richiamata con kubectl --dry-run; non è disponibile durante l'audit.

Scrivere modelli di vincolo referenziale

I modelli di vincolo referenziale sono modelli che consentono all'utente di vincolare un oggetto rispetto ad altri oggetti. Un esempio potrebbe essere "don't consentire la creazione di un pod prima dell'esistenza di una risorsa Ingress corrispondente". Un altro esempio potrebbe essere "non consentire a due servizi di avere lo stesso nome host".

Policy Controller consente di scrivere vincoli di riferimento esaminando il server API per un set di risorse fornito dall'utente. Quando una risorsa viene modificata, Policy Controller lo memorizza nella cache localmente in modo che sia possibile farvi facilmente riferimento nel codice sorgente Rego. Policy Controller rende disponibile la cache nella parola chiave data.inventory.

Le risorse con ambito cluster vengono memorizzate nella cache nella seguente posizione:

data.inventory.cluster["GROUP_VERSION"]["KIND"]["NAME"]

Ad esempio, un nodo denominato my-favorite-node potrebbe essere disponibile in

data.inventory.cluster["v1"]["Node"]["my-favorite-node"]

Le risorse con ambito a livello di spazio sono memorizzate nella cache qui:

data.inventory.namespace["NAMESPACE"]["GROUP_VERSION"]["KIND"]["NAME"]

Ad esempio, un ConfigMap denominato production-variables nello spazio dei nomi shipping-prod si trova sotto

data.inventory.namespace["shipping-prod"]["v1"]["ConfigMap"]["production-variables"]

Tutti i contenuti dell'oggetto sono archiviati in questa posizione della cache e possono essere consultati nel tuo codice sorgente Rego come preferisci.

Ulteriori informazioni su Rego

Le informazioni precedenti forniscono le funzionalità uniche di Policy Controller che semplificano la scrittura dei vincoli sulle risorse Kubernetes in Rego. Un tutorial completo su come scrivere in Rego non rientra nell'ambito di questa guida. Tuttavia, la documentazione di Open Policy Agent contiene informazioni sulla sintassi e sulle funzionalità del linguaggio Rego stesso.

Installa il modello di vincolo

Dopo aver creato il modello di vincolo, utilizza kubectl apply per applicarlo e Policy Controller si occupa di importarlo. Controlla il campo status nel modello di vincolo per assicurarti che non ci siano errori che li identificano. Dopo l'importazione corretta, il campo status dovrebbe mostrare created: true e il valore di observedGeneration indicato nel campo status deve uguale a quello di metadata.generation.

Dopo aver importato il modello, puoi applicarvi i passaggi descritti nella sezione Creazione di vincoli.

Rimuovere un modello di vincolo

Per rimuovere un modello di vincolo, completa i seguenti passaggi:

  1. Verifica che non ci siano vincoli che vuoi conservare utilizzando il modello di vincolo:

    kubectl get TEMPLATE_NAME
    

    Se è presente un conflitto di denominazione tra il nome del modello di vincolo e un oggetto diverso nel cluster, utilizza il seguente comando:

    kubectl get TEMPLATE_NAME.constraints.gatekeeper.sh
    
  2. Rimuovi il modello di vincolo:

    kubectl delete constrainttemplate CONSTRAINT_TEMPLATE_NAME
    

Quando rimuovi un modello di vincolo, non puoi più creare vincoli che vi fanno riferimento.

Passaggi successivi