Isola i carichi di lavoro in pool di nodi dedicati


Questa pagina mostra come ridurre il rischio di attacchi di escalation dei privilegi nel cluster indicando a Google Kubernetes Engine (GKE) di pianificare i carichi di lavoro su un pool di nodi dedicato e separato, lontano dai carichi di lavoro con privilegi gestiti da GKE. Questa pagina si applica ai cluster Standard senza provisioning automatico dei nodi. Per separare i carichi di lavoro nei cluster Autopilot e nei cluster Standard con il provisioning automatico dei nodi abilitato, consulta Configurare la separazione dei carichi di lavoro in GKE.

Panoramica

I cluster GKE utilizzano carichi di lavoro con privilegi gestiti da GKE per abilitare funzionalità e caratteristiche specifiche dei cluster, come la raccolta delle metriche. A questi carichi di lavoro vengono concesse autorizzazioni speciali per essere eseguite correttamente nel cluster.

I carichi di lavoro di cui esegui il deployment nei tuoi nodi potrebbero essere compromessi da un'entità dannosa. L'esecuzione di questi carichi di lavoro insieme a carichi di lavoro con privilegi gestiti da GKE significa che un utente malintenzionato che esce da un container compromesso può utilizzare le credenziali del carico di lavoro con privilegi sul nodo per aumentare i privilegi nel cluster.

Prevenzione dei gruppi di lavoro

La tua difesa principale dovrebbe essere le tue applicazioni. GKE offre diverse funzionalità che consentono di proteggere i cluster e i pod. Nella maggior parte dei casi, consigliamo vivamente di utilizzare GKE Sandbox per isolare i carichi di lavoro. GKE Sandbox è basato sul progetto open source gVisor e implementa l'API kernel Linux nello spazio utente. Ogni pod viene eseguito su un kernel dedicato che esegue la sandbox delle applicazioni per impedire l'accesso a chiamate di sistema con privilegi nel kernel host. I carichi di lavoro in esecuzione in GKE Sandbox vengono pianificati automaticamente su nodi separati, isolati dagli altri.

Dovresti anche seguire i consigli descritti in Rafforzare la sicurezza del cluster.

Evitare attacchi di escalation dei privilegi

Se non puoi utilizzare GKE Sandbox e vuoi un ulteriore livello di isolamento oltre ad altre misure di protezione avanzata, puoi utilizzare le incompatibilità dei nodi e l'affinità dei nodi per pianificare i tuoi carichi di lavoro su un pool di nodi dedicato. Un'incompatibilità dei nodi indica a GKE di evitare di pianificare carichi di lavoro senza una tolleranza corrispondente (come i carichi di lavoro gestiti da GKE) su quei nodi. L'affinità dei nodi sui tuoi carichi di lavoro indica a GKE di pianificare i pod sui nodi dedicati.

Limitazioni dell'isolamento dei nodi

  • Gli aggressori possono comunque avviare attacchi DoS (Denial of Service) dal nodo compromesso.
  • I nodi compromessi possono ancora leggere molte risorse, inclusi tutti i pod e gli spazi dei nomi nel cluster.
  • I nodi compromessi possono accedere ai secret e alle credenziali utilizzate da ogni pod in esecuzione su quel nodo.
  • L'utilizzo di un pool di nodi separato per isolare i carichi di lavoro può influire sull'efficienza dei costi, sulla scalabilità automatica e sull'utilizzo delle risorse.
  • I nodi compromessi possono comunque bypassare i criteri di rete in uscita.
  • Alcuni carichi di lavoro gestiti da GKE devono essere eseguiti su ogni nodo del cluster e sono configurati per tollerare tutte le incompatibilità.
  • Se esegui il deployment di DaemonSet che hanno autorizzazioni elevate e possono tollerare qualsiasi incompatibilità, questi pod potrebbero essere un percorso per l'escalation dei privilegi da un nodo compromesso.

Come funziona l'isolamento dei nodi

Per implementare l'isolamento dei nodi per i carichi di lavoro:

  1. Controlla ed etichetta un pool di nodi per i tuoi carichi di lavoro.
  2. Aggiorna i carichi di lavoro con la tolleranza e la regola di affinità dei nodi corrispondenti.

Questa guida presuppone di iniziare con un pool di nodi nel tuo cluster. L'utilizzo dell'affinità dei nodi oltre alle incompatibilità dei nodi non è obbligatorio, ma lo consigliamo perché puoi beneficiare di un maggiore controllo sulla pianificazione.

Prima di iniziare

Prima di iniziare, assicurati di aver eseguito le seguenti attività:

  • Abilita l'API Google Kubernetes Engine.
  • Abilita l'API Google Kubernetes Engine
  • Se vuoi utilizzare Google Cloud CLI per questa attività, installa e initialize gcloud CLI. Se hai già installato gcloud CLI, scarica la versione più recente eseguendo gcloud components update.
  • Scegli un nome specifico per l'incompatibilità dei nodi e l'etichetta del nodo che vuoi utilizzare per i pool di nodi dedicati. In questo esempio utilizziamo workloadType=untrusted.

