使用 RHEL 的镜像模式构建、部署和管理操作系统


Red Hat Enterprise Linux 9

在 Red Hat Enterprise Linux 9 中使用 RHEL bootc 镜像

Red Hat Customer Content Services

摘要

RHEL bootc 镜像允许您构建、部署和管理操作系统,就像任何其他容器一样。您可以集中在单个容器原生工作流上,来管理从应用程序到底层操作系统的所有内容。

对红帽文档提供反馈

我们感谢您对我们文档的反馈。让我们了解如何改进它。

通过 Jira 提交反馈(需要帐户)

  1. 登录到 Jira 网站。
  2. 在顶部导航栏中点 Create
  3. Summary 字段中输入描述性标题。
  4. Description 字段中输入您对改进的建议。包括文档相关部分的链接。
  5. 点对话框底部的 Create

第 1 章 RHEL 的镜像模式简介

使用 RHEL 的镜像模式构建、测试,并使用与应用程序容器一样的工具和技术来部署操作系统。使用 registry.redhat.io/rhel9/rhel-bootc bootc 镜像可以使用 RHEL 的镜像模式。RHEL bootc 镜像与现有应用程序通用基础镜像(UBI)不同,它们包含通常排除的引导所需的其他组件,如内核、initrd、引导装载程序、固件等。

图 1.1. 使用 RHEL 的镜像模式构建、部署和管理操作系统

639 RHEL Bootable Container Bifrost 0524 1

红帽为以下计算机架构提供 bootc 镜像:

  • AMD 和 Intel 64 位体系架构 (x86-64-v2)
  • 64 位 ARM 架构(ARMv8.0-A)

RHEL 的镜像模式的好处贯穿于系统的整个生命周期。以下列表包含一些最重要的优点:

容器镜像比其他镜像格式更易于理解和使用,且可快速构建
Containerfiles,也称为 Dockerfile,提供了一种简单的方法来定义镜像的内容和构建指令。与其他镜像创建工具相比,构建和迭代容器镜像通常要快得多。
整合流程、基础架构和发布工件
因为您将应用程序作为容器分发,所以您可以使用同样的基础设施和流程来管理底层操作系统。
不可变的更新
正如容器化应用程序以不可变的方式更新一样,使用 RHEL 的镜像模式,操作系统也是如此。您可以以使用 rpm-ostree 系统的同样的方式引导到更新,并在需要时回滚。
警告

不支持使用 rpm-ostree 进行更改或安装内容。

跨混合云环境的可移植性
您可以在物理、虚拟化、云和边缘环境中使用引导镜像。

虽然容器为构建、传输和运行镜像提供基础,但在部署这些引导镜像后(使用安装机制),或者将它们转换为磁盘镜像非常重要,但系统不会作为容器运行。

支持的镜像类型 如下:

  • 容器镜像格式:OCI
  • 磁盘镜像格式:

    • ISO
    • QEMU copy-on-write (QCOW2), Raw
    • Amazon 机器镜像 (AMI)
    • 虚拟机镜像(VMI)
    • 虚拟机磁盘(VMDK)

容器通过提供以下可能性来简化 RHEL 系统的生命周期:

构建容器镜像
您可以通过修改 Containerfile 来在构建时配置操作系统。RHEL 的镜像模式可使用 registry.redhat.io/rhel9/rhel-bootc 容器镜像提供。您可以使用 Podman、OpenShift Container Platform 或其他标准容器构建工具来管理容器和容器镜像。您可以使用 CI/CD 管道自动化构建过程。
版本控制、镜像和测试容器镜像
您可以使用 Podman 或 OpenShift Container Platform 等任何容器工具版本、镜像、内省和签署您的派生的 bootc 镜像。
将容器镜像部署到目标环境中

有几个如何部署镜像的选项:

  • Anaconda: 是 RHEL 使用的安装程序。您可以使用 Anaconda 和 Kickstart 将所有镜像类型部署到目标环境中,以自动化安装过程。
  • bootc-image-builder :是一种容器化工具,它将容器镜像转换为不同类型的磁盘镜像,并可选择将它们上传到镜像注册中心或对象存储中。
  • bootc: 是一个负责从容器注册中心获取容器镜像,并将其安装到系统、更新操作系统,或从现有的基于 ostree 的系统进行切换的工具。RHEL bootc 镜像默认包含 bootc 工具,并可用于所有镜像类型。但是,请记住不支持 rpm-ostree,且不得用于进行更改。
更新您的操作系统
系统支持部署后带回滚的就地事务更新。默认情况下,自动更新是开启的。systemd 服务单元和 systemd 定时器单元文件检查容器注册中心中的更新,并将其应用到系统。由于更新是事务性的,所以需要重新启动。对于需要更复杂的或计划部署的环境,请禁用自动更新,并使用 bootc 工具更新您的操作系统。

RHEL 有两种部署模式。两者都在部署期间提供同样的稳定性、可靠性和性能。查看它们的不同:

  1. Package mode: 您可以使用 RHEL 镜像构建器构建基于软件包的镜像和 OSTree 镜像,您可以使用 composer-cli 或 web 控制台管理软件包模式镜像。操作系统使用 RPM 软件包,并使用 dnf 软件包管理器进行更新。root 文件系统是可变的。但是,操作系统不能作为容器化应用进行管理。请参阅 编写自定义的 RHEL 系统镜像 产品文档。
  2. 镜像模式 :一种构建、部署和管理 RHEL 的容器原生方法。同样的 RPM 软件包作为基础镜像提供,更新作为容器镜像部署。root 文件系统默认是不可变的,但 /etc/var 除外,大多数内容来自容器镜像。

您可以选择使用镜像模式或 Package mode 部署来构建、测试和共享您的操作系统。镜像模式 还允许您像任何其他容器化应用程序一样管理操作系统。

1.1. 先决条件

第 2 章 构建和测试 RHEL bootc 镜像

以下流程使用 Podman 来构建和测试您的容器镜像。您也可以使用其他工具,如 OpenShift Container Platform。有关使用容器配置 RHEL 系统的更多信息,请参阅 rhel-bootc-examples 存储库。

图 2.1. 使用 Containerfile 中的指令构建镜像,测试容器,将镜像推送到 registry,并与其他人共享

639 RHEL Bootable Container Bifrost 0524 2

通用 Containerfile 结构如下:

FROM registry.redhat.io/rhel9/rhel-bootc:latest

RUN dnf -y install [software] [dependencies] && dnf clean all

ADD [application]
ADD [configuration files]

RUN [config scripts]

可以在 ContainerfileDockerfile 中使用的命令一样。

但是,当将 rhel-9-bootc 镜像安装到系统时,Containerfile 中的以下命令会被忽略:

  • ENTRYPOINTCMD (OCI: Entrypoint/Cmd):您可以设置 CMD /sbin/init
  • ENV (OCI: Env): 更改 systemd 配置以配置全局系统环境。
  • EXPOSE (OCI: exposePorts):它独立于系统防火墙和运行时网络功能。
  • USER (OCI: User):配置 RHEL bootc 中的单个服务,以作为非特权用户运行。

rhel-9-bootc 容器镜像重复利用 OCI 镜像格式。

  • rhel-9-bootc 容器镜像在安装到系统时会忽略容器配置部分(Config )。
  • 当使用容器运行时(如 podmandocker )运行此镜像时,rhel-9-bootc 容器镜像不会忽略容器配置部分(Config)。
注意

此发行版本不支持构建自定义 rhel-bootc 基础镜像。

2.1. 构建容器镜像

使用 podman build 命令,使用 Containerfile 中的指令构建镜像。

先决条件

  • container-tools 元数据包已安装。

流程

  1. 创建 Containerfile

    $ cat Containerfile
    FROM registry.redhat.io/rhel9/rhel-bootc:latest
    RUN dnf -y install cloud-init && \
        ln -s ../cloud-init.target /usr/lib/systemd/system/default.target.wants && \
        dnf clean all

    这个 Containerfile 示例添加了 cloud-init 工具,因此它可以自动获取 SSH 密钥,并运行基础设施中的脚本,也可以从实例元数据中收集配置和 secret。例如,您可以将此容器镜像用于预生成的 AWS 或 KVM 客户机操作系统。

  2. 使用当前目录中的 Containerfile 构建 <image> 镜像:

    $ podman build -t quay.io/<namespace>/<image>:<tag> .

验证

  • 列出所有镜像:

    $ podman images
    REPOSITORY                                  TAG      IMAGE ID       CREATED              SIZE
    localhost/<image>                           latest   b28cd00741b3   About a minute ago   2.1 GB

2.2. 使用多阶段构建派生的可引导镜像

部署镜像应仅包含应用程序及其所需的运行时,而无需添加任何构建工具或不必要的库。要达到此目的,请使用两阶段 Containerfile: 一个阶段来构建工件,另一个用于托管应用程序。

使用多阶段构建时,您可以在 Containerfile 中使用多个 FROM 指令。每个 FROM 指令都可以使用不同的基础,每个基础都开始构建的新阶段。您可以选择将工件从一个阶段复制到另一个阶段,并排除您在最终镜像中不需要的所有内容。

多阶段构建提供了几个优点:

较小的镜像大小
通过将构建环境与运行时环境分开,最终镜像中仅包含必要的文件和依赖项,从而显著降低其大小。
提高了安全性
由于构建工具和不必要的库没有包括在最终镜像中,因此攻击面会减少,从而导致更安全的容器。
优化的性能
较小的镜像大小意味着更快地下载、部署和启动时间,从而提高了容器化应用的整体效率。
简化维护
当构建和运行时环境分隔时,最终镜像会更加干净,更易于维护,仅包含运行应用程序所需的内容。
清理构建
多阶段构建有助于避免中间文件出现问题,这些文件可能在构建过程中累积,确保只有基本工件使它成为最终镜像。
资源效率
在一个阶段构建并丢弃不必要的部分的功能,可以最大程度降低部署期间使用存储和带宽。
更好的层缓存
通过明确定义的阶段,Podman 可以通过加快将来的构建来有效地缓存之前阶段的结果。

以下 Containerfile 由两个阶段组成。第一个阶段通常命名为 builder,它编译了 golang 二进制文件。第二阶段从第一阶段复制 二进制文件。go-toolset 构建器的默认工作目录是 opt/ap-root/src

FROM registry.access.redhat.com/ubi9/go-toolset:latest as builder
RUN echo 'package main; import "fmt"; func main() { fmt.Println("hello world") }' > helloworld.go
RUN go build helloworld.go

FROM registry.redhat.io/rhel9/rhel-bootc:latest
COPY --from=builder /opt/app-root/src/helloworld /
CMD ["/helloworld"]

因此,最终的容器镜像包含 helloworld 二进制文件,但没有来自上一阶段的数据。

您还可以使用多阶段构建来执行以下操作:

在特定的构建阶段停止
在构建镜像时,您可以在指定的构建阶段停止。例如:
$ podman build --target build -t hello .

例如,您可以使用这种方法调试特定的构建阶段。

使用外部镜像作为阶段
您可以使用 COPY --from 指令从单独的镜像复制,使用本地镜像名称、本地可用的标签或容器 registry 中的标签 ID。例如:
COPY --from=<image> <source_path> <destination_path>_
使用前一个阶段作为新阶段
您可以使用 FROM 指令继续结束之前阶段的位置。示例:
FROM ubi9 AS stage1
[...]

FROM stage1 AS stage2
[...]

FROM ubi9 AS final-stage
[...]

2.3. 运行容器镜像

使用 podman run 命令运行并测试您的容器。

先决条件

  • container-tools 元数据包已安装。

