1 Star 0 Fork 26

yutiansut / rocker

forked from 範輝 / Rocker 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
MIT

Contents

  • ROCKER
    • 1.1. 亮点与特性
    • 1.2. 用户指南
    • 1.3. 架构说明
    • 1.4. 开发路线
    • 1.5. BUG
    • 1.6. 待办事宜

1. ROCKER

English Version

ROCKER 是一个在线解压进程沙箱实现, 针对的是基于 Linux 的资源受限的(即使是 docker 这样的容器实现自身的资源占用都是不能容忍的) IoT 系统, 旨在提高其资源利用率和系统安全性, 并且避免产生额外的性能开销.

通过将 App 程序文件及其它合适的文件压缩成squashfs包, 通常可以带来超过 60% 的磁盘空间节省, 这对于资源受限的 IoT 系统来说是非常有意义的. 与此同时, 由于 Linux 内核原生提供了动态按需解压支持, 相对于常规的 App 运行模式, 并不会产生额外的内存开销.

沙箱功能的安全性保证, 来自于Linux namespaces/cgroups, overlayfs, Rust 等基础设施, 以及大量的测试用例. 感谢 linus 大神, Rust 团队创造出这些伟大的基础设施.

1.1. 亮点与特性

  • 比 Docker 更优异的性能和资源利用率,启动容器不需要额外的镜像;
  • client 库使用纯 C 开发,裸金属开发模式, 除了 libc, 没有任何依赖;
  • server 端(库)使用 rust 开发, 坚如磐石的稳定性, 媲美 C/C++ 的运行效率和内存利用率;
  • 使用 crosstool-ng 组织交叉工具链, 可稳植性好, 稳定性高;
  • 代码风格强制统一, 整洁优雅;
  • 注重文档与测试;
  • 更多亮点, 欢迎深入源码探索...

1.2. 用户指南

1.2.1. 代码结构(简略)

整个项目分成 Client 端与 Server 端两部分, 类似于一个传统的 CS 架构, Client 端以库的形式给调用方使用.

..
├── core/                     # [Rust 代码] 服务端核心逻辑实现
├── rocker_server/            # [Rust 代码] CS server 端实现
├── librocker_client/         # [C    代码] CS client 库实现
├── librocker_client_wrapper/ # [Rust 代码] 通过 ffi 封装的 librocker_client 库,用于测试
├── tests/                    # [Rust 代码] 测试用例
├── README.md                 # 项目主文档
└── tools/

1.2.2. 环境配置与编译

1.2.2.1. 环境需求

对应的官方说明文档, 链接如下:

1.2.2.2. 编译

理论上本项目可在任何 crosstool-ng 和 rust 支持的架构体系上编译并运行, 非 x86(_x64) 平台上默认静态链接 musl 或 uclibc 库, 以简化对运行环境的依赖.

如下以TARGET=armv7-linux-musleabihf为例:

# 编译安装, 安装路径是项目根目录内的 install_dir
make TARGET=armv7-linux-musleabihf release

# 功能测试
make TARGET=armv7-linux-musleabihf test

# 性能测试
make TARGET=armv7-linux-musleabihf bench

1.2.3. 客户端库

调用示例如下:

// 由调用方定义的, 将在 ROCKER 中执行的回调函数及其参数
void *your_args = NULL;
int start_your_APP(void *args){};

// 初始化一个空白的 RockerRequest 结构体
RockerRequest req = ROCKER_request_new();

// 为 RockerRequest 结构体赋值
req.app_id = 1000;
req.uid = 1000;
req.gid = 1000;
req.app_pkg_path = "/tmp/your_APP.squashfs";
req.app_exec_dir = "/var/your_APP/execdir";
req.app_data_dir = "/var/your_APP/datadir";
req.app_overlay_dirs = { "/usr", "/var", "/etc", "/home", "/root" };

// 尝试在 ROCKER 中运行 APP
RockerResult res = ROCKER_enter_rocker(&req, start_my_APP, my_args);

if (ROCKER_ERR_success != res.err_no) {
    // 处理错误
}

// APP 运行结束, 清理环境
kill(res.guard_pid, SIGKILL);

