Verwenden von Pod-Vorlagen - Amazon EMR

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

Verwenden von Pod-Vorlagen

Ab den EMR Amazon-Versionen 5.33.0 oder 6.3.0 EKS unterstützt Amazon EMR on die Pod-Vorlagenfunktion von Spark. Ein Pod ist eine Gruppe von einem oder mehreren Containern mit gemeinsam genutzten Speicher- und Netzwerkressourcen und einer Spezifikation für die Ausführung der Container. Pod-Vorlagen sind Spezifikationen, die bestimmen, wie jeder Pod ausgeführt wird. Sie können Pod-Vorlagendateien verwenden, um die Treiber- oder Executor-Pod-Konfigurationen zu definieren, die Spark-Konfigurationen nicht unterstützen. Weitere Informationen zum Pod-Vorlagenfeature von Spark finden Sie unter Pod-Vorlage.

Anmerkung

Das Pod-Vorlagenfeature funktioniert nur mit Treiber- und Executor-Pods. Sie können Pods für Job-Einreicher nicht mithilfe der Pod-Vorlage konfigurieren.

Gängige Szenarien

Sie können definieren, wie Spark-Jobs auf gemeinsam genutzten EKS Clustern ausgeführt werden, indem Sie Pod-Vorlagen verwenden, bei denen EMR Amazon aktiviert ist. So können Sie Kosten sparen EKS und die Ressourcennutzung und Leistung verbessern.

  • Um die Kosten zu senken, können Sie Spark-Treiberaufgaben so planen, dass sie auf Amazon EC2 On-Demand-Instances ausgeführt werden, und gleichzeitig Spark-Executor-Aufgaben für die Ausführung auf Amazon EC2 Spot-Instances planen.

  • Um die Ressourcennutzung zu erhöhen, können Sie mehrere Teams dabei unterstützen, ihre Workloads auf demselben Cluster auszuführen. EKS Jedes Team erhält eine bestimmte EC2 Amazon-Knotengruppe, auf der es seine Workloads ausführen kann. Sie können Pod-Vorlagen verwenden, um eine entsprechende Toleranz auf ihren Workload anzuwenden.

  • Um die Überwachung zu verbessern, können Sie einen separaten Protokollierungs-Container ausführen, um Protokolle an Ihre bestehende Überwachungsanwendung weiterzuleiten.

Die folgende Pod-Vorlagendatei veranschaulicht beispielsweise ein gängiges Nutzungsszenario.

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>

Die Pod-Vorlage führt die folgenden Aufgaben aus:

  • Fügen Sie einen neuen Init-Container hinzu, der ausgeführt wird, bevor der Spark-Hauptcontainer gestartet wird. Der Init-Container teilt sich das aufgerufene EmptyDirVolume source-data-volume mit dem Spark-Hauptcontainer. Sie können Ihren Init-Container Initialisierungsschritte wie das Herunterladen von Abhängigkeiten oder das Generieren von Eingabedaten ausführen lassen. Dann verbraucht der Spark-Hauptcontainer die Daten.

  • Fügen Sie einen weiteren Sidecar-Container hinzu, der zusammen mit dem Spark-Hauptcontainer ausgeführt wird. Die beiden Container teilen sich ein weiteres EmptyDir-Volume namens metrics-files-volume. Ihr Spark-Auftrag kann Metriken wie Prometheus-Metriken generieren. Dann kann der Spark-Auftrag die Metriken in eine Datei schreiben und den Sidecar-Container die Dateien zur zukünfigen Analyse in Ihr eigenes BI-System hochladen lassen.

  • Fügen Sie dem Spark-Hauptcontainer eine neue Umgebungsvariable hinzu. Sie können festlegen, dass Ihr Auftrag die Umgebungsvariable verwendet.

  • Definieren Sie eine Knotenauswahl, sodass der Pod nur für die emr-containers-nodegroup-Knotengruppe geplant ist. Dies hilft dabei, Rechenressourcen für verschiedene Aufträge und Teams zu isolieren.

