云原生集群管理容器编排任务调度【免费下载链接】mesosApache Mesos项目地址https://gitcode.com/gh_mirrors/meso/mesos点击查看免费下载本文基于 Apache Mesos 官方文档docs/containerizer-internals.md展开深入解析 Mesos Agent 中 Containerizer 的创建与启动机制--containerizers标志如何决定容器器类型、Composing/Docker/Mesos 三类容器器的实现差异、Linux Launcher 如何用 freezer cgroup 与管道冻结子进程、以及各容器器的状态机。读完本文你将从 Agent 源码层面理解一个任务从launch到RUNNING的完整调用链并能据此排查容器启动失败、隔离器异常等问题。1. Containerizer 的角色与抽象 APIContainerizer容器器是 Mesos 中负责启动容器的组件。它拥有为 task/executor 启动的容器并负责其隔离isolation、资源管理resource management和事件如统计信息 statistics。从源码看所有容器器都继承自抽象基类 Containerizer其定义在mesos::internal::slave命名空间中核心虚函数包括方法作用recover(state)从 Agent 状态恢复所有容器化 executor系统上存在但不在 state 中的容器会被终止清理launch(containerId, containerConfig, environment, pidCheckpointPath)按ContainerConfig启动容器若ContainerID带 parent则尝试启动嵌套容器attach(containerId)建立 HTTP 连接以向容器流式输入/输出mesos-cat、mesos-tail等工具依赖它update(containerId, resourceRequests)动态更新容器资源usage(containerId)获取容器资源用量统计ResourceStatisticsstatus(containerId)获取 isolator 相关属性的运行时状态ContainerStatuswait(containerId)等待容器终止返回ContainerTerminationdestroy(containerId)销毁正在启动/运行的容器杀死全部进程并释放资源kill(containerId, signal)向运行中容器发送信号containers()/remove(containerId)/pruneImages(...)枚举容器、移除嵌套容器、清理无用镜像launch()的返回值为枚举LaunchResultSUCCESS、ALREADY_LAUNCHED、NOT_SUPPORTED——正是NOT_SUPPORTED让 Composing 容器器得以逐个尝试多个容器器见第 3 节。2. Containerizer 的创建--containerizers标志Agent 根据--containerizers标志创建容器器。若指定了多个容器器如docker,mesos则使用Composing 容器器将它们组合成一个逻辑容器器。2.1 标志定义在 src/slave/flags.cpp 中该标志的定义为add(Flags::containerizers, containerizers, Comma-separated list of containerizer implementations\n to compose in order to provide containerization.\n Available options are mesos and docker (on Linux).\n The order the containerizers are specified is the order\n they are tried.\n, mesos);要点逗号分隔、可选值为mesos与dockerLinux、书写顺序即尝试顺序、默认值为mesos。2.2Containerizer::create()的解析逻辑Containerizer::create() 是工厂入口其流程为用strings::split(flags.containerizers, ,)切分标志若发现重复条目直接报错Duplicate entries found in --containerizer flag在 Linux 上按需创建 Nvidia 组件若列表中含docker则无条件创建若只用mesos则还需--isolation中含gpu/nvidiaisolator见 containerizer.cpp#L239-L284遍历各类型mesos调用MesosContainerizer::create(...)docker调用DockerContainerizer::create(...)未知类型返回Unknown or unsupported containerizer若只创建出一个容器器直接返回它否则用ComposingContainerizer::create(containerizers)包装containerizer.cpp#L325-L336。这与文档描述完全一致--containerizersmesos时 Agent 直接持有MesosContainerizer实例--containerizersdocker,mesos时则持有 Composing 容器器。2.3 默认 executor 的补全当TaskInfo中没有指定 executor即纯命令任务时Agent 会为任务使用默认 executor——具体是mesos-executorMesos 容器器还是mesos-docker-executorDocker 容器器取决于当前使用的容器器。源码中对应的二进制名常量定义在 src/slave/constants.hppconstexpr char MESOS_DEFAULT_EXECUTOR[] mesos-default-executor;而 Docker 容器器侧则使用 MESOS_DOCKER_EXECUTORmesos-docker-executor。默认 executor 的资源开销很小默认值为 0.1 CPU、32MB 内存DEFAULT_EXECUTOR_CPUS、DEFAULT_EXECUTOR_MEM。3. Composing Containerizer组合模式的逐个尝试Composing 容器器将--containerizers指定的多个容器器组合成一个逻辑容器器组合模式 / composite design pattern自身不启动任何容器而是按顺序把launch委托给成员容器器。其核心逻辑在 ComposingContainerizerProcess::_launch这是一个递归延续函数containerizer迭代器记录当前尝试到哪一个当前容器器返回SUCCESS将内部状态从LAUNCHING置为LAUNCHED并挂接wait()回调待容器终止后从containers_表中移除记录返回非SUCCESS即不支持该任务containerizer移到下一个容器器继续尝试所有容器器都尝试完仍不支持返回NOT_SUPPORTED若期间有 destroy 正在进行直接返回Failure(Container was destroyed while launching)。每个容器由内部Container结构state 负责它的containerizer指针追踪状态只有LAUNCHING/LAUNCHED/DESTROYING三种composing.cpp#L126-L141。这种设计的意义在于配置--containerizersdocker,mesos的集群里Docker 任务走 Docker 容器器、普通任务自动落到 Mesos 容器器对用户完全透明。4. Docker Containerizer镜像、hook 与两种运行形态4.1 触发条件与启动步骤Docker 容器器使用 docker 包提供的 Docker 引擎来管理容器启动流程为仅当ContainerInfo::type为DOCKER时才启动源码中在 docker.cpp#L1153 检查containerConfig.container_info().type() ! ContainerInfo::DOCKER并返回NOT_SUPPORTED——这正是 Composing 容器器逐个尝试能生效的基础先拉取pull镜像DockerContainerizerProcess::pull() 调用docker-pull(...)并以metrics.image_pull计时调用 pre-launch hookAgent 的 HookManager 机制以两种方式之一启动 executor方式 AMesos Agent 运行在 Docker 容器内由 Agent 标志--docker_mesos_image是否存在来标识该值是启动 Mesos Agent 所用的 Docker 镜像任务带自定义 executor该 executor 在 Docker 容器中启动任务不带 executor只有 command默认 executormesos-docker-executor在 Docker 容器中启动并通过 Docker CLI 执行该命令。方式 BMesos Agent 不运行在 Docker 容器内任务带自定义 executor该 executor 在 Docker 容器中启动任务只有 commandAgentfork 一个子进程运行默认 executormesos-docker-executor后者再 spawn 一个 shell 通过 Docker CLI 执行命令。--docker_mesos_image的存在性检查在源码 docker.cpp#L328、L1271、L1398 等处反复出现其语义与 flags.cpp#L996-L1002 中的描述一致指定后容器器认为 Agent 跑在 Docker 中并用 Docker 容器启动 executor 以便 Agent 重启恢复时能 recover 它们。4.2 相关配置标志标志默认值说明--dockerdockerdocker 可执行文件的绝对路径--docker_mesos_image无Agent 所用的 Docker 镜像指定即进入方式 A--docker_socket/var/run/docker.sockUnix 默认资源名Docker daemon 的 socketWindows 上须为命名管道如//./pipe/docker_engine--docker_kill_orphanstrue允许容器器清理孤儿容器同一台宿主机跑多个 Agent 时应设为false避免互相清理--docker_remove_delay—Agent 判定容器 TERMINATED 后、执行docker rm前的等待时间如3days--docker_config无默认 Docker 配置文件绝对路径或 JSON 字符串用于私有镜像仓库认证这些标志的完整定义见 src/slave/flags.cpp#L973-L1028。Docker 容器器的完整行为另见 Docker 容器器文档。5. Mesos Containerizerprepare → fork → isolate → fetch → execMesos 容器器是原生容器器负责处理所有未指定ContainerInfo::DockerInfo的 executor/task。其启动五步流程在 MesosContainerizerProcess 中逐一实现并且每一步都对应一次状态迁移PREPARING ──► ISOLATING ──► FETCHING ──► RUNNING └──────────────┴───────────┴─────────► DESTROYING状态枚举的字符串化实现见 mesos/containerizer.cpp#L3490-L3499。5.1 第一步PREPARING——按顺序 prepare 各 isolatorlaunch()先将ContainerConfig检查点checkpoint落盘然后transition(containerId, PREPARING)并按 isolator 的注册顺序串行链接各 isolator 的prepare()mesos/containerizer.cpp#L1612-L1640// We prepare the isolators sequentially according to their ordering // to permit basic dependency specification, e.g., preparing a // filesystem isolator before other isolators. foreach (const OwnedIsolator isolator, isolators) { f f.then(... return isolator-prepare(containerId, containerConfig) ...); }注释点明了串行化的原因允许基本的依赖表达例如让 filesystem isolator 先于其他 isolator 准备。每个prepare()可返回OptionContainerLaunchInfo这些 launch info 会在后续合并成最终的ContainerLaunchInfo命令、工作目录、namespaces、环境变量等若多个 isolator 冲突地指定同一字段会直接失败。5.2 第二步fork executor子进程被冻结prepare 完成后容器器调用 Launcherfork 出 executor 子进程。源码中 launcher-fork() 的 argv 为mesos-containerizer launchMesosContainerizerLaunch::NAMElaunch flags 出于敏感考虑通过MESOS_CONTAINERIZER_前缀的环境变量传递而非命令行以免被宿主机上无权限用户通过ps看到。fork 时同时传入一对 pipepipes[0]/pipes[1]子进程被冻结、在隔离完成前不会继续执行——这正是文档所说 The forked child is blocked from executing until it is been isolated。子进程侧的阻塞点在 launch.cpp#L755-L769// Do a blocking read on the pipe until the parent signals us to continue. while ((length os::read(pipe[0], dummy, sizeof(dummy))) -1 errno EINTR) { continue; }--pipe_read/--pipe_write两个标志的定义见 launch.cpp#L118-L132其帮助文本明确写道Its used to synchronize with the parent process.5.3 第三步ISOLATING——并行调用各 isolator 的 isolate进入ISOLATING状态后isolate() 对每个 isolator 调用isolate(containerId, _pid)传入 fork 出的 pid并并行执行后用collect(futures)等待全部完成// Isolate the executor with each isolator. // NOTE: This is done is parallel and is not sequenced like prepare // or destroy because we assume there are no dependencies in isolation.与 prepare 的刻意串行相反isolate 被假设为无依赖因此并行以缩短启动时延。同时还会为每个 isolator 挂接watch()回调以捕获资源限制事件limited。5.4 第四步FETCHING——获取 executorfetch() 调用 Agent 的 Fetcher 按CommandInfo中的 URIs 下载 executor 到 sandbox 目录若配置了 hook还会触发HookManager::slavePostFetchHook(containerId, directory)。5.5 第五步exec——放行子进程并进入 RUNNINGexec()中父进程向 pipe 写端写入一个字符解冻的子进程恢复执行先运行 isolator 通过ContainerLaunchInfo下发的准备命令如 cgroups 挂载点调整等再exec到真正的 executor 二进制容器器随后transition(containerId, RUNNING)mesos/containerizer.cpp#L2388。5.6 Isolator容器器的插件层Isolator 负责为容器创建CPU、网络、存储、内存等资源相互隔离的环境。其虚函数 API 定义在 MesosIsolatorProcesssupportsNesting()、supportsStandalone()、recover()、prepare()、isolate()、watch()、update()、usage()、status()、cleanup()。各 isolator 的实现分布在 src/slave/containerizer/mesos/isolators/ 下的cgroups/、cgroups2/、namespaces/、network/、filesystem/、gpu/、linux/、posix/、xfs/等目录中具体行为与--isolation标志的用法见 Mesos 容器器文档。6. Launcherfork 与销毁容器的执行者Launcher 负责fork/销毁容器。抽象职责在容器化上下文中 fork 新进程子进程最终会 exec 给定路径的二进制并携带给定的 argv、flags 和环境子进程的 I/O 按指定 I/O 描述符重定向。6.1 Linux LauncherLinux launcher 是 Mesos 在 Linux 上的默认实现src/slave/containerizer/mesos/linux_launcher.cpp 中的关键步骤与文档描述一一对应为容器创建 freezer cgroup构造时调用cgroups::prepare(..., freezer, ...)取得 freezer 层级linux_launcher.cpp#L151-L209并校验该层级未挂载其他 cgroup 子系统创建 posix pipe用于宿主父进程与容器进程之间的通信用clone系统调用 spawn 子进程fork 路径上先ns::clone(*parentPid, enterFlags, child, cloneFlags)进入指定 namespace 后再 clone否则直接os::clone(child, cloneFlags)且cloneFlags | SIGCHLDlinux_launcher.cpp#L588-L661将新容器进程移入 freezer 层级Create the freezer cgroup, and add the child to the cgroup父进程向 pipe 写端写一个字符子进程完成阻塞读取后继续exec。freezer cgroup 的意义在于父进程随时可以通过冻结该 cgroup来暂停整个容器进程树例如资源更新、销毁前快照销毁时则按 freezer 中的 pid 集合整体杀掉容器。6.2 嵌套容器与 Linux namespaces自 Mesos 1.1.0 起支持嵌套容器。Linux Launcher 负责为嵌套容器 fork 子进程并按需克隆相应的 Linux namespaces。官方文档给出的顶层容器 vs 嵌套容器 namespace 支持对照表如下Linux Namespaces顶层容器Top Level Container嵌套容器Nested ContainerMountNot sharedNot sharedPIDConfigurableConfigurableNetwork UTSConfigurableShared w/ parentIPCNot shared - configurable (TBD)Not shared - configurable (TBD)CgroupShared w/ agent - Not shared (TBD)Shared w/ parent - Not shared (TBD)User (not supported)Shared w/ agentShared w/ parent术语说明原文档 Note对顶层容器shared表示容器与 Agent 共享该 namespace对嵌套容器shared表示嵌套容器与其父容器共享该 namespace。从源码结构看嵌套容器 fork 前会特殊处理进入父容器 mount namespace_enterNamespaces 含 CLONE_NEWNS 时 通过namespace_mnt_target标志让 launch 辅助进程先进入父容器的 mount namespace保证能访问到要启动的二进制然后再按 clone flags 创建新 namespace。6.3 Posix launcher文档标注 Posix launcher 为 TBD预留的无 cgroup 依赖实现方向。当前仓库中非 Linux 平台实际走SubprocessLauncher一类基于普通子进程的 Launcher其enterNamespaces/cloneNamespaces参数会被忽略见 mesos/containerizer.cpp#L2227-L2230 的注释。7. 容器器状态机对比文档最后给出两种容器器的状态集合两者均以RUNNING为核心、以DESTROYING收尾区别在于前置阶段状态Docker 容器器Mesos 容器器PREPARING—✔ISOLATING—✔PULLING✔—FETCHING✔✔RUNNING✔✔DESTROYING✔✔源码印证Docker 容器器PULLING在 docker.cpp#L443container-state Container::PULLING;置位destroy()会针对FETCHING/PULLING/RUNNING三种状态分别处理终止 fetch、终止docker pull、或等待 status 落定后清理见 docker.cpp#L2422-L2505Mesos 容器器每次状态迁移都经过统一的transition(containerId, ...)并对前一状态做CHECK_EQ断言如 fetch() 中 CHECK_EQ(container-state, ISOLATING)保证状态机不可乱序destroy()入口还会拒绝重复销毁state DESTROYING时直接失败。Docker 容器器的PULLING对应拉取镜像阶段、FETCHING对应获取 URIs 阶段Mesos 容器器的PREPARING/ISOLATING则分别对应 isolator 准备与隔离两个阶段见第 5 节。8. 延伸阅读与源码索引主题路径本文依据的官方文档docs/containerizer-internals.md容器器抽象基类src/slave/containerizer/containerizer.hpp容器器工厂create()src/slave/containerizer/containerizer.cppComposing 容器器src/slave/containerizer/composing.cppDocker 容器器src/slave/containerizer/docker.cppMesos 容器器launch/isolate/fetch/execsrc/slave/containerizer/mesos/containerizer.cppLauncher 接口与 Linux 实现src/slave/containerizer/mesos/launcher.hpp、linux_launcher.cpplaunch 辅助进程pipe 同步、execsrc/slave/containerizer/mesos/launch.cppIsolator 插件 APIsrc/slave/containerizer/mesos/isolator.hppAgent 容器器相关标志src/slave/flags.cppDocker 容器器行为docs/docker-containerizer.mdMesos 容器器与 Isolatorsdocs/mesos-containerizer.md嵌套容器与 Task Groupdocs/nested-container-and-task-group.md小结Mesos 的 Containerizer 层用容器器 isolator 插件的两级抽象实现了资源隔离的可插拔化Composing 容器器让docker,mesos组合配置按序透明尝试Mesos 容器器则以PREPARING → ISOLATING → FETCHING → RUNNING的状态机组织启动流程配合 Linux Launcher 的 freezer cgroup pipe 冻结/解冻 机制实现了先隔离、后放行的原子化容器启动。排查容器启动问题时的实用路径是先看 Agent 日志中的状态迁移再对照本文第 5、6 节的调用链定位卡在 prepare、isolate、fetch 还是 exec 阶段。赞分享云原生集群管理容器编排任务调度【免费下载链接】mesosApache Mesos项目地址https://gitcode.com/gh_mirrors/meso/mesos点击查看免费下载相关推荐Apache Mesos 容器化器Containerizer内部机制全解析创建流程、Launcher 与状态机Apache Mesos 容器化器Containerizer内部机制全解析创建流程、Launcher 与状态机 导读 本文深入剖析 Apache Meso集群管理任务调度后端Apache Mesos Containerizer 内部机制解析组合、Docker 与 Mesos 原生容器化的完整架构Apache Mesos Containerizer 内部机制解析组合、Docker 与 Mesos 原生容器化的完整架构 导读本文以 Apache Mes云原生Apache Mesos 容器化器Containerizer完全指南Composing / Docker / Mesos 三种方案与隔离机制详解Apache Mesos 容器化器Containerizer完全指南Composing / Docker / Mesos 三种方案与隔离机制详解 Apac云原生集群管理容器编排任务调度上一篇NocoBase 插件客户端样式与主题开发指南createStyles、Theme Token 与主题编辑器实战下一篇Cortex 项目中的 zap 结构化日志实践设计哲学、采样机制与 FAQ 全解创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考