Windows Docker的有趣事實

提示

本文最初發表於華來四公衆號,請掃描如下二維碼關注。給盆盆發微信(微信號:markpah),便可要求加入Windows Docker微信羣、或者微軟混合雲微信羣。您還能夠加入華來四QQ羣(423730487),以參加在線視頻講座。docker

wKiom1cHJsuSOSxEAABp2KWmV3g491.jpg


衆所周知,Docker能打通開發和運維的任督二脈,所謂DevOps是也。有朋友說,這符合王陽明的"知行合一"之教。ubuntu

 

而Windows Server 2016 TP4內置的Windows Docker亦已經出來一段時間,這裏就來和諸公彙報一下測試結果。windows

 

Linux和Windows,容器裏各有多少進程?bash


在安裝配置Container Host的時候,常常報錯Container OS Image下載失敗(沒辦法,牆內的緣故)。微信


什麼是Container OS?顧名思義,是從容器角度看到的OS。網絡


Container OS實際是應用所依賴的用戶模式(User mode)OS組件,對於Windows容器來講,例如ntdll.dll、kernel32.dll或者coresystem.dll之類的System DLL。主機上的全部容器共享內核模式(Kernel mode)OS組件,對於Windows,就是ntoskrnl.exe,還有驅動等。架構


例如對於如下命令,意味着Windows系統從docker映像中獲取Windows Server Core的用戶模式OS組件,並啓動cmd得到Shell。運維

docker run -it windowsservercore cmdide


Linux也是一理,若是運行如下命令,意味着從docker映像中獲取Ubuntu的用戶模式組件,而且啓動Bash Shell。工具

docker run -it ubuntu /bin/bash


對於以上兩個容器,Linux容器裏的進程比較少,能夠參考如下截圖:

wKiom1cRsyni1FpzAAGIn1uLX6I926.jpg

而Windows容器,則狀況略有不一樣。


在Windows主機上啓動Process Explorer,能夠看到這個Windows容器的進程相對多一些:

wKiom1cRtKnR3oFwAAlFKM7xgug817.jpg

這是由於在Windows系統中,須要給應用提供一些用戶模式的系統服務,例如DNS、DHCP、RPC等服務,這樣從容器的角度來看,容器得到了本身獨有的服務(通常是在各自的svchost裏運行),構成了所謂的Container OS。


咱們能夠用PowerShell命令查看容器內部啓動的Windows服務,大概有27個,參考附圖。

wKiom1cRtHnByIlNAAYaMLnowqM505.jpg


很惋惜,這個版本的Windows docker裏,雖然有遠程桌面服務,可是目前還不支持遠程桌面到容器,因此沒法使用容器應用的圖形化界面。


容器裏的應用,到底應該啓動多少Windows服務?因爲Windows服務的具體做用是非文檔化的,因此不像Linux能夠作到最精簡。可是因爲這些服務幾乎不佔用什麼額外的資源,對於容器性能沒有影響。


Windows容器的進程間怎麼隔離的?


在最新的測試版本里,容器對象的權限設置有了改變,只有SYSTEM權限才能查看。因此要查看Windows容器的進程隔離,須要用SYSTEM權限啓動Winobj。這能夠藉助Psexec來實現:

Psexec -i -d -s winobj.exe


能夠看到Windows對象空間裏多了一個Containers的節點,其下有若干個GUID分支,這些GUID表明系統裏的容器。其下每一個容器有本身獨立的BaseNamedObjects等命名空間,包括互斥信號量、內存Section、事件等。

wKioL1cRtbrCFQCmAAI57gSAY04674.jpg


能夠用PowerShell查看容器的GUID,參考附圖。

wKioL1cRtcqCJbM9AADLBoPrV-Y451.jpg


每一個容器節點下,有本身的Session分支,例如該容器,佔據了Windows系統的Session 2。如附圖所示。

wKiom1cRtSij3wS5AAIIFTqQfbY289.jpg

這就是爲何,無論用任務管理器,仍是PowerShell,抑或是Process Explorer等工具,咱們都在Windows主機裏看到容器裏的全部進程都會標記Session爲2。


藉助Process Explorer,咱們能夠看到容器裏的進程,所打開的Handle,其中就指向先前所看到的Windows容器對象命名空間。

wKioL1cRtgGBIeV3AAW-b5eUvNA537.jpg


同時還能看到,容器進程所在的WindowStation並非WinSta0,而是Service-0x0-3e7$,3e7的10進制等於999,等於九五之尊,這是SYSTEM服務所在的窗口站。因此容器進程沒法在Windows桌面上擁有圖形化界面。

