← 全部笔记

Linux 入门 · 10 虚拟机与沙箱

隔离的层次:每层隔开了什么

隔离是给一组程序划定运行边界:它能看到什么、能使用多少资源、请求交给哪个内核。边界让环境更一致、并行任务互不干扰,也让权限分配更清楚。

约 15 分钟 · 截至 2026-11-06,Ubuntu 26.04 LTS · 观察命令未实测

用户权限

程序权限检查宿主内核

共享 内核、目录树、网络

隔离 按身份限制操作

代价 启动快,增量开销低

chroot

程序新的 /宿主内核

共享 内核、网络

隔离 绝对路径的起点

代价 启动快,增量开销低

容器

程序独立视图宿主内核

共享 宿主内核

隔离 目录、进程、网络视图

代价 通常快、开销低

用户态内核
gVisor

程序Sentry宿主内核

共享 底层宿主内核

隔离 应用的内核接口

代价 轻量启动,调用有代价

轻量虚拟机
microVM

程序客体内核精简虚拟硬件

共享 物理硬件

隔离 独立内核、内存与设备

代价 精简启动,需客体内存

完整虚拟机

程序与系统客体内核通用虚拟硬件

共享 物理硬件

隔离 独立内核、内存与设备

代价 通常更重,设备更全

从共享同一个内核,走向独立客体内核 → 边界的位置改变了。速度与开销为定性比较,具体配置可能改变排序。

  • 宿主内核管理底层资源
  • 工作负载程序及其可见环境
  • 新增内核边界Sentry 或客体内核
图 1 六层改变的是共享与隔离的位置;microVM 与完整虚拟机都拥有客体内核。

学完你能

身份与路径

用户权限限制操作,chroot 改变路径起点

普通用户权限回答“谁能做什么”。你在进程、用户与权限里见过:内核依据进程的用户身份等信息检查访问。两个普通用户可以有不同的文件权限,但仍使用同一棵目录树、同一个网络环境;同一用户启动的两个任务也不会自动获得各自的项目边界。

chroot(change root,改变根目录)把一个进程解析绝对路径时的 / 换到指定目录。它常用于准备系统文件或修复环境,提供另一套目录布局;它没有另起内核,也不自动隔开网络、进程列表或资源用量。手册明确说它不是完整的安全沙箱。

普通进程从宿主 / 开始找文件

程序:打开 /etc/config 解析路径 宿主 / etc/configsrv/rootfs/etc/config 宿主内核检查文件权限

chroot 只替换进程的根目录

程序:打开 /etc/config 从新的 / 找起 宿主 /srv/rootfs → 进程 / etc/config 仍由宿主内核检查文件权限
图 2 同一个绝对路径可以指向不同位置,路径起点的变化没有建立新的内核边界。

两个程序只做了 chroot,分别进入不同目录,都想监听同一个地址的 8080 端口。chroot 能自动避免端口冲突吗?

选择第二项。chroot 只改路径解析;两个程序仍在同一个网络环境里。要让它们各用自己的 8080,需要另外建立网络隔离,或选择不同地址、端口。

深入一点:为什么新 / 不能单独当作安全边界?

chroot 不会关闭已打开的文件,也不改变当前工作目录。进程可能仍持有目录树外的访问入口;有足够权限的进程还可能改变自己的运行条件。这里仅用它理解“路径视图”,不运行需要特权的 chroot 实验。

视图与额度

容器分开资源视图,仍共用宿主内核

容器是一组在指定视图与权限下运行的进程。命名空间(namespaces)让进程看到各自的挂载点、进程编号或网卡和端口;控制组(control groups,cgroups)负责分组统计、限制 CPU、内存等资源。镜像提供文件环境,运行时负责把这些设置组合起来。

所以你可以从同一个镜像启动多套环境,各用自己的可写目录与网络视图。它们仍把系统调用交给宿主内核处理;容器镜像里的 Ubuntu 文件系统不会附带一颗正在运行的独立内核。回看镜像与容器,就能把“打包环境”和“执行边界”接起来。

同一个宿主内核物理 CPU、内存、磁盘仍共享 同一镜像 → 两份环境 测试 A测试 B自己的可写目录自己的可写目录 进程视图 A进程视图 B 网络 A :8080网络 B :8080 内存上限 1 GiB内存上限 1 GiB 处理调用
  1. 先确定同一个镜像,固定程序与依赖文件。图中是结构示例,不是命令执行记录。
  2. 给 A、B 各自的文件环境和可写目录;挂载命名空间决定各自看见哪些挂载点。只有不同目录,进程列表也会自动分开吗?
  3. 另外建立进程编号(PID)命名空间,给它们各自的进程视图。文件隔离并没有代替这一步。
  4. 网络命名空间让两边各有端口空间,可以分别监听 8080。是否对外连通,要再配连接和访问规则。有了各自的视图,内存就会自动均分吗?
  5. 不会。这里再用 cgroups 各设 1 GiB 内存上限;上限是限制,不是预留或保证。
  6. 两边的调用仍由同一个宿主内核处理。图的最后一层始终没有复制。
