Esecuzione di carichi di lavoro a tolleranza di errore a costi inferiori nei pod spot

Questa pagina mostra come eseguire carichi di lavoro a tolleranza di errore a costi inferiori utilizzando i pod Spot nei cluster Google Kubernetes Engine (GKE) Autopilot.

Panoramica

Nei cluster GKE Autopilot, i pod Spot sono pod eseguiti su nodi supportati da Compute Engine VM spot. I pod Spot hanno un prezzo inferiore rispetto ai pod Autopilot standard, ma possono essere rimossi da GKE ogni volta che sono necessarie risorse di calcolo per eseguire i pod standard.

I pod Spot sono ideali per l'esecuzione di carichi di lavoro senza stato, batch o a tolleranza di errore a costi inferiori rispetto all'esecuzione di questi carichi di lavoro come pod standard. Per utilizzare i pod Spot nei cluster Autopilot, modifica il manifest con la specifica del pod per richiedere i pod Spot.

Puoi eseguire i pod Spot sulla classe di computing Autopilot per uso generico predefinita, nonché sulle classi di computing specializzate che soddisfano requisiti hardware specifici. Per informazioni su queste classi di computing, consulta le Classi di computing in Autopilot.

Per scoprire di più sui prezzi dei pod Spot nei cluster Autopilot, consulta Prezzi di Google Kubernetes Engine.

I pod Spot sono esclusi dall'accordo sul livello del servizio Autopilot.

Vantaggi

L'utilizzo dei pod Spot nei cluster Autopilot offre i seguenti vantaggi:

  • Prezzi inferiori rispetto all'esecuzione degli stessi carichi di lavoro sui pod Autopilot standard.
  • GKE gestisce automaticamente la scalabilità automatica e la pianificazione.
  • GKE automatically applica automaticamente un taint ai nodi che eseguono i pod Spot per garantire che i pod standard, come i carichi di lavoro critici, non vengano pianificati su questi nodi. I deployment che utilizzano i pod Spot vengono aggiornati automaticamente con una tolleranza corrispondente corrispondente.

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à, installala e poi inizializza gcloud CLI. Se hai già installato gcloud CLI, scarica l'ultima versione eseguendo il gcloud components update comando. Le versioni precedenti di gcloud CLI potrebbero non supportare l'esecuzione dei comandi in questo documento.

Richiedere pod Spot nei carichi di lavoro Autopilot

Per richiedere che i pod vengano eseguiti come pod Spot, utilizza l' cloud.google.com/gke-spot=trueetichetta in un nodeSelector o nell'affinità nodo nella specifica del pod. GKE esegue automaticamente il provisioning dei nodi che possono eseguire i pod Spot.

I pod Spot possono essere rimossi e terminati in qualsiasi momento, ad esempio se le risorse di calcolo sono richieste altrove in Google Cloud. Quando si verifica una terminazione, i pod Spot sul nodo di terminazione possono richiedere un periodo di tolleranza fino a 15 secondi prima della terminazione, concesso in base al criterio del "best effort", specificando il campo terminationGracePeriodSeconds.

Il periodo di tolleranza massimo concesso ai pod Spot durante il prerilascio è di 15 secondi. Se richiedi più di 15 secondi in terminationGracePeriodSeconds, non vengono concessi più di 15 secondi durante il prerilascio. Al momento della rimozione, al pod viene inviato il segnale SIGTERM, e deve eseguire i passaggi per l'arresto durante il periodo di tolleranza.

Per Autopilot, GKE applica automaticamente un taint ai nodi creati per eseguire i pod Spot e modifica questi carichi di lavoro con la tolleranza corrispondente. Il taint impedisce la pianificazione dei pod standard sui nodi che eseguono i pod Spot.

Utilizzare un nodeSelector per richiedere i pod Spot

Puoi utilizzare un nodeSelector per richiedere i pod Spot in un deployment. Aggiungi l'etichetta cloud.google.com/gke-spot=true al deployment, come nell'esempio seguente:

apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  template:
    metadata:
      labels:
        app: pi
    spec:
      nodeSelector:
        cloud.google.com/gke-spot: "true"
      terminationGracePeriodSeconds: 15
      containers:
      - name: pi
        image: perl:5.34.0
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never
  backoffLimit: 4

Utilizzare l'affinità nodo per richiedere i pod Spot

In alternativa, puoi utilizzare l'affinità nodo per richiedere i pod Spot. L'affinità nodo offre un modo più estensibile per selezionare i nodi su cui eseguire i carichi di lavoro. Ad esempio, puoi combinare diversi criteri di selezione per avere un controllo più preciso sulla posizione di esecuzione dei pod. Quando utilizzi l'affinità nodo per richiedere i pod Spot, puoi specificare il tipo di affinità nodo da utilizzare, come segue:

  • requiredDuringSchedulingIgnoredDuringExecution: devi utilizzare i pod Spot.
  • preferredDuringSchedulingIgnoredDuringExecution: utilizza i pod Spot in base al criterio del "best effort".

Per utilizzare l'affinità nodo per richiedere i pod Spot in un deployment, aggiungi la seguente regola nodeAffinity al manifest del deployment:

apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  template:
    metadata:
      labels:
        app: pi
    spec:
      terminationGracePeriodSeconds: 15
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: cloud.google.com/gke-spot
                operator: In
                values:
                - "true"
      containers:
      - name: pi
        image: perl:5.34.0
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never
  backoffLimit: 4

Richiedere i pod Spot in base al criterio del "best effort"

Per utilizzare l'affinità nodo per richiedere i pod Spot in base al criterio del "best effort", utilizza preferredDuringSchedulingIgnoredDuringExecution. Quando richiedi i pod Spot in base alle preferenze, GKE pianifica i pod nel seguente ordine:

  1. Nodi esistenti che possono eseguire i pod Spot con capacità allocabile disponibile.
  2. Nodi standard esistenti con capacità allocabile disponibile.
  3. Nuovi nodi che possono eseguire i pod Spot, se le risorse di calcolo sono disponibili.
  4. Nuovi nodi standard.

Poiché GKE preferisce i nodi standard esistenti con capacità allocabile rispetto alla creazione di nuovi nodi per i pod Spot, potresti notare che più pod vengono eseguiti come pod standard anziché come pod Spot, il che ti impedisce di sfruttare appieno i prezzi inferiori dei pod Spot.

Richieste di pod prerilasciabili

I cluster Autopilot supportano le richieste di pod prerilasciabili utilizzando il selettore cloud.google.com/gke-preemptible. I pod che utilizzano questo selettore vengono migrati automaticamente ai pod Spot e il selettore viene modificato in cloud.google.com/gke-spot.

Trovare ed eliminare i pod terminati

Durante la terminazione normale dei pod, kubelet assegna lo stato Failed e il motivo Shutdown ai pod terminati. Quando il numero di pod terminati raggiunge una soglia di 1000, la garbage collection pulisce i pod. Puoi anche eliminare manualmente i pod arrestati utilizzando il seguente comando:

kubectl get pods --all-namespaces | grep -i shutdown | awk '{print $1, $2}' | xargs -n2 kubectl delete pod -n

Impedire ai carichi di lavoro di utilizzare i pod Spot

Se hai pod Spot esistenti che vuoi aggiornare per l'esecuzione come pod standard, puoi utilizzare uno dei seguenti metodi:

  • Ricrea il carico di lavoro: elimina il deployment, rimuovi le righe nel manifest che selezionano i pod Spot e poi applica il manifest del deployment aggiornato al cluster.
  • Modifica il carico di lavoro: modifica la specifica del deployment mentre i pod sono in esecuzione nel cluster.

Con entrambi questi metodi, potresti riscontrare interruzioni minori del carico di lavoro.

Ricreare il carico di lavoro

I seguenti passaggi mostrano come eliminare il deployment esistente e applicare un manifest aggiornato al cluster. Puoi utilizzare questi passaggi anche per altri tipi di carichi di lavoro Kubernetes, come i job.

Per assicurarti che GKE inserisca i pod aggiornati sul tipo di nodo corretto, devi esportare lo stato esistente del carico di lavoro dal server API Kubernetes in un file e modificarlo.

  1. Scrivi la specifica del carico di lavoro in un file YAML:

    kubectl get deployment DEPLOYMENT_NAME -o yaml > DEPLOYMENT_NAME-on-demand.yaml
    

    Sostituisci DEPLOYMENT_NAME con il nome del deployment. Per altri tipi di carichi di lavoro, come job o pod, utilizza il nome della risorsa corrispondente nel comando kubectl get, ad esempio kubectl get pod.

  2. Apri il file YAML in un editor di testo:

    vi DEPLOYMENT_NAME-on-demand.yaml
    
  3. Rimuovi il nodeSelector per i pod Spot e la tolleranza che GKE ha aggiunto per i pod Spot dal file:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      annotations:
      # lines omitted for clarity
    spec:
      progressDeadlineSeconds: 600
      replicas: 6
      revisionHistoryLimit: 10
      selector:
        matchLabels:
          pod: nginx-pod
      strategy:
        rollingUpdate:
          maxSurge: 25%
          maxUnavailable: 25%
        type: RollingUpdate
      template:
        metadata:
        # lines omitted for clarity
        spec:
          containers:
          - image: nginx
            imagePullPolicy: Always
            name: web-server
            resources:
              limits:
                ephemeral-storage: 1Gi
              requests:
                cpu: 500m
                ephemeral-storage: 1Gi
                memory: 2Gi
            securityContext:
              capabilities:
                drop:
                - NET_RAW
            terminationMessagePath: /dev/termination-log
            terminationMessagePolicy: File
          dnsPolicy: ClusterFirst
          nodeSelector:
            cloud.google.com/gke-spot: "true"
          restartPolicy: Always
          schedulerName: default-scheduler
          securityContext:
            seccompProfile:
              type: RuntimeDefault
          terminationGracePeriodSeconds: 15
          tolerations:
          - effect: NoSchedule
            key: kubernetes.io/arch
            operator: Equal
            value: amd64
          - effect: NoSchedule
            key: cloud.google.com/gke-spot
            operator: Equal
            value: "true"
    status:
      #lines omitted for clarity
    

    Devi rimuovere sia la tolleranza sia il nodeSelector per indicare a GKE che i pod devono essere eseguiti su nodi on demand anziché su nodi Spot.

  4. Salva il manifest aggiornato.

  5. Elimina e riapplica il manifest del deployment al cluster:

    kubectl replace -f DEPLOYMENT_NAME-on-demand.yaml
    

    La durata di questa operazione dipende dal numero di pod che GKE deve terminare e pulire.

Modificare il carico di lavoro in loco

I seguenti passaggi mostrano come modificare un deployment in esecuzione in loco per indicare a GKE che i pod devono essere eseguiti su nodi on demand. Puoi utilizzare questi passaggi anche per altri tipi di carichi di lavoro Kubernetes, come i job.

Devi modificare l'oggetto del carico di lavoro nell'API Kubernetes perché GKE aggiunge automaticamente una tolleranza per i pod Spot alla specifica del carico di lavoro durante l'ammissione del carico di lavoro.

  1. Apri il manifest del carico di lavoro per la modifica in un editor di testo:

    kubectl edit deployment/DEPLOYMENT_NAME
    

    Sostituisci DEPLOYMENT_NAME con il nome del deployment. Per altri tipi di carichi di lavoro, come job o pod, utilizza il nome della risorsa corrispondente nel comando kubectl edit, ad esempio kubectl edit pod/POD_NAME.

  2. Nell'editor di testo, elimina il selettore di nodi o la regola di affinità nodo per i pod Spot e la tolleranza che GKE ha aggiunto al manifest, come nell'esempio seguente:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: example-deployment
      namespace: default
    spec:
      replicas: 1
      selector:
        matchLabels:
          type: dev
      template:
        metadata:
          labels:
            type: dev
        spec:
          nodeSelector:
            cloud.google.com/gke-spot: "true"
          tolerations:
          - effect: NoSchedule
            key: cloud.google.com/gke-spot
            operator: Equal
            value: "true"
          containers:
          - name: nginx
            image: nginx
            ports:
            - containerPort: 80
    
  3. Salva il manifest aggiornato e chiudi l'editor di testo. La configurazione dell'oggetto aggiornata indica a GKE che i pod devono essere eseguiti su nodi on demand. GKE ricrea i pod per inserirli su nuovi nodi on demand.

Verificare che i carichi di lavoro vengano eseguiti su nodi on demand

Per verificare che i carichi di lavoro aggiornati non vengano più eseguiti sui pod Spot, esamina il carico di lavoro e cerca la tolleranza per i pod Spot:

  • Esamina il carico di lavoro:

    kubectl describe deployment DEPLOYMENT_NAME
    

L'output non mostra una voce per cloud.google.com/gke-spot nel campo spec.tolerations.

Passaggi successivi