Controlla ed etichetta un pool di nodi per i carichi di lavoro

Crea un nuovo pool di nodi per i tuoi carichi di lavoro e applica un'incompatibilità dei nodi e un'etichetta dei nodi. Quando applichi un'incompatibilità o un'etichetta a livello di pool di nodi, tutti i nuovi nodi, come quelli creati con la scalabilità automatica, riceveranno automaticamente le incompatibilità e le etichette specificate.

Puoi anche aggiungere incompatibilità dei nodi ed etichette dei nodi ai pool di nodi esistenti. Se utilizzi l'effetto NoExecute, GKE rimuove tutti i pod in esecuzione su quei nodi che non tollerano la nuova incompatibilità.

Per aggiungere un'incompatibilità e un'etichetta a un nuovo pool di nodi, esegui questo comando:

gcloud container node-pools create POOL_NAME \
    --cluster CLUSTER_NAME \
    --node-taints TAINT_KEY=TAINT_VALUE:TAINT_EFFECT \
    --node-labels LABEL_KEY=LABEL_VALUE

Sostituisci quanto segue:

  • POOL_NAME: il nome del nuovo pool di nodi per i carichi di lavoro.
  • CLUSTER_NAME: il nome del tuo cluster GKE.
  • TAINT_KEY=TAINT_VALUE: una coppia chiave-valore associata a una TAINT_EFFECT di pianificazione. Ad esempio, workloadType=untrusted.
  • TAINT_EFFECT: uno dei seguenti valori effetto: NoSchedule, PreferNoSchedule o NoExecute. NoExecute offre una garanzia di rimozione migliore rispetto a NoSchedule.
  • LABEL_KEY=LABEL_VALUE: coppie chiave-valore per le etichette dei nodi, che corrispondono ai selettori specificati nei manifest del carico di lavoro.

Aggiungi una tolleranza e una regola di affinità dei nodi ai tuoi carichi di lavoro

Dopo l'incompatibilità con il pool di nodi dedicato, nessun carico di lavoro può eseguire la pianificazione su di esso a meno che non abbia una tolleranza corrispondente all'incompatibilità aggiunta. Aggiungi la tolleranza alla specifica per i carichi di lavoro per consentire la programmazione dei pod sul pool di nodi incompatibile.

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

L'esempio seguente aggiunge una tolleranza per l'incompatibilità workloadType=untrusted:NoExecute e una regola di affinità nodo 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: TAINT_KEY
        operator: Equal
        value: TAINT_VALUE
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: LABEL_KEY
                operator: In
                values:
                - "LABEL_VALUE"
      containers:
      - name: sleep
        image: ubuntu
        command: ["/bin/sleep", "inf"]

Sostituisci quanto segue:

  • TAINT_KEY: la chiave di incompatibilità che hai applicato al pool di nodi dedicato.
  • TAINT_VALUE: il valore di incompatibilità applicato al pool di nodi dedicato.
  • LABEL_KEY: la chiave di etichetta del nodo che hai applicato al pool di nodi dedicato.
  • LABEL_VALUE: il valore dell'etichetta del nodo che hai applicato al pool di nodi dedicato.

Quando aggiorni il deployment con kubectl apply, GKE ricrea i pod interessati. La regola di affinità dei nodi forza i pod a collegarsi al pool di nodi dedicato che hai creato. La tolleranza consente di posizionare solo i pod sui nodi.

Verificare che la separazione funzioni

Per verificare che la pianificazione funzioni correttamente, esegui il comando seguente e controlla se i tuoi carichi di lavoro si trovano nel pool di nodi dedicato:

kubectl get pods -o=wide

Consigli e best practice

Dopo aver configurato l'isolamento dei nodi, ti consigliamo di procedere come segue:

  • Limita pool di nodi specifici ai carichi di lavoro gestiti da GKE solo aggiungendo l'incompatibilità components.gke.io/gke-managed-components. L'aggiunta di questa incompatibilità impedisce ai tuoi pod di pianificare su quei nodi, migliorando l'isolamento.
  • Quando crei nuovi pool di nodi, puoi impedire l'esecuzione della maggior parte dei carichi di lavoro gestiti da GKE su questi nodi aggiungendo la tua incompatibilità ai pool di nodi.
  • Ogni volta che esegui il deployment di nuovi carichi di lavoro nel tuo cluster, ad esempio durante l'installazione di strumenti di terze parti, controlla le autorizzazioni richieste dai pod. Ove possibile, evita di eseguire il deployment di carichi di lavoro che usano autorizzazioni elevate per i nodi condivisi.

Passaggi successivi