Isolare i carichi di lavoro in pool di nodi dedicati

Questo documento spiega come migliorare la sicurezza e la gestione del tuo cluster Kubernetes isolando i carichi di lavoro dei container all'interno di node pool dedicati in Google Distributed Cloud (GDC) air-gapped. L'isolamento dei carichi di lavoro ti offre un maggiore controllo sui pod e riduce il rischio di attacchi di escalation dei privilegi nel tuo cluster Kubernetes. Per saperne di più sui vantaggi e sui limiti dei node pool dedicati, consulta la panoramica dell'isolamento dei nodi.

Esistono diversi flussi di lavoro coinvolti nell'isolamento dei carichi di lavoro dei container, tra cui:

  • Applica taint ed etichetta a un node pool: applica un taint e un'etichetta a un pool di nodi in modo che i pod vengano respinti dal pool di nodi, a meno che non siano etichettati in modo specifico per l'esecuzione in quel node pool.

  • Aggiungi una tolleranza e una regola di affinità nodo: applica tolleranze e regole ai pod per forzarne l'esecuzione solo sul pool di nodi designato.

  • Verifica che la separazione funzioni: conferma che i pool di nodi contaminati eseguano solo i pod che hai etichettato per l'esecuzione.

Questi workflow sono destinati a utenti come gli amministratori IT all'interno del gruppo di amministratori della piattaforma, responsabili della gestione dei node pool di un cluster Kubernetes, e agli sviluppatori di applicazioni all'interno del gruppo di operatori di applicazioni, responsabili della gestione dei carichi di lavoro dei container. Per ulteriori informazioni, consulta Pubblico della documentazione GDC con air gap.

Prima di iniziare

Per completare le attività descritte in questo documento, devi richiedere le autorizzazioni necessarie e preparare l'ambiente.

Richiedere ruoli IAM

Devi disporre di ruoli specifici per ottenere le autorizzazioni necessarie per isolare i carichi di lavoro dei container nel tuo cluster Kubernetes. I ruoli necessari dipendono dal fatto che tu stia lavorando all'interno di un cluster condiviso con ambito organizzazione o di un cluster standard con ambito progetto. Per saperne di più, consulta Configurazioni del cluster Kubernetes.

Ruoli del cluster condivisi

Contatta l'amministratore IAM dell'organizzazione per richiedere i seguenti ruoli per contaminare ed etichettare un pool di nodi in un cluster condiviso:

  • Amministratore cluster utente (user-cluster-admin): crea, elimina, modifica o visualizza le risorse di un cluster condiviso ospitato sul server API di gestione. Questo ruolo fornisce l'accesso ai node pool del cluster condiviso.

  • Sviluppatore cluster utente (user-cluster-developer): crea, elimina, modifica o visualizza un cluster condiviso. Questo ruolo fornisce l'accesso alle API del data plane ospitate all'interno del cluster condiviso.

Questi ruoli non sono associati a uno spazio dei nomi.

Ruoli del cluster standard

Contatta l'amministratore IAM del progetto per richiedere i seguenti ruoli per contaminare ed etichettare un pool di nodi in un cluster standard:

  • Amministratore cluster (cluster-admin): crea, elimina, modifica o visualizza tutte le risorse in un cluster standard. Questo ruolo fornisce l'accesso alle API del piano dati ospitate all'interno del cluster standard che regolano le risorse del cluster.

  • Sviluppatore cluster (cluster-developer): crea, elimina, modifica o visualizza un cluster standard. Questo ruolo fornisce l'accesso alle API Data Plane ospitate all'interno del cluster standard che governano il cluster.

  • Amministratore cluster standard (standard-cluster-admin): crea, elimina, modifica o visualizza le risorse di un cluster standard ospitato sul server API Management. Questo ruolo fornisce l'accesso ai node pool del cluster standard.

Questi ruoli sono associati allo spazio dei nomi del progetto.

prepara l'ambiente

Per eseguire comandi su un cluster Kubernetes utilizzando l'API, assicurati di disporre delle seguenti risorse:

  • Accedi e genera il file kubeconfig per il cluster Kubernetes.

  • Utilizza il percorso kubeconfig del cluster Kubernetes per sostituire KUBERNETES_CLUSTER_KUBECONFIG in queste istruzioni.

  • Accedi e genera il file kubeconfig per il server API di gestione.

  • Utilizza il percorso kubeconfig del server API di gestione per sostituire MANAGEMENT_API_SERVER in queste istruzioni.

  • Scegli un nome specifico per il taint del nodo e l'etichetta del nodo che vuoi utilizzare per i node pool dedicati. Ad esempio, workloadType=untrusted.

Applica taint ed etichetta un nuovo pool di nodi

