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. Node 环境变量 process.env.NODE_ENV 之webpack应用

    转载来源:https://github.com/wfzong/NODE_ENV_TEST,这里还有源码可以学习,谢谢原作者的分享! 对于process.env.NODE_ENV困惑起因为在配置webp ...

  2. j2ee之监听页面请求

    本博客的起因是我想监听浏览器端每个页面都访问了哪些资源~~: 我是个菜鸡,所以我要记在我的小本本上,我怕忘了又~~~: 代码我是写在springboot2.1中的,有兴趣的同学可以玩一下~ 1:代码如 ...

  3. 《Linux就该这么学》 - 必读的红帽系统与红帽linux认证自学手册

    <Linux就该这么学>   本书作者刘遄从事于linux运维技术行业,较早时因兴趣的驱使接触到了Linux系统并开始学习. 已在2012年考下红帽工程师RHCE_6,今年又分别考下RHC ...

  4. cdh集群ip更改

    #---1.修改每个用户的hosts vi /etc/hosts #127.0.0.1 localhost localhost.localdomain localhost4 localhost4.lo ...

  5. Lesson 1-1

    1.1常见难记的几种运算符 1.1.1 除运算 ‘/’ 除运算的结果为小数,即浮点数. >>> 10/3 3.3333333333333335 >>> 10/2 5 ...

  6. java请求URL带参之防XSS攻击

    1.web.xml新增filter配置 <!-- URL请求参数字符过滤或合法性校验 --> <filter> <filter-name>XssFilter< ...

  7. nginx 学习 不断更新

    nginx 常用全局变量 $uri: 当前请求的uri,不带参数 $request_uri: 请求的uri,带完整参数 $host: http请求报文中host首部,如果没有则以处理此请求的虚拟主机的 ...

  8. 深入理解position属性&containing block

    一.包含块(Containing Block) 要讲position,首先就涉及到一个概念:包含块. 1.包含块介绍 包含块简单理解就是一个定位参考块,就是"大盒子里套小盒子"中那 ...

  9. 开发中常用的JS知识点集锦

    索引 1.对象深拷贝 2.网络图片转base64, 在线图片点击下载 3.常用CSS样式记录(超出宽高省略展示/播放icon/按钮背景颜色渐变...) 4.对象深拷贝 5.对象深拷贝 6.对象深拷贝 ...

  10. linux系统优化配置

    # 2 millions system-wide sysctl -w fs.file-max=2097152 sysctl -w fs.nr_open=2097152 echo 2097152 > ...