DockerContainerizer的实现在文件src/slave/containerizer/docker.cpp中

 

  1. Future<bool> DockerContainerizer::launch(
  2.     const ContainerID& containerId,
  3.     const ExecutorInfo& executorInfo,
  4.     const
    string& directory,
  5.     const Option<string>& user,
  6.     const SlaveID& slaveId,
  7.     const PID<Slave>& slavePid,
  8.     bool checkpoint)
  9. {
  10.   return dispatch(
  11.       process.get(),
  12.       &DockerContainerizerProcess::launch,
  13.       containerId,
  14.       None(),
  15.       executorInfo,
  16.       directory,
  17.       user,
  18.       slaveId,
  19.       slavePid,
  20.       checkpoint);
  21. }

 

转而调用DockerContainerizerProcess::launch,无论是TaskInfo里面有ContainerInfo,还是ExecutorInfo里面有ContainerInfo,都由这个函数处理,只不过分支不同。

  1. Future<bool> DockerContainerizerProcess::launch(
  2.     const ContainerID& containerId,
  3.     const Option<TaskInfo>& taskInfo,
  4.     const ExecutorInfo& executorInfo,
  5.     const
    string& directory,
  6.     const Option<string>& user,
  7.     const SlaveID& slaveId,
  8.     const PID<Slave>& slavePid,
  9.     bool checkpoint)
  10. {
  11.   Option<ContainerInfo> containerInfo;
  12.  
  13.   if (taskInfo.isSome() && taskInfo.get().has_container()) {
  14.     containerInfo = taskInfo.get().container();
  15.   } else
    if (executorInfo.has_container()) {
  16.     containerInfo = executorInfo.container();
  17.   }
  18.  
  19.   if (containerInfo.isNone()) {
  20.     LOG(INFO) << "No container info found, skipping launch";
  21.     return
    false;
  22.   }
  23.  
  24.   if (containerInfo.get().type() != ContainerInfo::DOCKER) {
  25.     LOG(INFO) << "Skipping non-docker container";
  26.     return
    false;
  27.   }
  28.  
  29.   Try<Container*> container = Container::create(
  30.       containerId,
  31.       taskInfo,
  32.       executorInfo,
  33.       directory,
  34.       user,
  35.       slaveId,
  36.       slavePid,
  37.       checkpoint,
  38.       flags);
  39.  
  40.   if (container.isError()) {
  41.     return Failure("Failed to create container: " + container.error());
  42.   }
  43.  
  44.   containers_[containerId] = container.get();
  45.  
  46.   if (taskInfo.isSome()) {
  47.     LOG(INFO) << "Starting container '" << containerId
  48.               << "' for task '" << taskInfo.get().task_id()
  49.               << "' (and executor '" << executorInfo.executor_id()
  50.               << "') of framework '" << executorInfo.framework_id() << "'";
  51.   } else {
  52.     LOG(INFO) << "Starting container '" << containerId
  53.               << "' for executor '" << executorInfo.executor_id()
  54.               << "' and framework '" << executorInfo.framework_id() << "'";
  55.   }
  56.  
  57.   if (HookManager::hooksAvailable()) {
  58.     HookManager::slavePreLaunchDockerHook(
  59.         container.get()->container,
  60.         container.get()->command,
  61.         taskInfo,
  62.         executorInfo,
  63.         container.get()->name(),
  64.         container.get()->directory,
  65.         flags.sandbox_directory,
  66.         container.get()->resources,
  67.         container.get()->environment);
  68.   }
  69.  
  70.   if (taskInfo.isSome() && flags.docker_mesos_image.isNone()) {
  71.     // Launching task by forking a subprocess to run docker executor.
  72.     return container.get()->launch = fetch(containerId, slaveId)
  73.       .then(defer(self(), [=]() { return pull(containerId); }))
  74.       .then(defer(self(), [=]() {
  75.         return mountPersistentVolumes(containerId);
  76.       }))
  77.       .then(defer(self(), [=]() { return launchExecutorProcess(containerId); }))
  78.       .then(defer(self(), [=](pid_t pid) {
  79.         return reapExecutor(containerId, pid);
  80.       }));
  81.   }
  82.  
  83.   string containerName = container.get()->name();
  84.  
  85.   if (container.get()->executorName().isSome()) {
  86.     // Launch the container with the executor name as we expect the
  87.     // executor will launch the docker container.
  88.     containerName = container.get()->executorName().get();
  89.   }
  90.  
  91.   // Launching task or executor by launching a seperate docker
  92.   // container to run the executor.
  93.   // We need to do so for launching a task because as the slave
  94.   // is running in a container (via docker_mesos_image flag)
  95.   // we want the executor to keep running when the slave container
  96.   // dies.
  97.   return container.get()->launch = fetch(containerId, slaveId)
  98.     .then(defer(self(), [=]() { return pull(containerId); }))
  99.     .then(defer(self(), [=]() {
  100.       return mountPersistentVolumes(containerId);
  101.     }))
  102.     .then(defer(self(), [=]() {
  103.       return launchExecutorContainer(containerId, containerName);
  104.     }))
  105.     .then(defer(self(), [=](const Docker::Container& dockerContainer) {
  106.       return checkpointExecutor(containerId, dockerContainer);
  107.     }))
  108.     .then(defer(self(), [=](pid_t pid) {
  109.       return reapExecutor(containerId, pid);
  110.     }));
  111. }

 

