Uso dei modelli di pod - Amazon EMR

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Uso dei modelli di pod

A partire dalle EMR versioni di Amazon 5.33.0 o 6.3.0, Amazon EMR on EKS supporta la funzionalità di template pod di Spark. Un pod è un gruppo di uno o più container, con risorse di rete e archiviazione condivise e una specifica per l'esecuzione dei container. I modelli di pod sono specifiche che determinano la modalità di esecuzione di ciascun pod. È possibile utilizzare i file dei modelli di pod per definire le configurazioni dei pod driver o executor non supportate dalle configurazioni Spark. Per ulteriori informazioni sulla funzione dei modelli di pod di Spark, consulta Modelli di pod.

Nota

La funzione dei modelli di pod funziona solo con i pod driver ed executor. Non puoi configurare i pod Job Submitter utilizzando il modello di pod.

Scenari comuni

Puoi definire come eseguire i job Spark su EKS cluster condivisi utilizzando modelli di pod con Amazon EMR attivo EKS e risparmiare costi e migliorare l'utilizzo delle risorse e le prestazioni.

  • Per ridurre i costi, puoi pianificare le attività dei driver Spark da eseguire su istanze Amazon EC2 On-Demand mentre pianificare le attività di esecuzione di Spark da eseguire su istanze Amazon Spot. EC2

  • Per aumentare l'utilizzo delle risorse, puoi supportare più team che eseguono i propri carichi di lavoro sullo stesso cluster. EKS Ogni team riceverà un gruppo di EC2 nodi Amazon designato su cui eseguire i propri carichi di lavoro. È possibile utilizzare i modelli di pod per applicare una tolleranza corrispondente al carico di lavoro.

  • Per migliorare il monitoraggio, è possibile eseguire un container di log separato per inoltrare i log all'applicazione di monitoraggio esistente.

Ad esempio, il file del modello pod riportato di seguito illustra uno scenario di utilizzo comune.

apiVersion: v1 kind: Pod spec: volumes: - name: source-data-volume emptyDir: {} - name: metrics-files-volume emptyDir: {} nodeSelector: eks.amazonaws.com/nodegroup: emr-containers-nodegroup containers: - name: spark-kubernetes-driver # This will be interpreted as driver Spark main container env: - name: RANDOM value: "random" volumeMounts: - name: shared-volume mountPath: /var/data - name: metrics-files-volume mountPath: /var/metrics/data - name: custom-side-car-container # Sidecar container image: <side_car_container_image> env: - name: RANDOM_SIDECAR value: random volumeMounts: - name: metrics-files-volume mountPath: /var/metrics/data command: - /bin/sh - '-c' - <command-to-upload-metrics-files> initContainers: - name: spark-init-container-driver # Init container image: <spark-pre-step-image> volumeMounts: - name: source-data-volume # Use EMR predefined volumes mountPath: /var/data command: - /bin/sh - '-c' - <command-to-download-dependency-jars>

Il modello di pod completa le attività seguenti:

  • Aggiungi un nuovo container init da eseguire prima dell'avvio del container principale Spark. Il contenitore init condivide il EmptyDirvolume chiamato source-data-volume con il contenitore principale di Spark. È possibile fare in modo che il container init esegua i passaggi di inizializzazione, come il download di dipendenze o la generazione di dati di input. In seguito, il container principale Spark consuma i dati.

  • Aggiungi un altro container sidecar da eseguire insieme al container principale Spark. I due container stanno condividendo un altro volume EmptyDir chiamatometrics-files-volume. Il processo Spark può generare parametri quali i parametri Prometheus. In seguito il processo Spark può inserire i parametri in un file e fare in modo che il container sidecar carichi i file nel proprio sistema BI per analisi future.

  • Aggiungi una nuova variabile ambiente al container principale Spark. Puoi fare in modo che il processo utilizzi la variabile ambiente.

  • Definisci un selettore di nodi, in modo che il pod sia pianificato solo sul gruppo di nodi emr-containers-nodegroup. Ciò consente di isolare le risorse di calcolo tra i processi e i team.

Abilitazione dei modelli di pod con Amazon EMR on EKS

Per abilitare la funzionalità di modello di pod con EMR Amazon attivoEKS, configura le proprietà Spark spark.kubernetes.driver.podTemplateFile e fai riferimento spark.kubernetes.executor.podTemplateFile ai file del modello di pod in Amazon S3. Spark scarica quindi il file del modello di pod e lo utilizza per costruire pod driver ed executor.

Nota

Spark utilizza il ruolo di esecuzione del processo per caricare il modello di pod, pertanto il ruolo di esecuzione del processo deve disporre delle autorizzazioni per accedere ad Amazon S3 per caricare i modelli di pod. Per ulteriori informazioni, consulta Creazione di un ruolo di esecuzione di processo.

Puoi utilizzare il SparkSubmitParameters per specificare il percorso di Amazon S3 al modello di pod, come dimostra il seguente JSON file di esecuzione del processo.

{ "name": "myjob", "virtualClusterId": "123456", "executionRoleArn": "iam_role_name_for_job_execution", "releaseLabel": "release_label", "jobDriver": { "sparkSubmitJobDriver": { "entryPoint": "entryPoint_location", "entryPointArguments": ["argument1", "argument2", ...], "sparkSubmitParameters": "--class <main_class> \ --conf spark.kubernetes.driver.podTemplateFile=s3://path_to_driver_pod_template \ --conf spark.kubernetes.executor.podTemplateFile=s3://path_to_executor_pod_template \ --conf spark.executor.instances=2 \ --conf spark.executor.memory=2G \ --conf spark.executor.cores=2 \ --conf spark.driver.cores=1" } } }

In alternativa, puoi utilizzare il configurationOverrides per specificare il percorso di Amazon S3 al modello di pod, come dimostra il seguente JSON file di esecuzione del processo.

{ "name": "myjob", "virtualClusterId": "123456", "executionRoleArn": "iam_role_name_for_job_execution", "releaseLabel": "release_label", "jobDriver": { "sparkSubmitJobDriver": { "entryPoint": "entryPoint_location", "entryPointArguments": ["argument1", "argument2", ...], "sparkSubmitParameters": "--class <main_class> \ --conf spark.executor.instances=2 \ --conf spark.executor.memory=2G \ --conf spark.executor.cores=2 \ --conf spark.driver.cores=1" } }, "configurationOverrides": { "applicationConfiguration": [ { "classification": "spark-defaults", "properties": { "spark.driver.memory":"2G", "spark.kubernetes.driver.podTemplateFile":"s3://path_to_driver_pod_template", "spark.kubernetes.executor.podTemplateFile":"s3://path_to_executor_pod_template" } } ] } }
Nota
  1. È necessario seguire le linee guida di sicurezza quando si utilizza la funzionalità modello pod con Amazon EMR attivoEKS, ad esempio isolando il codice dell'applicazione non attendibile. Per ulteriori informazioni, consulta Best practice di sicurezza per Amazon EMR su EKS.

  2. Non è possibile modificare i nomi dei container principali Spark utilizzando spark.kubernetes.driver.podTemplateContainerName e spark.kubernetes.executor.podTemplateContainerName, perché questi nomi sono codificati come spark-kubernetes-driver e spark-kubernetes-executors. Se si desidera personalizzare il container principale Spark, è necessario specificarlo in un modello di pod con questi nomi codificati.

Campi del modello di pod

Considera le seguenti restrizioni di campo quando configuri un modello di pod con EMR Amazon EKS attivo.

  • Amazon EMR on EKS consente solo i seguenti campi in un modello di pod per consentire una corretta pianificazione dei processi.

    Seguono i campi a livello di pod consentiti:

    • apiVersion

    • kind

    • metadata

    • spec.activeDeadlineSeconds

    • spec.affinity

    • spec.containers

    • spec.enableServiceLinks

    • spec.ephemeralContainers

    • spec.hostAliases

    • spec.hostname

    • spec.imagePullSecrets

    • spec.initContainers

    • spec.nodeName

    • spec.nodeSelector

    • spec.overhead

    • spec.preemptionPolicy

    • spec.priority

    • spec.priorityClassName

    • spec.readinessGates

    • spec.runtimeClassName

    • spec.schedulerName

    • spec.subdomain

    • spec.terminationGracePeriodSeconds

    • spec.tolerations

    • spec.topologySpreadConstraints

    • spec.volumes

    Seguono i campi a livello di container principale Spark consentiti:

    • env

    • envFrom

    • name

    • lifecycle

    • livenessProbe

    • readinessProbe

    • resources

    • startupProbe

    • stdin

    • stdinOnce

    • terminationMessagePath

    • terminationMessagePolicy

    • tty

    • volumeDevices

    • volumeMounts

    • workingDir

    Quando si utilizzano campi non consentiti nel modello di pod, Spark genera un'eccezione e il processo ha esito negativo. L'esempio seguente mostra un messaggio di errore nel log del controller Spark a causa di campi non consentiti.

    Executor pod template validation failed. Field container.command in Spark main container not allowed but specified.
  • Amazon EMR on EKS predefinisce i seguenti parametri in un modello di pod. I campi specificati in un modello di pod non devono sovrapporsi a questi campi.

    Seguono i nomi predefiniti dei volumi:

    • emr-container-communicate

    • config-volume

    • emr-container-application-log-dir

    • emr-container-event-log-dir

    • temp-data-dir

    • mnt-dir

    • home-dir

    • emr-container-s3

    Seguono i montaggi di volume predefiniti che si applicano solo al container principale Spark:

    • Nome:emr-container-communicate; MountPath: /var/log/fluentd

    • Nome:emr-container-application-log-dir; MountPath: /var/log/spark/user

    • Nome:emr-container-event-log-dir; MountPath: /var/log/spark/apps

    • Nome:mnt-dir; MountPath: /mnt

    • Nome:temp-data-dir; MountPath: /tmp

    • Nome:home-dir; MountPath: /home/hadoop

    Seguono le variabili ambiente predefinite che si applicano solo al container principale Spark:

    • SPARK_CONTAINER_ID

    • K8S_SPARK_LOG_URL_STDERR

    • K8S_SPARK_LOG_URL_STDOUT

    • SIDECAR_SIGNAL_FILE

    Nota

    È comunque possibile utilizzare questi volumi predefiniti e montarli nei container sidecar aggiuntivi. Ad esempio, è possibile utilizzare emr-container-application-log-dir e montarlo sul proprio container sidecar definito nel modello di pod.

    Se i campi specificati sono in conflitto con uno qualsiasi dei campi predefiniti nel modello di pod, Spark genera un'eccezione e il processo ha esito negativo. L'esempio seguente mostra un messaggio di errore nel log dell'applicazione Spark a causa di conflitti con i campi predefiniti.

    Defined volume mount path on main container must not overlap with reserved mount paths: [<reserved-paths>]

Considerazioni sui container sidecar

Amazon EMR controlla il ciclo di vita dei pod forniti da Amazon. EMR EKS I container sidecar devono seguire lo stesso ciclo di vita del container principale Spark. Se inietti contenitori sidecar aggiuntivi nei tuoi pod, ti consigliamo di integrarli con la gestione del ciclo di vita dei pod definita da EMR Amazon in modo che il contenitore sidecar possa fermarsi quando il contenitore principale Spark esce.

Per ridurre i costi, è consigliabile implementare un processo che impedisce ai pod driver con container sidecar di continuare a funzionare al termine del processo. Il driver Spark elimina i pod executor quando l'executor viene terminato. Tuttavia, al termine di un programma driver, i container sidecar aggiuntivi continuano a funzionare. Il pod viene fatturato fino a quando Amazon EMR on non EKS ripulisce il driver pod, in genere meno di un minuto dopo il completamento del container principale di Spark del driver. Per ridurre i costi, puoi integrare i contenitori sidecar aggiuntivi con il meccanismo di gestione del ciclo di vita EKS definito da Amazon EMR on per i driver e gli executor pod, come descritto nella sezione seguente.

Il container principale Spark nei pod driver ed executor invia heartbeat a un file /var/log/fluentd/main-container-terminated ogni due secondi. Aggiungendo il emr-container-communicate volume EMR predefinito di Amazon al tuo contenitore sidecar, puoi definire un sottoprocesso del tuo contenitore sidecar per tracciare periodicamente l'ora dell'ultima modifica per questo file. Il sottoprocesso si arresta se scopre che il container principale Spark arresta il heartbeat per una durata di tempo maggiore.

Nell'esempio seguente viene illustrato un sottoprocesso che tiene traccia del file heartbeat e si arresta. Replace (Sostituisci) your_volume_mount con il percorso in cui monti il volume predefinito. Lo script è raggruppato all'interno dell'immagine utilizzata dal container sidecar. In un file del modello di pod, è possibile specificare un container sidecar con i seguenti comandi sub_process_script.sh e main_command.

MOUNT_PATH="your_volume_mount" FILE_TO_WATCH="$MOUNT_PATH/main-container-terminated" INITIAL_HEARTBEAT_TIMEOUT_THRESHOLD=60 HEARTBEAT_TIMEOUT_THRESHOLD=15 SLEEP_DURATION=10 function terminate_main_process() { # Stop main process } # Waiting for the first heartbeat sent by Spark main container echo "Waiting for file $FILE_TO_WATCH to appear..." start_wait=$(date +%s) while ! [[ -f "$FILE_TO_WATCH" ]]; do elapsed_wait=$(expr $(date +%s) - $start_wait) if [ "$elapsed_wait" -gt "$INITIAL_HEARTBEAT_TIMEOUT_THRESHOLD" ]; then echo "File $FILE_TO_WATCH not found after $INITIAL_HEARTBEAT_TIMEOUT_THRESHOLD seconds; aborting" terminate_main_process exit 1 fi sleep $SLEEP_DURATION; done; echo "Found file $FILE_TO_WATCH; watching for heartbeats..." while [[ -f "$FILE_TO_WATCH" ]]; do LAST_HEARTBEAT=$(stat -c %Y $FILE_TO_WATCH) ELAPSED_TIME_SINCE_AFTER_HEARTBEAT=$(expr $(date +%s) - $LAST_HEARTBEAT) if [ "$ELAPSED_TIME_SINCE_AFTER_HEARTBEAT" -gt "$HEARTBEAT_TIMEOUT_THRESHOLD" ]; then echo "Last heartbeat to file $FILE_TO_WATCH was more than $HEARTBEAT_TIMEOUT_THRESHOLD seconds ago at $LAST_HEARTBEAT; terminating" terminate_main_process exit 0 fi sleep $SLEEP_DURATION; done; echo "Outside of loop, main-container-terminated file no longer exists" # The file will be deleted once the fluentd container is terminated echo "The file $FILE_TO_WATCH doesn't exist any more;" terminate_main_process exit 0