// 更稳健的清理方法
RockerResult res2 = ROCKER_get_guardname(res.guard_pid);
if (ROCKER_ERR_success == res2.err_no && \
        0 == strcmp(res.guard_name, res2.guard.name)) {
    kill(res.guard_pid, SIGKILL);
}

详情参见 librocker_client.

1.3. 架构说明

以下将以'时序图'的形式论述具体的逻辑架构.

1.3.2. 时序图

节点名称 定义
App 将要启动的前台业务进程
AppMaster 资源调度进程, App 大管家
RockerClient 提供给 AppMaster 使用的 client 库,负责与 RockerMaster 及 RockerGuard 交互
RockerGuard App 所在虚拟沙箱的 1 号进程, 由 RockerMaster 创建,负责执行 '在线解压' 和 '虚拟沙箱' 机制的具体逻辑
RockerMaster ROCKER 服务端资源调度接口
Kernel Linux 内核

NOTE: RockerClient 通常与 AppMaster 属于同一进程, 文档中出于可读性的考虑, 对二者做了逻辑层面的拆分.

1.3.2.1. 概览

_

(0) start App; (1) request new rocker

AppMaster 调用 RockerClient 的 API, 向 RockerMaster 请求创建新的 rocker, 并在其中运行指定的 App. 新 Rocker 的具体配置信息由 AppMaster 在其请求信息中指定.

(2) create new rocker-guard

RockerMaster 收到请求, 创建一个新的 rocker 虚拟沙箱环境, 其中的 1 号进程就是 RockerGuard, RockerGuard 扮演的角色类似于常规 Linux 系统中的 init 或 systemd 进程, 若该进程退出, 即意味着其所在的虚拟沙箱环境的完全销毁(所有的进程及磁盘挂载都会被 Kernel 自动清理).

(3)

RockerMaster 创建完对应的 RockerGuard 实例, 后续的与 AppMaster 的交互, 将由 RockerGuard 直接执行, RockerMaster 不再参与.