如果是TaskInfo里面的ContainerInfo,则调用launchExecutorProcess(containerId)。

如果是ExecutorInfo里面的ContainerInfo,则调用launchExecutorContainer(containerId, containerName)。

 

DockerContainerizerProcess::launchExecutorProcess实现如下:

  1. Future<pid_t> DockerContainerizerProcess::launchExecutorProcess(
  2.     const ContainerID& containerId)
  3. {
  4.   Container* container = containers_[containerId];
  5.   container->state = Container::RUNNING;
  6.  
  7.   // Prepare environment variables for the executor.
  8.   map<string, string> environment = executorEnvironment(
  9.       container->executor,
  10.       container->directory,
  11.       container->slaveId,
  12.       container->slavePid,
  13.       container->checkpoint,
  14.       flags,
  15.       false);
  16.  
  17.   // Include any enviroment variables from ExecutorInfo.
  18.   foreach (const Environment::Variable& variable,
  19.            container->executor.command().environment().variables()) {
  20.     environment[variable.name()] = variable.value();
  21.   }
  22.  
  23.   // Pass GLOG flag to the executor.
  24.   const Option<string> glog = os::getenv("GLOG_v");
  25.   if (glog.isSome()) {
  26.     environment["GLOG_v"] = glog.get();
  27.   }
  28.  
  29.   vector<string> argv;
  30.   argv.push_back("mesos-docker-executor");
  31.  
  32.   return logger->prepare(container->executor, container->directory)
  33.     .then(defer(
  34.         self(),
  35.         [=](const ContainerLogger::SubprocessInfo& subprocessInfo)
  36.           -> Future<pid_t> {
  37.     // If we are on systemd, then extend the life of the executor. Any
  38.     // grandchildren's lives will also be extended.
  39.     std::vector<Subprocess::Hook> parentHooks;
  40.     // Construct the mesos-docker-executor using the "name" we gave the
  41.     // container (to distinguish it from Docker containers not created
  42.     // by Mesos).
  43.     Try<Subprocess> s = subprocess(
  44.         path::join(flags.launcher_dir, "mesos-docker-executor"),
  45.         argv,
  46.         Subprocess::PIPE(),
  47.         subprocessInfo.out,
  48.         subprocessInfo.err,
  49.         dockerFlags(flags, container->name(), container->directory),
  50.         environment,
  51.         lambda::bind(&setup, container->directory),
  52.         None(),
  53.         parentHooks);
  54.  
  55.     if (s.isError()) {
  56.       return Failure("Failed to fork executor: " + s.error());
  57.     }
  58.  
  59.     // Checkpoint the executor's pid (if necessary).
  60.     Try<Nothing> checkpointed = checkpoint(containerId, s.get().pid());
  61.  
  62.     if (checkpointed.isError()) {
  63.       return Failure(
  64.           "Failed to checkpoint executor's pid: " + checkpointed.error());
  65.     }
  66.  
  67.     // Checkpoing complete, now synchronize with the process so that it
  68.     // can continue to execute.
  69.     CHECK_SOME(s.get().in());
  70.     char c;
  71.     ssize_t length;
  72.     while ((length = write(s.get().in().get(), &c, sizeof(c))) == -1 &&
  73.            errno == EINTR);
  74.  
  75.     if (length != sizeof(c)) {
  76.       return Failure("Failed to synchronize with child process: " +
  77.                      os::strerror(errno));
  78.     }
  79.  
  80.     return s.get().pid();
  81.   }));
  82. }

 

