Incus 实战:用一套 API 统一管理系统容器与虚拟机
2026/9/18 13:00:06 网站建设 项目流程

1. 从 LXD 分叉说起:Incus 到底解决了谁的痛点

如果你这两年一直在用 LXD 管容器和虚拟机,大概率会在某个版本升级之后发现事情变得有点微妙——原本干净的系统容器管理工具,逐渐被塞进越来越多商业化的东西,命令行提示、文档入口、生态绑定都在往一个方向收拢。Incus 就是在这个背景下出现的,它由 Linux Containers 社区从 LXD 分叉而来,目标很明确:做一个中立、开放、把容器和虚拟机用同一套 API 管起来的编排管理引擎。

我最初注意到它,是因为手头有一批边缘节点需要跑一些“长得像虚拟机、但启动要快”的负载。用 Docker 吧,它天生是应用容器,systemd、多进程、内核调参这些事做起来别扭;用 VMware 或者传统 KVM 吧,启动慢、资源开销大,快照和批量编排又得另配一套工具。Incus 刚好卡在中间这条缝里:既能起完整的系统容器,也能起真正的 QEMU 虚拟机,而且两者共用同一套incus命令、同一个 REST API、同一套存储池和网络模型。

这篇文章写给三类人看。第一类是已经在用 LXD、想找个平滑迁移路径的人;第二类是用 Docker Compose 跑小规模服务、但发现“应用程序容器”这个抽象不够用的人;第三类是正在评估虚拟化方案、被一堆安装教程绕晕的人——网上那些 vmware 虚拟机安装教程、虚拟机安装 linux 步骤、vm 虚拟机网络适配器报错排查的内容,很多时候你其实只是想“快速起一台 Linux 跑点东西”,那 Incus 值得你花半小时了解一下。

需要先说清楚的是,Incus 不是要取代 K8s。K8s 管的是应用编排层,Incus 管的是“机器”这一层——容器也好、虚拟机也好,在它眼里都是一个“实例”。这两者完全可以叠加使用,后面我会专门讲怎么把 Incus 当成 K8s 节点的底层供给层。

2. 核心概念拆解:实例、项目、存储池、网络

2.1 实例:把容器和虚拟机塞进同一个抽象里

Incus 里最重要的一个词叫实例(instance)。一个实例可以是系统容器,也可以是虚拟机,对外暴露的命令几乎一样:incus startincus stopincus execincus snapshotincus copy,容器和虚拟机通用。这个设计的好处是,你写运维脚本的时候不用分两套逻辑去判断“这是容器还是虚拟机”。

具体差别在底层:

  • 系统容器走的是 LXC,共享宿主机内核,启动通常在几百毫秒到一两秒,内存开销非常小,一台 8G 内存的机器跑十几个轻量容器毫无压力。
  • 虚拟机走的是 QEMU,带独立内核,启动十几秒,但隔离性更强,可以跑不同内核版本、可以装 Windows、可以模拟异构硬件。

提示:如果你要跑的是单进程服务,比如一个小 API,其实 Docker 那一层更轻;但如果你要跑 systemd、要装一堆系统级依赖、要像操作一台真机那样ssh进去改配置,系统容器比应用容器顺手太多。

2.2 项目(project):多人多环境隔离的落地方式

Incus 的项目是我觉得设计得最实用的一块。你可以把它理解成一个命名空间,里面装着独立的实例、镜像、配置文件、存储卷。默认有个default项目,你可以再建devstagingteam-a,彼此看不到对方的实例。

为什么这个重要?因为很多团队在共享一台物理机时,最头疼的就是“谁把谁的容器删了”“谁能看到谁的环境变量”。用项目隔开之后,再配合有限的资源配额(比如限制 dev 项目最多用 4 核 8G),共享物理资源这件事才真正可控。

incus project create dev incus project set dev limits.cpu 4 incus project set dev limits.memory 8GiB incus project switch dev

切到 dev 项目之后,你incus list看到的就只有 dev 里的实例了,这种上下文切换的手感比在命令里到处加-p dev舒服很多。

2.3 存储池:选型直接决定快照和迁移体验

