如何启用从 Docker 容器内启动 Spark-Mesos 作业?

How to enable a Spark-Mesos job to be launched from inside a Docker container?

总结:

是否可以从 Docker 容器内提交 Mesos 上的 Spark 作业,容器中有 1 个 Mesos master(无 Zookeeper)和 1 个 Mesos agent,每个 运行 在单独的 Docker 容器(目前在同一主机上)? http://mesos.apache.org/documentation/latest/container-image/ 中描述的 Mesos containerizer 似乎适用于 Mesos 应用程序被简单封装在 Docker 容器和 运行 中的情况。我的 Docker 应用程序与根据用户输入在 运行 时间实例化的多个 PySpark Mesos 作业交互性更强。 Docker 容器中的驱动程序本身并不是 运行 Mesos 应用程序。只有用户启动的作业请求会作为 PySpark Mesos 应用程序处理。

细节:

我现在有 3 个 Docker 基于 centos:7 linux 和 运行ning 的容器在同一台主机上:

  1. 容器"Master"运行安装一个 Mesos Master。

  2. 容器"Agent"运行安装一个 Mesos 代理。

  3. Container "Test" with Spark and Mesos installed where I 运行 a bash shell 并从命令行启动以下 PySpark 测试程序.

    from pyspark import SparkContext, SparkConf
    from operator import add
    
    # Configure Spark                                               
    sp_conf = SparkConf()
    sp_conf.setAppName("spark_test")
    sp_conf.set("spark.scheduler.mode", "FAIR")
    sp_conf.set("spark.dynamicAllocation.enabled", "false")
    sp_conf.set("spark.driver.memory", "500m")
    sp_conf.set("spark.executor.memory", "500m")
    sp_conf.set("spark.executor.cores", 1)
    sp_conf.set("spark.cores.max", 1)
    sp_conf.set("spark.mesos.executor.home", "/usr/local/spark-2.1.0")
    sp_conf.set("spark.executor.uri", "file://usr/local/spark-2.1.0-bin-without-hadoop.tgz")
    sc = SparkContext(conf=sp_conf)
    
    # Simple computation
    x = [(1.5,100.),(1.5,200.),(1.5,300.),(2.5,150.)]
    rdd = sc.parallelize(x,1)
    tot = rdd.foldByKey(0,add).collect()
    cnt = rdd.countByKey()
    time = [t[0] for t in tot]
    avg = [t[1]/cnt[t[0]] for t in tot]
    print 'tot=', tot
    print 'cnt=', cnt
    print 't=', time
    print 'avg=', avg
    

我使用的相关软件版本如下:

以下工作正常:

这是失败:

使用 Spark 的 MASTER=mesos://127.0.0.1:5050,当我从测试容器内部启动我的 PySpark 测试程序时,Mesos Master 和 Agent 的日志中都有 activity,并且在失败前的几秒内, Mesos UI 显示为作业分配的资源完全在可用范围内。然而,PySpark 测试程序随后失败并显示:WARN scheduler.TaskSchedulerImpl: Initial job has not accepted any resources;检查您的集群 UI 以确保工作人员已注册并拥有足够的资源.

我的步骤如下。

启动 Mesos Master:

docker run -it --net=host -p 5050:5050 the_master

大师日志的相关摘录显示:

I0418 01:05:08.540192 27 master.cpp:383] Master 15b354eb-6a20-4bc9-a13b-6533b1e91bd2 (localhost) started on 127.0.0.1:5050
I0418 01:05:08.540210 27 master.cpp:385] Flags at startup: --agent_ping_timeout="15secs" --agent_reregister_timeout="10mins" --allocation_interval="1secs" --allocator="HierarchicalDRF" --authenticate_agents="false" --authenticate_frameworks="false" --authenticate_http_frameworks="false" --authenticate_http_readonly="false" --authenticate_http_readwrite="false" --authenticators="crammd5" --authorizers="local" --framework_sorter="drf" --help="false" --hostname_lookup="true" --http_authenticators="basic" --initialize_driver_logging="true" --log_auto_initialize="true" --logbufsecs="0" --logging_level="INFO" --max_agent_ping_timeouts="5" --max_completed_frameworks="50" --max_completed_tasks_per_framework="1000" --max_unreachable_tasks_per_framework="1000" --quiet="false" --recovery_agent_removal_limit="100%" --registry="replicated_log" --registry_fetch_timeout="1mins" --registry_gc_interval="15mins" --registry_max_agent_age="2weeks" --registry_max_agent_count="102400" --registry_store_timeout="20secs" --registry_strict="false" --root_submissions="true" --user_sorter="drf" --version="false" --webui_dir="/usr/local/mesos-1.2.0/build/../src/webui" --work_dir="/var/lib/mesos" --zk_session_timeout="10secs"

