1. 课程导入与RHEL容器技术全景

欢迎进入《RHEL容器运行环境与应用交付》课程。在开始动手之前,我们需要先建立一张"技术地图":RHEL 上的容器并不是单一工具,而是一组职责清晰、可以互相替换又彼此协作的组件集合。理解它们各自"管什么、不管什么",是后续所有实验和排障工作的前提。

学习目标

完成本课程后,你应当能够:在 RHEL 9 上安装并验证 Podman、Buildah、Skopeo、CRI-O 等组件;使用无守护进程方式构建、传输和运行 OCI 镜像;通过 systemd 与 Quadlet 把容器纳入系统服务生命周期管理;理解从镜像构建到运行调度的完整交付链路,并能定位链路中任一环节的故障。本节的第一个任务,就是把这几个组件放进同一张关系图里看清楚。

核心组件与职责边界

RHEL 容器技术栈可以按"构建—传输—运行—编排—系统集成"五个动作来划分:

  • Buildah:负责构建镜像。它可以直接从 Containerfile 构建,也可以先创建容器、在容器内执行命令、再提交为镜像,适合脚本化和精细控制。
  • Skopeo:负责镜像的搬运与检查。它能在 registry、本地目录、docker-archive、OCI 布局之间复制镜像,并可在不下载完整镜像的情况下查看远端镜像的 manifest 和标签。
  • Podman:负责运行容器和 Pod。它是无守护进程(daemonless)的,直接以普通用户或 root 身份调用 runc/crun,支持 rootless 模式。
  • CRI-O:面向 Kubernetes 的容器运行时,实现 CRI 接口,被 kubelet 调用,负责 Pod 级别的容器生命周期。
  • systemd / Quadlet:负责把容器变成受系统管理的服务,实现开机自启、依赖顺序、重启策略和日志归集。

需要特别强调的是:Podman 与 CRI-O 都遵循 OCI 运行时规范,但服务对象不同——Podman 面向人和脚本,CRI-O 面向 kubelet。二者共享底层 runc/crun 与内核能力(namespaces、cgroups、SELinux),因此镜像格式和运行时行为保持一致。

RHEL 容器技术栈:从镜像构建到运行调度 Buildah 构建 OCI 镜像 Containerfile / 脚本 Skopeo 镜像搬运与检查 registry / dir / oci Podman 运行容器 / Pod rootless / daemonless CRI-O Kubernetes 运行时 CRI 接口 共享底层运行时:runc / crun + OCI 镜像规范 namespaces · cgroups v2 · SELinux · seccomp · capabilities systemd 集成层 Quadlet (.container / .pod) · podman generate systemd · 开机自启 · 重启策略 · journald 日志 将容器纳入系统服务生命周期,实现生产级可靠性 应用交付链路 源码 → Buildah 构建镜像 → Skopeo 推送 registry → Podman/CRI-O 拉取运行 → systemd 托管服务 构建 传输 运行 编排

容器与虚拟机:不是替代,而是不同抽象层

很多初学者会把容器理解为"轻量级虚拟机",这个类比在入门时有用,但会误导后续的架构判断。二者的关键差异在于抽象层次:

对比维度虚拟机容器
隔离对象硬件虚拟化,独立内核进程级隔离,共享宿主内核
启动时间秒级到分钟级毫秒级到秒级
镜像体积GB 级(含完整 OS)MB 级(仅应用与依赖)
资源开销每台 VM 固定内存/CPU 预留按进程实际使用,弹性共享
安全边界Hypervisor 硬件级隔离内核 namespaces + SELinux + seccomp
典型工具KVM、VMware、Hyper-VPodman、CRI-O、Docker

在 RHEL 上,容器安全依赖多层机制协同:SELinux 为容器进程打上 container_t 标签,限制其只能访问标记为 container_file_t 的文件;cgroups v2 控制 CPU、内存、IO 配额;seccomp 过滤危险系统调用;rootless 模式下普通用户通过 user namespace 映射获得容器内 root 权限,但宿主机上仍是普通用户。这些机制共同构成了"共享内核但互不越界"的边界。

应用交付的完整链路

把上述组件串起来,一条典型的 RHEL 应用交付链路如下:

  1. 开发者编写 Containerfile,用 buildah bud 构建镜像,得到本地 OCI 镜像。
  2. 用 skopeo copy 将镜像推送到内部 registry(如 Quay 或 Harbor),并可用 skopeo inspect 验证 manifest。
  3. 目标主机用 podman pull 拉取镜像,以 rootless 方式运行验证。
  4. 验证通过后,编写 Quadlet .container 文件,放入 ~/.config/containers/systemd/,执行 systemctl --user daemon-reload 并启动服务。
  5. 若部署到 Kubernetes,则由 kubelet 通过 CRI 调用 CRI-O 拉取同一镜像并调度运行。

这条链路的一个关键特性是镜像格式统一:Buildah 构建的 OCI 镜像,Skopeo 可以搬运,Podman 可以运行,CRI-O 也可以运行。这意味着同一份制品可以在开发机、测试环境和生产集群之间无缝流转,不需要为不同运行时重新打包。

学习建议:本课程后续章节会逐一深入每个组件。建议在阅读时始终把当前组件放回本节这张全景图中,问自己三个问题:它接收什么输入?它产生什么输出?它和上下游组件通过什么接口交互?这样能避免"会敲命令但不懂原理"的困境。

环境准备提示

后续实验建议在 RHEL 9.x 上进行,最小化安装即可。开始前可先确认基础环境:

# 确认系统版本与容器工具可用性
cat /etc/redhat-release
podman --version
buildah --version
skopeo --version

# 查看当前用户是否具备 rootless 运行条件
podman info --format '{{.Host.Security.Rootless}}'

如果 podman info 报错,通常需要检查 /etc/containers/registries.conf 中的镜像源配置,以及 subuid/subgid 是否为当前用户分配了足够的从属 UID/GID 范围。这些细节会在后续章节展开。

现在你已经有了整体图景:Buildah 管构建,Skopeo 管搬运,Podman 管运行,CRI-O 管 Kubernetes 运行时,systemd 管服务生命周期,底层共享 runc/crun 与内核隔离机制。接下来我们将从最基础的镜像构建开始,逐步把这张图上的每个节点变成你手中的实际能力。