Incus 的存储池支持dir、btrfs、zfs、lvm、ceph这几种驱动。我的经验是:

驱动适用场景快照速度迁移支持
dir临时测试、单机简单用慢,走文件复制仅冷迁移
btrfs单机、要快照、磁盘不算大秒级支持增量
zfs单机或小集群、要压缩去重秒级支持增量,体验最好
lvm传统环境、块设备管理成熟支持,但需 thin pool
ceph多节点集群、要共享存储支持在线迁移

如果你打算做集群、要做实例的实时迁移,ceph 是唯一省心的选择,因为它是共享存储,实例在两台机器之间搬的时候不用复制整块磁盘。单机自用的话,我通常会选 zfs,快照、克隆、增量备份都很舒服。

注意:选 dir 驱动跑生产是我踩过的最大的坑。快照一个几十 G 的实例要等几分钟,而且不支持增量迁移,集群里基本没法用。dir 只适合做镜像模板测试。

2.4 网络:bridge、ovn、macvlan 该怎么挑

Incus 的网络模型分几层:网桥(bridge)、OVN、物理网卡直通(macvlan/sriov)、以及最基础的 loopback。日常最常用的是bridge,它会在宿主机上创建一个虚拟网桥,实例通过它拿到内网 IP,再由宿主机做 NAT 出网。

  • 单机自用,bridge 加默认 NAT,开箱即用,incus admin init会问你要不要建一个。
  • 多机集群、实例要跨节点通信,上OVN,这是 Incus 里做软件定义网络的核心,能实现跨节点二层互通、ACL、负载均衡。
  • 实例需要直接拿物理网段的 IP、或者要跑组播协议,用macvlan,但它有个限制——宿主机和容器之间默认不能直接通信,这点要提前想清楚。

3. 环境搭建与第一次启动实操

3.1 三种安装方式,按你的环境挑

Incus 的安装方式主要有三类,我按适用性排个序:

方式一:发行版官方仓库(推荐给生产环境)

Debian 12、Ubuntu 22.04 之后的版本、部分 RHEL 系发行版都已经把 Incus 收进仓库了。

sudo apt update sudo apt install incus

装完把当前用户加进incus-admin组,重新登录一次才能免 sudo。

sudo usermod -aG incus-admin $USER

方式二:Zabbly 提供的上游仓库(推荐给想要新版本的场景)

发行版仓库里的版本通常落后几个小版本,想用新特性就从上游源装。

方式三:Snap 安装(最省事但我不太喜欢)

Snap 版本打包得比较完整,但和宿主机文件系统的交互、存储池路径选择上会有点绕,适合不想折腾依赖的场景。

提示:安装完第一件事是incus info看版本和支持的特性列表,比如有没有projects、有没有ovnqemu相关的能力,这决定了你后面能用哪些功能。

3.2incus admin init的每个问题都在问什么

这个交互式初始化是新手最容易糊里糊涂点过去的环节,我把关键几问的意思翻译一下:

  • Clustering:问你要不要组集群。单机选 no,集群的话后面要用incus admin init --preseed走自动化。
  • Storage backend:前面讲的 dir/btrfs/zfs/lvm/ceph。生产建议 zfs 或 ceph。
  • Storage pool name:默认default,可以改,集群里多池管理时命名要清楚。
  • Network bridge:要不要建默认网桥incusbr0,建议建,不然后面得手动配。
  • IPv4/IPv6 address:网桥的网段,默认 10.x 段,注意别和你现有的内网段冲突,冲突会导致路由混乱。
  • NAT:要不要做地址转换出网,一般选 yes。
  • Fan networking:跨多子网做叠加网络,单机用不上选 no。
  • Metrics / images server:监控接口和镜像源,镜像源默认官方仓库够了。

它最后会生成一个preseed 文件,这才是精华。你可以把这个文件保存下来,后面批量部署机器时直接incus admin init --preseed < config.yaml,几十台机器一键初始化,配置完全一致。

3.3 镜像源与安全:别忽略镜像这一环

