服务器之家

服务器之家 > 正文

一文教你探测虚拟环境是物理机、虚拟机还是容器?

时间:2021-01-12 23:14     来源/作者:高效运维

目前裸机(物理机)、虚拟机、容器是云计算提供计算服务的三种主流形式。那么如何判断一个虚拟shell环境到底是物理机、虚拟机还是容器呢?

更进一步,如果是物理机,这个物理机厂商是什么,虚拟机到底是 KVM 还是 XEN,容器是 Docker 还是 rkt、lxc 等?

更进一步,如果是虚拟机,是否可以判断这个虚拟机是运行在 AWS 还是阿里或者 OpenStack,是否能够获取虚拟机的 UUID、instance-type、vpc-id、安全组等信息?

这有点像我们在开发中经常使用的反射(reflection)机制,通过反射可以知道一个类实例(instance)的类(class)是什么,更进一步可以知道这个类的父类是什么、实现了哪些方法、包含哪些属性等。

以下是我用到的一些方法,仅供参考。

1、判断容器

目前还没有什么方法能够100%准确判断虚拟环境是否是容器,至少我没有找到相关文献。

如果环境有systemd-detect-virt命令,则可以直接通过systemd-detect-virt -c命令判断,如果输出为none则不是容器,否则会输出容器类型,比如lxc。目前很少容器里面放systemd的,我见过的就只有 LXD 的ubuntu镜像,因此这种方法适用性不广。

除此之外,可通过其他tricks判断,最简便的方法判断PID为1的进程,如果该进程就是应用进程则判断是容器,而如果是init进程或者systemd进程,则不一定是容器,当然不能排除是容器的情况,比如LXD/lXC实例的进程就为/sbin/init。

容器和虚拟机不一样的是,容器和宿主机是共享内核的,因此理论上容器内部是没有内核文件的,除非挂载了宿主机的/boot目录:

一文教你探测虚拟环境是物理机、虚拟机还是容器?

另外,我们知道容器是通过cgroup实现资源限制,每个容器都会放到一个cgroup组中,如果是Docker,则cgroup的名称为docker-xxxx,其中xxxx为Docker容器的UUID。

而控制容器的资源,本质就是控制运行在容器内部的进程资源,因此我们可以通过查看容器内部进程为1的cgroup名称获取线索。

如下是我通过 Docker 跑 busybox 的 cgroup 信息:

一文教你探测虚拟环境是物理机、虚拟机还是容器?

我们不仅可以知道这是 Docker 容器,还获取了 Docker 容器的 UUID 为 9ba…11。

根据如上的结论,判断一个虚拟环境是否 Docker 的脚本为:

一文教你探测虚拟环境是物理机、虚拟机还是容器?

当然如果仅仅判断是否 Docker 容器,还能通过判断是否存在 .dockerenv 文件区分是否Docker 容器:

一文教你探测虚拟环境是物理机、虚拟机还是容器?

rkt 容器类似,输出结果如下:

一文教你探测虚拟环境是物理机、虚拟机还是容器?

如上的 \x2d 为-号:

一文教你探测虚拟环境是物理机、虚拟机还是容器?

因此判断一个虚拟环境是否 rkt 的脚本为:

一文教你探测虚拟环境是物理机、虚拟机还是容器?

好奇 AWS lambda 的运行环境是什么,于是写了个函数输出 /proc/1/cgroup,结果为:

一文教你探测虚拟环境是物理机、虚拟机还是容器?

猜测是一种叫 sandbox 的运行环境,估计也是一种容器。

判断虚拟环境是否为容器环境相对比较复杂,目前没有完美的方案,总结过程如下:

判断是否可运行 systemd-detect-virt -c 命令,如果输出为 none 则不是容器,否则可确定容器类型。

判断 PID 1 如果为应用本身,则该虚拟环境是容器,否则不能确定是否是容器。

判断是否存在加载的内核文件,如果不存在,则可判断为容器,否则不能确定是否为容器。

判断是否存在 /.dockerenv 文件,如果存在则为 Docker 容器,否则不能确定是否为容器。读取 /proc/1/cgroup 文件,判断是否包含 docker、rkt 等关键字,如果包含,则说明为容器,否则不能确定是否为容器。

另外,需要特别注意的是,容器必须最先判断,因为容器本身并没有任何的硬件虚拟化,容器看到的硬件特性信息和宿主机看到的完全一样,因此下面介绍的通过lscpu以及DMI信息判断是否是虚拟机或者物理机,对容器并不适用。换句话说,不能因为lscpu的Hypervisor vendor值为KVM就说明一定是KVM虚拟机,因为它也有可能是容器。下文均假设已经排除为容器的情况。

2、判断物理机

如果使用了 systemd,则可以直接通过 systemd-detect-virt 命令判断是否物理机:

一文教你探测虚拟环境是物理机、虚拟机还是容器?

如果输出为 none,则说明是物理机。

当然也可根据 lscpu 命令输出,看是否有 Hypervisor vendor 属性,如果没有该属性,则一般为物理机,如果存在该属性则一定是虚拟机:

一文教你探测虚拟环境是物理机、虚拟机还是容器?

获取物理机的信息最直接的方式是查看 DMI 信息 /sys/firmware/dmi/tables/DMI,使用 dmidecode 命令解码:

一文教你探测虚拟环境是物理机、虚拟机还是容器?

如上可以看出这是台物理机,厂商为 HP,型号为 ProLiant DL380 Gen9,序列号为6CU6468KKD。

通过 ipmitool 命令可以查看物理服务器的带外 IP:

一文教你探测虚拟环境是物理机、虚拟机还是容器?

当然如果是虚拟机,如上命令会执行失败。另外也可以通过其他命令查看物理信息,如lshw 命令。

3、判断虚拟机

其实前面已经提到了,如果使用了systemd,则可以直接通过 systemd-detect-virt 命令判断是否虚拟机:

如果是虚拟机,则会输出虚拟机类型,如 kvm、oracle(virtualbox)、xen 等。

当然也可根据 lscpu 命令输出,查看 Hypervisor vendor 属性值:

一文教你探测虚拟环境是物理机、虚拟机还是容器?

通过如上命令,我的一台 AWS 虚拟机输出为 Xen,阿里云虚拟机为 KVM,VirtualBox虚拟机也输出为 KVM,这是因为我使用了 KVM 硬件加速虚拟化。

我的搬瓦工虚拟机输出也为 KVM,可见搬瓦工主机也是 KVM 虚拟机。

通过如上方法可以获取虚拟机的虚拟化类型,能否获取更多信息呢?参考物理机的获取方式,我们可以通过 dmidecode 命令获取更多的虚拟机信息。比如我在一台 OpenStack 虚拟机运行如下命令:

一文教你探测虚拟环境是物理机、虚拟机还是容器?

如上 Manufacturer 为 OpenStack Foundation,说明运行在 OpenStack 平台,Version为 Nova 版本,根据 OpenStack 的 releases 可知 15.0.1 对应为 OpenStack Ocata 版本,而 UUID 即虚拟机的 UUID。

AWS 上的一台虚拟机输出为:

一文教你探测虚拟环境是物理机、虚拟机还是容器?

在 Version 中标明了 amazon 字样。

阿里云虚拟机如下(感谢L神提供的输出):

一文教你探测虚拟环境是物理机、虚拟机还是容器?

可见虽然可以从 system 信息中获取云厂商的线索,但其实虚拟机的 system 信息并没有统一的标准,有的在 version 中体现,有的在 Product Name 中表现,完全取决于云厂商自己的配置。

如上整合如下脚本初略判断:

一文教你探测虚拟环境是物理机、虚拟机还是容器?

如上也可以判断公有云是否基于 OpenStack 实现,比如华为虚拟机输出为 OpenStack,可大致猜测华为的公有云是基于 OpenStack 实现的。

AWS 以及 OpenStack 系的虚拟机还可以通过 metadata 或者 ConfigDrive 获取更多信息,以 metadata 为例:

获取虚拟机的 ID:

一文教你探测虚拟环境是物理机、虚拟机还是容器?

获取 instance type (规格):

一文教你探测虚拟环境是物理机、虚拟机还是容器?

获取虚拟机的公有IP(弹性IP),这个挺有用的,因为在虚拟机没法通过ifconfig查看弹性IP,经常登录虚拟机后,忘记自己的公有IP:

一文教你探测虚拟环境是物理机、虚拟机还是容器?

其他的比如 vpc-id、ami id(镜像id)、安全组、公钥名等都可以通过该方式获取。

如果是 OpenStack,还可以使用 OpenStack 的 metadata 获取更多信息:

一文教你探测虚拟环境是物理机、虚拟机还是容器?

如上可获取虚拟机的租户 ID、volume type 等信息。当然邪恶点可以通过查看 userdata获取虚拟机初始化 root 密码。AWS 甚至可以查看 AccessKeyId 以及SecretAccessKey。

4、总结

如上总结了几种判断虚拟化环境类型的方法,不一定准确,仅供参考,当然也可能还有其他更好的方法。

如下是根据前面的结论写的一个探测虚拟化类型的脚本,不一定健壮完备,仅供参考:

一文教你探测虚拟环境是物理机、虚拟机还是容器?

一文教你探测虚拟环境是物理机、虚拟机还是容器?

原文地址:https://mp.weixin.qq.com/s?__biz=MzA4Nzg5Nzc5OA==&mid=2651694337&idx=1&sn=8dd8ebdbe7c2ea68572c68613a499cf8&chksm=8bcb66a8bcbcefbeb1143b3e3bd6b7c583e03574f353b0c30d185e35c7bff203198e12a6b2ba&mpshare=1&

相关文章

热门资讯

2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
Intellij idea2020永久破解,亲测可用!!!
Intellij idea2020永久破解,亲测可用!!! 2020-07-29
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
歪歪漫画vip账号共享2020_yy漫画免费账号密码共享
歪歪漫画vip账号共享2020_yy漫画免费账号密码共享 2020-04-07
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总 2020-11-13
返回顶部