- 集群管理
- 任务调度
- 后端
【免费下载链接】mesos
Apache Mesos
Mesos Mini 是 Apache Mesos 社区维护的 Docker 镜像,它让你在本地用一条docker run命令获得一个“真集群”:一个 Mesos master、一个 Mesos agent 和一个示例框架 Marathon。读完本文,你既能掌握 Mesos Mini 的完整使用流程(启动、通过 Marathon API 部署应用、停止与镜像 tag 选择),也能从源码层面理解它是如何在一个容器内用 systemd 编排多服务、内嵌 Docker Daemon(Docker-in-Docker)解决嵌套 cgroup 问题的——这对编写框架端到端集成测试、模拟 master failover 等场景直接有用。
为什么需要 Mesos Mini
能在 Docker 中一键拉起本地 Mesos 集群,可以显著简化以下场景:
- 现场演示(Demo):在会场网络不稳定的情况下做 Mesos 现场演示,本地容器化集群不依赖外部网络服务。
- 框架开发:用本地 Mesos 集群为框架编写端到端集成测试,并且可以轻易地自动化进测试套件(CI)。
- 测试未发布的 Mesos 新特性:虽然也可以从源码构建 Mesos,但大多数框架开发者不熟悉构建流程且耗时较长,直接用快照镜像更方便。
这个思路类似 Kubernetes 生态的 minikube 或早期的 minimesos 工具。由于 minimesos 已不再维护,Apache Mesos 社区决定在 Mesos 仓库内自行维护一套方案,以简化 CI 集成。
快速上手:一条命令启动本地集群
前提是宿主机已安装 Docker(文档在 Linux 与 MacOS 上均验证过)。执行:
$ docker run --rm --privileged -p 5050:5050 -p 5051:5051 -p 8080:8080 mesos/mesos-mini参数说明:
--rm:容器退出后自动删除容器对象;--privileged:容器内需要操作 cgroup、挂载、网络等,必须放开特权;-p 5050:5050:Mesos master UI(见MESOS_ADVERTISE_IP等配置,master 监听 5050);-p 5051:5051:Mesos agent;-p 8080:8080:Marathon UI 与 API。
启动后,容器内会运行 1 个 master、1 个 agent 和 1 个示例框架(Marathon),可分别访问:
- Mesos master UI:
http://localhost:5050 - Mesos agent:
http://localhost:5051 - Marathon UI:
http://localhost:8080
通过 Marathon 部署应用
可以在本地集群里像生产环境一样用 Marathon 提交应用。例如把如下内容保存为app.json:
{ "id": "test", "cmd": "sleep 1000", "cpus": 1, "mem": 128, "disk": 0, "instances": 1, "container": { "docker": { "image": "alpine" }, "type": "DOCKER" }, "networks": [ { "mode": "host" } ] }然后通过 Marathon 的 v2 API 提交:
$ curl -X POST -d @app.json -H "Content-type: application/json" http://localhost:8080/v2/apps注意这里提交的是type: DOCKER的容器,它走的是 Mesos agent 的Docker Containerizer(见下文“内嵌 Docker Daemon”一节),而不是 UCR,这正是 Mesos Mini 想要覆盖的典型生产路径。
停止本地集群使用docker stop <CONTAINER_ID>。由于容器内所有状态都在容器内,容器停止后所有产物(work dir、嵌套容器等)都会随之清理,天然“无残留”。
镜像 tag 规范
社区维护以下 Docker 镜像 tag(以 Docker Hub 上的mesos/mesos-mini为准):
| Tag | 含义 | 示例 |
|---|---|---|
master | master 分支最新 HEAD | mesos/mesos-mini:master |
<RELEASE_BRANCH> | 发布分支最新 HEAD | 1.7.x |
master-<DATE> | master 分支快照构建 | master-2018-11-19 |
<RELEASE_BRANCH>-<DATE> | 发布分支快照构建 | 1.7.x-2018-11-19 |
注意:不支持1.7.x之前的发布分支,之后的新发布分支都会被支持。
从源码看,tag 的生成逻辑就在 CI 脚本 mini.sh 中:脚本先用git describe --exact-match判断 HEAD 是否为精确 tag——是则推 tag 名镜像;否则取当前所在远端分支(形如[0-9]+\.[0-9]+\.x,找不到则回退为master)拼出<分支>-<日期>作为快照 tag,并把分支名作为“latest” tag 推送。这与上表的 tag 规范一一对应。
它是如何实现的
用 systemd 管理多个服务
Mesos Mini 容器内直接用systemd编排多个守护进程。Dockerfile 的关键步骤包括:
- 设置
ENV container docker并清理系统自带的无关 service(getty、dbus、logind 等),只保留精简的 systemd 环境(Dockerfile); - 内嵌静态版 Docker 17.12.0 CE 到
/usr/local/bin,并复制docker.service、docker_daemon.json(Dockerfile); - 安装 Marathon(1.6.322)并复制
marathon.service(Dockerfile); - 执行
systemctl enable docker mesos-slave mesos-master marathon,将四个服务设为开机自启(Dockerfile); - 容器入口为
entrypoint.sh,最终exec /usr/sbin/init让 systemd 成为 PID 1(entrypoint.sh),并用STOPSIGNAL SIGRTMIN+3通知容器停止时向 systemd 发送标准停机信号,走优雅停止流程(Dockerfile)。
其中mesos-master.service、mesos-slave.service这两个 unit 来自 Mesos 打包脚本 support/packaging/common/,与正式发行版使用的同一套 systemd 单元文件——这也是“尽量模仿生产环境”的体现。
由此带来一个非常实用的能力:可以单独重启某个服务。例如重启 Mesos master:
$ docker exec <CONTAINER_ID> systemctl restart mesos-master同理也可以重启 agent(mesos-slave)、Marathon 或 Docker daemon。这对需要模拟master failover的端到端集成测试尤其有用——测试脚本可以随时把 master 杀掉再拉起,观察框架的重注册行为。
各服务的环境变量配置同样以 systemd 环境文件的形式提供:
- master 环境:master_environment 中设置
MESOS_CLUSTER=mesos-mini、MESOS_ADVERTISE_IP=127.0.0.1、MESOS_WORK_DIR=/var/lib/mesos/master; - agent 环境:agent_environment,这是理解 UCR/Docker Containerizer 行为的关键,后面详述。
内嵌 Docker Daemon(Docker in Docker)
Mesos Mini 的目标之一是尽可能贴近生产配置。为了让框架能真正拉起 Docker 容器(type: DOCKER的 task),容器内嵌了一个 Docker Daemon。你可以在宿主机上直接查看 Mesos 集群内部的 Docker 容器:
$ docker exec <CONTAINER_ID> docker ps从实现看,几个细节保证了“嵌套容器”的正确性:
- cgroup parent 的嵌套。docker_env.sh 在 dockerd 启动前读取容器自身 PID 1 的 memory cgroup 路径,生成
CGROUP_PARENT=<容器cgroup>/docker写入环境变量文件;docker.service 以dockerd --cgroup-parent=${CGROUP_PARENT}启动并设置Delegate=yes。这样内层 Docker 容器的 cgroup 全部嵌套在 Mesos Mini 容器自己的 cgroup 之下,Mini 容器退出时不会在宿主机留下任何 cgroup 残留。 - 存储驱动选择 vfs。docker_daemon.json 中配置
"storage-driver": "vfs",避免 overlay 等存储驱动在容器嵌套场景下的兼容性问题,代价是磁盘占用略大——对一个测试镜像而言是可接受的取舍。 - 内嵌 dockerd 使用静态二进制(Docker 17.12.0 CE),不依赖 CentOS 发行版自带的 docker 包,保证版本可控(Dockerfile)。
UCR 的 cgroup 布局修复
对 Mesos Containerizer(UCR),Mesos Mini 打开了生产环境中通常启用的大部分 isolator。可以从 agent_environment 看到 agent 的实际启动配置:
MESOS_CONTAINERIZERS=mesos,docker MESOS_ISOLATION=filesystem/linux,network/cni,cgroups/cpu,cgroups/mem,cgroups/blkio,cgroups/devices,disk/du,docker/runtime,volume/sandbox_path,volume/host_path,posix/rlimits,namespaces/pid,linux/capabilities即同时启用mesos(UCR)与docker两种 containerizer,并叠加 cgroup、namespace、rlimits 等一套接近生产的 isolator 组合。UCR 的网络走 CNI:MESOS_NETWORK_CNI_CONFIG_DIR=/etc/mesos/cni指向 ucr-default-bridge.json(mesos-cni-port-mapper+ bridge 委托,子网172.31.254.0/24),CNI 插件 v0.7.4 由 Dockerfile 预装到/usr/libexec/mesos/cni。
但这里有一个嵌套容器特有的坑:外层 Docker 会为每个 cgroup 子系统做 bind mount,例如把当前容器的 cgroup 绑定到子系统根:
/sys/fs/cgroup/memory/docker/<cid> -> /sys/fs/cgroup/memory这会“骗过”依赖/proc/<pid>/cgroup的组件——因为该 proc 文件不受 bind mount 影响,Mesos agent 与 UCR 据此判断进程所属 cgroup 时会得到与实际挂载点不符的路径。
entrypoint.sh 的解决方式是:容器启动时解析/proc/self/mountinfo,找出所有 Docker 做的 cgroup bind mount,然后对每个子系统再叠加一层 bind mount,在/sys/fs/cgroup/<subsystem>/docker/<cid>下重建“等同于宿主机”的 cgroup 布局:
$ mkdir -p /sys/fs/cgroup/memory/docker/<cid> $ mount --bind /sys/fs/cgroup/memory /sys/fs/cgroup/memory/docker/<cid>之后再把 agent 的--cgroups_root指向这一层。从当前仓库的 agent_environment 看,该标志的取值是$(grep memory /proc/1/cgroup | cut -d: -f3)/mesos,即容器 PID 1 所在 memory cgroup 路径(形如docker/<cid>)下的mesos子目录——与博客描述的思路一致:让 agent 认为自己运行在“宿主机”的 cgroup 树上,从而在 Mini 容器退出时不遗留任何 cgroup 痕迹。
其他值得一提的 agent 配置
继续看 agent_environment:
MESOS_IMAGE_PROVIDERS=DOCKER+MESOS_IMAGE_PROVISIONER_BACKEND=copy:agent 可直接从 Docker 镜像仓库拉取镜像并复制进 UCR 沙箱(UCR 拉镜像路径);MESOS_DISK_PROFILE_ADAPTOR=org_apache_mesos_UriDiskProfileAdaptor:通过 uri_disk_profile.json 模块从http://localhost/mesos_disk_profiles.json轮询加载磁盘 profile(10 秒一次),用于演示资源 provider/磁盘 profile 能力;MESOS_SYSTEMD_ENABLE_SUPPORT=false、MESOS_HOSTNAME_LOOKUP=false:在容器环境下关闭 hostname 反查等不适合的操作。
Marathon 侧,marathon.sh 中的启动参数也呼应了本文档“当前限制”一节:--internal_store_backend "mem"与--disable_ha说明 Marathon 使用内存存储而非 ZooKeeper;marathon.service 还设置了Restart=always与RestartSec=5,即使测试中把 Marathon 杀掉它也会自动拉起。
构建与 CI
Mesos Mini 的构建脚本托管在 Mesos 仓库 support/mesos-mini/ 目录中。build.sh 是两阶段构建:
- 先调用
support/packaging/centos/下的脚本构建基础镜像mesos/mesos-centos(基于 centos7.dockerfile 编译安装完整 Mesos 发行版); - 再以
mesos/mesos-centos:<tag>为BASE_IMAGE_NAME构建 Dockerfile,产出mesos/mesos-mini:<tag>。
也就是说,mesos/mesos-mini使用mesos/mesos-centos作为基础镜像。有些用户只需要“安装了 Mesos 的镜像”而不是完整 Mini 集群,mesos/mesos-centos正好满足这一需求,其 tag 规则与 mini 相同。
Jenkins CI 通过 mini.sh 与 docker-centos.sh 每日自动为受支持的发布分支和 master 分支构建并推送快照镜像(对应上文的<分支>-<日期>tag)。如需为 Mini 提交 bug 修复或新功能,遵循 Apache Mesos 的贡献流程即可。
当前限制
- 只能启动一个Mesos agent(单节点集群,无法模拟多 agent 拓扑);
- Marathon 使用内存存储而非 ZooKeeper(见
--internal_store_backend mem),容器重启后 Marathon 状态不保留; - 未启用 SSL(master/agent 均为 HTTP 明文)。
如果你的集成测试需要验证 HA(多 master、ZooKeeper 选主)或多 agent 场景,Mesos Mini 无法覆盖,需要自行编排多容器环境。
小结
Mesos Mini 的价值在于“用最小成本获得一条贴近生产的路径”:systemd 编排的 master/agent/Marathon、双 containerizer(UCR + Docker)、生产级 isolator 组合、CNI 网络与镜像 provider,全部收敛在一条docker run命令里;而 cgroup bind mount 重建、cgroup-parent嵌套、--cgroups_root重定位等细节,则保证了容器停止后零残留。对于框架开发者,它既是现成的本地测试集群,也模拟了 failover 等运维动作的验证手段。关键源码入口汇总:support/mesos-mini/Dockerfile、support/mesos-mini/entrypoint.sh、support/mesos-mini/mesos/agent_environment、support/jenkins/mini.sh。
- 集群管理
- 任务调度
- 后端
【免费下载链接】mesos
Apache Mesos
相关推荐
DataHub Quickstart:用 datahub CLI 一条命令拉起本地 DataHub 全栈实例
DataHub Quickstart:用 datahub CLI 一条命令拉起本地 DataHub 全栈实例 本文基于 DataHub 仓库的官方快速入门文档
AI 技能AI 写作人工智能深度研究AI 应用Apache Mesos容器化实战:Mesos容器化与Docker容器化对比分析
Apache Mesos作为 分布式系统内核 ,为构建和运行 分布式应用程序 提供了强大的资源管理能力。在容器化技术盛行的今天,Mesos提供了两种主要的容器化
云原生DLSS Swapper:3 步给游戏换上新版 DLSS,不催厂商更新
DLSS Swapper:3 步给游戏换上新版 DLSS,不催厂商更新 厂商迟迟不给老游戏推送新版 DLSS,而新版往往帧率更高、伪影更少。DLSS Swapp
桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考