Incus 用的是 Linux Containers 的镜像服务器,里面容器镜像和虚拟机镜像都有,images:后面接别名就能拉。命令很简单:

incus launch images:ubuntu/22.04 first-container incus launch images:debian/12 first-vm --vm

但我要专门提醒镜像安全这件事。默认镜像源是官方维护的,问题不大,但一旦你引入第三方镜像、或者用incus import导入别人给的镜像压缩包,就相当于把一段未知的 rootfs 跑在自己机器上。我的做法是:

  • 生产环境只从可信源拉镜像,锁定版本,不要用latest这类浮动别名;
  • 导入外部镜像后,进实例里检查一遍开机自启项、/etc/passwd、cron、systemd unit;
  • 对容器尤其注意,容器共享宿主机内核,镜像里的危险操作面比虚拟机更大。

4. 日常运维:启动容器、开虚拟机、快照、迁移

4.1 启动一个系统容器并把它调成可远程访问

我拿 Ubuntu 22.04 举例,一条命令起容器:

incus launch images:ubuntu/22.04 web01

进去装东西:

incus exec web01 bash

但这时候容器里默认没有 sshd,你想从别的机器 ssh 进去,得在容器里装openssh-server,再导入公钥。我的做法是建一个 profile,把 ssh、常用包、时区这些东西预置好,以后每次 launch 直接--profile myprofile就带上了,省得每次重复劳动。

incus profile create myprofile incus profile add web01 myprofile

profile 可以挂载设备、设置资源限制、注入 cloud-init、配置安全策略,是 Incus 里做标准化最重要的工具。建议一定要克制地用 profile:基础镜像 + 一个通用 profile + 一两个场景专用 profile,比给每个容器单独调参数好维护得多。

4.2 开虚拟机:和容器几乎同一条命令

虚拟机的启动就多一个--vm参数:

incus launch images:ubuntu/22.04 vm01 --vm

这里有几个点值得展开。

第一,虚拟机默认磁盘大小。镜像默认给的根盘可能只有 10G 左右,跑点重活就不够。启动时可以指定:

incus launch images:ubuntu/22.04 vm01 --vm -d root,size=60GiB

或者起来之后扩容:

incus config device set vm01 root size=80GiB

第二,虚拟机怎么进。Incus 会往虚拟机里注入 cloud-init,默认给你一个ubuntu用户和随机密码,你可以incus exec vm01 passwd改密码,也可以注入自己的公钥。incus console vm01 --type=vga能打开图形控制台,装 Windows 或者给虚拟机调引导顺序的时候会用得上。

第三,虚拟机性能优化。Incus 现在支持virtiofs做主机和虚拟机之间的目录共享,比过去的 9p 性能好很多。设备加一句:

incus config device add vm01 shared disk source=/host/data path=/mnt/data

磁盘和网卡默认就是 virtio,这个不用改。CPU 和内存限制用limits.cpulimits.memory设就行。

第四,虚拟机里跑什么。我见过有人用 Incus 的虚拟机装 Windows、装各种 Linux 发行版做测试环境,也见过用它跑 Docker、跑 K8s 节点。后者其实挺香的:宿主机装 Incus,里面起几台虚拟机,每台虚拟机里装 Docker 或者 kubelet,物理机变成一台“多节点实验室”,比装一堆 VMware 省资源多了。那些 vmware 虚拟机安装 ubuntu 的教程里折腾半天的网卡适配、汉化包、蓝屏问题,用 Incus 起虚拟机基本不会再遇到。

4.3 快照、备份、恢复:这套流程一定要跑通一次

快照:

incus snapshot create web01 before-upgrade

回滚:

incus snapshot restore web01 before-upgrade

导出备份:

incus export web01 /backup/web01.tar.gz

导入:

incus import /backup/web01.tar.gz restored-web01

快照能不能秒级完成,取决于你的存储驱动——zfs 和 btrfs 是几乎瞬时的,dir 就要等。备份文件是完整的实例打包,包括配置和存储卷,适合做冷备份。

注意:快照不是备份。快照和实例共享底层存储,磁盘坏了两个一起没。真正的可靠做法是快照 + 定期export到外部存储,或者集群里配合 ceph 做多副本。