图 3 容器的文件、进程、网络视图和资源上限需要分别建立,底层共用宿主内核。

把四项需求交给对应机制;先选条目,再选类别。

  • A 看不到 B 的工作目录挂载
  • A 的内存上限是 1 GiB
  • A、B 分别监听自己的 8080
  • 限制 B 能使用的 CPU 时间
namespaces:分开视图
cgroups:管理额度

“看见什么”与“用多少”是两条轴。只有命名空间并不能保证资源可控;只有配额也不会自动分开目录、进程或网络。

你想并行跑 20 个来自同一可信项目的测试环境,依赖一致、端口互不冲突、内存有上限,不需要更换内核。优先选什么?

终端是交互入口,不会自动建立文件、端口与资源边界。

chroot 没有分开网络空间,也不限制内存用量。

容器复用内核,适合这类高密度环境。需要为每份环境指定工作目录、网络与配额;“有 20 个容器”仍不等于总资源足够。

深入一点:容器的权限边界还靠什么?

实际运行时通常还组合 capabilities(把特权拆成小项)、seccomp(限制可用系统调用)和 AppArmor(按策略限制资源访问)。它们仍由宿主内核执行。原理放在后续的容器隔离页;本页不要求你配置这些机制。

调用路径

gVisor 接住系统调用,虚拟机运行客体内核

需要缩小应用直接接触宿主内核的范围时,可以增加一层内核边界。gVisor 是一种沙箱运行时,用运行在用户态的应用内核 Sentry 实现 Linux 系统调用接口。应用先请求 Sentry;Sentry 及配套组件再通过受限的路径使用宿主资源。它不是单纯的调用过滤器,也不是启动一套通用客体 Linux。

microVM(轻量虚拟机)则真正启动客体内核。以 Firecracker 为例,它利用 Linux 的 KVM(Kernel-based Virtual Machine,内核虚拟机支持)提供硬件虚拟化,并精简虚拟设备。完整虚拟机同样有客体内核,但通常提供更通用的设备与系统环境;“轻量”主要说明取舍,不能单凭名称判断隔离强弱。

普通容器

工作负载视图 应用:读文件 / 发请求 系统调用 宿主 Linux 内核 管理资源 宿主硬件

gVisor

工作负载视图 应用:读文件 / 发请求 系统调用 Sentry 应用内核 受限访问 宿主 Linux 内核

microVM / 完整 VM

工作负载视图 应用:读文件 / 发请求 系统调用 客体 Linux 内核 虚拟设备 监控器 / KVM → 宿主硬件
图 4 沿系统调用往下追:普通容器到宿主内核,gVisor 到 Sentry,虚拟机到客体内核。

例如同一份 Linux 应用可以交给普通容器运行时,也可以在兼容性允许时交给 gVisor;镜像相似,调用路径已经不同。Kata Containers 则把容器管理接口与轻量虚拟机结合起来,让工作负载在客体内核内运行。它可以使用不同监控器,不能把 Kata 当成 Firecracker 的别名,也不能假设每个容器必有一台单独 VM。

沿图中的调用路径填空,写“宿主”“Sentry”或“客体”。

普通容器的系统调用由 内核处理;gVisor 的应用调用先到 ;microVM 内运行的是 内核。

这三个入口的差别比工具名称更有用。gVisor 仍使用宿主内核来获得底层资源,只是应用不直接使用宿主完整的系统调用接口;虚拟机把客体内核放进虚拟化边界。

深入一点:gVisor 是否一定不用硬件虚拟化?

不一定。gVisor 有不同的系统调用拦截平台,其中也有基于 KVM 的实现。它的关键区别是由 Sentry 实现应用内核接口,而不是是否出现 KVM 这个名字。图只比较应用的请求路径,省略了文件代理等配套组件。

共享与代价

独立内核增加选择,也增加启动与维护成本

启动更少的系统,通常就能更快、更省地复制环境。权限、chroot 和普通容器不需要引导新内核;gVisor 要额外处理系统调用,开销与兼容性取决于应用。microVM 保留客体内核但精简设备;完整虚拟机更适合通用系统环境,也通常要准备更多客体内存、系统文件和维护工作。

下面的“独立视图”不等于独占物理设备,也不等于无法连接。共享目录、虚拟网卡和网络路由可以按需接通边界;隔离层不会替你决定哪些数据应该开放。启动耗时还受镜像是否已下载、缓存、客体服务和快照影响,这里不列未经测试的毫秒或内存数字。

层次内核文件系统网络启动与资源取舍
普通用户共用宿主内核同一目录树,按权限访问共用网络环境直接启动进程;增量成本低
chroot共用宿主内核改变根目录;不复制底层文件不会自动改变无需新内核;需准备可用文件环境
普通容器共用宿主内核挂载视图可分开;挂载可共享可独立网络空间;也可配置共享通常启动快、密度高;要明确设配额
gVisorSentry 实现应用接口;底层依赖宿主沙箱文件视图;映射可共享可用沙箱网络栈;依配置接通轻量启动;调用和输入输出可能更贵,须验兼容性
microVM独立客体内核客体文件系统;后端存储仍在宿主客体网络栈 + 虚拟网卡设备精简,仍需客体内存和启动过程
完整虚拟机独立客体内核客体磁盘;可显式共享目录客体网络栈 + 虚拟网卡通用设备、完整系统;通常启动与维护更重