流程

  • 根据 quay.io/<namespace>/<image>:<tag> 容器镜像运行名为 mybootc 的容器:

    $ podman run -it --rm --name mybootc quay.io/<namespace>/<image>:<tag> /bin/bash
    • -i 选项创建一个交互式会话。如果不使用 -t 选项,shell 将保持打开状态,但您无法对 shell 输入任何东西。
    • -t 选项打开一个终端会话。如果不使用 -i 选项,shell 会打开,然后退出。
    • 容器退出后,--rm 选项删除 quay.io/<namespace>/<image>:<tag> 容器镜像。

验证

  • 列出所有正在运行的容器:

    $ podman ps
    CONTAINER ID  IMAGE                                    COMMAND          CREATED        STATUS            PORTS   NAMES
    7ccd6001166e  quay.io/<namespace>/<image>:<tag>  /sbin/init  6 seconds ago  Up 5 seconds ago          mybootc

2.4. 将容器镜像推送到注册中心

使用 podman push 命令将镜像推送到您自己的或第三方注册中心,并与其他人共享。以下流程使用 Red Hat Quay 注册中心。

先决条件

  • container-tools 元数据包已安装。
  • 镜像在本地系统上构建并提供。
  • 您已创建了 Red Hat Quay 注册中心。如需更多信息,请参阅 概念验证 - 部署 Red Hat Quay

流程

  • quay.io/<namespace>/<image>:<tag> 容器镜像从本地存储推送到注册中心:

    $ podman push quay.io/<namespace>/<image>:<tag>

第 3 章 构建和管理逻辑绑定的镜像

通过使用逻辑绑定的镜像,您可以支持生命周期绑定到基本 bootc 镜像的容器镜像。这有助于为应用程序和操作系统划分不同的操作流程,容器镜像从基础镜像引用为镜像文件或等同。因此,您可以为系统安装管理多个容器镜像。您可以轻松将容器用于生命周期密集型工作负载,如安全代理和监控工具。通过使用 bootc upgrade 命令,您可以升级所有内容。

3.1. 逻辑绑定的镜像

逻辑地绑定的图像与物理绑定的图像不同。两种方法都提供了一些优点和缺点。

使用逻辑上绑定的镜像,将容器镜像与基础 bootc 系统镜像关联。以下是生命周期绑定工作负载的示例,其活动通常不会在主机外更新:

  • logging,如 journald→remote log forwarder 容器
  • 监控,如 Prometheus node_exporter
  • 配置管理代理
  • 安全代理

逻辑绑定镜像的另一重要属性是它们必须存在于主机上,可能来自引导过程的早期阶段。

与 Podman 或 Docker 等工具的默认使用不同,镜像可能会在引导启动后动态拉取,这需要可正常工作的网络。例如,如果远程 registry 临时不可用,主机系统可能会在不进行日志转发或监控的情况下运行,这并不是必须的。通过逻辑地绑定镜像,您可以像 systemd 单元中使用 ExecStart= 一样引用容器镜像。

逻辑绑定的镜像具有以下优点:

  • 您可以在不重新下载应用程序容器镜像的情况下更新 bootc 系统。
  • 您可以在不修改 bootc 系统镜像的情况下更新应用程序容器镜像,这对开发工作特别有用。

在使用逻辑上绑定的镜像时,您必须管理多个容器镜像以便系统安装逻辑绑定的镜像。这是一个优点,也是一个缺点。例如,对于断开连接或离线安装,您必须镜像所有容器,而不仅仅是一个。在此模型中,应用程序镜像仅从基础镜像引用为 .image 文件或等同文件。

bootc 升级由以下步骤组成:

  1. 获取新的基础镜像。
  2. 读取新的基础镜像 root 文件系统,以发现逻辑上绑定的镜像。
  3. 将任何发现的、逻辑绑定的镜像拉取到 bootc-owned /usr/lib/bootc/storage 中。

3.2. 使用逻辑绑定的镜像

每个逻辑上绑定的镜像都在 Podman Quadlet .image.container 文件中定义

先决条件

  • container-tools 元数据软件包已安装。

流程

  1. 创建 Containerfile

    $ cat Containerfile
    FROM quay.io/<namespace>/<image>:latest
    COPY ./<app_1>.image /usr/share/containers/systemd/<app_1>.image
    COPY ./<app_2>.container /usr/share/containers/systemd/<app_2>.container
    
    RUN ln -s /usr/share/containers/systemd/<app_1>.image /usr/lib/bootc/bound-images.d/<app_1>_image && \ ln -s /usr/share/containers/systemd/<app_2>_.image /usr/lib/bootc/bound-images.d/my-app.image
  2. .container 定义中,使用:

    GlobalArgs=--storage-opt=additionalimagestore=/usr/lib/bootc/storage

    在这个 Containerfile 示例中,通过在 /usr/lib/bootc/bound-images.d 目录中创建一个指向 .image.container 文件的符号链接,选择镜像以逻辑方式绑定。

    创建符号链接后,您可以使用 引导升级或 bootc 开关。新 bootc 镜像中定义的绑定镜像会自动拉取到 bootc 镜像存储中,并可用于 Podman 等容器运行时。

  3. 使用以下命令,明确将镜像配置为指向 bootc 存储作为额外镜像存储:

    podman --storage-opt=additionalimagestore=/usr/lib/bootc/storage run <image>

bootc-image-builder 作为技术预览提供,是一种容器化工具,可从 bootc 镜像创建磁盘镜像。您可以使用您构建的镜像来在不同的环境(如边缘、服务器和云)中部署磁盘镜像。

使用 bootc-image-builder 工具,您可以将 bootc 镜像转换为用于各种不同平台和格式的磁盘镜像。将 bootc 镜像转换为磁盘镜像等同于安装 bootc。将这些磁盘镜像部署到目标环境后,您可以直接从容器注册中心更新它们。

注意

此发行版本不支持使用 bootc-image-builder 构建来自私有注册中心的基本磁盘镜像。

bootc-image-builder 工具支持生成以下镜像类型:

  • 磁盘镜像格式,如 ISO,适用于断开连接的安装。
  • 虚拟磁盘镜像格式,例如:

    • QEMU copy-on-write (QCOW2)
    • Amazon 机器镜像(AMI)/— Raw
    • 虚拟机镜像(VMI)

运行虚拟机或服务器时从容器镜像部署是有好处的,因为您可以获得同样的安装结果。从同一容器镜像构建它们时,这种一致性可跨越多个不同镜像类型和平台。因此,您可以在平台间维护操作系统镜像时最小化工作量。您还可以使用 bootc 工具更新从这些磁盘镜像部署的系统,而不必使用 bootc-image-builder 重新创建和上传新磁盘镜像。

注意

通用基础容器镜像不包括任何默认密码或 SSH 密钥。另外,使用 bootc-image-builder 工具创建的磁盘镜像不包含通用磁盘镜像中提供的工具,如 cloud-init。这些磁盘镜像只是转换的容器镜像。

虽然您可以直接部署 rhel-9-bootc 镜像,但您也可以创建自己的从这个 bootc 镜像派生的自定义镜像。bootc-image-builder 工具使用 rhel-9-bootc OCI 容器镜像作为输入。

4.2. 安装 bootc-image-builder

bootc-image-builder 旨在用作容器,它不作为 RHEL 中的 RPM 软件包提供。要访问它,请按照以下流程操作。

先决条件

  • container-tools 元数据软件包已安装。元数据软件包包含所有容器工具,如 Podman、Buildah 和 Skopeo。
  • 您已认证到 registry.redhat.io。详情请参阅 红帽容器注册中心身份验证

流程

  1. 登录以认证到 registry.redhat.io

    $ sudo podman login registry.redhat.io
  2. 安装 bootc-image-builder 工具:

    $ sudo podman pull registry.redhat.io/rhel9/bootc-image-builder

验证

  • 列出拉取到本地系统的所有镜像:

    $ sudo podman images
    REPOSITORY                                    TAG         IMAGE ID      CREATED       SIZE
    registry.redhat.io/rhel9/bootc-image-builder  latest      b361f3e845ea  24 hours ago  676 MB

4.3. 使用 bootc-image-builder 创建 QCOW2 镜像

为您要运行命令的架构将 RHEL bootc 镜像构建到 QEMU 磁盘镜像(QCOW2)镜像中。

RHEL 基础镜像不包括默认用户。可选,您可以使用 --config 选项注入用户配置来运行 bootc-image-builder 容器。或者,您可以使用 cloud-init 配置基础镜像,以便在第一次引导时注入用户和 SSH 密钥。请参阅 用户和组配置 - 使用 cloud-init 注入用户和 SSH 密钥

先决条件

  • 您已在主机机器上安装了 Podman。
  • 您已在主机机器上安装了 virt-install
  • 您有运行 bootc-image-builder 工具的 root 访问权限,并在 --privileged 模式下运行容器,以构建镜像。

流程

  1. 可选:创建一个 config.toml 来配置用户访问,例如:

    [[customizations.user]]
    name = "user"
    password = "pass"
    key = "ssh-rsa AAA ... user@email.com"
    groups = ["wheel"]
  2. 运行 bootc-image-builder。另外,如果您想要使用用户访问配置,请将 config.toml 作为参数传递。

    注意

    如果您没有容器存储挂载和 本地镜像 选项,则您的镜像必须是公共镜像。

    1. 以下是创建公共 QCOW2 镜像的示例:

      $ sudo podman run \
          --rm \
          -it \
          --privileged \
          --pull=newer \
          --security-opt label=type:unconfined_t \
          -v ./config.toml:/config.toml \
          -v ./output:/output \
          registry.redhat.io/rhel9/bootc-image-builder:latest \
          --type qcow2 \
          --config /config.toml \
        quay.io/<namespace>/<image>:<tag>
    2. 以下是创建私有 QCOW2 镜像的示例:

      $ sudo podman run \
          --rm \
          -it \
          --privileged \
          --pull=newer \
          --security-opt label=type:unconfined_t \
          -v $(pwd)/config.toml:/config.toml:ro \
          -v $(pwd)/output:/output \
          -v /var/lib/containers/storage:/var/lib/containers/storage \
          registry.redhat.io/rhel9/bootc-image-builder:latest \
          --local
          --type qcow2 \
          quay.io/<namespace>/<image>:<tag>

      您可以在 output 文件夹中找到 .qcow2 镜像。

4.4. 使用 bootc-image-builder 创建 VMDK 镜像

从 bootc 镜像创建虚拟机磁盘(VMDK),并在 WMware 的虚拟化平台(如 vSphere)中使用它,或使用 VirtualBox 中的 Virtual Machine Disk (VMDK)。

先决条件

  • 您已在主机机器上安装了 Podman。
  • 您已使用 podman login registry.redhat.io 向 Red Hat Registry 进行身份验证。
  • 您已拉取 rhel9/bootc-image-builder 容器镜像。

流程

  1. 使用以下内容创建一个 Containerfile

    FROM registry.redhat.io/rhel9/rhel-bootc:9.4
    RUN dnf -y install cloud-init open-vm-tools && \
    ln -s ../cloud-init.target /usr/lib/systemd/system/default.target.wants && \
    rm -rf /var/{cache,log} /var/lib/{dnf,rhsm} && \
    systemctl enable vmtoolsd.service
  2. 构建 bootc 镜像:

    # podman build . -t localhost/rhel-bootc-vmdk
  3. 从之前创建的 bootc 镜像创建 VMDK 文件:

    # podman run \
    --rm \
    -it \
    --privileged \
    -v /var/lib/containers/storage:/var/lib/containers/storage \
    -v ./output:/output \
    --security-opt label=type:unconfined_t \
    --pull newer \
    registry.redhat.io/rhel9/bootc-image-builder:9.4
    --local \
    --type vmdk \
    localhost/rhel-bootc-vmdk:latest

    --local 选项使用本地容器存储来源原始镜像来生成 VMDK,而不是远程存储库。

