国产韩日影视精品_中文字幕一区二区三区在线不卡_久久亚洲综合色一区二区三区 _国产成人久久久

【六六互聯】長期出售【美國抗投訴服務器】【歐洲抗投訴服務器】【亞洲抗投訴服務器】

目前裸機(物理機)、虛擬機容器云計算提供計算服務的主流形式

目前裸機(物理機)、虛擬機、容器是云計算提供計算服務的主流形式

目前裸機(物理機)、虛擬機容器云計算提供計算服務的三種主流形式。那么如何判斷一個虛擬shell環境到底是物理機、虛擬機還是容器呢?

更進一步,如果是物理機,這個物理機廠商是什么,虛擬機到底是KVM還是XEN,容器是Docker還是rkt、lxc等?

更進一步,如果是虛擬機,是否可以判斷這個虛擬機是運行在AWS還是阿里或者OpenStack,是否能夠獲取虛擬機的UUID、instance-type、vpc-id、安全組等信息?

這有點像我們在開發中經常使用的反射(reflection)機制,通過反射可以知道一個類實例(instance)的類(class)是什么,更進一步可以知道這個類的父類是什么、實現了哪些方法、包含哪些屬性等。

以下是我用到的一些方法,僅供參考。

01 判斷容器

目前還沒有什么方法能夠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虛擬機,因為它也有可能是容器。下文均假設已經排除為容器的情況。