当前位置: 首页 > article >正文

通过定制initramfs实现从单系统分区到双系统的无缝升级

背景

我们的客户有一些本地部署的网关设备(CentOS 7)需要做固件升级。 原有的单系统分区架构缺乏有效的回滚机制, 升级遇到故障后无法回滚, 导致服务中断, 用户体验差

目标

设计一种解决方案, 自动将客户的网关设备从单系统分区平滑升级到双系统,同时保证用户配置(IP, DNS, 登录口令)不丢失
整个升级过程对客户完全透明, 无需客户进行额外操作(比如添加磁盘, 创建新机器)

方案

方案描述优点缺点
定制initramfs通过定制initramfs进入紧急模式,预先加载升级包和配置文件到内存,再重建磁盘分区用户无感知, 且备份了旧的配置内存空间有限, 升级包+解压后系统文件需小于内存
安装ISO下载并安装目标系统ISO不需要单独出一个升级包客户的配置很难同步, 升级后需要用户做一些手动配置

最终采用定制initramfs方案。 客户虚拟机内存最低配置是8G, 需保证initramfs阶段的升级包+解压后系统文件小于8G
测试结果: c7最小化镜像900M, 安装后磁盘占用1.3G; 安装Microk8s后磁盘占用3G左右, 升级包1.7G, initramfs用掉4G内存, 远小于8G, 可行

实现

在这里插入图片描述

目标系统分区设计

# lsblk
NAME         MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda            8:0    0   10G  0 disk
├─sda1         8:1    0    2M  0 part
├─sda2         8:2    0    1G  0 part /boot
└─sda3         8:3    0  8.8G  0 part
  ├─VA-root  253:0    0  7.8G  0 lvm  /
  ├─VA-image 253:1    0  512M  0 lvm  /image
  └─VA-data  253:2    0  512M  0 lvm  /data

升级包设计

内容描述
目标系统的分区表文件(sgdisk)使用sgdisk导出的新系统的分区表文件,支持双系统启动
目标系统文件的压缩包(.tar.xz)把虚拟机导出到OVA,再把VMDK根文件系统中所有文件备份成压缩包
initramfs-convert.img基于官方ISO的initramfs定制
vmlinuz-convert一个压缩内核, 直接从官方ISO取
upgrade.sh二阶段执行, 一阶段在客户机上执行, 下载升级包, 进入紧急模式; 二阶段在initramfs执行, 完成分区重建, 安装和启动目标系统

实现细节:

  • 分区方案采用BIOS/GPT, BIOS是为了兼容老客户, GPT可以支持2T以上磁盘, 可扩展性和性能更好
  • tar备份目标系统时, 需要--numeric-owner保留文件的UID/GID, 以及文件扩展属性xattr(有snap的应用运行状态)

难点

initramfs空间有限, 需要尽可能压缩升级包

  • 使用CentOS 7官方的minimal ISO做镜像(900M)
  • 只分配必要磁盘空间, 等客户升级成功后动态分配剩余空间, 使升级包尽可能做小
  • 导出OVA前, 清理临时文件,日志文件, 禁用交换分区
  • 使用压缩比率高的压缩算法(xz)

调试方法

1.手动进入GRUB rescue模式加载内核, 手动挂载磁盘根分区,查看失败日志

set root=(hd0,gpt2)
linux (hd0,gpt2)/vmlinuz-convert root=/dev/mapper/VA-root ro rd.lvm.lv=VA/root
initrd (hd0,gpt2)/initramfs-convert.img

2.先对虚拟机做快照, 如果调试失败通过快照迅速恢复系统

调试问题

Q: 切换到新系统后, 输入正确的用户名和密码也无法登录, console一直打印localhost login
A: 通过手动进入GRUB rescue模式调试, 挂载磁盘日志发现是SELinux的问题, 将目标系统的SELinux设置为disabled后,问题得到解决


http://www.kler.cn/a/578480.html

相关文章:

  • 手抖护理全攻略:从生活点滴改善症状
  • AI 智能:开拓未知疆域的科技先锋
  • 11-Agent中配置自己的插件
  • 芋道源码 —— Spring Boot 缓存 Cache 入门
  • 搭建农产品管理可视化,助力农业智能化
  • scala函数的至简原则
  • Android Retrofit + RxJava + OkHttp 网络请求高效封装方案
  • 线性表相关代码(顺序表+单链表)
  • C++蓝桥杯基础篇(九)
  • UE4 World, Level, LevelStreaming从入门到深入
  • 【Linux系统编程】初识系统编程
  • RMAN备份bug-审计日志暴涨(select action from gv$session)
  • ECC升级到S/4 HANA的功能差异 物料、采购、库存管理对比指南
  • 软件网络安全测试用例
  • 【深度学习】Pytorch:更换激活函数
  • docker-compose Install reranker(fastgpt支持) GPU模式
  • 阿里云扩容操作步骤
  • 云效、流水线、Gradle缓存问题、build.gradle配置snapshot
  • 从0开始的操作系统手搓教程28:实现Syscall架构体系
  • 8.大模型微调学习案例:基于 Hugging Face、8位量化与 LoRA 适配器的方案