(4) preparing, need CAP_SYS_ADMIN {#1}

RockerGurad 根据 AppMaster 的要求, 创建对应的 rocker 环境, 此过程需要 CAP_SYS_ADMIN 能力或 root 权限, 具体的细节将在接下来的 1.3.1.1 节中描述.

(5) send rocker-entrance

RockerGuard 将创建好的 rocker 入口, 发送给 RockerClient.

(6) start App in rocker {#2}

RockerClient 进入新创建的 rocker 环境, 在其中将 App 启动起来, 具体的细节将在 1.3.1.3 节中描述.

(7) PID of guard\App

App 启动完成之后, RockerClient 将 Guard 及 App 的 PID 等相关信息返回 AppMaster, 以供 AppMaster 的后续管理. 至此, RockerClient 完成其在单次 App 启动中使命, 不再参与后续环节.

(8) stop all; (10) kill

AppMaster 停止 App 的方式有两种, 一种是按照常规的逻辑自行管理, 另一种是通过 kill RockerGuard 的方式自动完成.

两种方式各有利弊,

  • 前者对 AppMaster 来说可以有更细粒度的控制, 但环境清理的彻底性需由自身保证(参见接下来第 9 步的说明);
  • 后者通过 kill RockerGuard 触发 Kernel 的自动清理机制, 可以简化 AppMaster 的实现逻辑, 并保证环境清理的彻底性, 但 AppMaster 将不能对这个清理过程进行任何定制.

(9) exit self

RockerGuard 自动退出的条件是其所在的 rocker 虚拟沙箱中的其它进程已经全部退出, 若 AppMaster 遗漏了某个进程, 将会导致此 rocker 的资源永远不被释放.

(11) send SIGCHLD

RockerGuard 退出后, RockerMaster 收到 SIGCHLD 信号, 可选的执行一些对应的内部逻辑.

(12) rocker's [PID 1] exited

内核探知到某个 rocker(pid namespace) 中的 1 号进程退出.

(13) broadcast SIGKILL(auto, very clean); (14) umount overlay; (15) destroy useless loop device

内核自动清理其中的所有资源(包括递归产生的衍生资源).

1.3.2.2. 子图 {#1}

_

(0) clone(MNT|PID)

RockerMaster 以带 CLONE_MNT 与 CLONE_PID 标志的 clone 接口创建 RockerGuard 实例, 参见 man clone(2).

(1) create loop device

RockerGuard 调用 ioctl 调口获取可用的 loop 设备, 参见 man loop(4).

(2) bind App.sqfs to loop; (3) mount loop to exec-path

将打包成 squashfs 格式的 App 程序包, 绑定到新获取的 loop 设备上, RockerGuard 将该 loop 设备挂载到 AppMaster 要求的执行路径.

创建 App.sqfs 及绑定挂载的过程, 类似于如下的命令行逻辑:


#将 App 程序文件制作成 squashfs 包, 需先安装 squashfs-tools 工具
mksquashfs ./AppDir ./App.sqfs

#将 squashfs 包绑定到 loop 设备
losetup /dev/loop8 ./App.sqfs

#挂载到指定目录
mount ./App.sqfs /mnt/AppExecDir

(4) build overlay {#1}

RockerGuard 创建 overlay 读写隔离层, 具体细节将在 1.3.1.2 节说明.

(5) remount /proc

重新挂载 /proc, 以使新 pid_namespace 内的 pid 信息正常显示.

(6) unshare(USER)

前述工作完成以后, RockerGuard 进程调用 unshare 接口进入新的专用 user_namespace, 之后 rocker 内的任何操作都是在这个权限受限的 user_namespace 中进行, 参见 man unshare(2).

(7) done

RockerGuard 准备工作完成, 通知 RockerMaster.

(8) set uid_map

RockerMaster 为 RockerGuard 设置 uid_map(需要 CAP_SETUID) 及 gid_map(需要 CAP_SETGID). 设置 gid_map 之前, 须向 /proc/[RockerGuard PID]/setgroups 文件中写入 "deny" 值, 参见 man user_namespaces(7).

1.3.2.3. 子图 {#1} {#1}

_

(0) get all visiable top-dir except /proc,/sys,/dev,/run

遍历根下的所有顶层目录, 排除动态目录, 如 /proc, /sys, /dev, /run 等.

(1) top-dir act as 'lowerdir', and finally merged to themself

根下所有可见的顶层目录, 均在独立的 mnt_namespace 中原地叠加 overlay 隔离层, 以使每个 App 均拥有独立的可读写虚拟文件系统, 参见 内核文档 overlayfs.

以 ID 为 1000 的 App 挂载 /usr 为例, 假设其 upperdir 与 workdir 分别为 /private/1000/upperdir 与 /private/1000/workdir, overlay 挂载过程类似于如下的命令行逻辑:

mount -t overlay overlay /usr \
    -o lowerdir=/usr,upperdir=/private/1000/upperdir,workdir=/private/1000/workdir

1.3.2.4. 子图 {#2}

_

(0) rocker created

RockerGuard 准备好新的 rocker 环境后, 通知 RockerClient 端.

(1) fork out a child process, (2) setns(USER|MNT|PID)

RockerClient 创建一个子进程, 子进程调用系统的 setns 接口进入新的 rocker 环境.

(3) run App in child's brother process

在 (1) 中创建的子进程中再创建一个子进程, 在其中启动前台 App 进程.

这一步新建的子进程, 实质是 (1) 中子进程的兄弟进程, 通过带 CLONE_PARENT 标志的 clone 实现, 其父进程与 (1) 中子进程的父进程一致, 如此以来 AppMaster 可以收到 App 进程终止时发送的 SIGCHLD 信号, 参见 man clone(2).

(4) PID of guard\App

RockerClient 将 RockerGuard 及 App 的 PID 等信息返回给 AppMaster.

1.4. 开发路线

添加更多的实用功能, 如下所示的 App 进程智能调度算法 就是其中之一:

_

1.5. BUG

  • ...

1.6. 待办事宜

  • 完善英文版文档;
  • 添加日志落盘功能;
  • 添加更多的功能与性能测试用例;
  • ...
MIT License Copyright (c) 2019 西门 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

简介

我用 Rust 写了一个内嵌式 docker 展开 收起
Rust
MIT
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
Rust
1
https://gitee.com/yutiansut/rocker.git
git@gitee.com:yutiansut/rocker.git
yutiansut
rocker
rocker
master

搜索帮助

14c37bed 8189591 565d56ea 8189591