wKioL1cRtoXwICZTAAgeP4-gpYQ626.jpg


還能夠查看一個有意義的對象,Windows容器所掛載的主機目錄,相似於Linux容器的Volume。

wKioL1cRtqWDy3dVAAPkQ73bwEc496.jpg


Windows容器的文件系統怎麼隔離的?


和Linux同樣,Windows容器映像採用分層的文件系統,基於映像建立容器後,至關於在只讀的分層文件系統上再覆蓋一層可讀寫的文件系統層。若是要修改的文件在最上層的可讀寫層裏沒有,則沿着分層的Layer找到目標文件後,將其用COW(Copy on write:寫時複製)複製到可讀寫層再修改。


讓咱們進入到Windows主機的如下目錄:

C:\ProgramData\Microsoft\Windows\Hyper-V\Containers


該目錄下列出全部經過PowerShell命令建立的容器文件。其下有文件夾和文件,都以容器的GUID來命名。

wKiom1cRtjbxAYwnAAUYGvvyu-s712.jpg


其中的926A300B-ACB7-4B28-9D86-45BF82C1211C.vhdx就是該容器的最上層的可讀寫層,是一個VHDX文件。


記住該可讀寫層並非一個完整的文件系統,它須要和Image的現有文件系統組成Union File System。若是嘗試雙擊該VHDX(只能嘗試掛載中止狀態的容器VHDX),試圖掛載到Windows系統,會彈出如下報錯信息,提示該虛擬硬盤沒法掛載。

wKiom1cRtubhxEuLAAFNljQwIqo295.jpg


Image的文件系統位於如下路徑(Windows Server Core的Container OS文件):

C:\ProgramData\Microsoft\Windows\Images\CN=Microsoft_WindowsServerCore_10.0.10586.0\Files


若是用Process Explorer查看容器進程訪問的Dll,能夠看到其訪問的路徑爲Container OS文件。

wKiom1cRtxLj6lHVAAZEqSe8sdI014.jpg


若是是用docker命令建立的進程,道理相似,可是其可讀寫層文件系統位於如下路徑:

C:\ProgramData\docker\windowsfilter

wKiom1cRt2_A3PvuAAWn7RWf7to967.jpg


Windows容器還有註冊表


和Linux不同,Windows容器須要考慮註冊表的隔離問題。


下面讓咱們進入PowerShell命令建立的Windows容器文件夾內部。

C:\ProgramData\Microsoft\Windows\Hyper-V\Containers\926A300B-ACB7-4B28-9D86-45BF82C1211C\Hives

wKiom1cRt_yRpi7OAAHsULkQsQ4385.jpg


在這個Hives文件夾下方,有不少命名爲*_Delta的文件,這是容器所訪問的註冊表配置單元文件。


從命名方式中能夠看到,容器的註冊表和文件系統同樣,也採用分層架構,最上層的是可讀寫的註冊表命名空間。而Image映像也有隻讀部分的註冊表空間,路徑以下。

C:\ProgramData\Microsoft\Windows\Images\CN=Microsoft_WindowsServerCore_10.0.10586.0\Hives

wKiom1cRuIGRwgEiAAH5S8IPJg8906.jpg


在Process Explorer裏能夠看到可讀寫層、只讀層註冊表合併後所加載的內容。

wKiom1cRuKzwAxo8AAoVotGDato324.jpg


Docker命令所建立的容器,方法相似,位於相似如下路徑:

wKiom1cRuQGj3cx9AAHqs4aJq44117.jpg


Windows容器的資源限制


你們知道,Docker能夠調用CGroup技術來限制Linux容器的CPU、內存等資源佔用。而在Windows容器裏,內存資源的限制,則是經過Windows的JO(做業對象)技術來實現。


能夠參考如下技術來限定Windows容器的CPU、內存和磁盤IO。例如能夠將容器的內存限定爲最大佔用爲5GB。

https://msdn.microsoft.com/en-us/virtualization/windowscontainers/management/manage_resources?f=255&MSPPError=-2147217396


而後用Process Explorer打開任意一個容器進程的屬性對話框,切換到Job標籤頁。

wKiom1cRuTGDIcNsAAFNRGAkCYw791.jpg

能夠看到全部容器進程共享一個做業對象,並且該做業對象的內存限額(Job Memory Limit)爲5GB。


寫到如今,手都酸了,此次就到這裏吧,下次有空再一塊兒討論容器的網絡隔離,和Azure container service整合等高大上的技術吧。

相關文章
相關標籤/搜索