containerd/overlaybd

GitHub: containerd/overlaybd

Overlaybd 是一种基于块设备的分层容器镜像格式,通过按需拉取远程镜像数据来大幅加速容器和虚拟机的启动过程。

Stars: 374 | Forks: 78

# Overlaybd ![logo](https://github.com/containerd/overlaybd/blob/main/docs/assets/overlaybd_logo.svg) Overlaybd(overlay block device)是一种新颖的分层块级镜像格式,专为容器、安全容器设计,同时也适用于虚拟机。它是论文 [DADI: Block-Level Image Service for Agile and Elastic Application Deployment. USENIX ATC'20](https://www.usenix.org/conference/atc20/presentation/li-huiba) 的开源实现。 [Scaling up Without Slowing Down: Accelerating Pod Start Time. KubeCon+CloudNativeCon Europe 2024](https://youtu.be/RJ6Lt9bVNTw) Overlaybd 基于 [PhotonLibOS](https://github.com/alibaba/PhotonLibOS),这是一个高效的 LibOS 框架。 Overlaybd 有 2 个核心组件: * **Overlaybd** 是一种基于块设备的镜像格式,将一系列基于块的层提供合并视图,作为一个虚拟块设备。LBA 查找算法采用了线性化的 B+ 树和 AVX-512 来优化性能,显著将搜索速度提升了 10 倍。[查找性能](https://github.com/containerd/overlaybd/blob/main/docs/lsmt_lookup.md) * **Zfile** 是一种支持可寻址在线解压的压缩文件格式。 此仓库是基于 [TCMU](https://www.kernel.org/doc/Documentation/target/tcmu-design.txt) 的 overlaybd 实现。 Overlaybd 可用作[加速容器镜像](https://github.com/containerd/accelerated-container-image)的存储后端,这是一种远程容器镜像解决方案,通过按需拉取镜像数据,而无需在容器启动前下载和解包整个镜像。 得益于块设备的通用性,overlaybd 也是一种广泛适用于大多数运行时的镜像格式,包括 qemu/kvm 以及任何其他支持块或 scsi API 的运行时。 Overlaybd 是 containerd 的一个__非核心__子项目。 ## 设置 ### 系统要求 Overlaybd 通过 TCMU 提供虚拟块设备,因此需要 TCMU 内核模块。TCMU 在 Linux 内核中实现,并被大多数 Linux 发行版支持。 检查并加载 target_core_user 模块。 ``` modprobe target_core_user ``` ### 从 RPM/DEB 安装 您可以从 [发布页面](https://github.com/containerd/overlaybd/releases) 下载我们的 RPM/DEB 包并进行安装。 二进制文件将安装到 `/opt/overlaybd/bin/`。 运行 `/opt/overlaybd/bin/overlaybd-tcmu`,日志存储在 `/var/log/overlaybd.log` 中。 最好将 `overlaybd-tcmu` 作为服务运行,以便在意外崩溃后能够重新启动。 ### 从源码构建 #### 要求 要从源代码构建 overlaybd,需要以下依赖项: * CMake >= 3.14 * gcc/g++ >= 7 * Libaio、libcurl、libnl3、glib2 和 openssl 运行时及开发库。 * CentOS 7/Fedora: `sudo yum install libaio-devel libcurl-devel openssl-devel libnl3-devel libzstd-static e2fsprogs-devel` * CentOS 8: `sudo yum install libaio-devel libcurl-devel openssl-devel libnl3-devel libzstd-devel e2fsprogs-devel` * Debian/Ubuntu: `sudo apt install libcurl4-openssl-dev libssl-dev libaio-dev libnl-3-dev libnl-genl-3-dev libgflags-dev libzstd-dev libext2fs-dev pkg-config automake libtool # libgtest-dev // for test` * Mariner/AzureLinux: `sudo yum install libaio-devel libcurl-devel openssl-devel libnl3-devel e2fsprogs-devel glibc-devel libzstd-devel binutils ca-certificates-microsoft build-essential` #### 构建 你需要使用 git 来检出源代码: ``` git clone https://github.com/containerd/overlaybd.git cd overlaybd git submodule update --init ``` 整个项目由 CMake 管理。二进制文件和资源文件将被安装到 `/opt/overlaybd/`。 ``` mkdir build cd build cmake .. # -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=true -DBUILD_TESTING=true make -j sudo make install ``` 考虑到某些 libcurl 和 libopenssl 存在 API 变更,如果想要构建确保兼容的 libcurl 和 openssl 版本,并将其作为静态库链接到可执行文件中。 注意,构建 libcurl 和 openssl 依赖于 `autoconf` `automake` 和 `libtool`。 ``` cmake -D BUILD_CURL_FROM_SOURCE=1 .. ``` 如果你想使用[原始 libext2fs](https://github.com/tytso/e2fsprogs) 而不是我们[定制版的 libext2fs](https://github.com/data-accelerator/e2fsprogs)。 ``` cmake -D ORIGIN_EXT2FS=1 .. ``` 有关 `ORIGIN_EXT2FS` 的更多信息,请访问 [USERSPACE_CONVERTOR](https://github.com/containerd/accelerated-container-image/blob/main/docs/USERSPACE_CONVERTOR.md#libext2fs)。 如果你想使用 DSA 硬件来加速 CRC 计算。 ``` cmake -D ENABLE_DSA=1 .. ``` 如果你想使用 avx512 来加速 CRC 计算。 ``` cmake -D ENABLE_ISAL=1 .. ``` 如果你想使用 QAT 来加速压缩/解压缩。然而,目前仅集成了解压缩部分。由于 LZ4 已经是一种非常高效的压缩算法,我们的测试表明,当压缩比显著超过某个阈值时,只有在 4KB 块大小和 256 批处理大小下,QAT 的性能才能超越 CPU。 ``` cmake -D ENABLE_QAT=1 .. ``` 有关更多信息,请转到 `overlaybd/src/overlaybd/zfile/README.md`。 最后,为 overlaybd-tcmu 后端存储设置一个 systemd 服务。 ``` sudo systemctl enable /opt/overlaybd/overlaybd-tcmu.service sudo systemctl start overlaybd-tcmu ``` ## 配置 ### overlaybd 配置 默认配置文件 `overlaybd.json` 安装在 `/etc/overlaybd/`。 ``` { "logConfig": { "logLevel": 1, "logPath": "/var/log/overlaybd.log" }, "cacheConfig": { "cacheType": "file", "cacheDir": "/opt/overlaybd/registry_cache", "cacheSizeGB": 4 }, "gzipCacheConfig": { "enable": true, "cacheDir": "/opt/overlaybd/gzip_cache", "cacheSizeGB": 4 }, "credentialConfig": { "mode": "file", "path": "/opt/overlaybd/cred.json" }, "ioEngine": 0, "download": { "enable": true, "delay": 600, "delayExtra": 30, "maxMBps": 100 }, "p2pConfig": { "enable": false, "address": "localhost:19145/dadip2p" }, "exporterConfig": { "enable": false, "uriPrefix": "/metrics", "port": 9863, "updateInterval": 60000000 }, "enableAudit": true, "auditPath": "/var/log/overlaybd-audit.log", "serviceConfig": { "enable": false, "address": "http://127.0.0.1:9862" } } ``` | 字段 | 描述 | |---------------------|-------------------------------------------------------------------------------------------------------| | logConfig.logLevel | 日志文件的日志级别,0 - DEBUG,1 - INFO,2 - WARN,3 - ERROR | | logConfig.logPath | 日志文件的路径,默认值为 `/var/log/overlaybd.log`。 | | logConfig.logSizeMB | 日志文件的大小限制,单位为 MB,默认为 `10` (10 MB)。 | | logConfig.logRotateNum | 日志文件的轮转数量,默认为 `3`。 | | ioEngine | 用于打开本地文件的 IO 引擎:psync 0, libaio 1, posix aio 2。 | | cacheConfig.cacheType | 使用的 cache 类型,支持 `file`、`ocf` 和 `download`。 | | cacheConfig.cacheDir | 远程镜像数据的 cache 目录。 | | cacheConfig.cacheSizeGB | cache 的最大大小,单位为 GB。 | | cacheConfig.refillSize | 从源填充的大小,单位为字节。默认为 `262144` (256 KB)。 | | gzipCacheConfig.enable | 是否启用解压后的 gzip 文件 cache。 | | gzipCacheConfig.cacheDir | 解压后的 gzip 数据的 cache 目录。 | | gzipCacheConfig.cacheSizeGB | cache 的最大大小,单位为 GB。 | | gzipCacheConfig.refillSize | 从源填充的大小,单位为字节。默认为 `262144` (256 KB)。 | | credentialFilePath(legacy) | 用于在 registry 上拉取镜像的凭证。默认值为 `/opt/overlaybd/cred.json`。 | | credentialConfig.mode | 用于 lazy-loading 的认证模式。
- `file` 表示从 `credentialConfig.path` 读取凭证。
- `http` 表示向 `credentialConfig.path` 发送 http 请求
- `https` 表示向 `credentialConfig.path` 发送 https 请求,带有可选的客户端证书认证和 CA 锁定
- `uds` 表示通过与 `http` 模式相同的 http 请求,但通过位于 `credentialConfig.path` 的 Unix-domain socket 进行 | | credentialConfig.path | 凭证文件路径或由 `mode` 决定的 url | | credentialConfig.client_cert_path | 可选。客户端证书文件的路径(`https` 模式)。可以在同一个 PEM 文件中包含私钥。 | | credentialConfig.client_key_path | 可选。客户端私钥文件的路径(`https` 模式)。仅当私钥与证书分开存放时需要。 | | credentialConfig.server_ca_path | 可选。用于验证服务器的 CA 证书路径(`https` 模式)。如果省略,则使用系统 CA 包。设置后,**仅**信任此 CA 文件。 | | download.enable | 是否启用后台下载。 | | download.delay | overlaybd 设备启动后等待开始下载任务的秒数。 | | download.delayExtra | 附加到 delay 的随机额外延迟,避免太多任务在同一时间启动。 | | download.maxMBps | 下载任务的速度限制,单位为 MB/s。 | | download.blockSize | 从源下载的块大小,单位为字节。默认为 `262144` (256 KB)。 | | p2pConfig.enable | 是否启用 p2p proxy。 | | p2pConfig.address | 用于 p2p 下载的 proxy,格式为 `localhost:/`,取决于 dadip2p.yaml | | exporterConfig.enable | 是否创建用于展示 Prometheus 指标的服务器。 | | exporterConfig.uriPrefix | 用于导出指标的 URI 前缀。 | | exporterConfig.port | 用于展示指标的 http 服务器端口。 | | exporterConfig.updateInterval | 更新指标的时间间隔,单位为微秒。 | | enableAudit | 是否启用审计。 | | enableThread | 是否启用 overlaybd 设备在独立线程中运行。注意 `cacheType` 应为 `ocf`。默认为 `false`。 | | auditPath | 审计文件的路径,默认值为 `/var/log/overlaybd-audit.log`。 | | registryFsVersion | registry 客户端版本,'v1' 基于 libcurl,'v2' 基于 photon http。默认值为 'v2'。 | | prefetchConfig.concurrency | 用于重新加载 trace 的预取并发数,默认为 `16` | | certConfig.certFile | SSL/TLS 客户端证书文件的路径 | | certConfig.keyFile | SSL/TLS 客户端密钥文件的路径 | | userAgent | 自定义的 userAgent,用于标识 HTTP 请求。默认值为包版本,例如 'overlaybd/1.1.14-6c449832' | | serviceConfig.enable | 启用实时快照 API 服务,默认为 `false`。 | | serviceConfig.address | API 服务监听地址,默认为 `http://127.0.0.1:9862`。 | ### 凭证配置 当需要认证时会重新加载凭证。如果使用临时凭证,必须在过期前更新凭证,否则 overlaybd 将不断重新加载直到设置了有效的凭证。 Overlaybd 支持多种凭证模式。以下是一些 `credentialConfig` 字段的示例。 - 模式 **file** `credentialConfig.path` 应类似于 '.docker/config.json',如下所示: ``` #### /etc/overlaybd/config.json #### { "logLevel": 1, "logPath": "/var/log/overlaybd.log", ... "credentialConfig": { "mode": "file", "path": "/opt/overlaybd/cred.json" }, ... } #### /opt/overlaybd/cred.json #### { "auths": { "hub.docker.com": { "username": "username", "password": "password" }, "hub.docker.com/hello/world": { "auth": "dXNlcm5hbWU6cGFzc3dvcmQK" } } } ``` - 模式 **http** `credentialConfig.path` 应为开发人员实现的、能够回复凭证信息的服务器监听地址。 ``` #### /etc/overlaybd/config.json #### { "logLevel": 1, "logPath": "/var/log/overlaybd.log", ... "credentialConfig": { "mode": "http", "path": "localhost:19876/auth" }, ... } ``` overlaybd 将向服务器发送带有 `remote_url` 的 http 请求,如下所示: ``` { "traceId": "${trace_id}" "success": true or false "data": { "auths": { "hub.docker.com": { "username": "username", "password": "password" } } } } ``` 我们在 `test/simple_auth_server.cpp` 中编写了一个示例 http 服务器。 - 模式 **https** `credentialConfig.path` 应为 HTTPS 服务器的监听地址。与 `http` 模式不同,路径中必须包含 `https://` 方案前缀(例如 `https://localhost:19876/auth`)。可选的 `client_cert_path`/`client_key_path` 字段可启用客户端证书认证,而 `server_ca_path` 将信任锁定到特定的 CA。对于本地认证服务器,提供全部三个字段可以确保仅与该服务器进行安全通信(双向 TLS)。 ``` #### /etc/overlaybd/config.json #### { "logLevel": 1, "logPath": "/var/log/overlaybd.log", ... "credentialConfig": { "mode": "https", "path": "https://localhost:19876/auth", "client_cert_path": "/etc/overlaybd/client.crt", "client_key_path": "/etc/overlaybd/client.key", "server_ca_path": "/etc/overlaybd/ca.crt" }, ... } ``` overlaybd 将通过 mTLS 向服务器发送带有 `remote_url` 的 https 请求,如下所示: 所有三个 TLS 字段都是可选的,并且可以独立配置: - `client_cert_path` 设置客户端证书。如果 PEM 文件也包含私钥,则可以省略 `client_key_path`。 - `client_key_path` 设置客户端私钥。仅当私钥与证书不在同一个文件时才需要。 - 如果省略 `server_ca_path`,则使用系统 CA 包来验证服务器证书。设置 `server_ca_path` 后,**仅**使用指定的 CA 文件 — 不会参考系统 CA 包。 - 模式 **uds** `credentialConfig.path` 应为 Unix-domain socket 的文件系统路径。overlaybd 将通过该 socket 建立连接,并使用与 `http` 模式相同的 HTTP 请求/响应格式进行通信。 ``` #### /etc/overlaybd/config.json #### { "logLevel": 1, "logPath": "/var/log/overlaybd.log", ... "credentialConfig": { "mode": "uds", "path": "/run/overlaybd/creds.sock" }, ... } ``` overlaybd 将通过 socket 建立连接并发送如下请求: 此处的 HTTP host(此处为 `localhost`)是一个占位符 — 请求始终通过配置的 socket 建立连接。服务器响应格式与 `http` 模式相同。 安全模型:UDS 无法通过网络访问,并受到 socket 文件系统权限的限制。在 helper 端通过设置 socket 的 owner/group 以及非全局可读的权限模式(例如 `0600` 或 `0660`)来限制访问;overlaybd 客户端本身不会强制执行此操作。 ## 用法 ### 与 containerd 一起使用 请安装 overlaybd 并参考[加速容器镜像](https://github.com/containerd/accelerated-container-image)。Overlaybd 与 containerd 深度集成,易于。 ### 独立使用 对于其他场景,用户可以手动使用 overlaybd。Overlaybd 作为 TCMU 的后端存储工作,因此用户可以通过与 configfs 交互来运行 overlaybd 镜像。 #### 配置文件 需要使用配置文件来描述 overlaybd 镜像,仅支持本地镜像和 registry 镜像。以下是一个示例 JSON 配置文件: ``` { "repoBlobUrl": "https://obd.cr.aliyuncs.com/v2/overlaybd/sample/blobs", "lowers" : [ { "file" : "/opt/overlaybd/layer0" }, { "dir": "/var/lib/containerd/root/io.containerd.snapshotter.v1.overlayfs/snapshots/1000", "digest": "sha256:e3b0d67cfa3a37dfed187badc7766e3db64d492c4db2dc4260997b41af1b28f3", "size": 43446424 } ], "resultFile": "/home/overlaybd/1/result" } ``` | 字段 | 描述 | | --- | --- | | repoBlobUrl | 远程镜像的 repository blobs url。对于 registry 镜像是必填项。 | | lowers | 按从底层到顶层的顺序描述镜像底层(lower layers)的列表。 | | file | 表示相应的层是本地文件。如果使用本地文件,则不需要其他选项。 | | dir | 表示相应的层在下载后将存储在此目录中。 | | digest and size | 远程层的 digest 和大小。对于远程层是必填项。 | | resultFile | 用于保存失败原因的文件。如果设备成功启动,成功信息将写入该文件;否则,将通过此文件报告失败。 | #### 启动 以下是启动 overlaybd 镜像的示例。 首先,创建 overlaybd tcmu 设备。 ``` mkdir -p /sys/kernel/config/target/core/user_1/vol1 echo -n dev_config=overlaybd//root/config.v1.json > /sys/kernel/config/target/core/user_1/vol1/control echo -n 1 > /sys/kernel/config/target/core/user_1/vol1/enable ``` 然后,创建一个 tcm loop 设备。 ``` mkdir -p /sys/kernel/config/target/loopback/naa.123456789abcdef/tpgt_1/lun/lun_0 echo -n "naa.123456789abcdef" > /sys/kernel/config/target/loopback/naa.123456789abcdef/tpgt_1/nexus ln -s /sys/kernel/config/target/core/user_1/vol1 /sys/kernel/config/target/loopback/naa.123456789abcdef/tpgt_1/lun/lun_0/vol1 ``` 接着会生成一个块设备 `/dev/sdX`,overlaybd 镜像即可在本地使用。此外,overlaybd 设备还可以通过 iscsi 在远程主机上使用。 #### 清理 只需按相反的顺序删除 configfs 中的文件和目录即可。 #### 可写层 Overlaybd 提供了 log-structured 可写层和 sparse-file 可写层。log-structured 层是仅追加的,并将所有写入转换为顺序写入,从而使镜像构建/转换过程通常更快。sparse-file 可写层更适合容器运行时。 使用 `overlaybd-create` 创建可写层。 ``` /opt/overlaybd/bin/overlaybd-create ${data_file} ${index_file} ${virtual size} ``` 使用 `-s` 创建 sparse-file 可写层。 必须在 overlaybd 配置文件中设置 upper 选项才能使用可写层。只能有一个可写层,它始终作为顶层工作。示例: ``` { "repoBlobUrl": ..., "lowers" : [ ... ], "upper": { "index": "${index_file}", "data": "${data_file}" }, "resultFile": "/home/overlaybd/1/result" } ``` 如果设置了 upper,overlaybd 设备将作为可写设备启动。数据写入产生的差异将存储在 upper 的索引和数据文件中。 在写入数据并销毁设备后,需要执行 `overlaybd-commit` 命令将层提交为只读层,随后可作为底层使用。 ``` /opt/overlaybd/bin/overlaybd-commit ${data_file} ${index_file} ${commit_file} ``` 最后,可能需要进行压缩。 ``` /opt/overlaybd/bin/overlaybd-zfile ${commit_file} ${zfile} ``` 带有在线解压功能的 zfile 可作为底层使用。 ### 实时快照 Overlaybd 支持在不停止设备的情况下创建实时快照。此功能允许您捕获可写层的当前状态,并在其上方堆叠一个新的可写层。 #### 设备 ID 要使用实时快照功能,您需要在创建 overlaybd 设备时指定一个设备 ID。设备 ID 以分号分隔符附加到配置路径中: ``` echo -n dev_config=overlaybd//root/config.v1.json;123 > /sys/kernel/config/target/core/user_1/vol1/control ``` #### 启用 API 服务 将以下内容添加到您的 `overlaybd.json` 中: ``` "serviceConfig": { "enable": true, "address": "http://127.0.0.1:9862" } ``` #### 创建快照 向 `/snapshot` 端点发送一个 HTTP POST 请求: ``` curl -X POST "http://127.0.0.1:9862/snapshot?dev_id=123&config=/path/to/new_config.json" ``` 响应将采用 JSON 格式: ``` { "success": true, "message": "Snapshot created successfully" } ``` #### 新配置格式 新的配置文件应将当前的可写层作为最后一个底层包含在内: ``` { "lowers": [ { "file": "/opt/overlaybd/layer0" }, { "file": "/path/to/current_upper_data.lsmt" } ], "upper": { "index": "/path/to/new_upper_index.lsmt", "data": "/path/to/new_upper_data.lsmt" } } ``` **注意**:新的可写层必须与旧的可写层不同。 ## 内核模块 [DADI_kmod](https://github.com/data-accelerator/dadi-kernel-mod) 是 overlaybd 的一个内核模块。它可以将本地的 overlaybd 格式文件作为 loop 设备或 device-mapper 使用。 ## 贡献 欢迎贡献![CONTRIBUTING](CONTRIBUTING.md) ## 许可证 Overlaybd 在 Apache License, Version 2.0 下发布。
标签:Bash脚本, containerd, 块存储, 存储加速, 安全测试工具, 容器镜像, 按需加载, 虚拟块设备