需要验证时,先观察两类信息:发行版文件说明用户态环境,内核信息说明当前接口报告的内核。下面是可在已有 Ubuntu 26.04 终端与其普通容器内分别运行的只读观察命令,不安装软件、不改系统;本环境没有 Docker 或 Ubuntu 虚拟机,未实测,不提供输出。

# 在宿主终端与普通容器内各运行一次,再比较
cat /etc/os-release
uname -r

在原生 Linux 宿主的普通容器里,前者读容器文件,后者报告共享内核的信息。单凭一条 uname 不能鉴定隔离强度,沙箱可以实现自己的报告接口;Docker Desktop 或 WSL2 还可能先有一层 Linux 虚拟机。若要安装运行时或修改系统配置,建议在虚拟机或容器里试。

你要验证某个 Linux 内核补丁,必须实际启动修改后的内核。只更换容器里的 Ubuntu 镜像够吗?

选择第一项。普通容器换的是文件环境;补丁需要真正运行在内核里。选择支持目标内核与设备的完整 VM 或适合的 microVM,再验证补丁已引导生效。

按场景选择

先明确需要隔开什么,再选择最低够用的一层

选择从需求开始:环境差异、权限范围、资源用量和内核需求各是什么?对可信项目的 20 份短测试,容器常是合适起点;对不信任的外来代码,优先评估 gVisor 或虚拟机边界,同时核对兼容性、资源额度、挂载与联网范围。需要不同内核时,选择能启动目标内核的 VM。

agent 作为协作者,也需要清楚的工作环境。并行任务可以各有工作目录、依赖、缓存和资源额度;哪些凭据、文件和服务可访问应显式分配。Git worktree能分开检出目录,但本身不隔开内核、网络或权限。更细的组合留给进程级沙箱与 agent 环境。

宿主目录 /work/shared 显式挂载 /project 沙箱内的程序 请求服务 Sentry 或客体内核
图 5 显式共享的目录仍是入口,增加内核边界不会撤销已授予的数据访问。

给不信任的代码选了 microVM,却把存有私钥的目录以可读方式共享进去。请解释:独立内核解决了什么,为什么仍应调整挂载?

独立客体内核把应用与宿主内核隔在虚拟化边界两侧;但共享目录是主动提供的访问通道。程序依然可以按授予的权限读取其中的私钥。应只提供任务所需的文件,把凭据移出共享范围,按需设置只读、联网和资源额度。

  • 区分内核边界与文件访问授权
  • 说明共享目录中的可读凭据仍可被读取
  • 提出减少共享范围的具体调整

服务要执行外部用户提交的 Linux 程序。希望减少它直接接触宿主内核的接口,暂时不需要完整桌面系统。哪个方案最符合这些条件?

chroot 只替换路径起点,应用仍直接调用宿主内核。

镜像提供用户态文件,不会为普通容器创建独立内核。

gVisor 与 microVM 提供两种不同的内核边界,适合进一步评估。还应以真实工作负载验证功能和开销;已授予的文件、网络访问与资源额度仍需配置,不能由工具名称代替。

带走的模型

沿着视图、额度与内核三条线检查边界

上一页的磁盘与文件加密讨论数据何时能解开;本页讨论数据可用后,运行中的程序能接触哪些资源。下一页继续拆开虚拟机:Hypervisor、KVM/QEMU、Multipass 与 WSL2,看独立客体内核具体运行在哪里。

来源与核对范围

以下为截至 2026-11-06 核对的一手资料。Ubuntu 26.04 LTS 是本路线的学习环境;gVisor、Firecracker、Kata 是可选技术,不表示 Ubuntu 默认已安装或采用它们。

  1. Linux credentials(7):进程用户身份与权限检查;chroot(2):路径解析的变化及安全边界限制。
  2. Linux namespaces(7):各类命名空间隔离的资源;内核 cgroup v2 文档:资源分组、控制与限制。
  3. Docker Engine security:容器组合命名空间、控制组与权限机制。
  4. gVisor 架构导论:Sentry、请求路径与边界;性能指南:系统调用与输入输出开销;网络配置:沙箱网络与配置选择。
  5. Firecracker 官方说明:KVM、精简设备与 microVM;本页未引用官网启动速度作为实测数据。
  6. Kata Containers 架构:容器接口、轻量虚拟机与客体内核。
  7. Ubuntu Server:虚拟化与容器:系统容器、应用容器和虚拟机的区别。
  8. GNU uname(1) 手册与 os-release 说明:内核信息与发行版文件的不同含义。观察命令未实测,无终端输出。