4. 容器基础与ThinkSystem适配

在ThinkSystem上部署容器化负载之前,需要先厘清三个层次的概念:镜像(Image)、运行时(Runtime)与编排(Orchestration)。它们分别回答“运行什么”“用什么跑”“怎么调度和管”这三个问题。很多现场问题——例如容器启动慢、镜像拉取失败、Pod反复重启——根源往往不在应用本身,而在于这三层的适配关系没有理清。

镜像:分层只读模板与可写层

容器镜像是一个分层(Layer)的只读模板,每一层代表一次文件系统变更。以常见的 nginx:1.25 为例,它通常由基础操作系统层(如 debian 或 alpine)、依赖安装层、应用二进制层和配置层叠加而成。容器启动时,运行时会在镜像最上层叠加一个可写层(Container Layer),所有运行时写入都落在这一层,镜像本身保持不变。这种“写时复制(Copy-on-Write)”机制使得同一镜像可以同时启动多个容器实例,而磁盘占用只增加可写层的差异部分。

在ThinkSystem上,镜像存储默认位于 /var/lib/containerd 或 /var/lib/docker,具体取决于所选运行时。若服务器使用NVMe SSD作为系统盘,镜像层读取性能会明显优于SATA SSD;若使用HDD,则建议将镜像存储目录单独挂载到SSD分区,避免镜像拉取和解压成为瓶颈。可通过以下命令确认存储驱动与目录:

# containerd 环境
ctr plugins ls | grep -i snapshot
# Docker 环境
docker info | grep -i "storage driver"
df -h /var/lib/containerd /var/lib/docker

镜像命名遵循 [registry/]repository[:tag|@digest] 格式。生产环境建议使用 digest 而非浮动 tag,例如 registry.example.com/app@sha256:abc...,以确保每次拉取的都是同一份内容。ThinkSystem若处于内网环境,应提前配置私有Registry或镜像缓存节点,避免跨公网拉取导致超时。

运行时:从Docker到containerd与Podman

运行时是真正负责创建容器进程、挂载文件系统、配置cgroup和namespace的组件。当前主流选择有三类:Docker Engine、containerd 和 Podman。Docker Engine 自带 dockerd 守护进程和完整的CLI生态,适合开发与单机部署;containerd 是更轻量的底层运行时,Kubernetes 默认通过 CRI 接口调用它;Podman 则采用无守护进程(daemonless)架构,支持 rootless 模式,适合对安全隔离要求较高的场景。

在ThinkSystem上安装时,需注意操作系统版本与运行时版本的匹配。以 RHEL 9 / Rocky 9 为例,推荐通过官方仓库安装 containerd:

# 安装 containerd
dnf install -y containerd
# 生成默认配置
containerd config default > /etc/containerd/config.toml
# 启用 SystemdCgroup(K8s 环境必须)
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
systemctl enable --now containerd

若选择 Podman,安装后可直接以普通用户运行 rootless 容器,无需启动守护进程:

dnf install -y podman
podman run -d --name web -p 8080:80 nginx:1.25
podman ps
podman inspect web | grep -i cgroup

调优方面,ThinkSystem通常具备多核CPU和大内存,建议关注以下参数:containerd 的 max_concurrent_downloads 可适当提高以加速镜像拉取;snapshotter 若使用 overlayfs,需确认内核版本支持;Podman 的 --cgroup-manager=systemd 可让资源限制更精确。此外,若服务器启用了SELinux,需确保容器存储目录的上下文正确,否则会出现权限拒绝。

编排基础:从单机到集群的过渡

编排解决的是“多个容器如何协同、如何调度、如何自愈”的问题。单机场景下,Docker Compose 或 Podman Compose 已足够;多节点场景则需要 Kubernetes 或 Nomad 等编排系统。Kubernetes 通过 CRI 与 containerd 对接,通过 CNI 插件(如 Calico、Flannel)实现Pod网络,通过 CSI 插件对接ThinkSystem的存储资源。

在ThinkSystem上搭建Kubernetes集群时,建议先确认以下前置条件:关闭Swap、加载 br_netfilter 和 overlay 内核模块、设置 net.bridge.bridge-nf-call-iptables=1。这些步骤直接影响Pod网络和Service转发是否正常。一个常见的验证方式是部署一个测试Pod并检查其IP连通性:

kubectl run test --image=nginx:1.25 --port=80
kubectl get pod -o wide
kubectl exec -it test -- curl -s http://<pod-ip>

若Pod一直处于 ContainerCreating,通常需要检查CNI插件是否就绪、镜像是否拉取成功、以及节点资源是否充足。ThinkSystem的BMC日志和OS的 dmesg 也能提供底层线索,例如OOM Killer是否杀死了容器进程。

ThinkSystem 容器三层适配关系 编排层 Orchestration Kubernetes Docker Compose Podman Compose Nomad / 其他调度器 运行时层 Runtime containerd Docker Engine Podman (rootless) CRI-O / runc / crun 镜像层 Image 基础OS层 依赖/库层 应用二进制层 配置层 + 可写层 ThinkSystem 硬件 + OS 内核(cgroup / namespace / overlayfs / SELinux) 调度 / 自愈 / 服务发现 创建进程 / 挂载 / 隔离 分层只读 / 写时复制

安装与调优的关键检查点

无论选择哪种运行时,在ThinkSystem上完成安装后,建议按以下顺序验证:第一,确认内核模块已加载,lsmod | grep overlay 和 lsmod | grep br_netfilter 应有输出;第二,确认cgroup版本,stat -fc %T /sys/fs/cgroup 返回 cgroup2fs 表示cgroup v2;第三,运行一个最小容器并检查其资源限制是否生效,例如 docker run --rm --memory=256m alpine free -m 应显示约256MB内存上限。

若使用Kubernetes,还需确认kubelet的 --container-runtime-endpoint 指向正确的containerd socket(通常为 unix:///run/containerd/containerd.sock)。ThinkSystem若配置了多网卡,建议将Pod网络绑定到业务网卡,避免与管理网卡混用导致带宽争抢。存储方面,若使用本地NVMe,可通过Local PV方式提供给Pod;若使用SAN或NAS,则需部署对应的CSI驱动。

在ThinkSystem上做容器调优时,优先关注三件事:镜像存储是否落在SSD、cgroup v2是否启用、SELinux上下文是否正确。这三项覆盖了大多数“容器启动慢”和“权限拒绝”类问题。

最后需要强调的是,镜像、运行时和编排并非孤立的三层,而是通过标准接口逐层对接:编排层通过CRI调用运行时,运行时通过snapshotter管理镜像层,镜像层最终落在宿主机的文件系统上。理解这条链路,才能在出现问题时快速定位是镜像拉取、运行时配置还是编排调度环节出了偏差。