Aktivierung von Pod-Vorlagen mit Amazon EMR on EKS

Um die Pod-Vorlagenfunktion bei aktiviertem EMR Amazon zu aktivierenEKS, konfigurieren Sie die Spark-Eigenschaften spark.kubernetes.driver.podTemplateFile und spark.kubernetes.executor.podTemplateFile verweisen Sie auf die Pod-Vorlagendateien in Amazon S3. Spark lädt dann die Pod-Vorlagendatei herunter und verwendet sie, um Treiber- und Executor-Pods zu erstellen.

Anmerkung

Spark verwendet die Auftragausführungsrolle, um die Pod-Vorlage zu laden, sodass die Auftragausführungsrolle über Zugriffsberechtigungen für Amazon S3 verfügen muss, um die Pod-Vorlagen zu laden. Weitere Informationen finden Sie unter Erstellen einer Aufgabenausführungsrolle.

Sie können das verwendenSparkSubmitParameters, um den Amazon S3 S3-Pfad zur Pod-Vorlage anzugeben, wie die folgende JSON Jobausführungsdatei zeigt.

{ "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" } } }

Alternativ können Sie den verwenden, configurationOverrides um den Amazon S3-Pfad zur Pod-Vorlage anzugeben, wie die folgende JSON Jobausführungsdatei zeigt.

{ "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" } } ] } }
Anmerkung
  1. Sie müssen die Sicherheitsrichtlinien befolgen, wenn Sie die Pod-Vorlagenfunktion verwenden, wenn EMR Amazon aktiviert istEKS, z. B. das Isolieren von nicht vertrauenswürdigem Anwendungscode. Weitere Informationen finden Sie unter Bewährte Methoden für Sicherheit in Amazon EMR in EKS.

  2. Sie können die Namen der Spark-Hauptcontainer nicht mit spark.kubernetes.driver.podTemplateContainerName und spark.kubernetes.executor.podTemplateContainerName ändern, da diese Namen als spark-kubernetes-driver und spark-kubernetes-executors fest codiert sind. Wenn Sie den Spark-Hauptcontainer anpassen möchten, müssen Sie den Container in einer Pod-Vorlage mit diesen hartcodierten Namen angeben.

Pod-Vorlagenfelder

Beachten Sie bei der Konfiguration einer Pod-Vorlage mit aktiviertem Amazon EMR die folgenden FeldeinschränkungenEKS.

  • Amazon EMR on EKS erlaubt nur die folgenden Felder in einer Pod-Vorlage, um eine korrekte Jobplanung zu ermöglichen.

    Dies sind die zulässigen Felder auf Pod-Ebene:

    • 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

    Dies sind die zulässigen Felder auf Spark-Hauptcontainerebene:

    • env

    • envFrom

    • name

    • lifecycle

    • livenessProbe

    • readinessProbe

    • resources

    • startupProbe

    • stdin

    • stdinOnce

    • terminationMessagePath

    • terminationMessagePolicy

    • tty

    • volumeDevices

    • volumeMounts

    • workingDir

    Wenn Sie unzulässige Felder in der Pod-Vorlage verwenden, löst Spark eine Ausnahme aus und der Auftrag schlägt fehl. Das folgende Beispiel zeigt eine Fehlermeldung im Spark-Controller-Protokoll, die auf unzulässige Felder zurückzuführen ist.

    Executor pod template validation failed. Field container.command in Spark main container not allowed but specified.
  • Amazon EMR on EKS definiert die folgenden Parameter in einer Pod-Vorlage vordefiniert. Die Felder, die Sie in einer Pod-Vorlage angeben, dürfen sich nicht mit diesen Feldern überschneiden.

    Dies sind die vordefinierten Volume-Namen:

    • 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

    Dies sind die vordefinierten Volume-Mounts, die nur für den Spark-Hauptcontainer gelten:

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

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

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

    • Name:mnt-dir; MountPath: /mnt

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

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

    Dies sind die vordefinierten Umgebungsvariablen, die nur für den Spark-Hauptcontainer gelten:

    • SPARK_CONTAINER_ID

    • K8S_SPARK_LOG_URL_STDERR

    • K8S_SPARK_LOG_URL_STDOUT

    • SIDECAR_SIGNAL_FILE

    Anmerkung

    Sie können diese vordefinierten Volumes weiterhin verwenden und sie in Ihre zusätzlichen Sidecar-Container einbinden. Sie können beispielsweise emr-container-application-log-dir verwenden und in Ihrem eigenen Sidecar-Container bereitstellen, der in der Pod-Vorlage definiert ist.

    Wenn die von Ihnen angegebenen Felder mit einem der vordefinierten Felder in der Pod-Vorlage in Konflikt stehen, löst Spark eine Ausnahme aus und der Auftrag schlägt fehl. Das folgende Beispiel zeigt eine Fehlermeldung im Spark-Anwendungsprotokoll aufgrund von Konflikten mit den vordefinierten Feldern.

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

