ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

iSulad轻量级容器引擎在OpenEuler上的部署实践

iSulad轻量级容器引擎在OpenEuler上的部署实践 装容器引擎第一反应基本都是Docker但如果你用的是OpenEuler尤其是对资源敏感、想走国产化路线的环境其实还有另一个更贴合的选项——iSulad。iSulad是OpenEuler社区孵化的轻量级容器引擎兼容OCI和CRI规范尺寸小、启动快C语言实现依赖比Docker少得多。这篇实践手册是我自己从零到一把iSulad在OpenEuler上跑起来的完整记录包括环境准备、仓库配置、镜像拉取、第一个容器、命令对照、常见坑点以及和Docker混用时的注意事项。适合刚接触OpenEuler、想尝试非Docker方案的人也适合需要在边缘或受限环境里做容器化的朋友参考。1. 为什么选iSulad轻量容器引擎的定位与价值1.1 iSulad到底解决什么问题很多人第一次听说iSulad都会问一句有Docker不用为什么折腾这个答案其实在OpenEuler的设计目标里。OpenEuler面向的是服务器、边缘计算、嵌入式多种场景Docker虽然功能全但对运行环境的依赖比较重——需要dockerd、containerd、runc、networking等一堆组件协作在资源受限的设备上光是常驻内存就不是一笔小开销。iSulad的设计思路是从头做一个精简的容器引擎核心功能走OCI标准上层接口兼容CRI但内部实现不做Docker那套过度设计。它不依赖Docker守护进程那种大而全的体系而是通过lcr轻量容器运行时直接调用runc或clibcontainers整体进程数量和内存占用都能压下来。在256MB甚至更低内存的设备上iSulad是可以正常跑的Docker就比较吃力了。另外一点很实际国内用OpenEuler做信创、国产化替代的场景厂商对依赖链的审查比较严格。iSulad作为openEuler社区原生项目从内核适配、依赖库到安全加固都是沿着国产OS这条路走的要过等保、过适配认证比Docker更顺。1.2 与Docker、containerd、CRI-O的横向对比这几类容器引擎放在一起对比先理清楚它们的分层。Docker是完整的容器管理平台containerd和CRI-O是CRI标准的实现iSulad的定位其实介于containerd和Docker之间——它既实现了容器生命周期管理又通过插件支持了镜像管理、网络、日志等能力等于用更小的代码量做了Docker大部分核心功能。从资源占用角度看我实际在OpenEuler 22.03 LTS上测过Docker全家桶常驻内存大概在120MB到180MB之间iSulad加lcr加runc总共不到50MB。启动一个busybox容器Docker从命令发出到容器内进程起来大约在300ms到500msiSulad通常在100ms以内。差异的根源在于iSulad的架构精简了gRPC调用链和模块间通信省掉了不少中间层。功能上iSulad支持镜像管理pull、tag、push、容器生命周期、exec、logs、attach、资源限制、网络模式、volume挂载大部分日常运维操作都覆盖到了。和Docker相比主要缺的是Docker Compose类的高层编排、BuildKit构建缓存体系以及Docker Hub生态的深度整合。Compose这层可以交给Kubernetes或独立配置工具构建镜像也可以用其他方案补齐。1.3 什么时候该用iSulad什么时候别用不是所有场景都适合换iSulad。我整理了几个判断标准资源受限环境比如嵌入式设备、边缘网关、IoT盒子内存和CPU都是按兆算的这种情况iSulad是明显优势选项。国产化替代和信创项目要求底层依赖链可控、有社区官方支持iSulad是OpenEuler原生推荐。追求极致启动速度的场景比如函数计算冷启动、短生命周期任务iSulad的启动延时优势能直接转化为业务收益。已有大量Docker编排脚本和Compose文件迁移成本高的环境短期内不建议硬切。iSulad提供了docker API兼容接口和命令行兼容模式但Compose这种上层生态还是替代不了。依赖Docker特殊网络插件、复杂buildkit流水线、Docker Desktop式开发体验的场景老老实实用Docker。2. 部署前置准备OpenEuler系统与基础环境2.1 OpenEuler的安装与初始配置要点如果你手里还没有OpenEuler环境先从安装开始。OpenEuler支持x86_64和aarch64两种主流架构官方ISO可以在openEuler社区网站下载选择当前维护的LTS版本比如22.03 LTS或24.03 LTS。我这边用的22.03 LTS SP3aarch64架构安装时选的是“Server”最小化安装。安装过程有几个容易忽略的点分区时建议单独分一个/data或/var/lib容器数据盘iSulad的镜像和容器默认存储在/var/lib/isulad下后续扩容比根分区方便。时区要设对容器日志时间戳、健康检查的超时计算都依赖系统时间建议直接用Asia/Shanghai。root密码复杂度设置好后记得创建一个普通用户用于运维不要全程root操作这是基本习惯。系统起来后第一件事是检查版本和内核cat /etc/openEuler-release uname -a正常会看到类似openEuler 22.03 (LTS-SP3)的输出内核版本在5.10以上。内核太低的话iSulad对cgroup v2和overlayfs的支持会有问题。2.2 网络、主机名、时钟与内核参数OpenEuler的网络配置方式和CentOS/RHEL比较接近使用NetworkManager管理。我用nmtui做基本配置静态IP、网关、DNS一次搞定。nmtui systemctl restart NetworkManager主机名也要提前设好因为后面无论是单独用iSulad还是接入Kubernetes节点名都会暴露在容器网络和日志里。改主机名建议直接改/etc/hostname并同步更新/etc/hostshostnamectl set-hostname node1-edge时钟同步用chronydOpenEuler默认装好了systemctl enable --now chronyd chronyc sources -v内核参数方面如果你只是跑普通容器默认配置基本够用。如果要跑大规模容器或者做网络性能调优建议提前检查几个关键项sysctl net.ipv4.ip_forward sysctl net.bridge.bridge-nf-call-iptables容器网络需要开启IP转发bridge过滤iptables的规则也要确认。这些参数可以写到/etc/sysctl.d/99-isulad.conf里持久化cat /etc/sysctl.d/99-isulad.conf EOF net.ipv4.ip_forward 1 net.bridge.bridge-nf-call-ip6tables 1 net.bridge.bridge-nf-call-iptables 1 EOF sysctl --system2.3 配置dnf仓库在线安装的基础OpenEuler默认配置了官方的yum/dnf源装软件前先验证下能否正常访问dnf repolist dnf makecache如果机器在隔离网段或者内网环境就需要提前准备本地仓库或离线rpm包。这里有一个很多新手会卡住的点OpenEuler的dnf仓库分为OS、everything、EPOL等几个类别iSulad相关组件主要在EPOL仓库里。默认的openEuler.repo里可能只启用了OS和everything安装iSulad前要确认EPOL源可用dnf list available | grep -i isulad如果输出为空大概率是EPOL仓库没配好。我这边是在/etc/yum.repos.d/openEuler.repo里把EPOL源启用然后重新makecache就好了。3. iSulad部署实操全流程3.1 安装iSulad及依赖组件EPOL源就绪后安装iSulad本身很简单一步到位dnf install -y iSulad这个命令会自动拉取lcr、lxcfs、runc等依赖组件。如果提示缺少某个依赖版本多半是仓库版本不匹配或者EPOL没刷新缓存先跑一遍dnf clean all dnf makecache再重试。安装完成后先别急着启动先看关键信息isulad --version rpm -ql isulad | head -30了解安装目录结构对后续排查问题很有帮助。iSulad的二进制在/usr/bin/isulad默认配置在/etc/isulad/daemon.json日志通过systemd-journald管理运行目录在/var/run/isulad数据目录在/var/lib/isulad。3.2 配置daemon.json核心参数iSulad的配置文件是/etc/isulad/daemon.jsonJSON格式。这是整个部署过程中最需要理解的部分我逐一说明关键字段。默认配置注释很全但有几个参数我建议根据实际场景调整{ engine: lcr, runtime: runc, graph: /var/lib/isulad, state: /var/run/isulad, log-level: INFO, log-driver: stdout, hook-spec: /etc/isulad/hooks/default, cgroup-parent: , cgroup-manager: cgroupfs, native.cgroupdriver: cgroupfs }engine和runtime保持默认lcrrunc这是最成熟稳定的组合。graph指定镜像和容器数据的存储路径如果前面分好了独立数据盘这里改成对应挂载点。log-level建议在调试期间改成DEBUG稳定运行后再改回INFO。cgroup-manager有两个选项cgroupfs和systemd。如果你只单独跑iSuladcgroupfs足够如果要接入KubernetesKubelet默认用systemd驱动两边的cgroup manager必须保持一致否则会出现资源统计混乱的问题。registry字段可以配置镜像仓库地址和认证信息拉私有仓库镜像时会用到registry: { insecure_registries: [registry.internal.example.com:5000], registry_mirrors: [https://docker.mirrors.internal.example.com] }配置完成后用json格式校验一下文件避免低级错误python3 -m json.tool /etc/isulad/daemon.json3.3 启动服务并验证环境配置没问题就启动服务systemctl daemon-reload systemctl enable --now isulad systemctl status isulad启动后确认服务状态是active (running)。接着查一下进程和监听端口ps -ef | grep isulad ss -tlnp | grep isuladiSulad默认会监听unix socket路径是/var/run/isulad.sock部分版本也会监听TCP端口。如果选了CRI模式对接K8s还会在/var/run/isulad/cri.sock提供CRI接口。验证基本功能先看版本和系统信息isula version isula infoisula info会输出内核版本、存储驱动、cgroup驱动、镜像数量等关键信息。存储驱动显示overlay2就对了。如果显示devicemapper或者vfs说明配置文件或内核模块有问题后面拉镜像和运行容器会非常慢。再检查lxcfs是否正常挂载lxcfs用于在容器内呈现宿主机的/proc和/sys信息mount | grep lxcfsiSulad启动时默认会挂载lxcfs如果这步失败容器内看到的CPU核数、内存大小会是宿主机的完整值资源限制逻辑就会出问题。3.4 拉取镜像与运行第一个容器环境就绪后试一下镜像拉取。iSulad的CLI命令是isula语法与docker高度相似isula pull busybox:latest拉取过程中能看到镜像层下载日志。如果网络不好或仓库不稳定可能卡很久这时候可以按2.3节配置registry_mirrors。镜像就绪后运行第一个容器isula run -itd --name hello busybox sh isula ps isula exec -it hello sh在容器内执行ls、cat /etc/os-release看是否正常返回。然后退出容器测试stop和rmisula stop hello isula rm hello再验证一下端口映射方式iSulad支持-p参数做端口发布isula run -itd -p 8080:80 --name web nginx:latest curl http://宿主机IP:8080端口映射能通说明iptables规则和网络转发都正常。这是判断容器网络是否工作的一个实用探测方式。3.5 资源限制与常用运维操作资源限制方面iSulad的命令参数几乎和Docker对齐isula run -itd --name test-mem --memory128m --cpus0.5 busybox容器起来后可以进容器验证限制效果isula exec test-mem cat /sys/fs/cgroup/memory.max isula exec test-mem nproc注意如果你用lxcfs挂载了宿主机的/proc信息nproc的返回值可能会被lxcfs虚拟化显示的是容器允许的CPU配额而不是宿主机的核数。这正好反映了IxcFS的作用——容器内看到的资源视图应该被隔离而不是直接透传宿主机的。常用运维命令再做一次汇总isula stats实时查看容器资源占用对应docker statsisula top查看容器内进程对应docker topisula cp在容器和宿主机之间复制文件isula logs查看容器日志支持-f实时跟踪isula commit把容器保存为新镜像isula tag和isula push镜像打标签和推送仓库4. 命令体系与Docker的兼容性对照4.1 常用命令对照速查表从Docker切到iSulad最大的门槛就是命令迁移。我把高频操作整理成一张速查表直接对照着用即可操作Docker命令iSulad命令查看版本docker versionisula version查看系统信息docker infoisula info拉取镜像docker pull nginx:latestisula pull nginx:latest查看镜像docker imagesisula images删除镜像docker rmi nginx:latestisula rmi nginx:latest运行容器docker run -itd --name web nginxisula run -itd --name web nginx查看容器docker ps -aisula ps -a进入容器docker exec -it web shisula exec -it web sh查看日志docker logs -f webisula logs -f web停止/启动docker stop/start webisula stop/start web删除容器docker rm webisula rm web资源占用docker statsisula stats构建镜像docker build -t demo .isula build -t demo .容器提交docker commit web demo:v1isula commit web demo:v1是不是感觉直接平移就能用这正是iSulad刻意保持的兼容性设计。底层命令调用链是isula命令通过isulad的gRPC接口转发到lcr和docker通过dockerd转发到containerd的路径相似所以命令行为对齐得非常好。4.2 isula build与docker build的差异iSulad也有build命令语法和Dockerfile兼容但底层实现不一样isula build直接用native的容器构建流程通过lcr起临时容器执行RUN指令而不是采用BuildKit那种缓存机制。实际体验下来小项目的Dockerfile基本能直接build但是复杂构建场景也要注意。我实测的一个例子一个包含多阶段构建的DockerfileFROM golang:1.21 AS builder WORKDIR /app COPY . . RUN CGO_ENABLED0 go build -o app . FROM alpine:latest COPY --frombuilder /app/app /usr/local/bin/app ENTRYPOINT [app]isula build做这种多阶段构建是可以的但有几个细节需要注意构建缓存管理比较原始没有BuildKit那种精细的cache invalidation同一Dockerfile改一行后续层可能全部重来。构建上下文比较大时传输效率不如Docker建议把不必要文件写在.dockerignore里。构建过程中如果需要访问网络安装依赖要确保宿主机的网络和DNS配置正确构建容器默认使用宿主网络栈。如果你已经有成熟的CI/CD流程建议还是用专业的镜像构建工具iSulad的build定位是轻量场景下的“能构建”而不是“高吞吐构建”。4.3 与Kubernetes集成说明单独跑容器只是第一步生产环境里更常见的是用容器引擎承载Kubernetes节点。Kubernetes通过CRI接口与容器引擎通信iSulad对CRI的支持是官方主推的亮点功能。iSulad的CRI实现是原生支持的不需要额外装插件。Kubelet配好容器运行时端点指向/var/run/isulad/cri.sock对应runtime-endpoint配置即可。配置Kubelet时需要重点关注的是cgroup driver建议用systemd模式Kubelet --cgroup-driversystemddaemon.json里cgroup-manager也设成systemd。如果两边不一致Pod状态会显示为CreateContainerErrorkubelet日志里会有“failed to get cgroup stats”之类的报错。CRI模式下isula的命令照常可用相当于你既可以用kubectl管理Pod又可以用isula直接查看底层容器对排查问题很方便。kubectl exec和isula exec看到的容器视角是一致的。5. 实战踩坑与常见问题排查5.1 服务启动失败与日志分析iSulad服务起不来是第一个高频问题。判断方法systemctl status isulad -l journalctl -u isulad -n 100 --no-pager我遇到过一次典型的启动失败日志里提示failed to load containers: stat /var/lib/isulad/containers: no such file or directory原因是安装后启动前我手动改了graph路径但新路径下的目录结构没初始化。处理方式是先停服务手动建目录并设置好属主systemctl stop isulad mkdir -p /data/isulad chown -R isulad:isulad /data/isulad sed -i s|/var/lib/isulad|/data/isulad|g /etc/isulad/daemon.json systemctl start isulad另一个常见启动问题是socket文件权限导致客户端连不上。isula命令行报“connect /var/run/isulad.sock: permission denied”时需要把运行用户加入isulad组或者干脆用root用户执行管理命令。更安全的做法是改socket的属组和权限让运维账号通过组权限访问。5.2 镜像拉取慢与网络问题OpenEuler所在网络环境不一定能顺畅访问Docker Hub镜像拉取卡住很常见。排查路径是curl -I https://registry-1.docker.io/v2/如果不通或超时解决方案有配置registry_mirrors指向可用镜像加速器daemon.json里配好后重启isulad。配置insecure_registries走内网私有仓库适合公司内部镜像。直接使用静态IP和规划好DNS避免系统DNS解析出问题导致仓库域名解析失败。我实测过配置多个mirror的效果拉取一个200MB的镜像从三分钟级别降到三十秒级别改动只是daemon.json里的几行配置。5.3 容器退出与健康检查问题容器秒退是另一个高频困扰。排查思路要看事件顺序isula logs container-id常见原因有三种进程前台执行完毕直接退出、镜像缺少bash/sh导致ENTRYPOINT执行失败、资源限制太小导致启动被杀。分别对应不同排查方向如果容器入口是长驻进程但一启动就exit用isula logs看进程输出通常能直接看到报错原因。如果提示no such file或exec format error大概率是镜像架构不匹配比如在x86机器上跑arm64镜像需要确认镜像架构和宿主机一致。如果是OOM导致被杀看dmesg输出dmesg | grep -i oomdmesg里能看到容器进程是否被内核OOM killer干掉如果是调大内存限制或者优化进程内存占用。5.4 cgroup、lxcfs与资源限制问题资源限制常见的坑之一是cgroup driver配置不一致。前面提到接入Kubernetes时cgroup-manager必须和Kubelet保持一致。单机跑容器时这个字段不一致不会立刻报错但isula stats显示的资源统计会混乱。另一个坑和lxcfs有关。iSulad默认用lxcfs向容器注入宿主机的/proc和/sys视图但在部分内核版本上lxcfs挂载会失败。检查journalctl -u isulad -n 50 | grep -i lxcfs如果发现lxcfs启动失败可以先单独验证lxcfs是否正常lxcfs -v确认二进制没问题后看daemon.json里lxcfs相关配置某些版本需要显式启用lxcfs: { enable: true }重启后再看mount输出确认lxcfs正常挂载后再跑带资源限制的容器。如果lxcfs不能用至少要把容器内对/proc/cpuinfo和/proc/meminfo的读取交给cgroup本身限制避免容器内看到的资源和实际限制的配额严重不一致导致应用误判。5.5 残留容器与彻底清理容器管理过程中偶尔会因为非正常停止、掉电等情况留下残留状态。表现为isula ps -a能看到容器但状态异常或者状态目录里存在僵尸容器目录。处理方式systemctl stop isulad find /var/lib/isulad/containers -maxdepth 1 -type d确认是残留容器目录后可以直接移走隔离而不是直接删mkdir -p /var/lib/isulad/backup mv /var/lib/isulad/containers/container-id /var/lib/isulad/backup/ systemctl start isulad启动后确认容器列表正常再决定是否删除备份目录。这种操作方式比暴力rm要安全得多任何时候都能回退。如果整机想彻底卸载iSulad注意以下操作会删除所有容器和镜像数据执行前确认数据已备份。systemctl stop isulad dnf remove -y iSulad rm -rf /var/lib/isulad /var/run/isulad /etc/isulad6. 调优路径与生态扩展6.1 轻量化场景的几个调优建议iSulad本身就是为轻量化设计的但实际使用中还能进一步优化关闭不必要的镜像管理插件。如果你只从内网仓库拉镜像不涉及复杂镜像构建可以在配置里精简插件列表减少内存占用。不过这个操作需要确认你的使用场景确实用不到相关功能否则会变成负优化。日志大小限制。在daemon.json里配置max-log-size和max-log-file避免长期运行的容器撑爆磁盘。镜像定期清理。用isula system df查看磁盘占用用isula rmi清理无用悬空镜像或者结合cron脚本自动清理。这跟Docker的清镜像思路一致只是命令换成了isula。内存占用的实测数据我在部署验证时记录过刚启动完isulad常驻内存约38MB跑3个busybox容器后约52MB。这个量级的资源占用在嵌入式设备上是可以接受的Docker很难做到这个水平。6.2 与热门场景结合边缘推理和模型部署很多在OpenEuler上装iSulad的人并不是单纯为了跑Web服务而是做边缘AI和数据类工作负载。我近期验证了在iSulad里跑一个轻量目标检测模型推理服务用的rk3588开发板流程是宿主机装好NPU驱动和运行时库把推理服务的镜像打好后扔进iSulad启动容器时挂载NPU设备节点。设备和驱动挂载的配置要点isula run -itd \ --name yolov8-infer \ --device /dev/rknpu:/dev/rknpu \ -v /usr/lib/librknnrt.so:/usr/lib/librknnrt.so:ro \ -p 8000:8000 \ yolov8-server:v1容器内模型加载、推理输出都正常整体比裸机跑多了一层容器隔离但性能损耗基本在3%以内。这说明iSulad的设备和驱动透传能力是可靠的视频流推理这种高吞吐、低延时的场景也能撑住。大模型本地部署这类重负载场景iSulad同样可以承载。模型文件以卷挂载方式进容器GPU或NPU设备通过--device透传注意设置好共享内存大小避免推理框架崩溃isula run -itd \ --name vllm-server \ --device /dev/dri:/dev/dri \ -v /data/models:/models:ro \ --shm-size8g \ vllm:v1 \ python -m vllm.entrypoints.openai.api_server \ --model /models/qwen2.5-7b-instruct \ --port 8000实测下来OpenEuler配合iSulad做模型服务基础设施路径上是完全走得通的。如果你选型时拿不准用不用Docker可以放心评估iSulad。6.3 版本升级与配置迁移版本升级这件事iSulad做得还算平滑。我经历过22.03 LTS SP2升SP3流程是dnf update -y iSulad systemctl restart isulad升级后系统会自动做数据目录和配置的兼容。升级前我习惯做三件事备份daemon.json、导出当前镜像清单、确认业务容器可以滚动重启。如果你的环境里有生产容器升级前务必先拿测试环境做一轮容器生命周期验证重点检查网络、存储、exec这三个通路这三个地方最容易受版本升级影响。配置迁移方面/etc/isulad/daemon.json是向下兼容的新版本新增的配置项一般会带默认值旧配置缺失不影响启动。但强烈建议每次升级后对比一下rpm自带的daemon.json.rpmnew文件看看官方新增了哪些配置项能发现一些新特性和安全选项。写在最后的几点实操体会整套环境从无到有跑通我自己最深的感触是iSulad和Docker不是替代关系而是在不同场景下的差异化选型。你做虚拟机集群、标准数据中心、复杂CI/CD用Docker没有任何问题但如果你关心的是边缘侧的内存占用、信创环境下的依赖控制、国产OS的原生契合度iSulad确实值得动手试一下。几个容易被忽略但很重要的点再强调一遍EPOL仓库一定要配好否则安装直接失败daemon.json的cgroup-manager和上游编排工具要一致否则资源统计会乱lxcfs这块虽然不起眼但容器内资源视图是否正确全看它排障时优先检查挂载状态。最后再说一个我在升级和切换配置时反复用到的技巧改daemon.json之前先复制一份带时间戳的备份然后每次只改一个字段、重启一次、验证一个功能不要一次性改多个参数。容器引擎这类基础组件排障定位慢的原因往往不是问题本身复杂而是你同时动了太多变量。这个习惯帮我省了非常多的时间希望你用iSulad的时候也能用上。
返回列表