bootc 镜像的 VMDK 磁盘文件存储在 output/vmdk 目录中。

4.5. 使用 bootc-image-builder 创建 GCE 镜像

为您要运行命令的架构将 RHEL bootc 镜像构建到 gce 镜像。RHEL 基础镜像不包括默认用户。可选,您可以使用 --config 选项注入用户配置来运行 bootc-image-builder 容器。或者,您可以使用 cloud-init 配置基础镜像,以便在第一次引导时注入用户和 SSH 密钥。请参阅 用户和组配置 - 使用 cloud-init 注入用户和 SSH 密钥

先决条件

  • 您已在主机机器上安装了 Podman。
  • 您有运行 bootc-image-builder 工具的 root 访问权限,并在 --privileged 模式下运行容器,以构建镜像。

流程

  1. 可选:创建一个 config.toml 来配置用户访问,例如:

    [[customizations.user]]
    name = "user"
    password = "pass"
    key = "ssh-rsa AAA ... user@email.com"
    groups = ["wheel"]
  2. 运行 bootc-image-builder。另外,如果您想要使用用户访问配置,请将 config.toml 作为参数传递。

    注意

    如果您没有容器存储挂载和 本地镜像 选项,则您的镜像必须是公共镜像。

    1. 以下是创建 gce 镜像的示例:

      $ sudo podman run \
          --rm \
          -it \
          --privileged \
          --pull=newer \
          --security-opt label=type:unconfined_t \
          -v ./config.toml:/config.toml \
          -v ./output:/output \
          registry.redhat.io/rhel9/bootc-image-builder:latest \
          --type gce \
          --config /config.toml \
        quay.io/<namespace>/<image>:<tag>

      您可以在输出文件夹中找到 gce 镜像。

从 bootc 镜像创建 Amazon Machine Image (AMI),并使用它来启动 Amazon Web Service EC2 (Amazon Elastic Compute Cloud)实例。

先决条件

  • 您已在主机机器上安装了 Podman。
  • AWS 帐户中有一个现有的 AWS S3 存储桶。
  • 您有运行 bootc-image-builder 工具的 root 访问权限,并在 --privileged 模式下运行容器,以构建镜像。
  • 您已在帐户中配置了 vmimport 服务角色,来将 AMI 导入到 AWS 帐户中。

流程

  1. 从 bootc 镜像创建磁盘镜像。

    • 在 Containerfile 中配置用户详情。确保为它分配了 sudo 访问权限。
    • 使用 Containerfile 配置中的用户构建一个自定义操作系统镜像。它会创建一个具有无密码 sudo 访问权限的默认用户。
  2. 可选:使用 cloud-init 配置机器镜像。请参阅 用户和组配置 - 使用 cloud-init 注入用户和 SSH 密钥。以下是一个示例:

    FROM registry.redhat.io/rhel9/rhel-bootc:9.4
    
    RUN dnf -y install cloud-init && \
        ln -s ../cloud-init.target /usr/lib/systemd/system/default.target.wants && \
        rm -rf /var/{cache,log} /var/lib/{dnf,rhsm}
    注意

    您还可以使用 cloud-init ,使用实例元数据添加用户和其他配置。

  3. 构建 bootc 镜像。例如,要将镜像部署到 x86_64 AWS 机器,请使用以下命令:

    $ podman build -t quay.io/<namespace>/<image>:<tag> .
    $ podman push quay.io/<namespace>/<image>:<tag> .
  4. 使用 bootc-image-builder 工具从 bootc 容器镜像创建一个 AMI。

    $ sudo podman run \
      --rm \
      -it \
      --privileged \
      --pull=newer \
      -v $HOME/.aws:/root/.aws:ro \
      --env AWS_PROFILE=default \
      registry.redhat.io/rhel9/bootc-image-builder:latest \
      --type ami \
      --aws-ami-name rhel-bootc-x86 \
      --aws-bucket rhel-bootc-bucket \
      --aws-region us-east-1 \
    quay.io/<namespace>/<image>:<tag>
    注意

    以下标记必须一起指定。如果没有指定任何标记,AMI 被导出到 output 目录中。

    • --AWS-ami-name - AWS 中 AMI 镜像的名称
    • --AWS-bucket - 创建 AMI 时中间存储的目标 S3 存储桶名称
    • --AWS-region - 用于AWS 上传的目标区域

      bootc-image-builder 工具构建一个 AMI 镜像,并使用 AWS 凭证将其上传到 AWS s3 存储桶,以便在构建后推送并注册一个 AMI 镜像。

后续步骤

其他资源

4.7. 使用 bootc-image-builder 创建原始磁盘镜像

您可以使用 bootc- image-builder 将 bootc 镜像转换为采用 MBR 或 GPT 分区表的 Raw 镜像。RHEL 基础镜像不包括默认用户,因此您可以选择使用 --config 选项运行 bootc-image-builder 容器来注入一个用户配置。或者,您可以使用 cloud-init 配置基础镜像,以便在第一次引导时注入用户和 SSH 密钥。请参阅 用户和组配置 - 使用 cloud-init 注入用户和 SSH 密钥

先决条件

  • 您已在主机机器上安装了 Podman。
  • 您有运行 bootc-image-builder 工具的 root 访问权限,并在 --privileged 模式下运行容器,以构建镜像。
  • 您已在容器存储中拉取了目标容器镜像。

流程

  1. 可选:创建一个 config.toml 来配置用户访问,例如:

    [[customizations.user]]
    name = "user"
    password = "pass"
    key = "ssh-rsa AAA ... user@email.com"
    groups = ["wheel"]
  2. 运行 bootc-image-builder。如果要使用用户访问配置,请将 config.toml 作为参数传递:

    $ sudo podman run \
        --rm \
        -it \
        --privileged \
        --pull=newer \
        --security-opt label=type:unconfined_t \
        -v /var/lib/containers/storage:/var/lib/containers/storage \
        -v ./config.toml:/config.toml \
        -v ./output:/output \
        registry.redhat.io/rhel9/bootc-image-builder:latest \
        --local \
        --type raw \
        --config /config.toml \
      quay.io/<namespace>/<image>:<tag>

    您可以在 output 文件夹中找到 .raw 镜像。

4.8. 使用 bootc-image-builder 创建 ISO 镜像

您可以使用 bootc-image-builder 创建一个 ISO,您可以从其执行一个可引导容器的离线部署。

先决条件

  • 您已在主机机器上安装了 Podman。
  • 您有运行 bootc-image-builder 工具的 root 访问权限,并在 --privileged 模式下运行容器,以构建镜像。

流程

  1. 可选:创建一个 config.toml 来配置用户访问,例如:

    [[customizations.user]]
    name = "user"
    password = "pass"
    key = "ssh-rsa AAA ... user@email.com"
    groups = ["wheel"]
  2. 运行 bootc-image-builder。如果您不想添加任何配置,请省略 the -v $(pwd)/config.toml:/config.toml 参数。

    $ sudo podman run \
        --rm \
        -it \
        --privileged \
        --pull=newer \
        --security-opt label=type:unconfined_t \
        -v /var/lib/containers/storage:/var/lib/containers/storage \
        -v $(pwd)/config.toml:/config.toml \
        -v $(pwd)/output:/output \
        registry.redhat.io/rhel9/bootc-image-builder:latest \
        --type iso \
        --config /config.toml \
      quay.io/<namespace>/<image>:<tag>

    您可以在 output 文件夹中找到 .iso 镜像。

您可以使用 Kickstart 文件配置安装过程的各个部分,如设置用户、自定义分区和添加 SSH 密钥。您可以在 ISO 构建中包含 Kickstart 文件来配置安装过程的任何部分,但部署基础镜像除外。对于使用 bootc 容器基础镜像的 ISO,您可以使用 Kickstart 文件配置除 ostreecontainer 命令以外的任何内容。

例如,您可以使用 Kickstart 执行部分安装、完整安装甚至省略用户创建。使用 bootc-image-builder 构建包含自定义 Kickstart 的 ISO 镜像来配置您的安装过程。

先决条件

  • 您已在主机机器上安装了 Podman。
  • 您有运行 bootc-image-builder 工具的 root 访问权限,并在 --privileged 模式下运行容器,以构建镜像。

流程

  1. 创建 Kickstart 文件。以下 Kickstart 文件是一个完全无人值守的 Kickstart 文件配置示例,其中包含用户创建和分区说明。

    [customizations.installer.kickstart]
    contents = """
    lang en_GB.UTF-8
    keyboard uk
    timezone CET
    
    user --name <user> --password <password> --plaintext --groups <groups>
    sshkey --username <user> ssh-<type> <public key>
    rootpw --lock
    
    zerombr
    clearpart --all --initlabel
    autopart --type=plain
    reboot --eject
    """
  2. toml 格式保存 Kickstart 配置,以注入 Kickstart 内容。例如,config.toml
  3. 运行 bootc-image-builder,并包含您要添加到 ISO 构建的 Kickstart 文件配置。bootc-image-builder 会自动添加安装 容器镜像的 ostree container 命令。

    $ sudo podman run \
        --rm \
        -it \
        --privileged \
        --pull=newer \
        --security-opt label=type:unconfined_t \
        -v /var/lib/containers/storage:/var/lib/containers/storage \
        -v $(pwd)/config.toml:/config.toml \
        -v $(pwd)/output:/output \
        registry.redhat.io/rhel9/bootc-image-builder:latest \
        --type iso \
        --config /config.toml \
      quay.io/<namespace>/<image>:<tag>

    您可以在 output 文件夹中找到 .iso 镜像。

4.10. 验证和故障排除

如果您在配置 AWS 镜像需求时遇到任何问题,请参阅以下文档
有关用户、组、SSH 密钥和 secret 的更多详细信息,请参阅

第 5 章 使用本地源运行容器的最佳实践

在运行 RHEL bootc 镜像时,您可以访问在需要自定义传输层安全(TLS)根证书的内部 registry 中托管的内容。

仅使用本地资源将内容安装到容器有两个选项:

  • 绑定挂载:使用 example -v /etc/pki:/etc/pki,使用主机的存储覆盖容器的存储。
  • 派生镜像:通过利用 Containerfile 构建它,使用自定义证书创建新的容器镜像。

在适当的时候,您可以使用相同的技术来运行 bootc-image-builder' 容器或 bootc 容器。

5.1. 使用绑定挂载将自定义证书导入到容器

使用绑定挂载,使用主机的存储覆盖容器的存储。

流程

  • 运行 RHEL bootc 镜像并使用 bind mount,如 example -v /etc/pki:/etc/pki,使用主机的存储覆盖容器的存储:

    # podman run \
      --rm \
      -it \
      --privileged \
      --pull=newer \
      --security-opt label=type:unconfined_t \
      -v $(pwd)/output:/output \
      -v /etc/pki:/etc/pki \
      localhost/<image> \
      --type iso \
      --config /config.toml \
      quay.io/<namespace>/<image>:<tag>

验证

  • 列出容器内的证书:

    # ls -l /etc/pki

5.2. 使用 Containerfile 将自定义证书导入到容器

使用 Containerfile 构建它,使用自定义证书创建新容器镜像。