启动 Mesos 代理:

docker run -it --net=host -e MESOS_AGENT_PORT=5051 the_agent

代理的日志显示:

I0418 01:42:00.234244 40 slave.cpp:212] Flags at startup: --appc_simple_discovery_uri_prefix="http://" --appc_store_dir="/tmp/mesos/store/appc" --authenticate_http_readonly="false" --authenticate_http_readwrite="false" --authenticatee="crammd5" --authentication_backoff_factor="1secs" --authorizer="local" --cgroups_cpu_enable_pids_and_tids_count="false" --cgroups_enable_cfs="false" --cgroups_hierarchy="/sys/fs/cgroup" --cgroups_limit_swap="false" --cgroups_root="mesos" --container_disk_watch_interval="15secs" --containerizers="mesos" --default_role="*" --disk_watch_interval="1mins" --docker="docker" --docker_kill_orphans="true" --docker_mesos_image="spark-mesos-agent-test" --docker_registry="https://registry-1.docker.io" --docker_remove_delay="6hrs" --docker_socket="/var/run/docker.sock" --docker_stop_timeout="0ns" --docker_store_dir="/tmp/mesos/store/docker" --docker_volume_checkpoint_dir="/var/run/mesos/isolators/docker/volume" --enforce_container_disk_quota="false" --executor_registration_timeout="1mins" --executor_shutdown_grace_period="5secs" --fetcher_cache_dir="/tmp/mesos/fetch" --fetcher_cache_size="2GB" --frameworks_home="" --gc_delay="1weeks" --gc_disk_headroom="0.1" --hadoop_home="" --help="false" --hostname_lookup="true" --http_authenticators="basic" --http_command_executor="false" --http_heartbeat_interval="30secs" --initialize_driver_logging="true" --isolation="posix/cpu,posix/mem" --launcher="posix" --launcher_dir="/usr/local/mesos-1.2.0/build/src" --logbufsecs="0" --logging_level="INFO" --max_completed_executors_per_framework="150" --oversubscribed_resources_interval="15secs" --perf_duration="10secs" --perf_interval="1mins" --qos_correction_interval_min="0ns" --quiet="false" --recover="reconnect" --recovery_timeout="15mins" --registration_backoff_factor="1secs" --revocable_cpu_low_priority="true" --runtime_dir="/var/run/mesos" --sandbox_directory="/mnt/mesos/sandbox" --strict="true" --switch_user="false" --systemd_enable_support="false" --systemd_runtime_directory="/run/systemd/system" --version="false" --work_dir="/var/lib/mesos"

我收到以下针对 Mesos Master 和 Agent 的警告,但请忽略它,因为我现在 运行将所有内容都放在同一台主机上:

Master/Agent bound to loopback interface! Cannot communicate with remote schedulers or agents. You might want to set '--ip' flag to a routable IP address.

事实上,我分配可路由 IP 地址而不是 127.0.0.1 的测试未能改变我在此处描述的任何行为。

启动测试容器(使用 bash shell 进行测试):

docker run -it --net=host the_test /bin/bash

在所有三个容器(Master、Agent 和 Test)中设置的一些相关环境变量:

