Procedure consigliate per le funzionalità avanzate dell'utilità di pianificazione nel servizio Azure Kubernetes (AKS)

Quando si gestiscono i cluster nel servizio Azure Kubernetes (AKS), spesso è necessario isolare i team e i carichi di lavoro. Le funzionalità avanzate fornite dall'utilità di pianificazione Kubernetes consentono di controllare:

  • Quali pod possono essere pianificati in determinati nodi.
  • Modalità di distribuzione appropriata delle applicazioni multi-pod nel cluster.

Questo articolo sulle procedure consigliate è incentrato sulle funzionalità di pianificazione avanzate di Kubernetes per gli operatori del cluster. In questo articolo vengono illustrate le operazioni seguenti:

  • Usare taint e tolleranze per limitare i pod che possono essere pianificati sui nodi.
  • Stabilire che i pod vengano eseguiti su determinati nodi con i selettori di nodo o l'affinità tra nodi.
  • Suddividere o raggruppare i pod con l'affinità tra pod o l'anti-affinità.
  • Limitare la pianificazione dei carichi di lavoro che richiedono GPU solo nei nodi con GPU pianificabili.

Fornire nodi dedicati tramite taint e tolleranze

Materiale sussidiario sulle procedure consigliate:

Limitare l'accesso per applicazioni a elevato utilizzo di risorse, ad esempio controller in ingresso, a nodi specifici. Mantenere le risorse dei nodi disponibili per i carichi di lavoro che le richiedono e non consentire la pianificazione di altri carichi di lavoro sui nodi.

Quando si crea il cluster servizio Azure Kubernetes, è possibile distribuire i nodi con supporto GPU o un numero elevato di potenti CPU. Per altre informazioni, vedere Usare GPU nel servizio Azure Kubernetes. È possibile usare questi nodi per carichi di lavoro di elaborazione dati di grandi dimensioni, ad esempio Machine Learning (ML) o intelligenza artificiale (AI).

Poiché questo hardware delle risorse del nodo è in genere costoso da distribuire, limitare i carichi di lavoro che possono essere pianificati in questi nodi. Dedicare invece alcuni nodi nel cluster per eseguire servizi di ingresso e impedire altri carichi di lavoro.

Questo supporto per nodi diversi viene fornito usando più pool di nodi. Un cluster del servizio Azure Kubernetes supporta uno o più pool di nodi.

L'utilità di pianificazione Kubernetes usa taint e tolleranze per limitare i carichi di lavoro che possono essere eseguiti nei nodi.

  • Applicare un taint a un nodo per indicare che è possibile pianificare solo pod specifici.
  • Applicare quindi una tolleranza a un pod, consentendo loro di tollerare taint di un nodo.

Quando si distribuisce un pod in un cluster del servizio Azure Kubernetes, Kubernetes pianifica solo i pod nei nodi il cui taint è allineato alla tolleranza. I contenitori e le tolleranze interagiscono per garantire che i pod non siano pianificati in nodi inappropriati. Uno o più taints vengono applicati a un nodo, contrassegnando il nodo in modo che non accetti i pod che non tollerano i taints.

Si supponga, ad esempio, di aver aggiunto un pool di nodi nel cluster del servizio Azure Kubernetes per i nodi con supporto GPU. Si definisce il nome, ad esempio gpu, quindi un valore per la pianificazione. L'impostazione di questo valore su NoSchedule impedisce all'utilità di pianificazione Kubernetes di pianificare i pod con tolerazione non definita nel nodo.

az aks nodepool add \
    --resource-group myResourceGroup \
    --cluster-name myAKSCluster \
    --name taintnp \
    --node-taints sku=gpu:NoSchedule \
    --no-wait

Con un taint applicato ai nodi nel pool di nodi, si definisce una tolleranza nella specifica del pod che consente la pianificazione sui nodi. L'esempio seguente definisce sku: gpu e effect: NoSchedule per tollerare il taint applicato al pool di nodi nel passaggio precedente:

kind: Pod
apiVersion: v1
metadata:
  name: tf-mnist
spec:
  containers:
  - name: tf-mnist
    image: mcr.microsoft.com/azuredocs/samples-tf-mnist-demo:gpu
    resources:
      requests:
        cpu: 0.5
        memory: 2Gi
      limits:
        cpu: 4.0
        memory: 16Gi
  tolerations:
  - key: "sku"
    operator: "Equal"
    value: "gpu"
    effect: "NoSchedule"

