Isolare i carichi di lavoro in pool di nodi dedicati


Questa pagina mostra come ridurre il rischio di attacchi di escalation dei privilegi nel cluster chiedendo a Google Kubernetes Engine (GKE) di pianificare i carichi di lavoro in un pool di nodi dedicato e separato dai carichi di lavoro gestiti da GKE con privilegi. 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 workload privilegiati gestiti da GKE per attivare funzionalità e funzionalità specifiche del cluster, come la raccolta delle metriche. A questi carichi di lavoro vengono assegnate autorizzazioni speciali per l'esecuzione corretta nel cluster.

I carichi di lavoro di cui esegui il deployment sui nodi potrebbero essere potenzialmente compromessi da un'entità malintenzionata. L'esecuzione di questi carichi di lavoro insieme ai carichi di lavoro privilegiati gestiti da GKE significa che un utente malintenzionato che esce da un container compromesso può utilizzare le credenziali del carico di lavoro privilegiato sul nodo per eseguire la riassegnazione dei privilegi nel cluster.

Impedire i breakout dei contenitori

La tua difesa principale dovrebbe essere costituita dalle tue applicazioni. GKE offre diverse funzionalità che puoi utilizzare per rafforzare i tuoi cluster e pod. Nella maggior parte dei casi, consigliamo vivamente di utilizzare GKE Sandbox per isolare i workload. GKE Sandbox si basa sul progetto open source gVisor e implementa l'API del kernel Linux nello spazio utente. Ogni pod viene eseguito su un kernel dedicato che esegue il sandboxing delle applicazioni per impedire l'accesso alle chiamate di sistema privilegiate nel kernel host. I carichi di lavoro in esecuzione in GKE Sandbox vengono pianificati automaticamente su nodi separati, isolati da altri carichi di lavoro.

Devi anche seguire i consigli riportati in Rafforzamento della 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 rafforzamento, puoi utilizzare i contaminanti dei nodi e l'affinità dei nodi per pianificare i carichi di lavoro in un pool di nodi dedicato. Un'incompatibilità del nodo indica a GKE di evitare di pianificare carichi di lavoro senza una tolleranza corrispondente (ad esempio 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 utenti malintenzionati possono comunque avviare attacchi di tipo Denial of Service (DoS) dal node compromesso.
  • I nodi compromessi possono comunque leggere molte risorse, inclusi tutti i pod e gli spazi dei nomi nel cluster.
  • I nodi compromessi possono accedere ai secret e alle credenziali utilizzati 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 aggirare 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 tutti gli elementi dannosi.
  • Se esegui il deployment di DaemonSet con autorizzazioni elevate e che possono tollerare qualsiasi attacco di manomissione, questi pod potrebbero rappresentare un percorso per escalation dei privilegi da un nodo compromesso.

Come funziona l'isolamento dei nodi

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

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

Questa guida presuppone che tu inizi con un pool di nodi nel cluster. L'utilizzo dell'affinità dei nodi oltre ai taint dei nodi non è obbligatorio, ma lo consigliamo perché consente di avere un maggiore controllo sulla pianificazione.

Prima di iniziare

Prima di iniziare, assicurati di aver eseguito le seguenti operazioni:

  • Attiva l'API Google Kubernetes Engine.
  • Attiva l'API Google Kubernetes Engine
  • Se vuoi utilizzare Google Cloud CLI per questa attività, installa e poi inizializza gcloud CLI. Se hai già installato gcloud CLI, ottieni la versione più recente eseguendo gcloud components update.
  • Scegli un nome specifico per l'inquinamento del nodo e l'etichetta del nodo da utilizzare per i pool di nodi dedicati. Per questo esempio utilizziamo workloadType=untrusted.

Contaminare ed etichettare un pool di nodi per i tuoi workload

Crea un nuovo pool di nodi per i tuoi carichi di lavoro e applica un'etichetta e un'alterazione del nodo. Quando applichi un'etichetta o un'alterazione a livello di pool di nodi, tutti i nuovi nodi, come quelli creati dalla scalabilità automatica, riceveranno automaticamente le alterazioni e le etichette specificate.

Puoi anche aggiungere contaminazioni e etichette ai pool di nodi esistenti. Se utilizzi l'effetto NoExecute, GKE esegue l'espulsione di tutti i pod in esecuzione su quei nodi che non hanno una tolleranza per il nuovo taint.

Per aggiungere un'incompatibilità e un'etichetta a un nuovo pool di nodi, esegui il seguente 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 tuoi carichi di lavoro.
  • CLUSTER_NAME: il nome del tuo cluster GKE.
  • TAINT_KEY=TAINT_VALUE: una coppia chiave-valore associata a un TAINT_EFFECT di pianificazione. Ad esempio, workloadType=untrusted.
  • TAINT_EFFECT: uno dei seguenti valori dell'effetto: NoSchedule, PreferNoSchedule o NoExecute. NoExecute offre una garanzia di espulsione migliore rispetto a NoSchedule.
  • LABEL_KEY=LABEL_VALUE: coppie chiave-valore per le etichette dei nodi, che corrispondono ai selettori specificati nei manifest del tuo carico di lavoro.

Aggiungere una tolleranza e una regola di affinità dei nodi ai workload

Dopo aver contaminato il pool di nodi dedicato, nessun workload può essere pianificato su di esso, a meno che non abbia una tolleranza corrispondente all'incompatibilità che hai aggiunto. Aggiungi la tolleranza alla specifica per i 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 GKE di pianificare i carichi di lavoro solo in quel pool di nodi.

L'esempio seguente aggiunge una tolleranza per l'workloadType=untrusted:NoExecutecontaminazione 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: 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 contaminazione che hai applicato al pool di nodi dedicato.
  • TAINT_VALUE: il valore dell'alterazione che hai applicato al pool di nodi dedicato.
  • LABEL_KEY: la chiave dell'etichetta del nodo applicata al pool di nodi dedicato.
  • LABEL_VALUE: il valore dell'etichetta del nodo applicato al tuo 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 nel pool di nodi dedicato che hai creato. La tolleranza consente di collocare sui nodi solo questi pod.

Verificare il funzionamento della separazione

Per verificare che la pianificazione funzioni correttamente, esegui il seguente comando 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 solo ai carichi di lavoro gestiti da GKE aggiungendo il taint components.gke.io/gke-managed-components. L'aggiunta di questa incompatibilità impedisce la pianificazione dei tuoi pod su questi nodi, migliorando l'isolamento.
  • Quando crei nuovi pool di nodi, impedisci alla maggior parte dei carichi di lavoro gestiti da GKE di essere eseguiti 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 quando installi strumenti di terze parti, controlla le autorizzazioni richieste dai pod. Se possibile, evita di eseguire il deployment di carichi di lavoro che utilizzano autorizzazioni elevate per i nodi condivisi.

Passaggi successivi