HADOOP_HOME=/usr/local/hadoop-2.7.3
HADOOP_CONF_DIR=/usr/local/hadoop-2.7.3/etc/hadoop
SPARK_HOME=/usr/local/spark-2.1.0
SPARK_EXECUTOR_URI=file:////usr/local/spark-2.1.0-bin-without-hadoop.tgz
MASTER=mesos://127.0.0.1:5050
PYSPARK_PYTHON=/usr/local/anaconda2/bin/python
PYSPARK_DRIVER_PYTHON=/usr/local/anaconda2/bin/python
PYSPARK_SUBMIT_ARGS=--driver-memory=4g pyspark-shell
MESOS_PORT=5050
MESOS_IP=127.0.0.1
MESOS_WORKDIR=/var/lib/mesos
MESOS_HOME=/usr/local/mesos-1.2.0
MESOS_NATIVE_JAVA_LIBRARY=/usr/local/lib/libmesos.so
MESOS_MASTER=mesos://127.0.0.1:5050
PYTHONPATH=:/usr/local/spark-2.1.0/python:/usr/local/spark-2.1.0/python/lib/py4j-0.10.1-src.zip

运行 来自测试容器内部的 Mesos(非 Spark)测试:

/usr/local/mesos-1.2.0/build/src/examples/python/test-framework 127.0.0.1:5050

这会产生以下日志输出(正如我认为的那样):

I0417 21:28:36.912542 20 sched.cpp:232] Version: 1.2.0
I0417 21:28:36.920013 62 sched.cpp:336] New master detected at master@127.0.0.1:5050
I0417 21:28:36.920472 62 sched.cpp:352] No credentials provided. Attempting to register without authentication
I0417 21:28:36.924165 62 sched.cpp:759] Framework registered with be89e739-be8d-430e-b1e9-3fe55fa18459-0000
Registered with framework ID be89e739-be8d-430e-b1e9-3fe55fa18459-0000
Received offer be89e739-be8d-430e-b1e9-3fe55fa18459-O0 with cpus: 16.0 and mem: 119640.0
Launching task 0 using offer be89e739-be8d-430e-b1e9-3fe55fa18459-O0
Launching task 1 using offer be89e739-be8d-430e-b1e9-3fe55fa18459-O0
Launching task 2 using offer be89e739-be8d-430e-b1e9-3fe55fa18459-O0
Launching task 3 using offer be89e739-be8d-430e-b1e9-3fe55fa18459-O0
Launching task 4 using offer be89e739-be8d-430e-b1e9-3fe55fa18459-O0
Task 0 is in state TASK_RUNNING
Task 1 is in state TASK_RUNNING
Task 2 is in state TASK_RUNNING
Task 3 is in state TASK_RUNNING
Task 4 is in state TASK_RUNNING
Task 0 is in state TASK_FINISHED
Task 1 is in state TASK_FINISHED
Task 2 is in state TASK_FINISHED
Task 3 is in state TASK_FINISHED
Task 4 is in state TASK_FINISHED
All tasks done, waiting for final framework message
Received message: 'data with a \x00 byte'
Received message: 'data with a \x00 byte'
Received message: 'data with a \x00 byte'
Received message: 'data with a \x00 byte'
Received message: 'data with a \x00 byte'
All tasks done, and all messages received, exiting

运行 来自测试容器内部的 PySpark 测试程序:

python spark_test.py 

这会产生以下日志输出:

17/04/17 21:29:18 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
I0417 21:29:19.187747 205 sched.cpp:232] Version: 1.2.0
I0417 21:29:19.196535 188 sched.cpp:336] New master detected at master@127.0.0.1:5050
I0417 21:29:19.197453 188 sched.cpp:352] No credentials provided. Attempting to register without authentication
I0417 21:29:19.201884 195 sched.cpp:759] Framework registered with be89e739-be8d-430e-b1e9-3fe55fa18459-0001
17/04/17 21:29:34 WARN scheduler.TaskSchedulerImpl: Initial job has not accepted any resources; check your cluster UI to ensure that workers are registered and have sufficient resources

我在互联网上搜索了这个错误,但我找到的每个页面都表明这是一个常见错误,由分配给 Mesos 代理的资源不足引起。正如我提到的,Mesos UI 表明有足够的资源。如果您知道为什么我的 Spark 作业不接受来自 Mesos 的资源,或者如果您对我可以尝试的事情有任何建议,请回复。

感谢您的帮助。

此错误现已解决。万一有人遇到类似的问题,我想 post 在我的情况下,这是由于没有在 Mesos Master 和 Agent 容器中设置 HADOOP CLASSPATH 引起的。设置后,一切正常。