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. 【DOS】Win7系统文件夹名太长无法删除问题的解决

    一个测试工具产生了几个坑爹文件夹名为n个“x” ,系统提示删除不掉. 网上百度,说什么压缩.写bat文件...统统没用. 猛地看到右击菜单中安装了git客户端工具,想试试看.在该文件夹目录下Git B ...

  2. GIT----IDEA配置git

    配置git 创建本地厂库 可以选中项目所在的目录下 此时发现所有的页面的文件都变红,是因为变红的文件还没有add 添加提交的项目(add) 选中提交的文件右击,git ,add 如果想把整个项目都ad ...

  3. Bootstrap-datepicker3官方文档中文翻译---Event/事件(原文链接 http://bootstrap-datepicker.readthedocs.io/en/latest/index.html)

    Events/事件 DatePicker在某些情况下触发一些事件.所有事件都拥有   传递给任何事件处理程序的  事件对象的    附加数据.(译者注:这里英语拗口,汉语也拗口,我用空格给大家断断句) ...

  4. 模拟实现库函数的atoi、atof和itoa

    1.函数atoi atoi (表示 alphanumeric to integer)是把字符串转换成整型数的一个函数.广泛的应用在计算机程序和办公软件中.atoi( ) 函数会扫描参数 nptr字符串 ...

  5. sql server使用sql语句上传Excel到数据库

    USE pro GO SELECT  * INTO   temp_budget_price@201704170950 FROM    OPENDATASOURCE('Microsoft.Jet.OLE ...

  6. redis安装使用

    Redis是一个开源的使用ANSI C语言编写.遵守BSD协议.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API. 它通常被称为数据结构服务器,因为值(valu ...

  7. tensorflow用dropout解决over fitting-【老鱼学tensorflow】

    在机器学习中可能会存在过拟合的问题,表现为在训练集上表现很好,但在测试集中表现不如训练集中的那么好. 图中黑色曲线是正常模型,绿色曲线就是overfitting模型.尽管绿色曲线很精确的区分了所有的训 ...

  8. sql server按月份,按项目号展开表格

    原始数据: 01 RD21 6495.411402 RD21 87.43604 RD21 101.718405 RD21 1.538401 RD25 7803.303709 RD25 106.8375 ...

  9. SpringBoot配置文件

    一.配置文件 配置文件应该是无论在哪个框架中都是一个重要角色,而我们最为常用的xxx.xml和xxx.properties,还有springboot推荐使用的xxx.yml. 二.SpringBoot ...

  10. Python爬虫代理IP池

    目录[-] 1.问题 2.代理池设计 3.代码模块 4.安装 5.使用 6.最后 在公司做分布式深网爬虫,搭建了一套稳定的代理池服务,为上千个爬虫提供有效的代理,保证各个爬虫拿到的都是对应网站有效的代 ...