这个函数最终运行一个名为mesos-docker-executor的子进程,这是一个独立的二进制进程。这也是大多数使用mesos运行Docker的方式。

  1. [root@a061f582-9be2-45a8-bda5-2280926f825c ~]# ps aux | grep mesos-13beba1f-dcdf-4e6c-b88c-8fcdf56559bd-S2.838a1dc0-cc13-4bd0-9380-77809f95ad04 | grep -v grep
  2. root 13538 0.2 0.1 802432 18120 ? Ssl Jul27 16:03 mesos-docker-executor --container=mesos-13beba1f-dcdf-4e6c-b88c-8fcdf56559bd-S2.838a1dc0-cc13-4bd0-9380-77809f95ad04 --docker=docker --docker_socket=/var/run/docker.sock --help=false --launcher_dir=/usr/libexec/mesos --mapped_directory=/mnt/mesos/sandbox --sandbox_directory=/tmp/mesos/slaves/13beba1f-dcdf-4e6c-b88c-8fcdf56559bd-S2/frameworks/13beba1f-dcdf-4e6c-b88c-8fcdf56559bd-0000/executors/linkerdcos_cluster_mongodb.a50b6205-53a3-11e6-a67a-024214d517fa/runs/838a1dc0-cc13-4bd0-9380-77809f95ad04 --stop_timeout=0ns
  3. root 13548 0.0 0.0 126860 14916 ? Sl Jul27 0:00 docker -H unix:///var/run/docker.sock run --privileged --cpu-shares 102 --memory 536870912 -e MARATHON_APP_VERSION=2016-07-06T10:44:54.554Z -e HOST=10.25.161.248 -e MARATHON_APP_RESOURCE_CPUS=0.1 -e MONGODB_NODES=10.25.161.248 -e MARATHON_APP_DOCKER_IMAGE=linkerrepository/linkerdcos_mongodb_repl:1.0.1 -e PORT_10001=31166 -e MESOS_TASK_ID=linkerdcos_cluster_mongodb.a50b6205-53a3-11e6-a67a-024214d517fa -e PORT=31166 -e MARATHON_APP_RESOURCE_MEM=512.0 -e ENNAME=eth0 -e PORTS=31166 -e MARATHON_APP_RESOURCE_DISK=0.0 -e MARATHON_APP_LABELS= -e MARATHON_APP_ID=/linkerdcos/cluster/mongodb -e PORT0=31166 -e MESOS_SANDBOX=/mnt/mesos/sandbox -e MESOS_CONTAINER_NAME=mesos-13beba1f-dcdf-4e6c-b88c-8fcdf56559bd-S2.838a1dc0-cc13-4bd0-9380-77809f95ad04 -v /opt:/data:rw -v /tmp/mesos/slaves/13beba1f-dcdf-4e6c-b88c-8fcdf56559bd-S2/frameworks/13beba1f-dcdf-4e6c-b88c-8fcdf56559bd-0000/executors/linkerdcos_cluster_mongodb.a50b6205-53a3-11e6-a67a-024214d517fa/runs/838a1dc0-cc13-4bd0-9380-77809f95ad04:/mnt/mesos/sandbox --net host --name mesos-13beba1f-dcdf-4e6c-b88c-8fcdf56559bd-S2.838a1dc0-cc13-4bd0-9380-77809f95ad04 linkerrepository/linkerdcos_mongodb_repl:1.0.1
  4. [root@a061f582-9be2-45a8-bda5-2280926f825c ~]# docker ps | grep mesos-13beba1f-dcdf-4e6c-b88c-8fcdf56559bd-S2.838a1dc0-cc13-4bd0-9380-77809f95ad04
  5. 43a45be25f37 linkerrepository/linkerdcos_mongodb_repl:1.0.1 "/scripts/run.sh " 5 days ago Up 5 days mesos-13beba1f-dcdf-4e6c-b88c-8fcdf56559bd-S2.838a1dc0-cc13-4bd0-9380-77809f95ad04

 

