尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Incus实战:容器与虚拟机统一编排管理引擎

Incus实战:容器与虚拟机统一编排管理引擎 从 LXD 分叉出来的 Incus我第一次正经上手是在一台闲着的小型服务器上。那天我想同时跑三个测试环境一个系统容器当跳板机一台虚拟机当 Windows 之外的备用系统再来一个容器专门跑构建任务。以前我得分两套流程虚拟机走 libvirt/virsh容器走 Docker两边的网络、存储、快照策略各管各的出问题时排查路径完全不同。Incus 把这套割裂的状态收拢成了一个平面——它是新一代的容器与虚拟机编排管理引擎用同一套 REST API、同一套 CLI、同一套配置模型同时管理系统容器和 QEMU 虚拟机。关键词就三个容器、虚拟机、编排管理引擎。它适合谁我判断有三类人值得花时间手上只有一两台物理机或一台大内存的工作站想在上面铺开一堆隔离环境的用惯了 Proxmox 那种重界面想换一个更偏命令行和 API、更贴近自动化脚本的以及已经在跑 Kubernetes但需要给集群补一层系统级环境和虚拟机节点的。本文不打算复述官方文档而是按我自己的实操顺序把安装、初始化、实例创建、网络、存储、快照、集群、故障排查、安全加固从头走一遍中间夹着我踩过的坑和踩坑之后总结出来的配置参数。1. 版本分支与定位Incus 到底是个什么物种先把一个容易混淆的问题讲清楚不然选型阶段就会走偏。Incus 不是凭空长出来的新项目它是从 LXD 的代码基分叉出来的社区分支由 Linux Containers 社区的一批维护者继续推动。分叉的直接原因是治理模式的变化但从用户角度看真正有意义的变化是Incus 在保持原有能力的同时把容器和虚拟机统一编排这件事做得更彻底也更愿意拥抱更贴近基础设施层的用法。1.1 系统容器和应用容器根本不是一回事很多人一听容器就想到 Docker然后觉得 Incus 是重复造轮子。这是个典型的认知错位。Docker 那一类叫应用容器application container本质是一个进程加一层文件系统封装它的生命周期跟着进程走进程退出容器就结束追求的是秒级启停和镜像分层复用。Incus 管的主要是系统容器system container你可以把它理解成用容器技术实现的轻量虚拟机它有完整的 init 进程、有 systemd、能装 sshd、能跑 crontab、能像一台机器那样长期在线你进去之后ps aux能看到几十个进程而不是只有孤零零一个业务进程。这个区别直接决定了使用场景。我做 CI 构建节点的时候需要的是一个能装 Docker、能装编译工具链、能长跑 agent 的环境这时候系统容器就是对的我做业务服务部署的时候需要的是镜像层复用、滚动更新、和服务网格打通那还是应用容器的地盘。两者不冲突甚至经常叠在一起——你完全可以在一台 Incus 系统容器里再跑一套 Docker这在后面的配置里我会讲具体参数。1.2 为什么一台机器需要同时管这两类东西我自己遇到的真实痛点是资源浪费和管理割裂。一台机器 64 核 256G 内存如果全部跑虚拟机虚拟化开销和磁盘镜像占用都很可观如果全部跑应用容器又缺少完整的系统环境来做登入、做桌面、做内核参数调优。系统容器刚好卡在中间开销接近应用容器体验接近虚拟机还能给到更完整的隔离视图。而虚拟机在某些场景下是不可替代的。比如我要测试一个真实内核模块要在里面跑嵌套虚拟化要验证某个只认物理网卡的软件或者客户明确要求给我一台独立机器。Incus 的价值就在于这两类实例在它眼里地位是对等的——都是一个 instance都有incus exec、都有快照、都能迁移、都能用 profile 批量套配置。你不需要为虚拟机单独准备一套 Terraform provider也不需要为容器另外写一套 Ansible 剧本。1.3 和 LXD、Proxmox、Docker 的横向对照选型阶段最忌讳的就是听别人说这个好然后自己上手发现不对路。我整理了一张对照表按我自己的使用体感打分供你参考维度IncusLXDProxmox VEDocker/Compose系统容器原生支持原生支持LXC 支持较弱不适用虚拟机QEMU 原生QEMU 原生KVM 原生最成熟不适用管理界面CLI REST API 为主CLI REST APIWeb UI 为主CLI Compose集群能力内置轻量内置内置较重需要 Swarm/K8s镜像生态images 远程仓库多发行版同上模板 ISO应用镜像仓库学习曲线中概念少但命令多中低点鼠标就行低适合规模单机到中小集群单机到中小集群中小到中型单机服务部署一句话总结我的判断如果你要的是图形界面点几下就有虚拟机Proxmox 更省心如果你要的是一套 API 管住容器和虚拟机方便写自动化Incus 更顺手如果你只要跑业务服务Docker 加编排层就够了别硬上 Incus。2. 宿主机准备与安装地基打错后面全是坑安装本身不复杂复杂的是安装之前的判断。我见过太多人在一台内核版本老旧、文件系统选错、网络平面没规划好的机器上装完 Incus然后花三天时间排查为什么快照这么慢为什么实例迁移失败。这一章把这些前置条件讲透。2.1 宿主机的前置条件清单先列硬指标这些不满足的话Incus 装上了也用不顺内核版本建议 5.15 以上越新越好。非特权容器、idmap、cgroup v2 这些特性都依赖内核支持老内核上会出现能启动但限制项不生效这类隐蔽问题。cgroup v2现代发行版默认已经切到 v2用stat -fc %T /sys/fs/cgroup看一下返回cgroup2fs就是对的。如果是tmpfs说明还在 v1。虚拟机支持跑 QEMU 虚拟机需要/dev/kvm用ls -l /dev/kvm确认。再检查 CPU 是否开启虚拟化指令集grep -E vmx|svm /proc/cpuinfo有输出才行。BIOS/UEFI 里没开虚拟化的先开机箱设置里去开。内存与磁盘虚拟机实例的内存是从宿主机实际划走的别在 16G 的机器上规划五台 8G 的虚拟机。磁盘上如果用 ZFS建议给一个独立的块设备或分区别和数据盘混在一起。嵌套虚拟化如果要在 Incus 的虚拟机里再跑虚拟机需要开启内核模块参数。Intel 平台是kvm_intel.nested1AMD 平台是kvm_amd.nested1写进/etc/modprobe.d/后重新加载模块。提醒一句不要用 WSL 或者各类嵌套环境去做生产实验/dev/kvm经常不可用会让你误判 Incus 的能力。2.2 三种安装路径怎么选Incus 的安装方式大致三条路各有取舍发行版官方仓库Ubuntu 24.04 及更新的版本可以直接apt install incusDebian 也有打包。优点是省事、跟着系统更新缺点是版本可能落后几个小版本某些新特性用不上。上游维护的软件仓库Linux Containers 社区维护了面向主流发行版的仓库能拿到较新的版本。适合想要新特性、又不想自己编译的场景。加仓库源的时候注意用自己的发行版代号别照抄别人的。源码或容器化部署适合需要打补丁、需要定制构建的场景。日常使用不建议升级维护成本高。我的选择是宿主机用 Ubuntu 24.04直接走官方仓库的包然后在测试机上单独装一份较新的版本做对比。生产环境求的是可预测不是最新。安装完成后第一件事是确认服务在跑systemctl status incus --no-pager incus --version如果systemctl显示 socket 激活模式也是正常的Incus 默认用 socket 激活不要以为没启动。2.3 初始化向导存储池和网桥怎么选初始化用incus admin init交互式向导会问你几个关键问题。这里逐条讲我的选择理由因为这一步选错后面改起来很痛苦。存储后端怎么选这是最重要的一个决定后端快照能力配额支持适用场景zfs极快秒级原生支持首选单机和小集群都合适btrfs快支持宿主机本来就在跑 btrfs 时选lvm快需 thin pool支持没有 ZFS 环境的稳妥选择dir慢整目录复制不支持只做临时验证别上生产ceph快支持多节点共享存储、要做自动迁移时选我的经验是单机上直接上 ZFS哪怕多花十分钟配一个独立分区也值。ZFS 的快照是写时复制几百个实例天天打快照也不心疼dir后端打一次快照可能要几十秒而且空间翻倍。网桥怎么选如果你的宿主机有独立的物理网卡、局域网里还有 DHCP 服务器可以用macvlan或者把物理网卡桥接出去给实例直接拿局域网 IP如果只是想让实例能上网、能和宿主机通信用默认的 NAT 网桥就够初始化向导会自动建一个私有网段的网桥并开启地址转换。其他问题向导还会问你是否配置镜像自动更新、是否允许通过 HTTPS 访问 API、是否加入现有的集群。测试环境我一般让镜像自动更新开着生产环境会关掉改成手动、可回滚的更新流程。2.4 初始化完成后的验证清单向导跑完别急着用按这个清单核一遍incus list能正常返回空列表说明服务通了incus storage list看到你选的存储池状态是 createdincus network list看到网桥确认网段和 NAT 状态incus profile list至少有一个 default profileincus info --resources能打印出 CPU、内存、磁盘的完整资源视图要是incus list报权限错误说明你的用户不在incus-admin组里执行usermod -aG incus-admin $USER之后重新登录 shell。这一步不做你会一直得加sudo脚本里会很难看。3. 四个核心概念实例、镜像、配置文件、项目Incus 的概念数量其实不多但每一个都很关键。理顺这四个后面的命令基本都能自己推理出来。3.1 实例容器和虚拟机的统一抽象在 Incus 里容器和虚拟机统称 instance。这个统一不是文字游戏而是真的共享同一套操作动词launch创建、start/stop控制、exec执行命令、snapshot打快照、copy复制、move迁移、delete删除。唯一的区别是创建时的类型标记——不加--vm默认创建系统容器加了就是虚拟机。你可以用incus info看某个实例的详细信息里面会明确标出 type 是 container 还是 virtual-machine。也可以用incus list -c nst只列出名称、状态和类型输出干净。这里有个容易被忽略的细节虚拟机的相对开销主要在内存和磁盘上因为 QEMU 进程会常驻占用你分配的内存而容器是共享宿主机内核的空闲实例几乎不占内存。所以规划实例密度时容器可以放几十上百个虚拟机要看实际内存余额。3.2 镜像与远程仓库实例从哪来Incus 用远程镜像服务器来拉取系统镜像。默认会连上公共的镜像仓库里面有各种发行版的容器镜像和虚拟机镜像同名的镜像在拉取容器和虚拟机时对应的文件其实不同——容器用 rootfs 压缩包虚拟机用磁盘镜像。日常操作里这几个命令用得最多incus remote list # 看有哪些远程源 incus image list images: --filter archamd64 # 列出可用镜像 incus image list images:debian/12 # 看某个镜像的可用版本还有一件事必须知道从远程拉下来的镜像会缓存在本地第二次创建同版本实例是秒级的。所以你在一个环境里反复创建同一版本的实例成本极低。镜像还可以自己制作。做法是在一个容器里把环境配好、清理掉临时文件然后incus publish把它固化成一个本地镜像incus publish c1 --alias base-buildenv --reuse之后就能用incus launch base-buildenv c2直接创建省掉重复装依赖的时间。做这条链路的时候务必在 publish 之前清理/var/log、/tmp、shell 历史文件和 SSH 主机密钥否则每个实例都会带着同样的指纹和同样的日志很多奇怪问题都从这来。3.3 配置文件profile 和配置继承profile 是 Incus 里做批量配置的核心机制。它本质是一组配置项加一组设备的集合可以套到任意实例上。从应用顺序讲default profile 先应用然后是你指定的其他 profile最后是实例自身的配置越靠后优先级越高。我的习惯是准备三层 profiledefault放通用项比如默认网卡、默认 root 磁盘池、时区、DNS。role-*按角色分比如role-web放 HTTP 相关限制、role-build放 CPU 和内存配额。env-*按环境分比如env-staging放更小的资源上限、env-prod放更严格的限制。创建和配置的写法incus profile create role-build incus profile set role-build limits.cpu 4 incus profile set role-build limits.memory 8GiB incus profile device add role-build root disk path/ pooldefault size40GiB套用的时候按顺序写多个-pincus launch images:ubuntu/24.04 build01 -p default -p role-build -p env-staging有个坑要提醒profile 里的配置是快照式应用的修改 profile 之后已经存在的实例不会自动跟着变除非你显式执行incus profile assign重新分配或者重启实例。这个设计是为了避免一次误操作影响成百上千个运行中的实例但第一次遇到会让人以为配置没生效。3.4 项目天然的多租户隔离边界project 用来把一套 Incus 拆成互相看得见的隔间。每个 project 有自己独立的实例列表、独立的镜像命名空间可以选择是否隔离、独立的 profile甚至可以有独立的资源配额。incus project create staging \ -c features.imagesfalse \ -c features.profilestrue \ -c limits.containers20 \ -c limits.virtual-machines5 \ -c limits.memory32GiB \ -c limits.cpu16这里features.imagesfalse表示镜像命名空间共享默认项目的这样不用为每个项目重复拉镜像省磁盘features.profilestrue表示 profile 隔离让每个项目能自己定义角色配置。配额项里limits.memory是对该项目下所有实例内存之和的约束limits.cpu是 CPU 核数总和的上限。切换到某个项目操作加--project参数就行incus list --project staging incus launch images:alpine/3.20 a1 --project staging实际用下来project 最实用的场景不是真多租户而是把生产、预发、测试彻底隔开。三个环境在同一个 Incus 里各自有配额谁也影响不到谁但基础设施只需要维护一套。4. 从零到可用实例、网络、存储、快照全流程概念讲完了进入实际动手部分。这一章我按创建第一个实例到能当私有云用的顺序走一遍每条命令都说明意图。4.1 启动第一个系统容器最简单的命令只有一行incus launch images:debian/12 web01launch是创建并启动的合体命令。执行完你会看到它自动从远程拉镜像、解压、配置网卡、启动实例几秒钟之后incus list就能看到它处于 RUNNING 状态。进去看看incus exec web01 -- bash注意那个--分隔符前面是 Incus 参数后面是要在实例里执行的命令。这个分隔符不加的话Incus 会把你后面的参数当成自己的参数解析报莫名其妙的错。在实例里你可以像操作一台机器一样apt update、装服务、改配置。退出来之后用incus info web01看整体状态特别注意输出里的 IPv4 地址NAT 网桥下的实例会分到一个私网地址。给实例加资源限制也是直接设配置incus config set web01 limits.cpu 2 incus config set web01 limits.memory 2GiB incus config set web01 limits.memory.enforce hardlimits.memory.enforce有两个值soft只在内存压力大时限制hard是硬上限超过就触发 OOM。生产环境我建议先用 soft 观察确认业务内存峰值之后再切 hard不然容易出现业务正常但被 OOM 打断的怪事。关于在容器里跑 Docker需要额外打开几个开关incus config set web01 security.nestingtrue incus config set web01 security.syscalls.intercept.mknodtrue incus config set web01 security.syscalls.intercept.setxattrtrue这三个设置缺一个都可能出现镜像能拉但容器起不来的症状尤其是构建镜像的时候需要创建特殊设备节点mknod不放开就会报权限错误。4.2 启动一台虚拟机并注入 cloud-init创建虚拟机的命令只多一个--vmincus launch images:ubuntu/24.04 vm01 --vm \ --config limits.cpu2 \ --config limits.memory4GiB虚拟机的初始化比容器慢一些因为要分配磁盘、启动 QEMU 进程、跑一遍 cloud-init 流程。第一次创建时如果卡住先看incus info vm01的状态和 console 日志incus console vm01 --show-log能看到引导输出比瞎猜快得多。给虚拟机注入 cloud-init 配置是自动化的关键。准备一个 YAML 文件#cloud-config users: - name: ops sudo: ALL(ALL) NOPASSWD:ALL shell: /bin/bash ssh_authorized_keys: - ssh-ed25519 AAAA...your-key-here package_update: true packages: - curl - htop runcmd: - systemctl enable --now ssh然后把文件内容塞进配置项incus config set vm01 cloud-init.user-data - cloud-init.yaml注意-表示从标准输入读取并且要在实例第一次启动前设置否则 cloud-init 已经跑完一轮就不会再生效。如果已经启动过先incus stop vm01设好配置必要时清掉实例内的 cloud-init 状态目录再启动。这里有几个经验点密钥一定要用你本地实际的公钥别照抄示例runcmd里避免写太复杂的脚本给一个引导文件让实例自己去拉更可靠如果 cloud-init 没生效直接incus exec vm01 -- cat /var/log/cloud-init.log看日志比在配置文件里反复猜要快。4.3 存储卷与宿主机文件共享实例和宿主机之间传文件有两个层次的做法。轻量的用incus fileincus file push ./config.yaml web01/etc/app/config.yaml incus file pull web01/var/log/app.log ./app.log加-r可以递归推目录加-p会保留权限位。这个方式适合配置文件、日志这类小文件。需要长期共享目录的时候用磁盘设备挂载更合适incus config device add web01 data disk source/srv/data path/data这个设备在容器里就是一次 bind mount在虚拟机里会用 virtiofs 或相应的共享机制实现。要限制为只读加readonlytrue。宿主机上那个源路径必须存在否则实例启动会失败这一点经常被忽略。如果需要一个独立的块级存储卷而不是目录绑定可以单独创建incus storage volume create default vol-data size50GiB incus config device add web01 vol1 disk pooldefault sourcevol-data path/mnt/vol独立卷的好处是可以单独打快照、单独迁移、单独挂到别的实例上做数据盘非常合适。4.4 网络配置网桥、静态地址、端口转发默认 NAT 网桥能满足大部分需求实例能出网宿主机能访问实例实例之间能互通但外网进不来。要让外网访问实例里的服务有三种方案。第一种是网络转发直接在网桥上做映射incus network forward create br0 203.0.113.10 incus network forward port add br0 203.0.113.10 tcp 8080 10.10.0.5 80意思是把外部地址的 8080 映射到内网实例的 80 端口。这个方案的好处是转发规则集中在网络对象上一眼能看完所有对外暴露的端口。第二种是给实例的网卡加转发设备incus config device add web01 wwwproxy proxy \ listentcp:0.0.0.0:8080 \ connecttcp:127.0.0.1:80这个写法把宿主机 8080 的流量转到实例内部的 80配置跟着实例走删实例时规则自动清理我更喜欢这种。第三种是直接让实例拿局域网地址。把实例接到 macvlan 类型的网络上或者在支持的环境里接物理网桥实例就能和局域网里其他机器平起平坐。要注意 macvlan 下宿主机和实例之间默认不能直接通信需要额外做一层虚拟接口这个坑我踩过。给实例设静态地址的做法是incus config device override web01 eth0 ipv4.address10.10.0.5用override而不是set因为 eth0 是 profile 里定义的设备实例级别的修改要覆盖父级。4.5 快照、备份、迁移数据安全的三个层次我把这三件事分成三个层次理解快照是本地瞬间回滚点导出是离线归档复制/迁移是跨实例或跨节点的搬运。快照最简单incus snapshot create web01 pre-upgrade incus snapshot list web01 incus snapshot restore web01 pre-upgrade打快照前有个细节要注意如果实例里跑着数据库内存里的脏页和磁盘不一定一致快照恢复后可能崩溃。做法是先在实例内做一次 flush或者直接incus stop之后快照。对容器来说incus snapshot create默认是含状态的还是纯磁盘要看具体驱动ZFS 下可以做到很接近瞬时。导出成归档文件incus export web01 /backup/web01-$(date %F).tar.gz --optimized-storage--optimized-storage会利用存储后端的特性减少数据量ZFS 下它会走 send 流速度快、体积小。导入用incus import可以在另一台机器上恢复。复制和迁移incus copy web01 web02 # 同机复制 incus copy web01 remote:web02 # 复制到另一个远程 incus move web01 --target node2 # 迁到集群里的另一个节点跨机复制的速度瓶颈通常是网络和存储。如果实例带独立存储卷记得卷也要一起搬incus copy加--instance-only就只搬实例不搬卷这一点特别容易漏。提醒快照不是备份。快照和实例在同一块存储上存储池坏了快照一起坏。真备份必须导出到另一台机器或另一套存储。5. 组集群把几台物理机拼成一个资源池单机的 Incus 已经很好用了但真正体现编排管理引擎价值的是集群。Incus 的集群是内置的不需要额外部署控制面组件架构上是由数据库和 API 组成的轻量集群。5.1 集群组建的前提与步骤组建之前先想清楚一件事存储要不要共享。如果用 ZFS/LVM 这类本地存储实例是绑定在具体节点上的节点挂了实例不会自动飘走只能靠手动迁移或备份恢复。如果用 Ceph 这类分布式存储实例可以在节点之间自由迁移容错能力完全不同。我的建议是先想清楚你能不能接受节点故障需要人工介入如果不能那存储方案就得提前定成分布式的。组集群的动手流程大致是这样在第一台机器上启用集群并给它起名然后在第一台上生成加入令牌到第二台上用令牌加入。命令形态类似incus cluster enable node1 incus cluster add node2 # 输出一个加入令牌 # 在 node2 上 incus cluster join token集群是有成员数要求的两台机器只是个开始实际生产里至少三台更稳妥因为集群需要一定的共识节点数。加入之后用incus cluster list查看成员状态每个节点会有自己的角色标记。集群里有几个概念值得单独说incus cluster group可以把节点分组比如把高内存的机器分到mem-hungry组把带 GPU 的分到gpu组创建实例时用--target指定节点或者用--target group-name指定组引擎会从组里挑一个可用节点。这个机制做资源调度非常实用。5.2 实例迁移与故障处理集群里的迁移分两种冷迁移和热迁移。冷迁移是实例停着搬简单可靠热迁移是实例运行中搬要求后端存储支持共享且对内存状态有额外处理。日常我更常用冷迁移因为可控出问题好断点重来。手动迁移命令是incus move 实例 --target 节点。如果实例带独立的存储卷需要先移卷再移实例或者直接接受它跟着一起走。批量操作的时候可以写个循环但一定要加错误处理和 sleep集群在短时间内接受大量迁移任务时容易出现状态等待。故障处理方面最容易遇到的是节点失联。集群里某个节点因为网络或硬件原因掉线它在数据库里的状态可能会一直显示为在线或需修复这时候不要直接强行踢节点先在剩余节点上确认集群健康状态看是不是网络分区导致的。真需要踢掉节点用对应的集群成员移除命令注意移除前先把该节点上的实例处理好否则实例会变成孤儿需要按存储路径手工恢复。5.3 和 Kubernetes 的衔接思路Incus 和 Kubernetes 不冲突反而能互补。一个很实用的组合是用 Incus 提供稳定的系统环境Kubernetes 在上面跑业务容器。具体有两种典型做法一种是把 Incus 的虚拟机当作 Kubernetes 的节点。你可以用批量脚本创建十几台配置一致的虚拟机用 cloud-init 自动装好容器运行时和加入集群的脚本然后跑kubeadm join。这样节点环境完全可复制扩缩容就是多创建几台虚拟机。另一种是把 Incus 的系统容器当作构建节点或者持久化工作负载的载体。CI 系统需要一个能跑 Docker 的构建环境用 Incus 系统容器开一个就完事配好security.nestingtrue之后容器里跑 Docker 毫无问题。需要注意的边界是别在 Incus 里再套一层完整的 Kubernetes 控制面去做同一件事那会变成两套编排系统互相打架。分清谁负责机器谁负责应用就不容易乱。6. 故障排查实录我踩过的那些坑这一章是我自己遇到过的真实问题按现象、排查、解决的结构整理。写完这一章你大概率能省下好几个晚上。6.1 实例启动失败常见原因现象一incus launch卡在启动阶段状态一直是 STARTING。排查顺序先看incus info 实例再incus console 实例 --show-log看引导日志。最常见的原因是存储池空间不够——尤其是 ZFS 上没设配额镜像解压时才发现空间不足。其次是镜像本身损坏删掉本地缓存的镜像重新拉一次即可。现象二容器启动后立刻退出状态是 STOPPED。这多半是容器内的 init 或服务启动失败。用incus start 实例 --console附着上去看输出或者在启动参数里加boot.autostartfalse让它停在停止状态慢慢查配置。还有一个隐蔽原因是 profile 里的设备配置冲突比如 root 磁盘大小设得比已有数据还小。现象三容器里跑 Docker 报权限错误。前面提到的三个安全开关没打开是主因。另外还要检查存储驱动某些叠加文件系统上的存储驱动会报错把 Docker 的数据目录换到普通目录通常能绕开。6.2 网络不通的分层排查法网络问题我按从内到外的顺序排实例内部incus exec web01 -- ip addr看网卡有没有拿到地址ip route看默认路由。没地址说明 DHCP 没拿到可以手动设静态地址验证。宿主机到实例在宿主机上ping实例的私网地址。不通的话看网桥状态incus network list和ip link show。实例到外网实例内ping一个公网地址。不通通常是 NAT 或 DNS 的问题检查网桥的ipv4.nattrue是不是开着实例内的 DNS 配置是不是指向可用服务器。外网到实例检查转发规则有没有配对端口和协议注意 TCP 和 UDP 是分开配的配了 TCP 不代表 UDP 通。还有一个特别容易忽视的点宿主机上的防火墙规则可能会拦掉网桥转发的流量。排查时可以先临时放行验证确认是防火墙问题后再加精确规则别直接把防火墙全关。6.3 存储与快照相关的问题快照删不掉通常是有子快照或者正在被某个操作引用。incus snapshot list看全量列表按依赖顺序从新到旧删。存储池显示空间不足但磁盘还有空间这种情况在 LVM 上最常见是 thin pool 用满了需要扩容 thin pool而不是扩文件系统。ZFS 上则是配额和实际占用要分开看。实例迁移时报存储不支持跨存储池迁移必须显式指定目标池而且源和目标后端要能对接。某些后端之间不能直接搬只能走导出导入。6.4 虚拟机专属问题虚拟机的问题相对集中在几处启动慢通常是磁盘 IO 或内存不足无法进入图形控制台要先确认实例用的是 UEFI 还是传统引导以及控制台类型对不对KVM 不可用就是/dev/kvm不存在检查内核模块和 BIOS 设置虚拟机里想再跑虚拟机则要确认嵌套虚拟化参数已经生效通过cat /sys/module/kvm_intel/parameters/nested或对应 AMD 路径确认。6.5 排查速查表现象最可能原因快速验证处理方式实例卡在 STARTING存储空间不足incus storage info扩容或清理容器立即退出init 启动失败incus console --show-log修正启动命令容器内 Docker 报错安全开关未开查security.nesting打开三个开关实例无 IPDHCP 未获取ip addr设静态地址外网访问不通转发规则缺失incus network forward list补转发规则快照删除失败存在子快照snapshot list按序删除虚拟机无法启动无 KVM 支持ls /dev/kvm开启虚拟化迁移失败存储不共享查存储后端类型先导出再导入7. 安全加固与生产实践的几条硬规矩最后聊聊安全。Incus 默认已经比很多人想象的谨慎但生产环境还是要主动加固尤其是镜像安全和容器安全这两块。7.1 非特权容器与 idmap默认情况下 Incus 创建的是非特权容器容器内的 root 通过用户命名空间映射到宿主机上的一个高段 UID容器里我是 root在宿主机上其实是个普通用户。这个机制是安全的基础别为了图省事打开security.privilegedtrue。需要处理宿主机和容器之间的文件权限时用 idmap 显式映射incus config set web01 raw.idmap both 1000 1000这表示容器内的 UID 1000 和宿主机的 UID 1000 互相映射。挂载共享目录时如果权限不对多半就是这里没配对。如果想让每个实例有独立的 UID 区间可以开隔离模式incus config set web01 security.idmap.isolatedtrue incus config set web01 security.idmap.size65536这样即使多个实例使用相同的内部 UID在宿主机上也不会互相冲突。7.2 镜像来源与校验镜像安全是整条链路里最容易被忽略的一环。我的做法是只从可信的远程源拉镜像自建镜像在 publish 前清理掉所有带凭证的文件导出的镜像文件用哈希校验之后再入库并且给本地镜像打上明确的别名和说明避免团队里有人随手拉了来路不明的镜像就直接跑生产。如果团队规模大到需要私有镜像仓库可以自己搭一个兼容简单流协议的镜像服务用incus remote add挂上去。注意要开 HTTPS 并做好访问控制不要图方便内网明文裸跑。7.3 项目隔离与资源配额多团队共用一个 Incus 的时候一定要用 project 隔开并且给每个 project 设配额。项目级别的limits.cpu、limits.memory、limits.containers是防止某个团队用光整台机器的有效手段。配额的粒度也值得注意一个是项目总和上限一个是单实例上限。我一般会在项目层设总量在 profile 层设单实例上限两层都设既防个别实例失控也防总量超卖。7.4 备份策略与恢复演练备份这件事我的规矩是三条快照做恢复点导出做归档异地复制做灾难恢复。三层缺一层都不算完整。日常每天定时给关键实例打快照保留最近七天自动清理更早的周级每周导出一次归档到独立的备份存储保留四周月度每季度做一次恢复演练从归档恢复到一个临时实例确认能起得来、数据对得上最后这条最重要也最容易被跳过。备份文件存在不代表能恢复只有真正演练过的备份才算数。我见过备份跑了两年从来没恢复成功的案例原因只是一个存储驱动的选项在升级后行为变了。顺带说一句关于升级。Incus 的版本迭代节奏不快但生产环境升级前一定要先在测试环境从旧版本数据上演练一遍升级和回滚确认实例能正常启动再检查存储驱动的兼容性说明准备好数据库和关键实例的导出文件最后选一个流量低的时间窗一台一台滚动升级。集群环境下要避免同时重启所有节点否则会有实例状态不一致的风险。这套东西我用了大半年从单机上的几个实例到现在一个小集群上跑着几十个容器和十几台虚拟机最直观的体会是它把机器这件事变得和进程一样可编排。你不用再纠结某个服务是放在虚拟机还是容器里先用同一个命令行把它跑起来之后想换形式也可以直接复制和迁移。真要说有什么遗憾就是文档相对薄很多参数得靠incus config set --help和实际试错才能摸清楚所以上面这些经验才值得记下来。
返回列表