Überlegungen zu Sidecarcontainern

Amazon EMR kontrolliert den Lebenszyklus der von Amazon bereitgestellten Pods EMR amEKS. Die Sidecar-Container sollten dem gleichen Lebenszyklus folgen wie der Spark-Hauptcontainer. Wenn Sie zusätzliche Sidecar-Container in Ihre Pods einbauen, empfehlen wir Ihnen, das Pod-Lifecycle-Management zu integrieren, das Amazon EMR definiert, sodass sich der Sidecar-Container selbst stoppen kann, wenn der Spark-Hauptcontainer verlassen wird.

Um die Kosten zu senken, empfehlen wir Ihnen, einen Prozess zu implementieren, der verhindert, dass Treiber-Pods mit Sidecar-Containern nach Abschluss Ihres Aufträge weiter ausgeführt werden. Der Spark-Treiber löscht Ausführer-Pods, wenn der Ausführer fertig ist. Wenn ein Treiberprogramm abgeschlossen ist, werden die zusätzlichen Sidecar-Container jedoch weiter ausgeführt. Der Pod wird in Rechnung gestellt, bis Amazon EMR on den Treiber-Pod EKS bereinigt hat, normalerweise weniger als eine Minute, nachdem der Treiber-Spark-Hauptcontainer abgeschlossen ist. Um die Kosten zu senken, können Sie Ihre zusätzlichen Sidecar-Container in den Lifecycle-Management-Mechanismus integrieren, den Amazon EMR on sowohl für Treiber- als auch für Executor-Pods EKS definiert, wie im folgenden Abschnitt beschrieben.

Der Spark-Hauptcontainer in den Treiber- und Ausführer-Pods sendet heartbeat alle zwei Sekunden an eine /var/log/fluentd/main-container-terminated-Datei. Indem Sie Ihrem Sidecar-Container den von Amazon EMR vordefinierten emr-container-communicate Volume-Mount hinzufügen, können Sie einen Unterprozess Ihres Sidecar-Containers definieren, der regelmäßig den Zeitpunkt der letzten Änderung für diese Datei verfolgt. Der Unterprozess stoppt sich dann selbst, wenn er feststellt, dass der Spark-Hauptcontainer den heartbeat für einen längeren Zeitraum stoppt.

Das folgende Beispiel zeigt einen Unterprozess, der die Heartbeat-Datei verfolgt und sich selbst stoppt. Ersetzen your_volume_mount mit dem Pfad, in den Sie das vordefinierte Volume mounten. Das Skript ist in dem Image gebündelt, das vom Sidecar-Container verwendet wird. In einer Pod-Vorlagendatei können Sie einen Sidecar-Container mit den folgenden Befehlen sub_process_script.sh und main_command angeben.

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