Frood,一个 Alpine Initramfs NAS
我的 NAS,frood,有点奇怪的设置。它只是一个包含整个 Alpine Linux 系统的大型 initramfs。它令人愉快,我不明白为什么它不更常见。只要引导加载程序能找到内核和 initramfs,机器就能干净地启动。A/B 部署和回滚只是选择不同启动选项的问题。系统在构建 initramfs 的 git 仓库中以声明方式定义。对我来说重要的是,它并不是在某种复杂的 DSL 中定义的:如果我想让一个文件存在于 /etc/example.conf,我就把它放在 root/etc/example.conf,剩下的由我可以(也曾)阅读的几百行脚本来完成。配置它看起来与配置任何常规的 Alpine 系统没有什么不同。我可以通过一个 qemu 单行命令测试下一个部署。几乎没有活动组件。如果这听起来已经很吸引人,你可以跳到下面的“它是如何工作的”部分。但我总是喜欢从内存中运行系统的原因是:它很快且可以防止对系统存储设备的磨损,而系统存储设备通常是某个糟糕的 SD 卡,因为好的驱动器是专门用于 ZFS 池的。然而,你立即面临如何持久化配置更改的问题。Alpine 的解决方案是“无磁盘模式”,在此模式下,任何自定义都保存在一个 overlay 文件中。启动后,库存系统会在所有可用的文件系统中查找与 *.apkovl 匹配的文件,应用它,然后从本地缓存安装任何缺少的 apk 包。第一个问题是复杂性:生成和管理 apkovl 的工具 lbu(1) 非常好,但那个过程有很多活动组件。找到 apkovl,应用它,挂载新 fstab 中的文件系统,安装缺失的 apks,恢复启动过程。在过去的一年里,我多次遇到这个问题,要么是因为找不到文件系统,要么是因为没有安装 apks。启动过程依赖于包管理器!第二个问题是,我真的希望系统的状态能够在 git 中追踪。Graham Christensen 对声明式或不可变系统有一个非常好的提议 “Erase your darlings”。我在每次启动时都会清除我的系统。随着时间的推移,系统在其根分区上收集状态。这个状态生活在不同的目录(如 /etc 和 /var)中,代表着启动服务时每一步未被详细记录或顺序不正确的步骤。“对,运行 myapp-init。”这些小的、不重要的“哦,哦”步骤是最终丢失并且不会出现在你的运行手册中的部分。“只需下载 ca-certificates 到…来修复…”每一次快速修复都注定让你在三年后重蹈覆辙,当你最终进行那令人生畏的 RHEL 7 升级到 RHEL 8 时。“哦,touch /etc/ipsec.secrets,否则 l2tp 隧道将无法工作。”我过去通常通过 Ansible 进行(大多数)更改来解决这个问题,但随后我遇到了一个多层次的情况,我需要在 Ansible 中进行更改,然后进行部署,最后将其保存到 apkovl 的 lbu。在声明式系统中当然有许多替代方案:从 NixOS(听起来并不有趣)到 gokrazy(尚未准备好发布 ZFS)到像 buildroot 或更新的 u-root 这样的嵌入式工具链。不过,我真的很喜欢 Alpine:一个简单、打包良好、轻量级、没有 GNU 的 Linux 发行版。我不喜欢的是它的 init 和持久化机制。它是如何工作的 当它启动时,Linux 期望一个“initramfs”镜像。这是包含创建启动时第一个根文件系统所有文件的简单 cpio 存档。通常,这个系统的工作是加载足够的模块来挂载真实的 rootfs,然后切换到它。然而,我们没有什么阻止我们将整个系统放在里面!谁需要 rootfs? 构建 initramfs 起点是 alpine-make-rootfs,这是一个简短的(~500 行)脚本,用于构建容器镜像。它实际上占据了我们所需的 90%。 #!/bin/sh set -e wget https://raw.githubusercontent.com/alpinelinux/alpine-make-rootfs/v0.7.0/alpine-make-rootfs && echo 'e09b623054d06ea389f3a901fd85e64aa154ab3a alpine-make-rootfs' | sha1sum -c && chmod +x alpine-make-rootfs ROOTFS_DEST=$(mktemp -d) # 在 apk 安装期间停止 mkinitfs 的运行。 mkdir -p "$ROOTFS_DEST/etc/mkinitfs" echo "disable_trigger=yes" > "$ROOTFS_DEST/etc/mkinitfs/mkinitfs.conf" export ALPINE_BRANCH=edge export SCRIPT_CHROOT=yes export FS_SKEL_DIR=root export FS_SKEL_CHOWN=root:root PACKAGES="$(cat packages)" export PACKAGES ./alpine-make-rootfs "$ROOTFS_DEST" setup.sh alpine-make-rootfs 会从根目录复制文件,从 packages 文件中安装软件包,并在 chroot 中运行 setup.sh 脚本。然后,我们提取启动目录,并将其余内容打包成 initramfs 存档。 cd "$ROOTFS_DEST" mv boot "$IMAGE_DEST" find . | cpio -o -H newc | gzip > "$IMAGE_DEST/initramfs-lts" 这真的几乎就是全部了!令人印象深刻的是,Alpine 不需要几乎任何黑客就能做到这一点。 软件包 我们安装的软件包是您在服务器上通常会安装的常规东西。只有几个值得注意。 alpi
本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。
☕请我喝杯咖啡