openSUSE:原子和镜像更新的打包要求

跳转到:导航搜索

本文档描述了软件包符合 transactional-updatesystemd-sysext 以及 openSUSE 的快照和回滚功能的打包要求。

使用 transactional-update 的更新是原子的,这意味着,更新要么完全应用且没有错误,要么对系统不作任何更改。 此外,这种更新不应影响当前运行的进程。 如果更新失败,系统将看不到更新尝试,因此不会进行任何可见的更改,并且带有损坏更新的快照将被删除。 更新和所有更改仅在下次重新启动后可见,并且您始终可以重新启动到旧的快照以回滚更新所做的更改。 systemd-sysext 将带有额外软件(sysext-system 扩展)的镜像添加到正在运行的系统,这些镜像无需重新启动即可立即可见。 它们临时修改正在运行的系统,直到下次重新启动。

在所有情况下,RPM 格式的软件包都是起点。 这些软件包可以直接安装在系统中,或者可以从它们创建 OCI 镜像、文件系统镜像或 systemd-sysext 镜像,然后用于安装或更新系统。

定义

  • 镜像:如果本文档中使用“镜像”,则不是完整的磁盘原始镜像,而是分区的内容。 例如,镜像可能仅包含 /usr 的内容,如果 /usr 是自己的分区或 btrfs 子卷。 格式可以是原始分区、OCI 容器、tar 归档文件或类似格式。 镜像通常由 RPM 池构建。
  • hermetic-usr:操作系统资源(代码、数据文件等)应在不可变的 /usr 中保持hermetic。 这意味着 /usr 树应携带设置 /usr 之外的最小目录和文件集以使系统正常工作的一切。 然后可以将此 /usr 树以只读方式挂载到可写根文件系统,该文件系统最终将携带 /etc/var/home 中的本地配置、状态和用户数据。 有关所有详细信息和背景,请参阅 Fitting Everything Together
  • hermetic OS/usr 中全面定义:将 /usr 树与空的、否则未填充的根文件系统结合起来,它将成功启动,自动添加启动所必需的严格必要的文件和资源。

要求

对于 transactional-update,有两种方法可以安装系统和更新

  1. 通过 RPM
  2. 通过 OCI 容器(镜像)

OCI 镜像的要求比 RPM 更严格:RPM 可以具有 %pre/%post 脚本。 与在 Tumbleweed 或纯 SLES 上安装/更新时相比,它们的功能有限,但可以在快照内进行一些更改。 镜像(例如 OCI,但不仅限于此)没有 %pre/%post 脚本。 RPM 的脚本在构建镜像时在构建环境中运行,而不是在最终系统上运行。 因此,根本无法修改旧镜像的配置文件。 检查硬件的特殊功能是没有用的,因为最终系统将在不同的硬件上运行。

配置文件处理应遵循 配置文件的规范

用户数据和应用程序

用户数据和应用程序需要严格分离。 用户数据应位于主根子卷之外的另一个子卷中,应用程序应始终位于主根子卷中,而不是其他子卷中。 使用 /srv 在这方面是一个真正的问题:它包含应用程序、用户数据和配置文件混合在一起。 因此,它仅应由 ISV 和第三方供应商使用,而不应由分发商使用。

