1.2 容器与虚拟机:两种载具之争


1.2 容器与虚拟机:两种载具之争

本节摘要:容器与虚拟机都在做隔离,但隔离的对象不同——虚拟机隔离整台机器(含内核),容器隔离进程视图(共享内核)。本节承接上一节的"反例实验",从架构、启动速度、资源密度、安全边界四个维度讲透两者的取舍。

同一艘船的两种租法

上一节末尾我们用内核版本实验证明了容器不是虚拟机。本节接着往下挖:既然两者都在"隔出一片独立空间",它们的隔离方式到底差在哪?这个问题决定了你在实际项目里怎么选型——选错了不是不能用,而是白白付出十倍资源或者背上不该背的安全风险。

把码头比喻用到底,隔离有两种租法:

整船出租(虚拟机)。货主租下整艘船:船有自己独立的引擎、独立的船员编制、独立的导航系统,甚至船体都和别的船物理分开。想跑什么货、按什么航线走,全凭自己做主。代价是显而易见的——租整条船贵,起航前的例行检查慢,而且船上的引擎无论装多少货都要全功率待命。

标准箱共享船舱(容器)。所有货主共用同一条母船的引擎和船员(宿主机的操作系统内核),每个货主只租用自己的标准箱(容器),箱子与箱子之间有隔舱(命名空间),甲板上给每个箱子划定了载重配额(控制组)。起吊一只箱子只需几十秒,一天能装卸上千箱。

架构对比:差的那一层就是内核

看图说话,两种载具的堆叠结构差异一目了然。

图 1-1:虚拟机与容器的堆叠结构对比

图 1-1:虚拟机与容器的堆叠结构对比

图里的关键差异只有一处:虚拟机的每个实例带着自己的客户操作系统(独立内核),容器共享宿主内核。共享内核是容器一切优势与一切争议的总根源——

  • 优势一:启动快。容器进程不需要引导一个操作系统,本质只是被隔离的普通进程,启动以秒计,甚至以毫秒计。
  • 优势二:密度高。没有每个实例一套内核的开销,一台宿主机轻松跑几十上百个容器,同样的硬件能装下多得多的业务。
  • 争议:隔离弱。所有容器共用一个内核,内核漏洞理论上可能被利用来越狱(第 7 章的安全基线会讲怎么防御)。

用数据说话:启动时间与开销

架构差异落到数字上才直观。下面这个实验可以在任何装了 Docker 的机器上复现,用 time 命令测量从发令到容器启动完成(执行 echo 并退出)的耗时:

# 测量容器启动耗时:创建容器、运行 echo、退出 time docker run --rm alpine echo "箱子就位" # 输出示例: # 箱子就位 # real 0m0.812s <- 不到一秒,其中还包含镜像层解压检查 # user 0m0.052s # sys 0m0.019s

作为对照,一台普通云虚拟机从发出开机指令到 SSH 可登录,通常需要数十秒;带完整初始化脚本的虚机模板甚至要几分钟。数量级的差距来源于结构差异:容器没有"开机"这个环节,它只是启动了一个被限制视野的进程。

内存开销的差距同样悬殊。一个空载的 Alpine 容器进程组,额外内存开销通常在几 MB 量级;而一台最小化安装的 Linux 虚拟机,仅内核与基础服务就要吃掉数百 MB。同一台宿主机,容器方案的部署密度轻松达到虚拟机方案的一个数量级以上。密度优势可以亲手测出来:

# 同时起三只 nginx 箱子,观察整机资源占用 docker run -d --name density-a nginx:1.25-alpine docker run -d --name density-b nginx:1.25-alpine docker run -d --name density-c nginx:1.25-alpine docker stats --no-stream | grep density # NAME CPU % MEM USAGE / LIMIT MEM % # density-a 0.05% 6.1MiB / 3.7GiB 0.16% # density-b 0.04% 6.3MiB / 3.7GiB 0.17% # density-c 0.05% 6.4MiB / 3.7GiB 0.17% # 三只在航箱子合计不足 20MiB —— 这就是共享内核的密度红利 docker rm -f density-a density-b density-c > /dev/null # 演习完清场

选型:什么时候用哪个

工程上的取舍从来不是"谁取代谁",而是"谁在什么场景里划算":

维度 虚拟机 容器
隔离对象 整台机器(含内核) 进程视图(共享内核)
启动速度 分钟级 秒级以内
单实例开销 GB 级内存 MB 级内存
镜像体积 数 GB 起 数 MB 到数百 MB
跨内核 可以(客户机任意系统) 不行(镜像须匹配内核体系)
典型场景 强隔离多租户、异构系统 微服务、CI/CD、弹性伸缩

几个具体判断:给不同客户出卖算力的公有云底层,选虚拟机——强隔离是产品底线;公司内部的微服务与流水线,选容器——密度与速度直接换成真金白银;在一台 Windows 物理机上要跑老版本 Linux 应用,虚拟机——容器跨不了内核;要在同一套微服务里让某个遗留组件独占一套内核规避兼容性风险,容器里再嵌虚拟机(或反过来)都可行,两条技术路线本来就设计成可以叠用的。

容器的轻是拿安全边界换的:共享内核意味着容器的隔离强度上限低于虚拟机。把不可信代码隔离跑起来这件事,要么用虚拟机,要么在容器上叠加更多防线(用户态内核、沙箱运行时),第七章会展开。

体积账本:磁盘上的第三笔账

启动与内存之外,还有一笔容易被忽略的账——磁盘。虚拟机的交付物是整块磁盘文件,容器的交付物是分层压缩的镜像,量级差距同样是结构性的:

# 看一只最小化箱子的占地 docker images alpine # REPOSITORY TAG IMAGE ID CREATED SIZE # alpine 3.20 91ef0af61f39 2 weeks ago 7.8MB # <- 一整套能跑起来的用户态,不到 8MB

对照之下,一台最小化安装的 Linux 虚机磁盘文件普遍从数百 MB 起步。差距的来源还是那一条:箱子不装内核、不装管理程序、不装开机引导,只装应用真正用得上的用户态。三笔账——启动以秒计、内存以 MB 计、磁盘以 MB 计——叠加起来,就是第 6 章敢把十几个服务编成一队货轮的底气所在。

本节要点回顾

  • 隔离对象不同是两种载具的全部差异之源:虚拟机隔离机器,容器隔离进程视图。
  • 共享内核换来秒级启动与高密度,也带来隔离上限的争议。
  • 实测数据:容器启动不到一秒,虚拟机数十秒起;开销差一到一个数量级。
  • 选型不是二选一:强隔离用虚拟机,高密度快迭代用容器,两者可叠加。
  • 记住那个一行的验证实验:容器里看内核版本,和宿主机一模一样。

下一步沿时间轴看 Docker 自己的故事:它没有发明容器,却让容器成了人人能用的集装箱——靠的是什么。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U