Quando applichi un taint o un'etichetta a un nuovo pool di nodi, tutti i nodi, inclusi quelli aggiunti in un secondo momento, riceveranno automaticamente i taint e le etichette specificati. Non puoi rimuovere una taint o un'etichetta da un pool di nodi dopo che è stata applicata.

Per aggiungere un taint e un'etichetta a un nuovo pool di nodi, completa i seguenti passaggi:

  1. Modifica la sezione nodePools della risorsa personalizzata Cluster direttamente durante la creazione del node pool:

    nodePools:
      # Several lines of code are omitted here.
      - machineTypeName: n2-standard-2-gdc
        name: nodepool-1
        nodeCount: 3
        taints:
        - key: "TAINT_KEY"
          value: "TAINT_VALUE"
          effect: "TAINT_EFFECT"
        labels:
          LABEL_KEY: LABEL_VALUE
    

    Sostituisci quanto segue:

    • TAINT_KEY: la parte relativa alla chiave del taint della coppia chiave-valore associata a una pianificazione TAINT_EFFECT. Ad esempio: workloadType.
    • TAINT_VALUE: la parte del valore di taint della coppia chiave-valore associata a una pianificazione TAINT_EFFECT. Ad esempio: untrusted.
    • TAINT_EFFECT: uno dei seguenti valori di effetto:
      • NoSchedule: i pod che non tollerano questa incompatibilità non vengono pianificati sul nodo; i pod esistenti non vengono rimossi dal nodo.
      • PreferNoSchedule: Kubernetes evita di pianificare pod che non tollerano questa incompatibilità sul nodo.
      • NoExecute: il pod viene rimosso dal nodo se è già in esecuzione sul nodo, mentre non viene pianificato sul nodo se non è ancora in esecuzione sul nodo stesso.
    • LABEL_KEY: LABEL_VALUE: le coppie chiave-valore per le etichette dei nodi, che corrispondono ai selettori specificati nei manifest dei workload.
  2. Applica la risorsa Cluster per creare il nuovo pool di nodi:

    kubectl apply -f cluster.yaml --kubeconfig MANAGEMENT_API_SERVER
    

    Sostituisci MANAGEMENT_API_SERVER con il percorso kubeconfig del server API zonale in cui è ospitato il cluster Kubernetes.

Applica taint ed etichette a un pool di nodi esistente

Per applicare un taint o un'etichetta a un pool di nodi esistente, devi applicare le modifiche a ogni nodo esistente. Non puoi aggiornare dinamicamente le configurazioni pool di nodi.

Non puoi rimuovere un'incompatibilità o un'etichetta da un pool di nodi dopo che è stata applicata.

Per aggiungere una taint e un'etichetta a un pool di nodi esistente, completa i seguenti passaggi:

  1. Elenca i nodi nel pool di nodi dedicato:

    kubectl get node --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG \
        -l baremetal.cluster.gke.io/node-pool=NODE_POOL_NAME
    

    Sostituisci le seguenti variabili:

    • KUBERNETES_CLUSTER_KUBECONFIG: il percorso kubeconfig per il cluster Kubernetes.
    • NODE_POOL_NAME: il nome del tuo pool di nodi dedicato.

    Prendi nota di ogni ID nodo di tutti i nodi nel pool di nodi dall'output.

  2. Per ogni nodo nel pool di nodi, applica le incompatibilità:

    kubectl taint nodes NODE_ID \
        TAINT_KEY=TAINT_VALUE:TAINT_EFFECT \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    Sostituisci le seguenti variabili:

    • NODE_ID: l'ID del nodo worker nel pool di nodi dedicato.
    • TAINT_KEY=TAINT_VALUE: una coppia chiave-valore associata a una pianificazione TAINT_EFFECT. Ad esempio workloadType=untrusted.
    • TAINT_EFFECT: uno dei seguenti valori di effetto:
      • NoSchedule: i pod che non tollerano questa incompatibilità non vengono pianificati sul nodo; i pod esistenti non vengono rimossi dal nodo.
      • PreferNoSchedule: Kubernetes evita di pianificare pod che non tollerano questa incompatibilità sul nodo.
      • NoExecute: il pod viene rimosso dal nodo se è già in esecuzione sul nodo, mentre non viene pianificato sul nodo se non è ancora in esecuzione sul nodo stesso.
    • KUBERNETES_CLUSTER_KUBECONFIG: il percorso kubeconfig per il cluster Kubernetes.
  3. Per ogni nodo nel pool di nodi, applica le etichette corrispondenti ai selettori che definirai nei tuoi workload dei container:

    kubectl label NODE_ID \
        LABEL_KEY:LABEL_VALUE \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    Sostituisci le seguenti variabili:

    • NODE_ID: l'ID del nodo worker nel pool di nodi dedicato.
    • LABEL_KEY:LABEL_VALUE: le coppie chiave-valore per le etichette dei nodi, che corrispondono ai selettori che specifichi nei manifest dei carichi di lavoro.
    • KUBERNETES_CLUSTER_KUBECONFIG: il percorso kubeconfig per il cluster Kubernetes.

