When it comes to running different distributed applications besides Spark, running Spark in standalone mode (with the embedded cluster manager) is not a good choice for better cluster resources utilization. It would be better, in terms of resources scheduling and utilization, if there is a single cluster manager that has a global view of what is running and want to run on the cluster.
Without that single cluster manager, there are two main approaches for resources sharing and allocation:
Availing all cluster resources to all types of applications in the same time. However, that would lead to a great unfairly managed contention on resources.
Dividing the pool of resources into smaller pools; a pool for each application type. However, that would lead to inefficient utilization of resources as some applications might require more resources than allocated in the corresponding pool while in the same time less resources are sufficient for other applications. Hence, a dynamic way of resources allocation leads to better resources utilization.
There are different cluster managers that can do the job and overcome the issues highlighted above. Choosing one depends on the types of applications being run on the cluster as they all should speak the language of the manager. One of the cluster managers, that Spark applications can run on, is Apache YARN. The design of Apache YARN allows different YARN applications to coexist on the same cluster, so a Spark application can run at the same time as other types of applications (like Hadoop MapReduce jobs) which brings great benefits for manageability and cluster utilization.
In this post we will illustrate what are the benefits of running Spark on YARN, how to run Spark on YARN and we will mention important notes to take care of when running Spark on YARN.
First we will try to understand the architecture of both Spark and YARN.
Spark Architecture consists of Driver Program , Executors and Cluster Manager.
Driver Program:The driver program is responsible for managing the job flow and scheduling tasks that will run on the executors.
Executors: Executors are processes that run computation and store data for a Spark application.
Cluster Manager:Cluster Manager is responsible for starting executor processes and where and when they will be run. Spark supports pluggable cluster manager, it supports (YARN, Mesos, and its own “standalone” cluster manager)
YARN Architecture consists of Resource Manager, Node Manager, Application Master and Container.
Resource Manager: manages the use of resources across the cluster.
Node Manager: launches and monitors containers on cluster machines.
Application Master: manages the lifecycle of an application running on the cluster.
Container: It represents a collection of physical resources (CPU cores + memory) on a single node at a cluster. Those resources are allocated for the use of a worker slave.
Spark on YARN:
When running Spark on YARN each Spark executor runs as YARN container. Spark supports two modes for running on YARN, yarn-cluster mode and yarn-client mode.
- In yarn-client mode, the driver runs in the client process, and the application master is only used for requesting resources from YARN.
- yarn-client mode makes sense for interactive and debugging uses where you want to see your application’s output immediately (on the client process side).
- In yarn-cluster mode, the Spark driver runs inside an application master process which is managed by YARN on the cluster, and the client can go away after initiating the application.
- yarn-cluster mode makes sense for production jobs.
Why Run on YARN?
Running Spark on YARN has some benefits:
- YARN allows to dynamically share the cluster resources between different frameworks that run on YARN. For example, you can run a mapreduce job after that you can run a Spark job without any changes in YARN configurations.
- You can use YARN schedulers for categorizing, isolating, and prioritizing workloads.
- YARN is the only cluster manager for Spark that supports security. With YARN, Spark can use secure authentication between its processes.
How to Run on YARN
We used cloudera manager to install Spark and YARN. There wasn’t any special configuration to get Spark just run on YARN, we just changed Spark’s master address to yarn-client or yarn-cluster.
We want to mention some important issues that we have met during running Spark on YARN:
- Spark copies the Spark assembly JAR file to HDFS each time you run spark-submit. You can avoid doing this copy each time by manually uploading the Spark assembly JAR file to your HDFS. Then, set the SPARK_JAR environment variable to this HDFS path
hdfs dfs -mkdir -p /user/spark/share/lib hdfs dfs -put $SPARK_HOME/assembly/lib/spark-assembly_*.jar \ /user/spark/share/lib/spark-assembly.jar export SPARK_JAR=hdfs://<nn>:<port>/user/spark/share/lib/spark-assembly.jar
- Important configuration during submitting the job:
--executor-cores NUM Number of cores per executor (Default: 1) --num-executors NUM Number of executors to launch (Default: 2) --executor-memory NUM Amount of memory to use per executor process. --driver-memory NUM Amount of memory to use for the driver process.
- We noticed that YARN uses more memory than we set for each executor, after searching we discovered that YARN uses:
- executor memory + spark.yarn.executor.memoryOverhead for the executor.
- driver memory + spark.yarn.driver.memoryOverhead for the driver.
- We found that this memory overhead is the amount of off-heap memory (in megabytes) to be allocated per executor or driver. This is the memory that accounts for things like VM overheads, interned strings, other native overheads, etc. This tends to grow with the executor size (typically 6-10%).
- The local directories, used by Spark executors in saving map output files and RDDs that are stored on disk, will be the local directories configured for YARN (Hadoop YARN config yarn.nodemanager.local-dirs). If the user specifies spark.local.dir, it will be ignored.
- Sharing application files (e.g. jar) with executors:
- In yarn-client mode and Spark Standalone mode a link to the jar at the client machine is created and all executors receive this link to download the jar.
- In yarn-cluster mode, the jar is uploaded to hdfs before running the job and all executors download the jar from hdfs, so it takes some time at the beginning to upload the jar.
Comparison Between Spark on YARN and Standalone mode:
|Spark On YARN||Spark Standalone|
|Driver runs in||Application Master||Client||Client|
|Who requests resources||Application Master||Client|
|Who starts executor processes||YARN NodeManager||Spark Worker (Slave)|
|Support for Sparkshell||No||Yes||Yes|
|Sharing jar with executors||uploads jar to hdfs||creates link for the jar on the client||creates link for the jar on the client|
|Share cluster resources among different frameworks||Yes||No|
Running SparkPi in Standalone Mode
spark-submit \ --master spark://$SPARK_MASTER_IP:$SPARK_MASTER_PORT \ --class org.apache.spark.examples.SparkPi \ $SPARK_HOME/examples/lib/spark-examples_version.jar 10
Running SparkPi in YARN Client Mode
spark-submit \ --master yarn-client \ --class org.apache.spark.examples.SparkPi \ $SPARK_HOME/examples/lib/spark-examples_version.jar 10
Running SparkPi in YARN Cluster Mode
spark-submit \ --master yarn-cluster \ --class org.apache.spark.examples.SparkPi \ $SPARK_HOME/examples/lib/spark-examples_version.jar 10