DockerContainerizerProcess::launchExecutorContainer实现如下:

  1. Future<Docker::Container> DockerContainerizerProcess::launchExecutorContainer(
  2.     const ContainerID& containerId,
  3.     const
    string& containerName)
  4. {
  5.   if (!containers_.contains(containerId)) {
  6.     return Failure("Container is already destroyed");
  7.   }
  8.  
  9.   Container* container = containers_[containerId];
  10.   container->state = Container::RUNNING;
  11.  
  12.   return logger->prepare(container->executor, container->directory)
  13.     .then(defer(
  14.         self(),
  15.         [=](const ContainerLogger::SubprocessInfo& subprocessInfo)
  16.           -> Future<Docker::Container> {
  17.     // Start the executor in a Docker container.
  18.     // This executor could either be a custom executor specified by an
  19.     // ExecutorInfo, or the docker executor.
  20.     Future<Nothing> run = docker->run(
  21.         container->container,
  22.         container->command,
  23.         containerName,
  24.         container->directory,
  25.         flags.sandbox_directory,
  26.         container->resources,
  27.         container->environment,
  28.         subprocessInfo.out,
  29.         subprocessInfo.err);
  30.  
  31.     Owned<Promise<Docker::Container>> promise(new Promise<Docker::Container>());
  32.     // We like to propogate the run failure when run fails so slave can
  33.     // send this failure back to the scheduler. Otherwise we return
  34.     // inspect's result or its failure, which should not fail when
  35.     // the container isn't launched.
  36.     Future<Docker::Container> inspect =
  37.       docker->inspect(containerName, slave::DOCKER_INSPECT_DELAY)
  38.         .onAny([=](Future<Docker::Container> f) {
  39.             // We cannot associate the promise outside of the callback
  40.             // because we like to propagate run's failure when
  41.             // available.
  42.             promise->associate(f);
  43.         });
  44.  
  45.     run.onFailed([=](const
    string& failure) mutable {
  46.       inspect.discard();
  47.       promise->fail(failure);
  48.     });
  49.  
  50.     return promise->future();
  51.   }));
  52. }

 

运行一个Docker,在Docker里面运行Executor