Quando questo pod viene distribuito usando kubectl apply -f gpu-toleration.yaml, Kubernetes può pianificare correttamente il pod nei nodi con il taint applicato. Questo isolamento logico consente di controllare l'accesso alle risorse all'interno di un cluster.

Quando si applicano i taint, contattare gli sviluppatori e i proprietari delle applicazioni per consentire loro di definire le tolleranze richieste nelle proprie distribuzioni.

Per altre informazioni su come usare più pool di nodi nel servizio Azure Kubernetes, vedere Creare più pool di nodi per un cluster nel servizio Azure Kubernetes.

Comportamento di taint e tolleranze nel servizio Azure Kubernetes

Quando si aggiorna un pool di nodi nel servizio Azure Kubernetes, i taint e le tolleranze seguono un modello di set applicato ai nuovi nodi:

Cluster predefiniti che usano set di scalabilità di macchine virtuali di Azure

È possibile eseguire il taint di un pool di nodi dall'API del servizio Azure Kubernetes per avere nuovi nodi con scalabilità orizzontale ricevono i nodi specificati dall'API.

Supponiamo:

  1. Si inizia con un cluster a due nodi: nodo1 e nodo2.
  2. Si aggiorna il pool di nodi.
  3. Vengono creati altri due nodi: nodo3 e nodo4.
  4. I taint vengono passati rispettivamente.
  5. I nodo1 e nodo2 originali vengono eliminati.

Cluster senza supporto per set di scalabilità di macchine virtuali

Anche in questo caso, si supponga:

  1. È disponibile un cluster a due nodi: nodo1 e nodo2.
  2. Si aggiorna il pool di nodi.
  3. Viene creato un nodo aggiuntivo: nodo3.
  4. I taint del nodo1 vengono applicati a nodo3.
  5. Il nodo1 viene eliminato.
  6. Viene creato un nuovo nodo1 per sostituire il nodo1 originale.
  7. I taint del nodo2 vengono applicati al nuovo nodo1.
  8. Il nodo2 viene eliminato.

In sostanza, il nodo1 diventa nodo3 e il nodo2 diventa il nuovo nodo1.

Quando si ridimensiona un pool di nodi nel servizio Azure Kubernetes, i contenitori e le tolleranze non vengono gestiti dalla progettazione.

Controllare la pianificazione dei pod tramite selettori di nodo e affinità

Materiale sussidiario sulle procedure consigliate

Controllare la pianificazione dei pod nei nodi usando selettori di nodo, affinità dei nodi o affinità tra pod. Queste impostazioni consentono all'utilità di pianificazione di Kubernetes di isolare in modo logico i carichi di lavoro, ad esempio in base all'hardware nel nodo.

Taint e tolleranze isolano logicamente le risorse con un hard cut-off. Se il pod non tollera il taint di un nodo, non è pianificato nel nodo.

In alternativa, è possibile usare dei selettori di nodo. Ad esempio, si etichettano i nodi per indicare l'archiviazione SSD collegata localmente o una grande quantità di memoria e quindi definire nella specifica del pod un selettore di nodo. Kubernetes pianifica tali pod in un nodo corrispondente.

A differenza delle tolleranze, i pod senza un selettore di nodo corrispondente possono comunque essere pianificati in nodi etichettati. Questo comportamento consente l'utilizzo delle risorse inutilizzate sui nodi, dando tuttavia la priorità ai pod che definiscono il selettore di nodo corrispondente.

Verrà ora preso in esame un esempio di nodi con una quantità elevata di memoria. Questi nodi assegnano priorità ai pod che richiedono una quantità elevata di memoria. Per assicurarsi che le risorse non siano inattive, consentono anche l'esecuzione di altri pod. Il comando di esempio seguente aggiunge un pool di nodi con l'etichetta hardware=highmem al myAKSCluster nel myResourceGroup. Tutti i nodi nel pool di nodi hanno questa etichetta.

az aks nodepool add \
    --resource-group myResourceGroup \
    --cluster-name myAKSCluster \
    --name labelnp \
    --node-count 1 \
    --labels hardware=highmem \
    --no-wait

Una specifica del pod aggiunge quindi la proprietà nodeSelector per definire un selettore di nodo corrispondente all'etichetta impostata su un nodo:

kind: Pod
apiVersion: v1
metadata:
  name: tf-mnist
spec:
  containers:
  - name: tf-mnist
    image: mcr.microsoft.com/azuredocs/samples-tf-mnist-demo:gpu
    resources:
      requests:
        cpu: 0.5
        memory: 2Gi
      limits:
        cpu: 4.0
        memory: 16Gi
  nodeSelector:
      hardware: highmem

Quando si usano queste opzioni dell'utilità di pianificazione, contattare gli sviluppatori e i proprietari delle applicazioni per consentire loro di definire correttamente le specifiche dei pod.

Per altre informazioni sull'uso dei selettori di nodo, vedere Assigning Pods to Nodes (Assegnazione di pod ai nodi).

Affinità tra nodi

Un selettore di nodo è una soluzione di base per l'assegnazione di pod a un determinato nodo. L’affinità nodo offre maggiore flessibilità, consentendo di definire cosa accade se il pod non può essere associato a un nodo. È possibile:

  • Richiedere che l'utilità di pianificazione Kubernetes corrisponda a un pod con un host etichettato. Oppure
  • Preferire una corrispondenza, ma consentire di pianificare il pod in un host diverso se non è disponibile alcuna corrispondenza.

Nell'esempio seguente l'affinità tra nodi viene impostata su requiredDuringSchedulingIgnoredDuringExecution. Questa affinità richiede che l'utilità di pianificazione di Kubernetes usi un nodo con un'etichetta corrispondente. Se non è disponibile alcun nodo, il pod rimane in attesa che la pianificazione continui. Per consentire la pianificazione del pod in un nodo diverso, è invece possibile impostare il valore su DuringSchedulingIgnoreDurutionpreferito:

kind: Pod
apiVersion: v1
metadata:
  name: tf-mnist
spec:
  containers:
  - name: tf-mnist
    image: mcr.microsoft.com/azuredocs/samples-tf-mnist-demo:gpu
    resources:
      requests:
        cpu: 0.5
        memory: 2Gi
      limits:
        cpu: 4.0
        memory: 16Gi
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: hardware
            operator: In
            values:
            - highmem

La parte IgnoredDuringExecution dell'impostazione indica che il pod non deve essere rimosso dal nodo se le etichette del nodo cambiano. L'utilità di pianificazione di Kubernetes usa solo le etichette dei nodi aggiornate per la pianificazione dei nuovi pod, e non i pod già pianificati sui nodi.

Per altre informazioni, vedere la sezione relativa ad affinità e anti-affinità.

Affinità tra pod e anti-affinità

Un ultimo approccio per consentire all'utilità di pianificazione di Kubernetes di isolare in modo logico i carichi di lavoro consiste nell'usare l'affinità tra pod o l'anti-affinità. Queste impostazioni definiscono che i pod non devono o devono essere pianificati in un nodo con un pod corrispondente esistente. Per impostazione predefinita, l'utilità di pianificazione di Kubernetes tenta di pianificare più pod in un set di repliche tra i nodi. È possibile definire più regole specifiche in base a questo comportamento.

Ad esempio, si dispone di un'applicazione Web che usa anche Cache Redis di Azure.

  • Usare le regole di anti-affinità dei pod per fare in modo che l'utilità di pianificazione di Kubernetes distribuisca le repliche tra i nodi.
  • Si usano regole di affinità per assicurarsi che ogni componente dell'app Web sia pianificato nello stesso host di una cache corrispondente.

La distribuzione dei pod tra i nodi è simile alla seguente:

Nodo 1 Nodo 2 Nodo 3
webapp-1 webapp-2 webapp-3
cache-1 cache-2 cache-3

L'affinità tra pod e l'anti-affinità offrono una distribuzione più complessa rispetto ai selettori di nodo o all'affinità dei nodi. Con la distribuzione, si isolano logicamente le risorse e si controlla il modo in cui Kubernetes pianifica i pod nei nodi.

Per un esempio completo di questa applicazione Web con Cache di Azure per Redis, vedere Condivisione dei pod nello stesso nodo.

Passaggi successivi

Questo articolo ha illustrato le funzionalità avanzate dell'utilità di pianificazione di Kubernetes. Per altre informazioni sulle operazioni cluster in servizio Azure Kubernetes, vedere le procedure consigliate seguenti: