Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.
Uso de plantillas de pods
A partir de las versiones 5.33.0 o 6.3.0 de Amazon EMR, Amazon EMR en EKS es compatible con la característica de plantillas de pods de Spark. Un pod es un grupo de uno o más contenedores, con recursos de red y almacenamiento compartidos, y una especificación sobre cómo ejecutar los contenedores. Las plantillas de pods son especificaciones que determinan cómo ejecutar cada pod. Puede usar archivos de plantillas de pods para definir las configuraciones del pod de controlador o ejecutor que las configuraciones de Spark no admiten. Para obtener más información sobre la característica de plantillas de pods de Spark, consulte Plantillas de pods
nota
La característica de plantillas de pods solo funciona con los pods controladores y ejecutores. No puede configurar los pods del remitente de trabajos mediante la plantilla de pods.
Escenarios habituales
Puede definir cómo ejecutar los trabajos de Spark en clústeres de EKS compartidos mediante plantillas de pods con Amazon EMR en EKS y ahorrar costos y mejorar la utilización y el rendimiento de los recursos.
-
Para reducir los costos, puede programar las tareas del controlador de Spark para que se ejecuten en las instancias bajo demanda de Amazon EC2 y programar las tareas del ejecutor de Spark para que se ejecuten en las instancias de spot de Amazon EC2.
-
Para aumentar la utilización de los recursos, puede ayudar a varios equipos a ejecutar sus cargas de trabajo en el mismo clúster de EKS. Cada equipo dispondrá de un grupo de nodos de Amazon EC2 designado para ejecutar sus cargas de trabajo. Puede utilizar plantillas de pods para aplicar la tolerancia correspondiente a su carga de trabajo.
-
Para mejorar la supervisión, puede ejecutar un contenedor de registro independiente para reenviar los registros a la aplicación de supervisión existente.
Por ejemplo, el siguiente archivo de plantilla de pod muestra un escenario de uso común.
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>
La plantilla de pod lleva a cabo las tareas siguientes:
-
Agrega un nuevo contenedor de inicialización
que se ejecuta antes de que se inicie el contenedor principal de Spark. El contenedor de inicialización comparte el volumen EmptyDir denominado source-data-volume
con el contenedor principal de Spark. Puede hacer que su contenedor de inicialización ejecute los pasos de inicialización, como descargar dependencias o generar datos de entrada. A continuación, el contenedor principal de Spark consume los datos. -
Agregue otro contenedor asociado
que se ejecute junto con el contenedor principal de Spark. Los dos contenedores comparten otro volumen EmptyDir
llamadometrics-files-volume
. Su trabajo en Spark puede generar métricas, como las métricas de Prometheus. A continuación, el trabajo de Spark puede colocar las métricas en un archivo y hacer que el contenedor asociado cargue los archivos en su propio sistema de BI para análisis futuros. -
Agregue una nueva variable de entorno al contenedor principal de Spark. Puede hacer que el trabajo consuma la variable de entorno.
-
Defina un selector de nodos
para que el pod solo esté programado en el grupo de nodos emr-containers-nodegroup
. Esto ayuda a aislar los recursos de computación entre trabajos y equipos.
Habilitación de plantillas de pods con Amazon EMR en EKS
Para habilitar la característica de plantilla de pod con Amazon EMR en EKS, configure las propiedades de Spark spark.kubernetes.driver.podTemplateFile
y spark.kubernetes.executor.podTemplateFile
para que apunten a los archivos de plantillas de pods en Amazon S3. A continuación, Spark descarga el archivo de plantilla del pod y lo utiliza para crear los pods controladores y ejecutores.
nota
Spark usa el rol de ejecución de trabajos para cargar la plantilla de pod, por lo que el rol de ejecución de tareas debe tener permisos de acceso a Amazon S3 para cargar las plantillas de pods. Para obtener más información, consulte Crear un rol de ejecución de trabajos.
Puede utilizar los SparkSubmitParameters
para especificar la ruta de Amazon S3 a la plantilla del pod, tal como se muestra en el siguiente archivo JSON de ejecución de tareas.
{ "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" } } }
Como alternativa, puede usar las configurationOverrides
para especificar la ruta de Amazon S3 a la plantilla del pod, tal como se muestra en el siguiente archivo JSON de ejecución de tareas.
{ "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
-
Debe seguir las pautas de seguridad cuando utilice la característica de plantilla de pod con Amazon EMR en EKS, como aislar el código de una aplicación que no sea de confianza. Para obtener más información, consulte Prácticas recomendadas de seguridad de Amazon EMR en EKS.
-
No puede cambiar los nombres de los contenedores principales de Spark mediante
spark.kubernetes.driver.podTemplateContainerName
yspark.kubernetes.executor.podTemplateContainerName
, ya que estos nombres están codificados comospark-kubernetes-driver
yspark-kubernetes-executors
. Si quiere personalizar el contenedor principal de Spark, debe especificarlo en una plantilla de pod con estos nombres codificados.
Campos de plantilla de pod
Tenga en cuenta las siguientes restricciones de campo al configurar una plantilla de pod con Amazon EMR en EKS.
-
Amazon EMR en EKS solo permite los siguientes campos en una plantilla de pod para habilitar una programación adecuada de los trabajos.
Estos son los campos de nivel de pod permitidos:
-
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
Estos son los campos de nivel de contenedor principal de Spark permitidos:
-
env
-
envFrom
-
name
-
lifecycle
-
livenessProbe
-
readinessProbe
-
resources
-
startupProbe
-
stdin
-
stdinOnce
-
terminationMessagePath
-
terminationMessagePolicy
-
tty
-
volumeDevices
-
volumeMounts
-
workingDir
Cuando utiliza campos no permitidos en la plantilla de pod, Spark lanza una excepción y se produce un error en el trabajo. En el siguiente ejemplo, se muestra un mensaje de error en el registro del controlador de Spark porque hay campos no permitidos.
Executor pod template validation failed. Field container.command in Spark main container not allowed but specified.
-
-
Amazon EMR en EKS predefine los siguientes parámetros en una plantilla de pod. Los campos que especifique en una plantilla de pod no deben superponerse con estos campos.
Estos son los nombres de volumen predefinidos:
-
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
Estos son los montajes de volumen predefinidos que solo se aplican al contenedor principal de Spark:
-
Nombre:
emr-container-communicate
; MountPath:/var/log/fluentd
-
Nombre:
emr-container-application-log-dir
; MountPath:/var/log/spark/user
-
Nombre:
emr-container-event-log-dir
; MountPath:/var/log/spark/apps
-
Nombre:
mnt-dir
; MountPath:/mnt
-
Nombre:
temp-data-dir
; MountPath:/tmp
-
Nombre:
home-dir
; MountPath:/home/hadoop
Estas son las variables de entorno predefinidas que solo se aplican al contenedor principal de Spark:
-
SPARK_CONTAINER_ID
-
K8S_SPARK_LOG_URL_STDERR
-
K8S_SPARK_LOG_URL_STDOUT
-
SIDECAR_SIGNAL_FILE
nota
Puede seguir usando estos volúmenes predefinidos y montarlos en sus contenedores asociados adicionales. Por ejemplo, puede usar
emr-container-application-log-dir
y montarlo en su propio contenedor asociado definido en la plantilla de pod.Si los campos que especifique entran en conflicto con alguno de los campos predefinidos de la plantilla del pod, Spark lanza una excepción y se produce un error en el trabajo. En el siguiente ejemplo, se muestra un mensaje de error en el registro de la aplicación de Spark debido a conflictos con los campos predefinidos.
Defined volume mount path on main container must not overlap with reserved mount paths: [<reserved-paths>]
-
Consideraciones sobre los contenedores asociados
Amazon EMR controla el ciclo de vida de los pods aprovisionados por Amazon EMR en EKS. Los contenedores asociados deben seguir el mismo ciclo de vida que el contenedor principal de Spark. Si inyecta contenedores asociados adicionales en sus pods, le recomendamos que los integre con la administración del ciclo de vida de los pods que Amazon EMR define para que el contenedor asociado pueda detenerse solo cuando salga el contenedor principal de Spark.
Para reducir costos, le recomendamos que implemente un proceso que impida que los pods controladores con contenedores asociados sigan funcionando una vez que haya completado el trabajo. El controlador de Spark elimina los pods ejecutores cuando el ejecutor ha terminado. Sin embargo, cuando se completa un programa de controlador, los contenedores asociados adicionales siguen funcionando. El pod se factura hasta que Amazon EMR en EKS limpie el pod controlador, normalmente en menos de un minuto después de que se complete el contenedor principal de Spark del controlador. Para reducir costos, puede integrar sus contenedores asociados adicionales con el mecanismo de administración del ciclo de vida que Amazon EMR en EKS define para los pods controladores y ejecutores, tal y como se describe en la siguiente sección.
El contenedor principal de Spark de los pods ejecutores y controladores envía heartbeat
a un archivo /var/log/fluentd/main-container-terminated
cada dos segundos. Al agregar el montaje de volumen emr-container-communicate
predefinido de Amazon EMR a su contenedor asociado, puede definir un subproceso de dicho contenedor para hacer un seguimiento periódico de la hora de la última modificación de este archivo. A continuación, el subproceso se detiene automáticamente si descubre que el contenedor principal de Spark detiene el heartbeat
durante más tiempo.
El siguiente ejemplo muestra un subproceso que rastrea el archivo de latidos y se detiene solo. Sustituya your_volume_mount
por la ruta en la que monte el volumen predefinido. El script está incluido dentro de la imagen utilizada por el contenedor asociado. En un archivo de plantilla de pod, puede especificar un contenedor asociado con los comandos sub_process_script.sh
y 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