4.4 集群:从单机到多节点

Incus 集群的搭建逻辑比较特别,它要求先在一台机器上做 bootstrap,然后其他节点通过 join token 加入。核心命令:

incus cluster add node2

这条命令会打印一段 join 命令,拿到 node2 上执行,node2 就开始加入。加集群之前有几个必须满足的前提:

  • 所有机器的存储驱动必须一致(比如都用 ceph,或者都用 zfs 但配合共享存储做迁移);
  • 网络配置要能互通,尤其是 OVN 场景;
  • 时间同步要准,drbd 或者 raft 之类的机制对时间敏感。

集群搭好之后,incus list会显示每个实例在哪个节点,incus move web01 --target node3可以把实例挪到别的节点,配合 ceph 存储就能做在线迁移。这一套是 Incus 最有价值的部分之一——很多小团队想自己搭个“小号私有云”,不想上 OpenStack 那么重,Incus 集群是很好的中间选项。

5. 常见故障与排查技巧实录

5.1 容器启动失败:先看 log,再看配置

容器起不来,第一反应就是:

incus info web01 incus log web01

incus log一般是最终端的 lxc 交互内容,能直接看到 rootfs 里初始化脚本报的错、systemd 挂掉的原因。我遇到最多的三类:

现象常见原因处理方式
启动卡在 starting镜像里 systemd 版本与宿主内核不兼容换更新的基础镜像
启动秒退镜像 rootfs 损坏从快照恢复或重新 launch
起来但没网profile 没挂网卡、或网桥异常incus config show检查设备

提示:官方镜像里 rootfs 出问题的情况很少,一旦出现,多半是你自己通过incus file push往里塞文件的时候塞坏了。养成改动前先快照的习惯,成本很低。

5.2 网络问题的排查顺序

Incus 的网络问题排查,我固定走这个顺序:

  1. incus list看实例有没有 IP,没有就是网卡或 DHCP 的问题;
  2. ip a在宿主机上看网桥是否 up,网桥没有实例的 veth 接口说明设备没挂上;
  3. incus network list看网络状态,OVN 场景还要看 uplink 是否健康;
  4. 实例内部ping网关,网关不通就是二层问题;网关通但外网不通,是 NAT 或 DNS 的问题;
  5. 最后才怀疑宿主机防火墙规则。

宿主机上如果有 firewalld、ufw 或者自定义 iptables,很容易把网桥的转发规则挡掉,导致实例能拿到 IP 但出不了网。这个坑我踩过两次,都是因为装了别的软件动了转发链。

5.3 虚拟机相关的坑

虚拟机比容器复杂,常见几类:

  • 进不去:console 没配好,或者云镜像没有注入登录信息。incus console vm01 --type=vga看画面,不行就重新incus launch并检查镜像是否支持 cloud-init。
  • 性能差:默认没有启用任何加速的话会非常慢,确认宿主机开了 KVM;如果是嵌套虚拟化,确认加了nested支持。
  • 磁盘满:默认根盘小,前面已经讲过怎么扩容。注意扩容前先停实例,改配置后重启。
  • 迁移失败:源节点和目标节点存储驱动不一致,或者目标节点资源不够。

5.4 排查速查表

症状第一步第二步
实例无 IPincus listincus config show看网卡
外网不通实例内 ping 网关查宿主机 NAT 规则
快照很慢incus storage list看驱动考虑换 zfs/btrfs
迁移报错核对两端存储驱动核对目标节点容量
容器里 systemd 起不来incus log换镜像或检查 cgroup 配置
虚拟机黑屏console 看画面检查镜像和引导

6. 性能、安全与生态位置:几个容易被忽略的点

6.1 资源限制怎么写才不会被“打爆”

Incus 的资源限制写法比 Docker 直观,但细节需要注意。CPU 用limits.cpu表示核数,也可以写limits.cpu.allowance表示时间片配额;内存用limits.memory,超过直接 OOM;磁盘 IO 用limits.disk.priority

incus config set web01 limits.cpu 2 incus config set web01 limits.memory 2GiB

