Isolare i carichi di lavoro nei pool di nodi dedicati

Questa pagina mostra come ridurre il rischio di attacchi di escalation dei privilegi nel cluster configurando GKE su Azure in modo da pianificare i carichi di lavoro in un pool di nodi separato e dedicato, lontano dai carichi di lavoro gestiti con privilegi.

Panoramica

I cluster GKE su Azure utilizzano carichi di lavoro con privilegi che gestiamo per abilitare funzionalità e funzionalità specifiche del cluster, come la raccolta di metriche. A questi carichi di lavoro vengono concessi permessi speciali per essere eseguiti correttamente nel cluster.

I carichi di lavoro di cui esegui il deployment sui nodi potrebbero essere compromessi da un'entità dannosa. L'esecuzione di questi carichi di lavoro insieme ai carichi di lavoro di sistema con privilegi 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.

Prevenire le uscite dai container

La tua difesa principale dovrebbe essere costituita dalle tue applicazioni. GKE su Azure offre diverse funzionalità che puoi utilizzare per proteggere i cluster e i pod. Nella maggior parte dei casi, ti consigliamo vivamente di utilizzare Policy Controller e le funzionalità di sicurezza del kernel per proteggere i carichi di lavoro. Per ulteriori consigli sulla sicurezza, consulta la Panoramica sulla sicurezza.

Evitare attacchi di escalation dei privilegi

Se vuoi un ulteriore livello di isolamento oltre ad altre misure di protezione, puoi utilizzare le incompatibilità 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 su Azure di evitare di pianificare i carichi di lavoro senza una tolleranza corrispondente (ad esempio i carichi di lavoro gestiti da GKE su Azure) su questi nodi. L'affinità dei nodi sui tuoi carichi di lavoro indica a GKE su Azure di pianificare i pod sui nodi dedicati.

Limitazioni dell'isolamento dei nodi

  • Gli utenti malintenzionati possono comunque avviare attacchi Denial of Service (DoS) dal nodo 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 a secret e 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 ignorare i criteri di rete in uscita.
  • Alcuni carichi di lavoro gestiti da GKE su Azure devono essere eseguiti su ogni nodo del cluster e sono configurati per tollerare tutte le incompatibilità.
  • Se esegui il deployment di DaemonSet con autorizzazioni elevate e che 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, devi:

  1. Aggiungere un'incompatibilità e un'etichetta a un pool di nodi per i carichi di lavoro.
  2. Aggiornare i carichi di lavoro con la tolleranza e la regola di affinità dei nodi corrispondenti.

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

Prima di iniziare

Per eseguire i passaggi descritti in questa pagina, completa prima le seguenti operazioni:

Aggiungere un'incompatibilità e un'etichetta a un pool di nodi per i carichi di lavoro

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

Puoi anche aggiungere incompatibilità ed etichette dei nodi ai pool di nodi esistenti. Se utilizzi l'effetto NoExecute, GKE su Azure elimina tutti i pod in esecuzione su questi nodi che non hanno una tolleranza per la nuova incompatibilità.

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

gcloud container azure 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 cluster GKE su Azure.
  • 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 di effetto: NoSchedule, PreferNoSchedule o NoExecute. NoExecute offre una garanzia di eliminazione migliore rispetto a NoSchedule.
  • LABEL_KEY=LABEL_VALUE: coppie chiave-valore per le etichette dei nodi, che corrispondono ai selettori specificati nei manifest dei carichi di lavoro.

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

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

L'esempio seguente aggiunge una tolleranza per l'incompatibilità 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: 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à applicata 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 applicata al pool di nodi dedicato.
  • LABEL_VALUE: il valore dell'etichetta del nodo applicato al pool di nodi dedicato.

Quando aggiorni il deployment con kubectl apply, GKE su Azure 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 inserire solo questi pod sui nodi.

Verificare che la separazione funzioni

Per verificare che la pianificazione funzioni correttamente, esegui il comando seguente e controlla se i 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:

  • Limitare i pool di nodi specifici ai soli carichi di lavoro gestiti da GKE su Azure aggiungendo l'incompatibilità 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 l'esecuzione della maggior parte dei carichi di lavoro gestiti da GKE su Azure su questi nodi aggiungendo la tua incompatibilità a questi pool di nodi.
  • Ogni volta che esegui il deployment di nuovi carichi di lavoro nel 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 sui nodi condivisi.

Passaggi successivi