Please enable Javascript to view the contents

定制文件系统

 ·  ☕ 9 分钟

1. 重要

嵌入式领域,需要制作基于X86架构的文件系统定制方案。

文件系统主要包含以下三部分:

  • bootfs: 只包含linux内核的文件系统(包括grub)
  • rootfs: 除内核外的根文件系统
  • swfs: 自研软件

bootfs通过同一分区,存放多内核文件实现主备,软连接决定启动的内核。

rootfs通过A\B分区,实现主备,grub配置文件决定启动的根文件系统。

swfs通过A\B分区,实现主备,mount不同分区决定要运行的软件程序。

系统分区方案:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
磁盘、分区名称                  FS类型   大小  类型  挂载点
nvme0n1                                      disk 
├─nvme0n1p1                    vfat      1G  part  /boot/efi
├─nvme0n1p2                    ext4      2G  part  /boot
└─nvme0n1p3                    ext4  462.7G  part 
  ├─ubuntu--vg-ubuntu--lv      ext4    100G  lvm   /
  ├─ubuntu--vg-lv----b----root ext4    100G  lvm  
  ├─ubuntu--vg-lv--a--soft     ext4     10G  lvm  
  ├─ubuntu--vg-lv--b--soft     ext4     10G  lvm  
  ├─ubuntu--vg-lv--data        ext4    242G  lvm  
  └─ubuntu--vg-lv--sysconfig   ext4     20M  lvm  
  • boot分区只有一个nvme0n1p2,里面有内核、initrd、grub的配置文件。软链接的形式切换内核。
  • rootfs有A:ubuntu–vg-ubuntu–lv\B:ubuntu–vg-lv—-b—-root分区,通过grub配置文件中设置,加载哪个boot内核 + rootfs.
  • swfs有A:ubuntu–vg-lv–a–soft\B:ubuntu–vg-lv–b–soft软件分区。
  • userdatafs分区只有一个ubuntu–vg-lv–data, 软件生成的用户数据。
  • sysconfig分区只有一个ubuntu–vg-lv–sysconfig,存放SN MAC 环境变量等。

2. 需求

  1. 升级包制作:

    • 制作rootfs, 可dd至rootfs-A或rootfs-B分区,完成根文件系统安装,系统正常启动、驱动正常;
    • 制作bootfs, 可dd至bootfs-A或bootfs-B分区,完成内核安装,系统正常启动;
    • 制作userdatafs, 可dd至userdatafs-A或userdatafs-B分区,完成自研软件的安装,程序运行正常;
  2. 烧写包制作:基于启动盘,实现自动分区、安装操作系统(iso文件,由xorriso工具将bootfs、rootfs、userdatafs组合成一个完整的iso镜像)。

3. 升级包制作

3.1 rootfs制作方案

需要制作一个根文件系统,需要能打包软件运行环境,包括工具、驱动、环境配置。

3.1.1 Docker方案

3.1.1.1 基本介绍

docker是一个开源的应用容器引擎,允许开发者将应用及其依赖打包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上。docker可以用于构建、部署和运行任何软件,包括完整的Linux发行版。

3.1.1.2 使用场景

docker适用于以下场景:

  1. 快速部署应用和环境
  2. 创建隔离的开发和测试环境
  3. 微服务架构中的服务容器
  4. 系统镜像的快速构建和分发
3.1.1.3 使用流程

使用docker构建根文件系统的基本流程包括:

  1. 安装docker和相关工具
  2. 创建Dockerfile定义构建过程
  3. 构建镜像
  4. 运行容器进行测试
  5. 将环境commit镜像,并mount至制定目录
  6. mke2fs 命令将目录打包成二进制文件。
3.1.1.4 功能特点
  1. 内核兼容性:docker容器运行在主机内核之上,因此与主机内核版本(如Ubuntu 6.8.0-57-generic)高度兼容。docker容器的根文件系统是只读的,可以通过–read-only选项设置为"黄金镜像"。
  2. 镜像格式支持:docker支持多种镜像格式,但默认使用自己的镜像格式,可以通过docker save和docker load命令导出和导入镜像。docker还支持将镜像导出为tar格式,但不直接支持squashfs格式。
  3. 可定制性:docker通过Dockerfile提供高度可定制性,可以定义安装的包、环境变量、文件复制等操作。
  4. 资源占用:docker容器的资源占用相对较低,但相比debootstrap生成的系统稍大。
3.1.1.5 优缺点分析

优点:

  • 使用简单,有丰富的文档和社区支持
  • 可以快速创建和销毁环境
  • 镜像可以在不同系统间移植
  • 支持多阶段构建,优化镜像大小
  • 生态系统丰富,有大量预构建镜像缺点:
  • 对于嵌入式系统可能资源占用过高
  • 需要额外配置才能生成传统文件系统镜像
  • 默认不支持生成squashfs格式的镜像
  • 内核依赖于主机内核,不适合独立部署

问题:在第2步时,出现问题。nvidia驱动是制作成systemd服务的形式,但docker环境中没有systemd, 且环境兼容性没有debootstrap好,因此弃用此方案。

3.1.2 debootstrap方案

3.1.2.1 基本介绍

debootstrap是Debian/Ubuntu系统下用于构建基本根文件系统的工具。它可以在已安装的系统中创建另一个Debian基础系统,生成的目录符合Linux文件系统标准(FHS),包含/boot、/etc、/bin、/usr等标准目录结构。debootstrap生成的系统镜像体积相对较小,但功能强大,能够满足大多数基本系统需求。