Aggiungere una tolleranza e una regola di affinità dei nodi

Dopo aver applicato l'incompatibilità al pool di nodi dedicato, nessun workload può essere pianificato al suo interno, a meno che non abbia una tolleranza corrispondente all'incompatibilità che hai aggiunto. Aggiungi la tolleranza alla specifica dei tuoi workload per consentire la pianificazione di questi pod nel pool di nodi con incompatibilità.

Se hai etichettato il pool di nodi dedicato, puoi anche aggiungere una regola di affinità dei nodi per indicare a GDC di pianificare i carichi di lavoro solo su quel pool di nodi.

Per configurare il workload del container in modo che venga eseguito nel pool di nodi dedicato, completa i seguenti passaggi:

  1. Aggiungi le seguenti sezioni alla sezione .spec.template.spec del file manifest del carico di lavoro del container, ad esempio una risorsa personalizzata Deployment:

    tolerations:
    - key: TAINT_KEY
      operator: Equal
      value: TAINT_VALUE
      effect: TAINT_EFFECT
    affinity:
      nodeAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
          nodeSelectorTerms:
          - matchExpressions:
            - key: LABEL_KEY
              operator: In
              values:
              - "LABEL_VALUE"
    

    Sostituisci quanto segue:

    • TAINT_KEY: la chiave di taint che hai applicato al tuo pool di nodi dedicato.
    • TAINT_VALUE: il valore di taint che hai applicato al tuo pool di nodi dedicato.
    • TAINT_EFFECT: uno dei seguenti valori di effetto:
      • NoSchedule: i pod che non tollerano questa incompatibilità non vengono pianificati sul nodo; i pod esistenti non vengono rimossi dal nodo.
      • PreferNoSchedule: Kubernetes evita di pianificare pod che non tollerano questa incompatibilità sul nodo.
      • NoExecute: il pod viene rimosso dal nodo se è già in esecuzione sul nodo, mentre non viene pianificato sul nodo se non è ancora in esecuzione sul nodo stesso.
    • LABEL_KEY: la chiave di etichetta del nodo che hai applicato al tuo pool di nodi dedicato.
    • LABEL_VALUE: il valore dell'etichetta del nodo che hai applicato al tuo pool di nodi dedicato.

    Ad esempio, la seguente risorsa Deployment aggiunge una tolleranza per il taint workloadType=untrusted:NoExecute e una regola di affinità dei nodi per l'etichetta del nodo workloadType=untrusted:

    kind: Deployment
    apiVersion: apps/v1
    metadata:
      name: my-app
      namespace: default
      labels:
        app: my-app
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: my-app
      template:
        metadata:
          labels:
            app: my-app
        spec:
          tolerations:
          - key: workloadType
            operator: Equal
            value: untrusted
            effect: NoExecute
          affinity:
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions:
                  - key: workloadType
                    operator: In
                    values:
                    - "untrusted"
          containers:
          - name: my-app
            image: harbor-1.org-1.zone1.google.gdc.test/harborproject/my-app
            ports:
            - containerPort: 80
          imagePullSecrets:
          - name: SECRET
    
  2. Aggiorna il carico di lavoro del container:

    kubectl apply -f deployment.yaml -n NAMESPACE \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    Sostituisci le seguenti variabili:

    • NAMESPACE: lo spazio dei nomi del workload del container. Per i cluster condivisi, deve essere uno spazio dei nomi del progetto. Per i cluster standard, può essere qualsiasi spazio dei nomi.
    • KUBERNETES_CLUSTER_KUBECONFIG: il percorso kubeconfig per il cluster Kubernetes.

GDC ricrea i pod interessati. La regola di affinità dei nodi forza i pod nel pool di nodi dedicato che hai creato. La tolleranza consente di posizionare solo questi pod sui nodi.

Verificare che la separazione funzioni

Verifica che i pod che hai designato siano in esecuzione sul pool di nodi etichettato.

  • Elenca i pod nello spazio dei nomi specificato:

    kubectl get pods -o=wide -n NAMESPACE \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    Sostituisci le seguenti variabili:

    • NAMESPACE: lo spazio dei nomi del workload del container. Per i cluster condivisi, deve essere uno spazio dei nomi del progetto. Per i cluster standard, può essere qualsiasi spazio dei nomi.
    • KUBERNETES_CLUSTER_KUBECONFIG: il percorso kubeconfig per il cluster Kubernetes.

    L'output è simile al seguente:

    pod/kube-abc-12tyuj
    pod/kube-abc-39oplef
    pod/kube-abc-95rzkap
    

    Verifica che i tuoi workload siano in esecuzione nel pool di nodi dedicato.

Passaggi successivi