Mesos源码分析(14): DockerContainerier运行一个Task的更多相关文章

  1. Mesos源码分析(13): MesosContainerier运行一个Task

    MesosContainerizer的实现在文件src/slave/containerizer/mesos/containerizer.cpp中   Future<bool> MesosC ...

  2. Mesos源码分析

    Mesos源码分析(1): Mesos的启动过程总论 Mesos源码分析(2): Mesos Master的启动之一 Mesos源码分析(3): Mesos Master的启动之二 Mesos源码分析 ...

  3. Mesos源码分析(10): MesosSchedulerDriver的启动及运行一个Task

      MesosSchedulerDriver的代码在src/sched/sched.cpp里面实现.     Driver->run()调用start()     首先检测Mesos-Maste ...

  4. Appium Server 源码分析之启动运行Express http服务器

    通过上一个系列Appium Android Bootstrap源码分析我们了解到了appium在安卓目标机器上是如何通过bootstrap这个服务来接收appium从pc端发送过来的命令,并最终使用u ...

  5. Mesos源码分析(12): Mesos-Slave接收到RunTask消息

    在前文Mesos源码分析(8): Mesos-Slave的初始化中,Mesos-Slave接收到RunTaskMessage消息,会调用Slave::runTask.   void Slave::ru ...

  6. Solr4.8.0源码分析(14)之SolrCloud索引深入(1)

    Solr4.8.0源码分析(14) 之 SolrCloud索引深入(1) 上一章节<Solr In Action 笔记(4) 之 SolrCloud分布式索引基础>简要学习了SolrClo ...

  7. Mesos源码分析(11): Mesos-Master接收到launchTasks消息

    根据Mesos源码分析(6): Mesos Master的初始化中的代码分析,当Mesos-Master接收到launchTask消息的时候,会调用Master::launchTasks函数.   v ...

  8. Appium Android Bootstrap源码分析之启动运行

    通过前面的两篇文章<Appium Android Bootstrap源码分析之控件AndroidElement>和<Appium Android Bootstrap源码分析之命令解析 ...

  9. Mesos源码分析(5): Mesos Master的启动之四

      5. Create an instance of allocator.   代码如下   Mesos源码中默认的Allocator,即HierarchicalDRFAllocator的位置在$ME ...

随机推荐

  1. Python教学课程分享

    一.Python基本语法 1.1整数,实数,复数 前言: Python编程环境及方法 在python底层环境中唤醒python对话,直接在python中输入指令对系统进行命令编程 随意打开一个记事本或 ...

  2. Oracle中的substr()函数 详解及应用

    注:本文来源于<Oracle中的substr()函数 详解及应用> 1)substr函数格式   (俗称:字符截取函数) 格式1: substr(string string, int a, ...

  3. margin:auto你真的理解么?

    含义 margin:auto是具有强烈计算意味的关键字,用来计算元素对应方向应该获得的剩余空间大小 填充规则 (1) 如果一侧定值,一侧auto,则auto为剩余空间大小 (2) 如果两侧均是auto ...

  4. TopN案例

    准备三份数据 t1 2067 t2 2055 t3 2055 t4 1200 t5 2367 t6 255 t7 2555 t8 12100 t9 20647 t10 245 t11 205 t12 ...

  5. JavaScript 判断对象中是否有某属性

    判断对象中是否有某属性的常见方式总结,不同的场景要使用不同的方式. 一.点( . )或者方括号( [ ] ) 通过点或者方括号可以获取对象的属性值,如果对象上不存在该属性,则会返回undefined. ...

  6. hibernate-第二章-关系映射

    一,持久化类 持久化类就是之前写过的实体类 持久化类必须符合javabean规范,属性必须有set和get方法; 持久化类的属性类型可以是8种基本类型或对应的包装类,通常定义包装类型,因为包装类型可以 ...

  7. vue 结合 FileReader() 实现上传图片预览功能

    项目中 身份证上传需求: <div class="ID_pic_wrap"> <ul> <li> <img src="../.. ...

  8. [原创]Zynq SDIO WIFI SotfAP调试

    编译好kernel和driver 加载firmware后,运行下述命令. mkdir /var/run/ mkdir /var/run/hostapd   ifconfig -a           ...

  9. 记一次完整的asp.net-mvc页面优化过程

    最近在重构一个以前团队开发留下的MVC项目,项目结构堪称混乱,问题多多,但今天说的是页面打开速度的问题.项目中包括web后台系统,几乎随便点一个页面都要盯着白屏等待2-5秒之久,体验很差.通过对页面性 ...

  10. JavaScript判断各种数据类型

    typeof ,只可判断部分数据的数据类型 数字 字符串 布尔值 undefined function Object.prototype.toString.call() , 通用 function e ...