3.1.2.2 使用场景

debootstrap适用于以下场景:

  1. 构建嵌入式系统根文件系统
  2. 创建轻量级Linux发行版
  3. 在不同架构上交叉编译和部署系统
  4. 快速创建测试环境
3.1.2.3 使用流程

使用debootstrap构建根文件系统的基本流程包括:

  1. 安装必要的工具和依赖(debootstrap)
  2. 创建目标目录
  3. 使用debootstrap下载基础系统包(不包含内核文件)
  4. 切换根文件系统,并挂载必要的虚拟文件系统
  5. 配置系统环境
  6. 安装必要的软件包
  7. 生成最终的根文件系统镜像
3.1.2.4 功能特点
  1. 内核兼容性:debootstrap生成的系统可以与多种内核版本兼容,包括Ubuntu 6.8.0-57-generic。根据搜索结果,debootstrap可以用于构建带有initramfs的系统,该initramfs可以被内核直接启动。
  2. 镜像格式支持:debootstrap本身不直接生成特定格式的镜像,但可以与mkfs工具结合生成各种格式的文件系统镜像,如ext2、ext4等。通过额外的脚本,也可以生成squashfs格式的镜像。
  3. 可定制性:debootstrap提供较高的可定制性,可以根据需求选择安装的包和软件,配置系统参数。
  4. 资源占用:相比完整发行版,debootstrap生成的系统占用更少的磁盘空间和系统资源。
3.1.2.5 优缺点分析

优点:

  • 可以创建符合FHS标准的最小化系统
  • 支持多种Linux发行版和架构
  • 可以通过apt-get命令管理软件包
  • 灵活性高,可以根据需求定制系统内容
  • 支持在不同架构上交叉编译系统缺点:
  • 学习曲线较陡,需要了解Linux系统结构
  • 配置过程相对复杂,需要手动挂载多个虚拟文件系统
  • 生成的系统可能缺乏某些预配置的实用工具

3.1.3 方案对比

debootstrapdockerpacker
内核兼容性依赖主机内核,生成的标准Linux系统与多种内核版本兼容依赖主机内核,docker容器运行在主机内核之上,与主机内核高度兼容自定义内核,packer构建的是完整的系统镜像,包括指定的内核,与指定的内核版本高度兼容
镜像格式支持原生支持ext2/ext3/ext4等,通过额外脚本支持squashfs通过将镜像mount到指定目录,达到debootstrap的效果原生支持多种格式(ISO、Vagrant、AMI等),不直接支持squashfs
资源占用低,生成的系统体积小,资源占用低中,容器有一定开销,但相对较低中高,构建完整系统镜像,资源占用相对较高,具体取决于镜像大小和复杂度
学习曲线中,需要了解Linux系统结构和文件系统低到中,有丰富的文档和社区支持,但需要了解容器概念中到高,配置相对复杂,需要了解packer的工作原理
适用场景嵌入式系统、轻量级系统、跨架构部署应用容器化、微服务部署、快速环境搭建云服务器镜像、标准化镜像、多平台部署
不太适用场景复杂的应用部署、快速迭代开发独立的系统部署、对内核有特殊要求的场景简单的系统构建、资源受限的环境

3.1.3 结论

基于内核的兼容性、以及嵌入式领域技术栈,选择debootstrap制作 rootfs 的方案。

4. 烧写包制作

5. 计划

步骤状态工时
rootfs制作完成;已完成24
iso自动化分区方案待开始24
iso 镜像制作待开始8
rootfs系统配置完成,并同步更新烧写包、升级包rootfs待开始8
升级包整体方案验证待开始8
搭建流水线待开始40

6. 风险项识别

6.1 整体风险

技术方案: 烧写包自动分区,后自动向指定分区写入grub, 以及boot的方案待调研。

环境安装:工具、驱动安装自动化程度不高,并且需要精简文件系统内容,抽离驱动编译开发环境。

内核打包: 归档自动化打包脚本。

grub自动切换方案:待落地验证,目前为手动操作, 直接修改/boot/grub/grub.cfg文件实现A\B 根文件系统的切换。

系统集成方案:需要端到端了解整个文件系统制作过程,将构建过程拆解,实现稳定、高效的自动化打包方案。

6.2 环境可移植(一致性)

初步想法,通过容器将打包环境固化下来(rootfs 可能无法做到,待尝试),再通过流水线脚本将镜像创建的过程自动化。

将rootfs bootfs swfs的制作拆开成单独流水线,烧写ISO镜像整合这3个产物,再集合。后期频繁变动的应该是swfs,因此rootfs、bootfs应该是取缓存产物即可。

6.3 硬件资源需求

CPU: 16C 主频越高越好

Memory: 16G

Disk: 100G+ 高性能IO

网络:无翻墙需求

6.4 技术选型维护难度

熟悉Linux文件系统,熟悉grub启动流程、配置文件修改,熟悉

7. 效果预期

其他

升级过程说明(临时手动过程)

暂作记录,不是升级时的最终方案

  1. 拿到rootfs后,通过 U盘启动盘进入shell环境,并将img文件dd至相应分区
  2. resize2fs 将目标分区 resize
  3. 修改/boot/grub/grub.conf, 设置加载内核的配置(注意 挂载的rootfs分区,需要rw权限)
  4. 重启
分享

Hex
作者
Hex
CloudNative Developer

目录