流程

  1. 创建 Containerfile

    FROM <internal_repository>/<image>
    RUN  mkdir -p /etc/pki/ca-trust/extracted/pem/
    COPY tls-ca-bundle.pem /etc/pki/ca-trust/extracted/pem/
    RUN  rm -rf /etc/yum.repos.d/*
    COPY echo-rhel9_4.repo /etc/yum.repos.d/
  2. 构建自定义镜像:

    # podman build -t <your_image> .
  3. 运行 &lt ;your_image>:

    # podman run -it --rm <your_image>

验证

  • 列出容器内的证书:

    # ls -l /etc/pki/ca-trust/extracted/pem/
    tls-ca-bundle.pem

第 6 章 部署 RHEL bootc 镜像

您可以使用以下不同的机制来部署 rhel-bootc 容器镜像。

  • Anaconda
  • bootc-image-builder
  • bootc install

可用的 bootc 镜像类型如下:

  • 使用 bootc image-builder 生成的磁盘镜像,例如:

    • QCOW2 (QEMU copy-on-write、虚拟磁盘)
    • Raw (Mac 格式)
    • AMI (Amazon Cloud)
    • ISO:使用 USB 盘或 Install-on-boot 的无人值守安装方法。

创建可部署的分层的镜像后,有几种方法可将镜像安装到主机上:

  • 您可以使用以下机制,使用 RHEL 安装程序和 Kickstart 将分层的镜像安装到裸机系统:

    • 使用 USB 部署
    • PXE
  • 您还可以使用 bootc-image-builder 将容器镜像转换为 bootc 镜像,并将其部署到裸机或云环境中。

安装方法仅发生一次。部署镜像后,在更新发布时,将来的任何更新都将直接从容器注册中心应用。

图 6.1. 使用基本构建安装程序引导安装 或使用 Anaconda 和 Kickstart 部署容器镜像来部署 bootc 镜像

639 RHEL Bootable Container Bifrost 0524 3

图 6.2. 使用 bootc-image-builder 从 bootc 镜像创建磁盘镜像,并在不同的环境中部署磁盘镜像,如边缘、服务器和客户端,使用 Anaconda、bootc-image-builderbootc 安装

639 RHEL Bootable Container Bifrost 0524 4

使用 bootc-image-builder 工具从 RHEL bootc 镜像创建 QEMU 磁盘镜像后,您可以使用虚拟化软件来引导它。

先决条件

流程

验证

  • 连接到在其中运行容器镜像的虚拟机。如需了解更多详细信息,请参阅 连接到虚拟机

6.2. 使用 AMI 磁盘镜像将容器镜像部署到 AWS

在使用 bootc-image-builder 工具从 bootc 镜像创建 AMI 后,并将其上传到 AWS s3 存储桶后,您可以使用 AMI 磁盘镜像将容器镜像部署到 AWS。

先决条件

流程

  1. 在浏览器中,访问 Service→EC2 并登录。
  2. 在 AWS 控制台仪表盘菜单中,选择正确的地区。镜像必须具有 Available 状态,以表示它已被正确上传。
  3. 在 AWS 仪表盘上,选择您的镜像并点 Launch
  4. 在打开的新窗口中,根据您要启动镜像所需的资源来选择一个实例类型。点击 Review and Launch
  5. 查看您的实例详情。如果需要进行任何更改,您可以编辑任何部分。点 Launch
  6. 在启动实例之前,选择一个访问它的公钥。您可以使用您已有的密钥对,也可以创建一个新的密钥对。
  7. Launch Instance 来启动您的实例。您可以检查实例的状态,它显示为 Initializing

    实例状态变为 Running 后,Connect 按钮变为可用。

  8. Connect。此时会出现一个窗口,其中包含有关如何使用 SSH 进行连接的说明。
  9. 运行以下命令来设置私钥文件的权限,以便只有您可以读取它。请参阅 连接到您的 Linux 实例

    $ chmod 400 <your-instance-name.pem>
  10. 使用其公共 DNS 连接到您的实例:

    $ ssh -i <your-instance-name.pem>ec2-user@<your-instance-IP-address>
注意

除非停止它,否则您的实例继续运行。

验证

启动镜像后,您可以:

  • 尝试在浏览器中连接到 http://<your_instance_ip_address>
  • 检查在使用 SSH 连接到您的实例的过程中是否能够执行任何操作。

6.3. 使用 Anaconda 和 Kickstart 部署容器镜像

您可以使用 Anaconda 和 Kickstart 安装容器镜像,部署从红帽下载的 RHEL ISO 镜像。

警告

不支持使用 rpm-ostree 进行更改或安装内容。

先决条件

流程

  1. 创建一个 ostreecontainer Kickstart 文件。例如:

    # Basic setup
    text
    network --bootproto=dhcp --device=link --activate
    # Basic partitioning
    clearpart --all --initlabel --disklabel=gpt
    reqpart --add-boot
    part / --grow --fstype xfs
    
    # Reference the container image to install - The kickstart
    # has no %packages section. A container image is being installed.
    ostreecontainer --url registry.redhat.io/rhel9/rhel-bootc:9.4
    
    firewall --disabled
    services --enabled=sshd
    
    # Only inject a SSH key for root
    rootpw --iscrypted locked
    sshkey --username root "<your key here>"
    reboot
  2. 使用 9.4 Boot ISO 安装介质引导系统。

    1. 将具有以下内容的 Kickstart 文件附加到内核参数中:

      inst.ks=http://<path_to_your_kickstart>
  3. CTRL+X 引导系统。

6.4. 部署一个自定义 ISO 容器镜像

在使用 bootc-image-builder 构建 ISO 镜像后,生成的镜像是与 RHEL ISO 类似的系统,除了您的容器镜像内容嵌入到 ISO 磁盘镜像中。您不需要在安装过程中访问网络。您可以将生成的 ISO 磁盘镜像安装到裸机系统中。请参阅使用 bootc-image-builder 创建 ISO 镜像

先决条件

  • 您已创建了带有嵌入 bootc 镜像的 ISO 镜像。

流程

  1. 将您的 ISO 磁盘镜像复制到 USB 闪存驱动器中。
  2. 使用 USB 盘中的内容在断开连接的环境中执行裸机安装。

6.5. 通过 PXE 引导部署 ISO bootc 镜像

您可以使用网络安装通过 PXE 引导部署 RHEL ISO 镜像,以运行 ISO bootc 镜像。

先决条件

流程

  1. 将 RHEL 安装 ISO 镜像导出到 HTTP 服务器中。PXE 引导服务器现在可以提供 PXE 客户端。
  2. 引导客户端并开始安装。
  3. 当提示指定引导源时选择 PXE 引导。如果没有显示引导选项,请按键盘上的 Enter 键,或等待引导窗口打开。
  4. 在 Red Hat Enterprise Linux 引导窗口中,选择您想要的引导选项,然后按 Enter 键。
  5. 启动网络安装。

后续步骤

您可以使用 Containerfile 将配置注入到自定义镜像中。

流程

  1. 创建一个磁盘镜像。以下示例演示了如何将用户添加到磁盘镜像中。

    [[blueprint.customizations.user]]
    name = "user"
    password = "pass"
    key = "ssh-rsa AAA ... user@email.com"
    groups = ["wheel"]
    • Name - 用户名。必需
    • password - 未加密的密码。不是必需的
    • Key - SSH 公钥内容。不是必需的
    • groups - 要将用户添加到其中的组的数组。不是必需的
  2. 运行 bootc-image-builder ,并传递以下参数:

    $ sudo podman run \
        --rm \
        -it \
        --privileged \
        --pull=newer \
        --security-opt label=type:unconfined_t \
        -v $(pwd)/config.toml:/config.toml \
        -v $(pwd)/output:/output \
        registry.redhat.io/rhel9/bootc-image-builder:latest \
        --type qcow2 \
        --config config.toml \
        quay.io/<namespace>/<image>:<tag>
  3. 启动虚拟机,例如使用 virt-install

    $ sudo virt-install \
      --name bootc \
      --memory 4096 \
      --vcpus 2 \
      --disk qcow2/disk.qcow2 \
      --import \
      --os-variant rhel9

验证

  • 使用 SSH 访问系统:

    # ssh -i /<path_to_private_ssh-key> <user1>@<ip-address>

后续步骤

6.7. 使用 bootc 部署一个容器镜像

有了 bootc ,您就有了一个容器,它是真相的来源。它包含一个基本的构建安装程序,它作为 bootc install to-diskbootc install to-filesystem 提供。通过使用 bootc 安装方法,您不需要执行任何其他步骤来部署容器镜像,因为容器镜像包含一个基本的安装程序。

使用 RHEL 的镜像模式,您可以安装未配置的镜像,例如,没有默认密码或 SSH 密钥的镜像。

使用 RHEL ISO 镜像对设备执行裸机安装。

先决条件

  • 您已从红帽下载了用于您架构的 9.4 Boot ISO。请参阅 下载 RH 引导镜像
  • 您已创建了一个配置文件。

流程

  • 将配置注入正在运行的 ISO 镜像,例如:

    $ podman run --rm --privileged --pid=host -v /var/lib/containers:/var/lib/containers --security-opt label=type:unconfined_t <image> bootc install to-disk <path-to-disk>

6.8. 使用 to-filesystem 的高级安装

bootc install 包含两个子命令:bootc install to-diskbootc install to-filesystem

  • bootc-install-to-filesystem 执行到目标文件系统的安装。
  • bootc install to-disk 子命令包含一组固执己见的较低级别的工具,您可以单独调用它们。命令由以下工具组成:

    • mkfs.$fs /dev/disk
    • mount /dev/disk /mnt
    • bootc install to-filesystem --karg=root=UUID=<uuid of /mnt> --imgref $self /mnt

6.8.1. 使用 bootc install to-existing-root

bootc install to-existing-rootinstall to-filesystem 的一种变体。您可以使用它来将现有系统转换为目标容器镜像。

警告

这个转换删除了 /boot/boot/efi 分区,并可删除现有 Linux 安装。转换过程重复使用文件系统,即使已保留了用户数据,系统也不再以软件包模式引导。

先决条件

  • 您必须具有 root 权限才能完成这个流程。
  • 您必须匹配主机环境和目标容器版本,例如,如果您的主机是 RHEL 9 主机,则您必须有一个 RHEL 9 容器。使用 btrfs 在 Fedora 主机上安装 RHEL 容器,因为 RHEL 内核不支持该文件系统。

流程

  • 运行以下命令将现有系统转换为目标容器镜像。使用 -v /:/target 选项传递目标 rootfs

    # podman run --rm --privileged -v /dev:/dev -v /var/lib/containers:/var/lib/containers -v /:/target \
                --pid=host --security-opt label=type:unconfined_t \
                <image> \
                bootc install to-existing-root

    这个命令删除 /boot 中的数据,但现有操作系统中的所有其他内容不会被自动删除。这很有用,因为新镜像可以自动从以前的主机系统导入数据。因此,在 /sysroot 中后续重新启动后,容器镜像、数据库、用户主目录数据、/etc 中的配置文件都可用。

    您还可以通过添加 --root-ssh-authorized-keys /target/root/.ssh/authorized_keys 来使用 --root-ssh-authorized-keys 标志继承 root 用户 SSH 密钥。例如:

    # podman run --rm --privileged -v /dev:/dev -v /var/lib/containers:/var/lib/containers -v /:/target \
                --pid=host --security-opt label=type:unconfined_t \
                <image> \
                bootc install to-existing-root --root-ssh-authorized-keys /target/root/.ssh/authorized_keys

第 7 章 在构建 bootc 镜像时启用 FIPS 模式

FIPS 包括加密操作的标准。您可以在 bootc 镜像构建期间启用 FIPS 模式,在构建 bootc 镜像时启用 FIPS 模式,以将系统配置为只使用 FIPS 批准的模块。启用 FIPS 模式有两个选项:

  • 使用 bootc-image-builder 工具: 您必须将 FIPS 加密策略启用到 Containerfile 中。
  • 当执行 Anaconda 安装时:除了在 Containerfile 中启用 FIPS 加密策略外,还必须在引导时添加 fips=1 内核参数。

FIPS dracut 模块内置了基础镜像。默认为 boot=UUID= karg in bootc install-to-filesystem

7.1. 使用 bootc-image-builder 启用 FIPS 模式

使用 bootc-image-builderbootc install to-disk 创建磁盘镜像,并通过在构建镜像时将自定义 Containerfile 作为参数传递来启用 FIPS 模式。

先决条件

  • 您已在主机机器上安装了 Podman。
  • 您已在主机机器上安装了 virt-install
  • 您有运行 bootc-image-builder 工具的 root 访问权限,并在 --privileged 模式下运行容器,以构建镜像。

流程

  1. 创建一个 01-fips.toml 来配置 FIPS 启用,例如:

    # Enable FIPS
    kargs = ["fips=1"]
  2. 使用以下说明创建 Containerfile,以启用 fips=1 内核参数:

    FROM registry.redhat.io/rhel9/rhel-bootc:latest
    # Enable fips=1 kernel argument: https://containers.github.io/bootc/building/kernel-arguments.html
    COPY 01-fips.toml /usr/lib/bootc/kargs.d/
    # Enable the FIPS crypto policy
    # crypto-policies-scripts is not installed by default in RHEL-10
    RUN dnf install -y crypto-policies-scripts && update-crypto-policies --no-reload --set FIPS
  3. 使用当前目录中的 Containerfile 创建 bootc & lt;image> 兼容基本磁盘镜像:

    $ podman build -t quay.io/<namespace>/<image>:<tag> .

验证

  • 登录到系统后,检查是否启用了 FIPS 模式:

    $ *fips-mode-setup --check*
    FIPS mode is enabled.

7.2. 启用 FIPS 模式执行 Anaconda 安装

要创建磁盘镜像并在执行 Anaconda 安装时启用 FIPS 模式,请按照以下步骤执行:

先决条件

  • 您已在主机机器上安装了 Podman。
  • 您已在主机机器上安装了 virt-install
  • 您有运行 bootc-image-builder 工具的 root 访问权限,并在 --privileged 模式下运行容器,以构建镜像。

流程

  1. 创建一个 01-fips.toml 来配置 FIPS 启用,例如:

    # Enable FIPS
    kargs = ["fips=1"]
  2. 使用以下说明创建 Containerfile,以启用 fips=1 内核参数:

    FROM registry.redhat.io/rhel9/rhel-bootc:latest
    # Enable fips=1 kernel argument: https://containers.github.io/bootc/building/kernel-arguments.html
    COPY 01-fips.toml /usr/lib/bootc/kargs.d/
    # Install and enable the FIPS crypto policy
    RUN dnf install -y crypto-policies-scripts && update-crypto-policies --no-reload --set FIPS
  3. 使用当前目录中的 Containerfile 创建 bootc & lt;image> 兼容基本磁盘镜像:

    $ sudo podman run \
        --rm \
        -it \
        --privileged \
        --pull=newer \
        --security-opt label=type:unconfined_t \
        -v $(pwd)/config.toml:/config.toml:ro \
        -v $(pwd)/output:/output \
        -v /var/lib/containers/storage:/var/lib/containers/storage \
        registry.redhat.io/rhel9/bootc-image-builder:latest \
        --local
        --type qcow2 \
        quay.io/<namespace>/<image>:<tag>
  4. 在系统安装过程中启用 FIPS 模式:

    1. 引导 RHEL Anaconda 安装程序时,在安装屏幕上,按 TAB 键并添加 fips=1 内核参数。

      安装后,系统会自动以 FIPS 模式启动。

验证

  • 登录到系统后,检查是否启用了 FIPS 模式:

    $ *fips-mode-setup --check*
    FIPS mode is enabled.

第 8 章 管理 RHEL bootc 镜像

安装和部署 RHEL bootc 镜像后,您可以在容器镜像上执行管理操作,如更改或更新系统。系统支持部署后带回滚的就地事务更新。

这种管理(也称为第 2 天管理基线)包括从容器注册中心以事务方式获取新操作系统更新,并将系统引导到这些更新中,同时在出现故障时支持手动或自动回滚。

您还可以依赖自动更新,其默认是开启的。systemd 服务单元systemd 定时器单元 文件检查容器 registry 是否有更新,并将其应用到系统。您可以触发具有不同事件的更新过程,如更新应用程序。有自动化工具监视这些更新,然后触发 CI/CD 管道。需要重新启动,因为更新是事务性的。对于需要更复杂的或调度的推出部署的环境,您必须禁用自动更新,并使用 bootc 实用程序更新您的操作系统。

如需了解更多详细信息,请参阅 第 2 天操作支持

图 8.1. 手动更新安装的操作系统,根据需要更改容器镜像引用或回滚更改

639 RHEL Bootc Container Bifrost 0524 5

8.1. 切换容器镜像引用

您可以使用 bootc switch 命令更改用于升级的容器镜像引用。例如,您可以从 stage 切换到 production 标签。bootc switch 命令执行与 bootc upgrade 命令同样的操作,并额外更改容器镜像引用。

要手动切换现有的 基于 ostree 的 容器镜像引用,请使用 bootc switch 命令。

警告

不支持使用 rpm-ostree 进行更改或安装内容。

先决条件

  • 使用 bootc 引导的系统。

流程

  • 运行以下命令:

    $ bootc switch [--apply] quay.io/<namespace>/<image>:<tag>

    另外,当您要自动执行操作时,您可以使用 --apply 选项,如系统更改后的重启。

注意

bootc switch 命令的作用与 bootc 升级 相同。唯一的区别是容器镜像引用已更改。这允许在 /etc/var 中保留现有状态,例如主机 SSH 密钥和主目录。

8.2. 在 bootc 镜像 initramfs 中添加模块

rhel9/rhel-bootc 镜像使用 dracut 基础架构在镜像构建期间构建初始 RAM 磁盘( initrd )。initrd 构建并包含在容器内的 /usr/lib/modules/$kver/initramfs.img 位置。

您可以使用置入配置文件来覆盖 dracut 配置,并将其放在 /usr/lib/ dracut /dracut.conf.d/ <50-custom-added-modules.conf > 中,因此使用您要添加的模块重新创建 initrd

先决条件

  • 使用 bootc 引导的系统。

流程

  • 重新创建 initrd 作为容器构建的一部分:

    FROM <baseimage>
    COPY <50-custom-added-modules>.conf /usr/lib/dracut/dracut.conf.d
    RUN set -x; kver=$(cd /usr/lib/modules && echo *); dracut -vf /usr/lib/modules/$kver/initramfs.img $kver
    注意

    默认情况下,命令会尝试拉取正在运行的内核版本,这会导致错误。明确传递给 目标的 kernel 版本以避免出错。

8.3. 修改和重新生成 initrd

默认容器镜像在 /usr/lib/modules/$kver/initramfs.img 中包含预生成的初始 RAM 磁盘(initrd)。要重新生成 initrd,例如要添加 dracut 模块,请按照以下步骤执行:

流程

  1. 编写 drop-in 配置文件。例如:

    dracutmodules = "module"
  2. 将置入配置文件放在 dracut 通常使用的位置: /usr。例如:

    /usr/lib/dracut/dracut.conf.d/50-custom-added-modules.conf
  3. 作为容器构建的一部分,重新生成 initrd。您必须将内核版本明确传递给 dracut,因为它会尝试拉取运行的内核版本,这会导致错误。以下是一个示例:

    FROM <baseimage>
    COPY 50-custom-added-modules.conf /usr/lib/dracut/dracut.conf.d
    RUN set -x; kver=$(cd /usr/lib/modules && echo *); dracut -vf /usr/lib/modules/$kver/initramfs.img $kver

8.4. 从安装的操作系统执行手动更新

安装 RHEL 的镜像模式是一次性任务。您可以通过将更改推送到容器注册中心来执行任何其他管理任务,如更改或更新系统。

当使用 RHEL 的镜像模式时,您可以选择为您的系统执行手动更新。如果您有执行更新的自动化方法,如使用 Ansible,手动更新也很有用。由于默认启用了自动更新,要执行手动更新,您必须关闭自动更新。您可以选择以下选项之一来完成此操作:

  • 运行 bootc upgrade 命令
  • 修改 systemd 计时器文件

8.5. 关闭自动更新

要执行手动更新,您必须关闭自动更新。您可以选择以下流程中的选项之一来实现此目的。

流程

  • 禁用容器构建的计时器。

    • 通过运行 bootc upgrade 命令:

      $ systemctl mask bootc-fetch-apply-updates.timer
    • 通过修改 systemd 计时器文件。使用 systemd "drop-ins" 来覆盖计时器。在以下示例中,更新计划为每周一次。

      1. 使用以下内容创建一个 updates.conf 文件:

        [Timer]
        # Clear previous timers
        OnBootSec= OnBootSec=1w OnUnitInactiveSec=1w
      2. 将容器添加到您创建的文件中:

        $ mkdir -p /usr/lib/systemd/system/bootc-fetch-apply-updates.timer.d
        $ cp updates.conf /usr/lib/systemd/system/bootc-fetch-apply-updates.timer.d

8.6. 手动更新安装的操作系统

要手动从注册中心获取更新,并将系统引导至新更新,请使用 bootc upgrade。该命令将事务性就地更新从已安装的操作系统获取到容器镜像注册中心。命令查询注册中心,并为下一次启动将更新的容器镜像排队。它暂存对基础镜像的更改,而不是默认更改正在运行的系统。

流程

  • 运行以下命令:

    $ bootc upgrade [--apply]

    apply 参数是可选的,当要自动执行操作时,您可以使用它,比如系统更改后的重启。

注意

bootc upgradebootc update 命令是别名。

8.7. 从更新的操作系统执行回滚

您可以使用 bootc rollback 命令回滚以前的引导条目来还原更改。此命令通过将 rollback 下的部署排队等待下一个启动,来更改引导装载程序条目顺序。然后,当前部署变为回滚。所有已暂存的更改,如未应用的排队的升级,都被丢弃。

回滚完成后,系统会重启,更新计时器在 1 到 3 小时内运行,该小时会自动更新并将系统重启到您刚刚回滚的镜像。

警告

如果您执行回滚,系统将再次更新,除非您关闭自动更新。请参阅 关闭自动更新

先决条件

  • 您已对系统执行了更新。

流程

  • 运行以下命令:

    $ bootc rollback [-h|--help] [-V|--version]
注意

bootc rollback 命令的作用与 bootc 升级 相同。唯一的区别是被跟踪的容器镜像。这允许在 /etc/var 中保留现有状态,例如主机 SSH 密钥和主目录。

验证

  • 使用 systemd journal 来检查检测的回滚调用的日志消息。

    $ journalctl -b

    您可以看到类似如下的日志:

    MESSAGE_ID=26f3b1eb24464d12aa5e7b544a6b5468

8.8. 向系统组部署更新

您可以通过修改 Containerfile 来更改操作系统的配置。然后,您可以构建容器镜像并将其推送到注册中心。当您下次引导操作系统时,更新将被应用。

您还可以使用 bootc switch 命令更改容器镜像源。容器注册中心是数据源。请参阅 切换容器镜像参考

通常,在向系统组部署更新时,您可以使用中央管理服务来提供要安装在连接到中央服务的每个系统上的客户端。通常,管理服务要求客户端执行一次性注册。以下是如何将更新部署到系统组的一个示例。如果需要,您可以修改它来创建一个持久的 systemd 服务。

注意

为了清晰起见,示例中的 Containerfile 没有优化。例如,避免在镜像中创建多个层的一个好的优化是通过调用 RUN 一次。

您可以将客户端安装到 RHEL 镜像的镜像模式中,并在启动时运行它以注册系统。

先决条件

  • management-client 使用 cron 作业或单独的 systemd 服务处理未来的到服务器的连接。

流程

  • 创建一个具有以下特征的管理服务:它决定何时升级系统。

    1. 如果已包含在基础镜像中,请禁用 bootc-fetch-apply-updates.timer
    2. 使用 dnf 或适用于您客户端的一些其他方法安装客户端。
    3. 将管理服务的凭据注入到镜像中。

8.9. 检查清单健康状况

健康检查是第 2 天的操作之一。您可以手动检查容器镜像的系统健康状况和容器中运行的事件。

您可以通过在命令行上创建容器来设置健康检查。您可以使用 podman inspectpodman ps 命令显示容器的健康检查状态。

您可以使用 podman events 命令监控和输出 Podman 中发生的事件。如果适用,每个事件都包括时间戳、类型、状态、名称,以及镜像。

有关健康检查和事件的更多信息,请参阅监控容器 一章。

8.10. 自动化和 GitOps

您可以使用 CI/CD 管道自动化构建过程,以便更新过程可被事件触发,如更新一个应用程序。您可以使用自动化工具来跟踪这些更新并触发 CI/CD 管道。管道通过使用事务后台操作系统更新来保持系统最新。

8.11. 使用 Toolbx 检查 bootc 容器

在系统上安装软件存在一定的风险:它可以改变系统的行为,并在不再需要后留下不需要的文件和目录。您可以通过将您首选的开发和调试工具、编辑器和软件开发工具包(SDK)安装到 RHEL bootc 中包含的 Toolbx 实用程序中来防止这些风险,无需影响基础操作系统。您可以使用诸如 lesslsofrsyncsshsudounzip 等命令在主机系统上执行更改。

Toolbx 工具执行以下操作:

  1. registry.access.redhat.com/ubi9/toolbox:latest 镜像拉取到本地系统
  2. 从镜像启动容器
  3. 在容器内运行 shell,您可以通过它访问主机系统
注意

Toolbx 可以运行根容器或无根容器,具体取决于创建 Toolbx 容器的用户的权限。在主机系统上需要 root 权限的工具也应在 root 容器中运行。

默认容器名称是 rhel-toolbox。要检查 bootc 容器,请按照以下步骤执行:

流程

  1. 使用 toolbox create 命令启动 Toolbx 容器,并使用 toolbox enter 命令输入容器。

    • 以无根用户身份:

      $ toolbox create <mytoolbox>
    • 以 root 用户身份:

      $ sudo toolbox create <mytoolbox>
      Created container: <mytoolbox>
      Enter with: toolbox enter
    • 验证您是否拉取了正确的镜像:

      [user@toolbox ~]$ toolbox list
      IMAGE ID      IMAGE NAME    CREATED
      fe0ae375f149   registry.access.redhat.com/ubi{ProductVersion}/toolbox 5 weeks ago
      
      CONTAINER ID  CONTAINER NAME  CREATED         STATUS   IMAGE NAME
      5245b924c2cb  <mytoolbox>       7 minutes ago   created  registry.access.redhat.com/ubi{ProductVersion}/toolbox:8.9-6
      1. 进入 Toolbx 容器:

        [user@toolbox ~]$ toolbox enter <mytoolbox>
      2. 可选:检查是否拉取了正确的镜像
    • <mytoolbox> 容器中输入命令,并显示容器和镜像的名称:

      ⬢ [user@toolbox ~]$ cat /run/.containerenv
      engine="podman-4.8.2"
      name="<mytoolbox>"
      id="5245b924c2cb..."
      image="registry.access.redhat.com/ubi{ProductVersion}/toolbox"
      imageid="fe0ae375f14919cbc0596142e3aff22a70973a36e5a165c75a86ea7ec5d8d65c"
  2. 使用 Toolbx 安装开发工具:

    1. 安装您选择的工具,例如 Emacs 文本编辑器、GCC 编译器和 GNU 调试器 (GDB):

      ⬢[user@toolbox ~]$ sudo dnf install emacs gcc gdb
    2. 可选:验证是否安装了工具:

      ⬢[user@toolbox ~]$  dnf repoquery --info --installed <package_name>

      安装后,您可以继续以无根用户身份使用这些工具。

  3. 使用 Toolbx 对主机系统进行故障排除,而无需在主机系统上安装它们。

    1. 安装 systemd 套件,以便能够运行 journalctl 命令:

      ⬢[root@toolbox ~]# dnf install systemd
    2. 显示主机上运行的所有进程的日志消息:

      ⬢[root@toolbox ~]# j journalctl --boot -0
      Jan 02 09:06:48 user-thinkpadp1gen4i.brq.csb kernel: microcode: updated ear>
      Jan 02 09:06:48 user-thinkpadp1gen4i.brq.csb kernel: Linux version 6.6.8-10>
      Jan 02 09:06:48 user-thinkpadp1gen4i.brq.csb kernel: Command line: BOOT_IMA>
      Jan 02 09:06:48 user-thinkpadp1gen4i.brq.csb kernel: x86/split lock detecti>
      Jan 02 09:06:48 user-thinkpadp1gen4i.brq.csb kernel: BIOS-provided physical>
    3. 显示内核的日志消息:

      ⬢[root@toolbox ~]# journalctl --boot -0 --dmesg
      Jan 02 09:06:48 user-thinkpadp1gen4i.brq.csb kernel: microcode: updated ear>
      Jan 02 09:06:48 user-thinkpadp1gen4i.brq.csb kernel: Linux version 6.6.8-10>
      Jan 02 09:06:48 user-thinkpadp1gen4i.brq.csb kernel: Command line: BOOT_IMA>
      Jan 02 09:06:48 user-thinkpadp1gen4i.brq.csb kernel: x86/split lock detecti>
      Jan 02 09:06:48 user-thinkpadp1gen4i.brq.csb kernel: BIOS-provided physical>
      Jan 02 09:06:48 user-thinkpadp1gen4i.brq.csb kernel: BIOS-e820: [mem 0x0000>
    4. 安装 nmap 网络扫描工具:

      ⬢[root@toolbox ~]# dnf install nmap
    5. 扫描网络中的 IP 地址和端口:

      ⬢[root@toolbox ~]# nmap -sS scanme.nmap.org
      Starting Nmap 7.93 ( https://nmap.org ) at 2024-01-02 10:39 CET
      Stats: 0:01:01 elapsed; 0 hosts completed (0 up), 256 undergoing Ping Scan
      Ping Scan Timing: About 29.79% done; ETC: 10:43 (0:02:24 remaining)
      Nmap done: 256 IP addresses (0 hosts up) scanned in 206.45 seconds
      • -sS 选项执行 TCP SYN 扫描。大多数 Nmap 的扫描类型仅对特权用户提供,因为它们发送和接收原始数据包,这在 UNIX 系统上需要 root 访问权限。
  4. 停止 Toolbx bootc 容器。

    1. 离开容器,并返回到主机:

      ⬢ [user@toolbox ~]$ exit
    2. 停止 toolbox 容器:

      ⬢ [user@toolbox ~]$ podman stop <mytoolbox>
    3. 可选:删除 toolbox 容器:

      ⬢ [user@toolbox ~]$ toolbox rm <mytoolbox>

      或者,您也可以使用 podman rm 命令删除 bootc 容器。

第 9 章 在 bootc 系统中管理内核参数

您可以使用 bootc 来配置内核参数。默认情况下,bootc 使用存储在 /boot/loader/entries 中的引导装载程序配置文件。此目录定义提供给 Linux 内核的参数。一组内核参数是特定于机器的状态,但您也可以使用容器更新来管理内核参数。引导装载程序菜单条目在多个操作系统和引导装载程序间共享。

注意

目前,引导装载程序条目由 OSTree 后端编写。

9.1. 如何添加支持来使用 bootc 注入内核参数

bootc 工具使用通用操作系统内核。您可以通过以 TOML 格式添加自定义配置来注入内核参数,格式为 /usr/lib/bootc/kargs.d。例如:

# /usr/lib/bootc/kargs.d/10-example.toml
kargs = ["mitigations=auto,nosmt"]

您还可以使用 match-architectures 键使这些内核参数特定于架构。例如:

# /usr/lib/bootc/kargs.d/00-console.toml
kargs = ["console=ttyS0,114800n8"]
match-architectures = ["x86_64"]

9.2. 如何使用 bootc 安装配置修改内核参数

您可以使用以下方法在安装过程中使用 bootc install 添加内核参数:

  • 在容器镜像中添加内核参数。
  • 使用 bootc install --karg 命令添加内核参数。

您可以通过添加参数并在交换机、升级或编辑中应用这些参数,来在第 2 天操作中使用内核参数。添加内核参数并将其用于第 2 天操作涉及以下高级别步骤:

  1. 使用内核参数在 /usr/lib/bootc/kargs.d 中创建文件。
  2. 获取容器镜像以获取 OSTree 提交。
  3. 使用 OSTree 提交返回文件树。
  4. 导航到 /usr/lib/bootc/kargs.d
  5. 读取目录中每个文件。
  6. 将每个 kargs 文件的内容推送到包含所有所需 kargs 的文件中。
  7. kargs 传递给 stage () 函数。
  8. 应用这些参数以切换、升级或编辑。

9.3. 如何在 Containerfile 中注入内核参数

要在容器镜像中添加内核参数,请使用 Containerfile。以下是一个示例:

FROM registry.redhat.io/rhel9/rhel-bootc:latest

RUN mkdir -p /usr/lib/bootc/kargs.d
RUN cat <<EOF >> /usr/lib/bootc/kargs.d/console.toml
kargs = ["console=ttyS0,114800n8"]
match-architectures = ["x86_64"]
EOF

RUN cat <<EOF >> /usr/lib/bootc/kargs.d/01-mitigations.toml
kargs = ["mitigations=on", "systemd.unified_cgroup_hierarchy=0"]
match-architectures = ["x86_64", "aarch64"]
EOF

9.4. 如何在安装时注入内核参数

您可以在 a- karg 中使用 引导安装 来在安装过程中注入内核参数。因此,内核参数将变为 machine-local 状态。

例如,要注入内核参数,请使用以下命令:

# bootc install to-filesystem --karg
注意

目前,bootc 没有用于操作内核参数的 API。只有 rpm-ostree kargs 命令才支持 rpm-ostree。

bootc-image-builder 工具支持在安装过程中 custom.kernel.append

要使用 bootc-image-builder 添加内核参数,请使用以下自定义:

{
  "customizations": {
    "kernel": {
      "append": "mitigations=auto,nosmt"
    }
  }
}

9.6. 关于在安装后使用 kargs.d 更改内核参数

在安装后应用您对 kargs.d 文件并包含在容器构建中的更改,并将一组内核参数应用到当前的引导装载程序配置。这会保留任何本地机器内核参数。您可以使用任何工具来编辑 /boot/loader/entries 文件,这些文件采用标准化的格式。/boot 文件具有只读访问权限,用于限制可写入此文件系统的一组工具。

9.7. 如何在 bootc 系统中编辑内核参数

要执行机器本地更改,您还可以使用 rpm-ostree kargs 命令在 bootc 系统或 'rpm-ostree' 系统中编辑内核参数。更改通过 user/lib/bootc/kargs.d 路径进行,除了第一次引导更改之外,也会处理"Day 2"更改。

以下是可用于添加、修改或删除内核参数的选项。

rpm-ostree kargs [option]

--append=KEY=VALUE
附加内核参数。例如,它可用于多次使用的 console=。您可以将空值用于参数。
--replace=KEY=VALUE=NEWVALUE
替换现有的内核参数。只有在该参数已存在一个值时,才能将参数替换为 KEY=VALUE
--delete=KEY=VALUE
删除特定内核键值对或带有单个键值对的整个参数。
--append-if-missing=KEY=VALUE
附加内核参数。如果密钥已存在,则什么都不做。
--delete-if-present=KEY=VALUE
删除特定的内核键值对参数。缺少密钥时什么都不做。
--editor
使用编辑器修改内核参数。

如需更多信息,请检查帮助:

# rpm-ostree kargs --help

以下是一个示例:

# rpm-ostree kargs --append debug
Staging deployment... done
Freed: 40.1 MB (pkgcache branches: 0)
Changes queued for next boot. Run "systemctl reboot" to start a reboot

第 10 章 在 RHEL 的镜像模式中管理文件系统

目前,RHEL 的镜像模式使用 OSTree 作为后端,并默认为存储启用 composefs/opt/usr/local 路径是纯文本目录,而不是指向 /var 的符号链接。这可让您轻松在派生容器镜像中安装写入 /opt 中的第三方内容,例如:

10.1. 使用 /sysroot 的物理和虚拟 root

当系统被完全引导时,它与 chroot 类似,即操作系统更改当前运行的进程及其子项的明显根目录。物理主机根文件系统挂载到 /sysrootchroot 文件系统称为部署 root。

其余的文件系统路径是部署 root 的一部分,用作系统引导的最终目标。系统使用 ostree=kernel 参数来查找部署根。

/usr
这个文件系统会将所有操作系统内容保存在 /usr 中,目录(如 /bin )作为 /usr/bin 的符号链接。
注意

启用 composefs/usr/ 不同。这两个目录都是同一不可变镜像的一部分,因此您不需要使用 bootc 系统执行完整的 UsrMove

/usr/local
基础镜像被配置为使用 /usr/local 作为默认目录。
/etc

/etc 目录默认包含 mutable 持久状态,但它支持启用 etc.transient 配置选项。当目录处于可变持久性状态时,它会在升级过程中执行三向合并:

  • 使用新默认 /etc 作为基础
  • 将当前和之前的 /etc 之间的 diff 应用到新的 /etc 目录
  • 保留与 /etc 中相同部署的默认 /usr/etc 不同的本地修改文件。

ostree-finalize-staged.service 在创建新引导装载程序条目前在关闭过程中执行这些任务。

这是因为 Linux 系统的许多组件在 /etc 目录中提供默认配置文件。即使默认软件包没有提供,默认情况下,软件只检查 /etc 中的配置文件。非基于 bootc 镜像的、没有不同版本的 /etc 更新系统只在安装过程中填充,且不会在安装后随时更改。这会导致初始镜像版本影响 /etc 系统状态,并可能导致问题来应用更改,例如: /etc/sudoers.conf,需要外部干预。有关文件配置的详情,请参阅 构建和测试 RHEL bootc 镜像

/var
默认情况下,/var 目录中的内容是持久的。您还可以使 /var 或 子目录挂载点持久,无论是网络还是 tmpfs

只有一个 /var 目录。如果它不是不同的分区,则 /var 目录物理是绑定到 /ostree/deploy/$stateroot/var,并在可用的引导装载程序条目部署间共享。

默认情况下,/var 中的内容充当卷,即在初始安装过程中复制容器镜像中的内容,并在之后不会更新。

/var/etc 目录不同。您可以将 /etc 用于相对较小的配置文件,预期的配置文件通常绑定到 /usr 中的操作系统二进制文件。/var 目录有任意的大型数据,如系统日志、数据库和默认,如果操作系统状态被回滚,则不会回滚。

例如,进行 dnf downgrade postgresql 等更新不会影响 /var/lib/postgres 中的物理数据库。同样,进行 bootc 更新bootc 回滚 不会影响这个应用程序数据。

使用 /var 也会在应用新操作系统更新之前完全正常工作,即下载并就绪更新,但仅在重启时生效。同样适用于 Docker 卷,因为它将应用程序代码与其数据分离。

如果您希望应用程序具有预先创建的目录结构,例如 /var/lib/postgresql,则可以使用这个情况。为此,请使用 systemd tmpfiles.d。您还可以以单位使用 StateDirectory= &lt;directory& gt;。

其他目录
不支持在容器镜像中的 /run/proc 或其他 API Filesystems 中提供内容。除此之外,其他顶级目录(如 /usr/opt )与容器镜像相关联。
/opt
使用 composefsbootc 时,/opt 目录是只读的,以及其他顶级目录,如 /usr

当软件需要写入 /opt/exampleapp 中的其自己的目录时,常见的模式是使用要重定向到的符号链接,例如 /var 用于日志文件等操作:

RUN rmdir /opt/exampleapp/logs && ln -sr /var/log/exampleapp /opt/exampleapp/logs

另外,您可以将 systemd 单元配置为启动服务来动态进行这些挂载。例如:

BindPaths=/var/log/exampleapp:/opt/exampleapp/logs
启用临时 root
要默认启用完全临时可写 rootfs,请在 prepare-root.conf 中设置以下选项:
[root]
transient = true

这可让软件临时写入 /opt,对于必须保留的内容,到 /var 的符号链接。

10.2. 版本选择和引导

RHEL 的镜像模式默认使用 GRUB,但 s390x 架构除外。系统中当前可用的 RHEL 镜像模式的每个版本都有一个菜单条目。

菜单条目引用由 Linux 内核、initramfs 和链接到 OSTree 提交的哈希组成的 OSTree 部署,您可以使用 ostree=kernel 参数传递。

在启动过程中,OSTree 读取内核参数,以确定将哪些部署用作根文件系统。每次更新或更改系统(如软件包安装、添加内核参数)会创建一个新的部署。

这会启用在更新导致问题时回滚到以前的部署。

了解更多有关 RHEL 的镜像模式下用户、组、SSH 密钥和 secret 管理的信息。

11.1. 用户和组配置

RHEL 的镜像模式是通用操作系统更新和配置机制。您不能使用它来配置用户或组。唯一的例外是 bootc install 命令有 --root-ssh-authorized-keys 选项。

通用基础镜像的用户和组配置
通常,分发基础镜像没有任何配置。因为安全风险,不要在通用镜像中使用公开可用的私钥加密密码和 SSH 密钥。
通过 systemd 凭证注入 SSH 密钥
您可以使用 systemd 在某些环境中注入 root 密码或 SSH authorized_keys 文件。例如,使用系统管理 BIOS (SMBIOS)注入 SSH 密钥系统固件。您可以在本地虚拟化环境中配置这个,如 qemu
使用 cloud-init注入用户和 SSH 密钥
许多基础架构即服务(IaaS)和虚拟化系统使用通常由软件(如 cloud-initignition )处理的元数据服务器。请参阅 AWS 实例元数据。您使用的基础镜像可能包括 cloud-init 或 Ignition,或者您可以将其安装在您自己的派生镜像中。在这个模型中,SSH 配置在 bootc 镜像之外管理。
使用容器或单元自定义逻辑添加用户和凭证
cloud-init 等系统没有特权。您可以以您要启动容器镜像的方式注入您要管理凭证的任何逻辑,例如使用 systemd 单元。要管理凭据,您可以使用自定义网络托管的源,如 FreeIPA
在容器构建中静态添加用户和凭证

在面向软件包的系统中,您可以使用以下命令,使用派生的构建来注入用户和凭证:

RUN useradd someuser

您可以在 useradd 的默认 shadow-utils 实现中发现问题:用户和组 ID 是动态分配的,这可能导致偏移。

用户和组主目录,以及 /var 目录

对于使用持久性 /home → /var/home 配置的系统,在初始安装后,对容器镜像的 /var 所做的任何更改都不会应用到后续更新中。

例如,如果您将 /var/home/someuser/.ssh/authorized_keys 注入到一个容器构建中,则现有的系统不会获得更新的 authorized_keys 文件。

systemd 单元使用 DynamicUser=yes

对于系统用户,在可能的时候使用 systemd DynamicUser=yes 选项。

这比在软件包安装时分配用户或组的模式要好得多,因为它避免了潜在的 UID 或 GID 偏移。

使用 systemd-sysusers

例如,在派生的构建中使用 systemd-sysusers。如需更多信息,请参阅 systemd -sysusers 文档。

COPY mycustom-user.conf /usr/lib/sysusers.d

sysusers 工具在引导过程中根据需要更改传统的 /etc/passwd 文件。如果 /etc 是持久的,则这可以避免 UIDGID 偏移。这意味着 UIDGID 分配取决于特定机器随时间升级的方式。

使用 systemd JSON 用户记录
请参阅 JSON 用户记录 systemd 文档。与 sysusers 不同,这些用户的规范状态在 /usr 中。如果后续镜像删除了用户记录,则它也会从系统中消失。
使用 nss-altfiles

使用 nss-altfiles,您可以删除 systemd JSON 用户记录。它将系统用户分成 /usr/lib/passwd/usr/lib/group,与 OSTree 项目处理合并 /etc 的方式保持一致,因为它与 /etc/passwd 相关。目前,如果 /etc/passwd 文件在本地系统上以任何方式被修改,则不会在容器镜像中应用对 /etc/passwd 的后续更改。

rpm-ostree 构建的基础镜像默认启用了 nns-altfiles

另外,基础镜像有一个由 NSS 文件管理和预分配的系统用户,以避免 UID 或 GID 偏移。

在派生的容器构建中,您还可以将用户附加到 /usr/lib/passwd 中,例如:使用 sysusers.dDynamicUser=yes

用户的机器本地状态

文件系统布局取决于基础镜像。

默认情况下,用户数据存储在 /etc/etc/passwd/etc/shadowgroups 以及 /home中,具体取决于基础镜像。但是,通用基础镜像必须是机器本地持久状态。在此模型中,/home 是到 /var/home/user 的符号链接。

在系统置备时注入用户和 SSH 密钥

对于 /etc/var 被默认配置为持久的基础镜像,您可以使用 Anaconda 或 Kickstart 等安装程序注入用户。

通常,通用安装程序是为一次性 bootstrap 而设计的。然后,配置成为一个可变的机器本地状态,您可以使用一些其他机制在第 2 天操作中进行更改。

您可以使用 Anaconda 安装程序设置初始密码。但是,更改此初始密码需要不同的系统内工具,如 passwd

这些流在 bootc 兼容 系统中等效地工作,以支持用户直接安装通用基础镜像,而无需更改为不同的系统内工具。

临时主目录

许多操作系统部署最小化持久、可变和可执行状态。这可能会损坏用户主目录。

/home 目录可以被设置为 tmpfs,以确保用户数据在重启后被清除。当与临时 /etc 目录结合时,此方法工作得非常好。

要将用户的主目录设置为,例如,注入 SSH authorized_keys 或其他文件,请使用 systemd tmpfiles.d 片断:

f~ /home/user/.ssh/authorized_keys 600 user user - <base64 encoded data>

SSH 嵌入在镜像中,如:/usr/lib/tmpfiles.d/<username-keys.conf。另一个示例是嵌入在镜像中的服务,其可以从网络获取密钥并编写它们。这是 cloud-init 使用的模式。

UID 和 GID 偏移
/etc/passwd 和类似的文件是名称和数字标识符之间的映射。当映射是动态的,并与"无状态"容器镜像构建混合时,可能它可能会导致问题。每个容器镜像构建可能会因 RPM 安装顺序或其他原因而导致 UID 改变。如果该用户保持持久状态,则这可能是一个问题。要处理这种情况,请将其转换为使用 sysusers.d 或使用 DynamicUser=yes

11.2. 在 RHEL 的镜像模式下注入 secret

RHEL 的镜像模式没有用于 secret 的固执己见的机制。在某些情况下,您可以在系统中注入容器 pull secret,例如:

  • 要使 bootc 从需要身份验证的注册中心获取更新,您必须在文件中包含一个 pull secret。在以下示例中,creds secret 包含注册中心 pull secret。

    FROM registry.redhat.io/rhel9/bootc-image-builder:latest
    COPY containers-auth.conf /usr/lib/tmpfiles.d/link-podman-credentials.conf
    RUN --mount=type=secret,id=creds,required=true cp /run/secrets/creds /usr/lib/container-auth.json && \
        chmod 0600 /usr/lib/container-auth.json && \
        ln -sr /usr/lib/container-auth.json /etc/ostree/auth.json

    要构建它,请运行 podman build --secret id=creds,src=$HOME/.docker/config.json。使单个 pull secret 用于 bootc 和 Podman,方法是使用到容器镜像中嵌入的通用持久文件的两个位置的符号链接,如 /usr/lib/container-auth.json

  • 要让 Podman 获取容器镜像,请在 /etc/containers/auth.json 种包含一个 pull secret。使用这个配置,两个堆栈共享 /usr/lib/container-auth.json 文件。

    通过将它们嵌入到容器构建中来注入 secret
    如果注册中心服务器被适当保护,则您可以在容器镜像中包含 secret。在某些情况下,仅将 bootstrap secret 嵌入到容器镜像中是一种可行的模式,特别是在与让机器认证到集群的机制一起使用时。在此模式中,作为主机系统的一部分或容器镜像运行的置备工具使用 bootstrap secret 注入或更新其他 secret,如 SSH 密钥、证书等。
    使用云元数据注入 secret
    大多数生产基础设施即服务(IaaS)系统支持元数据服务器或等同的服务器,其可以安全地保护主机 secret,特别是 bootstrap secret。容器镜像可以包含 cloud-initignition 等工具来获取这些 secret。
    通过在磁盘镜像中嵌入 secret 来注入它们
    您只能在磁盘镜像中嵌入 bootstrap secret。例如,当您从一个输入容器镜像(如 AMI 或 OpenStack)生成一个云磁盘镜像时,磁盘镜像可以包含是有效的机器本地状态的 secret。轮转它们需要额外的管理工具或刷新磁盘镜像。
    使用裸机安装程序注入 secret
    安装程序工具通常支持通过 secret 注入配置。
    通过 systemd 凭证注入 secret
    systemd 项目有一个凭证概念,来确保获取凭证数据,并将其传递给系统和服务,这适用于某些部署方法。详情请查看 systemd 凭证 文档。

11.3. 配置容器 pull secret

要能够获取容器镜像,您必须使用"pull secret"配置主机系统,其中包括主机更新本身。如需了解更多详细信息,请参阅 RHEL 文档中的 在镜像模式中注入 secret 的附录。

您可以将容器 pull secret 配置为已构建镜像。如果您使用外部安装程序(如 Anaconda 用于裸机)或 bootc-image-builder,则必须使用任何适用的 pull secret 配置系统。

主机 bootc 更新将配置写入 /etc/ostree/auth.json 文件,该文件与 rpm-ostree 共享。

Podman 没有系统范围凭证。Podman 接受以下目录下的 containers-auth 位置:

  • /run: 这个目录的内容在重启后传播,这是不需要的。
  • /root: 属于 root 的主目录的一部分,默认为本地可可变状态。

要统一引导和 Podman 凭据,请为 bootc 和 Podman 使用单个默认全局 pull secret。以下容器构建是统一 bootc 和 Podman 凭据的示例。示例要求名为 creds 的 secret 包含要构建的 registry pull secret。

先决条件

  • 待定

流程

  1. bootc 和 Podman 之间创建一个符号链接以使用单个 pull secret。通过创建符号链接,您可以确保两个位置都存在于嵌入在容器镜像中的通用持久文件中。
  2. 创建 /usr/lib/container-auth.json 文件。

    FROM quay.io/<namespace>/<image>:_<tag>_
    COPY containers-auth.conf /usr/lib/tmpfiles.d/link-podman-credentials.conf
    RUN --mount=type=secret,id=creds,required=true cp /run/secrets/creds /usr/lib/container-auth.json && \
        chmod 0600 /usr/lib/container-auth.json && \
        ln -sr /usr/lib/container-auth.json /etc/ostree/auth.json

    运行 Containerfile 时,会出现以下操作:

    • Containerfile 使 /run/containers/0/auth.json 成为临时运行时文件。
    • 它创建一个指向 /usr/lib/container-auth.json 的符号链接。
    • 它还会创建一个持久文件,该文件也从 /etc/ostree/auth.json 链接。

11.4. 为 registry 注入 pull secret 并禁用 TLS

您可以为系统中的 registry 配置容器镜像、拉取 secret 和禁用 TLS。这些操作可让容器化环境从私有或不安全的 registry 中拉取镜像。

您可以包含容器 pull secret 和其他配置来访问基础镜像中的 registry。但是,在使用 Anaconda 安装时,安装环境可能需要重复的 "bootstrap" 配置副本以便在通过网络获取时访问目标 registry。

要在获取目标 bootc 容器镜像前对安装环境执行任意更改,您可以使用 Anaconda %pre 命令。

流程

  1. 配置 pull secret:

    %pre
    mkdir -p /etc/ostree
    cat > /etc/ostree/auth.json << 'EOF'
    {
            "auths": {
                    "quay.io": {
                            "auth": "<your secret here>"
                    }
            }
    }
    EOF
    %end

    使用这个配置,系统使用提供的身份验证凭据从 quay.io 拉取镜像,这些凭证存储在 /etc/ostree/auth.json 中。

  2. 为不安全的 registry 禁用 TLS:

    %pre
    mkdir -p /etc/containers/registries.conf.d/
    cat > /etc/containers/registries.conf.d/local-registry.conf << 'EOF'
    
    [[registry]]
    location="[IP_Address]:5000"
    insecure=true
    EOF
    %end

    使用这个配置,系统会从没有使用 TLS 保护的 registry 中拉取容器镜像。您可以在开发或内部网络中使用它。

您还可以使用 %pre 来:

  • 使用安装环境中所含的二进制文件,从网络获取数据,如 curl
  • 使用 update-ca-trust 命令将可信证书颁发机构注入到安装环境中 /etc/pki/ca-trust/source/anchors

您可以通过修改 /etc/containers 目录来配置不安全的 registry。

第 12 章 附录:系统配置

12.1. 临时运行时重新配置

您可以在基础镜像配置中执行动态重新配置。例如,您可以运行 firewall-cmd --permanent 命令,以便在重新引导后实现永久更改。

警告

默认情况下,/etc 目录具有持久性。如果您使用工具执行更改,如 firewall-cmd --permanent,系统上的 /etc 内容可能与容器镜像中描述的内容不同。

在默认配置中,首先在基础镜像中进行更改,然后在不重启运行系统的情况下对更改进行排队,然后同时写入,以仅将更改应用到内存中的现有系统。

您可以使用绑定挂载将 /etc 目录配置为临时。在这种情况下,etc 目录是计算机的本地根文件系统的一部分。例如,如果您使用 Anaconda kickstart 注入静态 IP 地址,它们会在升级之间保留。

在升级过程中应用三向合并,每个"部署"都有自己的 /etc 副本。

/run 目录
/run 目录是一个 API 文件系统,用于定义在系统重启时被删除。将 /run 目录用于临时文件。
动态重新配置模型
在 Pull 模型中,您可以使用 Podman API 包含直接嵌入在基础镜像中的代码或联系远程网络服务器的特权容器,然后使用 Podman API 启动额外的容器镜像。

在 Push 模型中,一些工作负载是通过 Ansible 等工具实现的。

systemd
您可以通过写入 /run/systemd 目录来使用 systemd 单元进行动态临时重新配置。例如,systemctl edit --runtime myservice.service 会动态更改 myservice.service 单元的配置,而不会持久更改。
NetworkManager
使用 /run/NetworkManager/conf.d 目录应用临时网络配置。使用 nmcli connection modify --temporary 命令,仅在内存中写入更改。如果没有- -临时 选项,命令会写入持久更改。
podman
使用 podman run --rm 命令在容器退出时自动移除容器。如果没有使用- rm 选项,podman run 命令会创建一个在系统重启后保留的容器。

12.2. 使用 dnf

rhel9/rhel-bootc 容器镜像包含 dnf。有几个用例:

使用 dnf 作为容器构建的一部分
您可以在 Containerfile 中使用 RUN dnf install 指令。
在运行时使用 dnf
警告

功能取决于 dnf 版本。您可能会得到一个 error: error: cannot not create transaction lock on /usr/share/rpm/.rpm.lock (Read-only file system)

您可以使用 bootc-usr-overlay 命令为 /usr 目录创建一个可写的覆盖文件系统。dnf install 写入此覆盖。您可以使用此功能安装调试工具。请注意,更改将在重新引导时丢失。

配置存储

支持的存储技术如下:

  • XFS/ext4
  • 逻辑卷管理(LVM)
  • Linux Unified Key Setup (LUKS)

您可以将其他存储软件包添加到主机系统。

  • 使用 bootc-image-builder 存储,您可以使用 bootc-image-builder 工具创建磁盘镜像。可用的分区和布局配置相对固定。默认文件系统类型派生自容器镜像的 bootc 安装配置。

带有 bootc install 的存储您可以使用 bootc install to-disk 命令进行扁平存储配置,并使用 bootc install to-filesytem 命令进行更高级的安装。如需更多信息,请参阅使用 to-filesystem进行高级安装

12.3. 设置主机名

要为您的系统设置自定义主机名,请修改 /etc/hostname 文件。您可以使用 Anaconda 或特权容器设置主机名。

引导系统后,您可以使用 hostnamectl 命令验证主机名。

12.4. 代理互联网访问

如果您要使用代理部署到需要访问互联网的环境,则需要配置服务以便它们可以根据需要访问资源。

这可以通过在您的配置中定义带有所需环境变量的单个文件,并通过对所有此类服务使用 systemd drop-in 单元文件来引用它。

定义通用代理环境变量
之后,需要访问互联网的每个服务都必须明确引用此通用文件。
# /etc/example-proxy.env
https_proxy="http://example.com:8080"
all_proxy="http://example.com:8080"
http_proxy="http://example.com:8080"
HTTP_PROXY="http://example.com:8080"
HTTPS_PROXY="http://example.com:8080"
no_proxy="*.example.com,127.0.0.1,0.0.0.0,localhost"
为核心服务定义置入单元
bootcpodman 工具通常需要代理配置。当前,bootc 并不总是作为 systemd 单元运行。
# /usr/lib/systemd/system/bootc-fetch-apply-updates.service.d/99-proxy.conf
[Service]
EnvironmentFile=/etc/example-proxy.env
为 podman systemd 单元定义代理使用

使用 Podman systemd 配置,类似添加 EnvironmentFile=/etc/example-proxy.env

您可以以 root 用户身份在 /etc/containers/containers.conf 配置文件中为 podman 和容器设置代理和环境设置,或者以非 root 用户身份在 $HOME/.config/containers/containers.conf 配置文件中设置配置。

第 13 章 附录:获取容器镜像的源代码

您可以在 红帽生态系统目录 中找到 bootc 镜像的源代码。

流程

  1. 访问 红帽生态系统目录并搜索 rhel-bootc
  2. Get this image 选项卡中,点 Get the source 并按照说明进行操作。
  3. 提取内容后,输入 RPM 软件包列表和其他内容资源在 extra_src_dir 目录中可用。

    .tar HEKETIles 是输入 git 存储库的快照,包含带有软件包列表的 YAML 文件。

第 14 章 附录:与上游项目相关的内容

您可以对以下上游 bootc 项目贡献:

法律通告

Copyright © 2024 Red Hat, Inc.
The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at http://creativecommons.org/licenses/by-sa/3.0/. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, the Red Hat logo, JBoss, OpenShift, Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent. Red Hat is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

关于红帽文档

Legal Notice

Theme

© 2026 Red Hat
返回顶部