与 transactional-update 兼容的 RPM 的要求

  • 所有文件必须存储在快照内,在我们的例子中是 /etc/usr,而不是 /var/opt/srv/usr/local 或其他任何位置。
  • (重新)启动守护进程是不可能的。
  • 修改 /usr/etc 之外的文件是不可能的。
  • 遵循 配置文件的规范 是可选的,但首选,因为这也可以解决配置文件的几个更新问题(参见 openSUSE:Packaging UsrEtc
  • 必须通过 systemd-tmpfiles 和 systemd 服务进行快照外部的修改。
  • 不允许软件在任何时候修改系统只读部分中的文件。

基于镜像更新的要求

  • 与 RPM 相同的规则
  • 没有 %pre/%post 脚本用于更新,它们仅在构建镜像时在构建环境中运行。
  • 软件包内容限制为 /usr(不包括 /usr/local),对于 systemd-sysext,/opt 也可以使用。
  • 遵循 配置文件的规范 配置文件的规范是强制性的,或者安装/调整配置文件必须通过 systemd 服务的黑客手段完成。
  • 只能在下次启动时创建新的系统用户和组,所有文件应由 root:root 拥有。

由于 systemd-sysext 使用镜像,因此适用于基于镜像的更严格的规则(hermetic-usr)没有任何例外。

完美的软件包

对于 transactional-update 和构建镜像而言,完美的软件包是遵循 hermetic-usr、没有 %pre/%post 或类似脚本且所有文件都由 root:root 拥有的 RPM。 系统用户和组仅在运行时或在首次启动后存储数据时需要,因此,如果用户、组和 /usr 之外的目录/文件仅通过 sysusers.dtmpfiles.d 配置文件在下次重新启动时创建,则就足够了。

虽然许多软件包已经遵循 hermetic-usr 原则,但没有 %pre/%post 脚本会使许多 RPM 无法被 openSUSE Tumbleweed 或 SUSE Linux Enterprise Server 使用,因此无法用于传统的 Linux 发行版。 在这里,在软件包安装期间重新启动 systemd 服务、创建系统用户和执行 systemd-tmpfiles 的可能性是必要的。 为此,应使用 用于 systemd 的标准 RPM 宏,我们知道它们与 transactional-update 兼容。

一致性测试

  • 检查 RPM 文件列表,所有内容必须位于 /usr(和 /etc)中
  • 安装 RPM,检查 %pre/%post 脚本访问了哪些文件

可能的解决方案

/var 中的文件和目录

RPM 不应将文件打包到 /var 中,因为这些文件无法在软件包的安装、更新或删除期间创建、更新或删除。 更好的解决方案是使用 systemd-tmpfiles 创建这些文件

  • 将文件存储在 /usr/share/usr/lib 下的目录中
  • 创建一个 /usr/lib/tmpfiles.d/<package>.conf 文件,该文件将文件复制或链接到 /var

一个示例(摘自 ypserv)如下所示

ypserv.conf

  d /var/yp 0755 - - -
  L /var/yp/Makefile - - - - ../../usr/lib/yp/ypMakefile
  L /var/yp/securenets - - - - ../../usr/lib/yp/securenets.example

ypserv.spec

  %post
  %tmpfiles_create ypserv.conf

有关更多信息,请阅读 tmpfiles 配置文件格式的文档

pam-config 和 /etc/pam.d

pam-config 由几个 RPM 在 %post 脚本中调用,以将 PAM 模块添加到 PAM 配置。 这在镜像情况下是不可能的,可能的解决方案如下

  • /etc/pam.d 移动到 /usr/share/factory/pam.d
  • 创建一个 /usr/share/tmpfiles.d/pam.d.conf 文件

pam.d.conf

   L /etc/pam.d

这将通过 systemd-tmpfiles 创建一个 /etc/pam.d/usr/share/factory/pam.d 的符号链接。


fillup 和 /etc/sysconfig

有两种可能的解决方案:1. 将您的 sysconfig 文件转换为“默认”配置文件,这些文件也采用 shell 可解析的 KEY=VALUE 格式。 /usr/etc/default/<example> 包含 RPM/发行版提供的文件,/etc/default/<example> 可以由管理员创建并覆盖单个值。

2. 像在“/var 中的文件和目录”示例中使用 /usr/share/factory 和 systemd-tmpfiles 一样。

fillup 不适用于 systemd-sysext,也不适用于 systemd-tmpfiles 的上述解决方法。 因此,最好根本不要使用 fillup。

未解决的问题和其他限制

存在一些未解决的问题

  • 虽然 %set_permissions 和类似的宏在构建镜像时有效,但该功能在运行系统中不起作用,因为根文件系统是只读的,并且无法更改权限。

参考资料