但有一类限制是瓶颈:存储配额。不加size的话,实例可以一直写直到把存储池写满,整个池子上的所有实例都受影响。生产环境我建议每个实例的根盘都显式设定大小,宁可设大点,也别让它无限制地写。

6.2 安全加固:容器安全 vs 虚拟机安全

容器安全的核心是:容器共享宿主机内核,逃逸风险永远存在。所以:

  • 尽量用非特权容器(Incus 默认就是非特权模式);
  • 不要用security.privileged=true,除非确实需要;
  • security.idmap.isolated=true隔离 UID/GID 映射;
  • 限制实例能用的内核能力,security.syscalls.*那一系列;
  • 镜像来源要可信,别乱导入外部 tar。

虚拟机安全的边界更清晰,因为它自带内核,逃逸路径少很多。代价是启动慢、占内存。如果你跑的是多租户场景、或者处理来自外部的不可信负载,虚拟机是更安全的默认选项

6.3 和 Docker、K8s、VMware 各自的边界

我经常被问“Incus 和 Docker 到底选哪个”,这个问题其实问错了方向。它们管的是不同层:

  • Docker / Compose:打包、分发、运行单个应用,镜像粒度是进程级;
  • K8s:应用编排层,管的是 pod、service、滚动更新;
  • Incus:机器层,管的是容器/虚拟机实例的创建、存储、网络、快照、迁移;
  • VMware / 传统虚拟化:面向企业级虚拟机平台,管理颗粒度更偏硬件和集群资源。

最实用的组合是Incus 管机器、K8s 管应用:用 Incus 起一堆虚拟机,每台虚拟机装 kubelet 加入集群,物理机上跑出一个小型 K8s 实验环境。比直接在所有节点装 Docker 更干净,也更能模拟真实多节点拓扑。那些折腾docker-compose up限制容器资源、容器故障排查的同学们,如果发现单机 Docker 玩不转多环境隔离,不妨试试把 Incus 作为下面一层。

6.4 镜像生态与自治的取舍

Incus 的镜像仓库是 Linux Containers 社区维护的,Ubuntu、Debian、Alpine、Fedora、Arch 这些主流发行版基本都有官方镜像,虚拟机镜像也很全。但生态规模确实比 Docker Hub 小很多,一些冷门发行版或者特殊镜像可能得自己 build。

好消息是 Incus 支持自己发布镜像到自建服务器,或者直接从 tarball 导入。团队内部完全可以搭一个本地镜像服务器,把公司标准化的操作系统封装成镜像,然后所有实例都从这个源起,版本控制和审计都清晰。这件事我做过一次,把内网的 base 镜像统一之后,线上“这台机器配置和别人不一样”的扯皮几乎消失了。

7. 我实际用下来的一些体会

Incus 这个工具最让我舒服的地方,其实是它把“容器和虚拟机是两种东西”这件事给磨平了。以前写运维脚本,起容器一套命令、起虚拟机另一套,文档要写两份,权限和网络配置也要分别处理。现在统一到同一套 API 之后,我写一个脚本,想跑容器就--vm不加,想跑虚拟机就加,其余全部复用。

另一件我觉得值得说的是项目 + profile 的组合。这两个东西搭起来之后,一个共享物理机就能像小号私有云一样,给不同团队分配环境、配资源上限、预置常用配置。以前这件事要么用 K8s 的 namespace 硬做、要么靠人工约定,都不太顺。Incus 原生支持这套,省了太多绕路。

至于要不要现在就从 LXD 迁到 Incus,我的判断是:如果你对上游治理和长期可维护性敏感,越早迁越好;现在 Incus 的版本已经稳定,迁移路径也清晰。如果只是单机跑两个测试容器,用哪个都行。

最后分享一个小技巧:incus admin init生成的 preseed 文件当成基础设施代码来管理。我习惯把它丢进 git,每次环境变更都改这个文件再重放,而不是手敲命令改配置。这样几个月之后你回头看,机器的所有关键配置都有据可查,重装或者横向扩展也就是重放一遍的事。这个习惯看着不起眼,但真正救场的时候,它比任何文档都管用。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询