Windows Docker第一時間揭祕-盆盆跑微軟兩會

【編者的話】這是盆盆談微軟兩會(Build/Iginte)系列之一。文章引用孫建波老師關於Linux內核的6大命名空間隔離,看Windows Docker如何實現相似隔離,同時又有哪些不一樣。文章素材取自Build和Ignite大會視頻,但主要展現盆盆本身的分析和研究,還望你們指正爲謝。html


今天在微信羣裏聽一位兄弟提到,Docker能將DevOps(意即"開發"和"運維")整合在一塊兒,暗合王陽明先生的「知行合一」之教,這真是一種有趣的說法。linux


話說從頭,盆盆在《Windows Dcoker深刻原理分析》裏曾經提到Build大會後,您能夠在華來四公衆號裏回覆docker8,閱讀這篇文章(能夠在微信裏搜索並關注公衆號:sysinternal),會第一時間給你們介紹Windows Docker技術。docker


還沒看過Build在線視頻的朋友,您能夠泡杯咖啡,帶上耳機,靜靜地欣賞如下由Taylor Brown主講的Windows Docker講座,咱們的文章就以此爲藍本。這裏須要注意的是,如下的論述,大可能是盆盆根據Taylor的demo效果所作的推論,並非Taylor本人的陳述,因此並不必定正確。若有問題,還望你們多ubuntu

多指點哈。windows

http://channel9.msdn.com/Events/Build/2015/2-704sass


容器即隔離bash


拿你們熟悉的Linux Docker來看,其涉及到Linux內核所提供的Namespace隔離技術和資源控制的CGroup技術。微信


這裏推薦你們閱讀浙大SEL研究生孫建波老師的文章《Docker背後的內核知識——Namespace資源隔離》:網絡

http://www.infoq.com/cn/articles/docker-kernel-knowledge-namespace-resource-isolation?from=timeline&isappinstalled=0session


孫建波老師提到了一張表格,其中列出了Linux內核所支持的6種隔離:曰主機名、曰IPC、曰進程ID、曰網絡、曰文件系統、曰帳號。


儘管Windows內核實現和Linux不一樣,可是二者仍是有很多可比擬處。因此盆盆根據Build大會上Mark Russinovich這位大神以及Taylor Brown的講座,來條分縷析。


文件系統隔離


先來看看浙大SEL另外一位大牛孫宏亮老師的文章《Docker源碼分析(九):Docker鏡像 》。這篇文章清晰地描述了Linux Docker的文件系統隔離,多層的可疊加文件系統。

http://blog.daocloud.io/docker-source-code-analysis-part9/


孫宏亮老師指出:假設咱們下拉了Ubuntu:14.04映像,並經過命令docker run –it ubuntu:14.04 /bin/bash將其啓動運行。則Docker爲其建立的rootfs以及容器可讀寫的文件系統參見下圖。從容器的視角來看,雖然只有一個邏輯的完整文件系統,但該文件系統由「2層」組成,分別爲讀寫文件系統和只讀文件系統(按只讀層還能夠再邏輯分層,因此極大地節省磁盤空間)。

wKiom1Vhv2jzEwo1AACi-9Fcksw515.jpg


Windows Docker一樣如此,頂層的沙盒層(sandbox layer)是可讀寫的,只容許該容器本身佔用,而其餘層則是隻讀的,可供不一樣容器共享。在下圖中,底層的基礎OS層和中間的應用程序框架層都是隻讀的,而頂層的沙盒層則可讀寫,在容器的視角看來,它獨佔了完整的OS。這有點相似於Hyper-V的差別磁盤鏈(頂部的子盤才能讀寫,其上方的全部父盤和Base盤都是隻讀的)。

wKioL1VhwQOxUWXpAAGdUvZCbHE961.jpg


爲了說明文件系統隔離的魔力,Taylor得意地在Windows Container裏執行刪除C盤根目錄下全部文件和註冊表鍵值,儘管這個容器被毀了,可是根本不會影響其餘容器,更不會影響主機。

wKiom1Vhv4bw0Y-SAAHdz1pYCIc531.jpg


盆盆猜想,在容器的視角里,若是隻是讀取一個文件,該文件在最頂端的沙盒層裏只有重解析點(reparse point);只有在修改該文件時,纔會用copy-on-writer的方法從下方的只讀層中把文件內容複製到可讀寫的沙盒層。


建立Windows Container


視頻裏演示了一個很棒的demo。有一段簡單的代碼,在console裏顯示「This is a pretty cool app」。

wKioL1VhwSGy-eYpAADZmNs2ZaA806.jpg


這是用來構建Windows Docker映像的Dockerfile。這個文件由如下4行命令組成:

  • 第1行:代表該映像基於windowsservercore這個Base映像,能夠將其理解爲rootfs

  • 第2行:表示工做目錄是C盤根目錄

  • 第3行:將應用目錄複製到容器映像裏

  • 第4行:啓動該應用程序

wKiom1Vhv6fBToHaAAClhkuH2W8974.jpg


很快用docker build命令將其構建爲容器映像,Tag是1。從命令結果中能夠看到Dockerfile裏的每一個命令都被執行,在執行第4個命令時,會生成一個臨時的容器。

wKioL1VhwUGDwnqOAAG9Z1-E6SY488.jpg


Docker映像構建完成後,只需運行docker run命令便可快速啓動該映像,併成功顯示"This is a pretty cool app..."。

wKiom1Vhv7-wh6I7AADveoCZYAM167.jpg


經過使用docker history命令,咱們能夠查看容器映像的構建歷史,這甚至能夠用來逆向生成Dockerfile。例如視頻裏演示了sysinternals這個映像的構建歷史。從中咱們能夠看到:首先記錄維護人員是誰;而後指定工做目錄是C盤根目錄;再者是將sysinternals suite這個工具軟件目錄拷貝到容器映像裏;而後設定容器的運行帳戶;最後設置啓動Ipconfig以便顯示容器的IP地址。

wKioL1VhwVnicR6nAADvz1IJEyE289.jpg


IPC隔離


和Linux Docker Container同樣,Windows Server Container也採用IPC隔離機制。這其實是利用Windows本身的session隔離機制。


會話(session)隔離機制,最初是用在Windows終端服務和快速用戶切換中。可是從Windows Vista開始,Windows也採用這種技術對系統會話進行隔離,Windows系統的服務和進程會佔用原來的控制檯會話(會話0),然後續的用戶會依次使用會話一、會話2等等。


從《Windows Internals》裏咱們能夠學習到,不一樣會話裏的應用,不可以發送窗口消息(Window Message,以防止粉碎***)。不一樣會話裏擁有不一樣的對象命名空間,例如不一樣容器,有本身獨立的BaseNamedObjects目錄,包含事件、互斥信號和內存段等對象。這樣不一樣容器在同一個Windows主機上訪問同一個命名對象,就不會致使衝突。如下的WinObj截圖雖然不是取自Windows Docker系統,可是道理是同樣的。

wKiom1Vhv9qDwdwxAAJdagMAcS4426.jpg


有興趣的朋友能夠參考盆盆在9年前發表在ITECN博客上的文章,介紹會話隔離技術:

http://blogs.itecn.net/blogs/winvista/archive/2006/06/09/SrvSession0.aspx


視頻裏演示了Docker容器的會話隔離能力,Taylor啓動了兩個容器,都是從同一個windowsservercore映像裏建立出來。其中一個容器,能夠運行Tasklist命令,看到該容器運行在會話14中。並且還能看到兩個系統進程,一個是System進程,表明操做系統自己,另外一個是空閒進程,這兩個進程都運行在會話0裏。

wKioL1VhwXHysexjAAGpKjhgR5o804.jpg


在同一個映像所建立的另外一個容器裏,咱們能夠看到該容器運行在會話15中,一樣能夠看到System和空閒進程。Taylor的解釋是因爲容器是共享Windows Kernel的,因此容易能夠看到System進程的PID是同樣的,都是4。其實在全部Windows主機上,System進程的PID都是4。

wKiom1Vhv-_zB9D_AAHSSL_-Hw4832.jpg


網絡隔離+圖形化訪問


和Linux容器同樣,Windows容器也能夠有本身的獨立網絡配置。

wKioL1VhwZHhfeLzAAE29cREuQ8686.jpg


因爲傳統的Windows應用大可能是有GUI的,因此這些應用可能須要經過圖形化方式進行遠程操控。


視頻裏Taylor舉了一個sysinternals容器的例子。有趣的是,這個demo原本是Mark Russsinovich的保留曲目,惋惜Keynote的時間十分寶貴,最Mark沒能有足夠的時間去演示。


Taylor演示啓動Sysinternals Suite裏的經典工具Process Explorer,因爲該工具帶GUI,因此雖然進程已經在容器裏啓動,可是在Docker Client裏沒法直接遠程顯示。


如何才能正常顯示呢?Taylor用了一個CC命令,直接鏈接到該容器的IP地址。從demo裏咱們能夠看出,實際上這個CC命令鏈接到容器的RDP服務上,這樣就至關於直接經過終端服務鏈接到容器裏的會話裏。

wKioL1VhwbLzEHx7AAI9V74brwI268.jpg


盆盆在《Windows Dcoker深刻原理分析》裏曾經提到Windows Docker的前身DrawBridge在其沙盒裏實現了RDP服務(請在華來四公衆號裏回覆docker8,閱讀這篇文章),Windows Docker的原理應該相似。

wKiom1VhwDCBV5zVAADl8b8wTpI349.jpg


Linux Docker也能訪問圖形化界面,在如下的這篇文章《在 Docker 中運行 OpenOffice》裏介紹,只需在Dockerfiles裏添加安裝X Server的命令,就能借助VNC客戶端鏈接到OpenOffice圖形化界面。

http://linux.cn/article-5305-weibo.html


PID隔離


在Linux容器裏,容器裏的PID有本身的獨立命名空間。從演示的狀況來看,Windows容器的PID隔離方法看上去略有不一樣。


在前面IPC隔離一節,咱們能夠經過Tasklist命令確認不一樣的容器,其CSRSS、Lsass、SVCHOST等系統進程的PID有所不一樣,可見彼此之間是徹底隔離的。


那麼從宿主機的角度來看呢?


咱們能夠看Process Explorer的例子(該例子是在Ignite大會上由Taylor所演示的),因爲Process Explorer是在終端會話裏打開的,因此咱們能夠在容器的任務管理器裏看到有兩個會話

  • 14是Docker客戶端訪問的會話

  • 而15則是經過RDP訪問的會話


能夠看到Process Explorer的進程有兩個版本。顯然,會話14是Taylor在Docker客戶端裏運行的結果(可是咱們沒法看到圖形化界面),而會話15則是RDP訪問的結果。


二者的運行帳戶不同,RDP登陸的運行身份爲Administrator(應該和Docker History一致),而會話14則是System帳戶。


如下是容器裏的任務管理器。

wKioL1VhwciCfYlMAAIjFougUmY378.jpg


這個任務管理器是從容器的角度來看的,咱們能夠記下其中的若干SVCHOST進程的PID。接下來咱們打開宿主機的任務管理器,從全局的角度來查看。能夠發現,從宿主機的角度來看,能看到每一個容器裏的進程,其PID和容器裏面的版本是同樣的。

wKiom1VhwFfSjakCAAJ8PBbciQ4316.jpg


用戶帳戶隔離


Linux內核擁有帳戶隔離能力,可讓容器裏的進程以root身份運行,可是在宿主機上,該帳戶其實是普通用戶權限。


在Taylor的這個演示中,咱們也能「察覺」到一些蛛絲馬跡。在PID隔離一節的兩個任務管理器截圖裏,容器裏的版本能夠看到Process Explorer的運行帳戶爲Administrator,可是從宿主機上查看,該帳戶爲空。因此Windows容器有可能也實現了相似的帳戶隔離技術。


計算機名和域名隔離


Windows容器擁有本身的計算機名和域名隔離能力,這樣在網絡上,Windows容器看上去相似於一臺獨立的虛擬機。


不過因爲共享內核,因此Windows容器目前應該不支持活動目錄,畢竟同一臺宿主機上全部容器應該都具備同一個SID,這樣就沒法加域(沒法驗證計算機帳戶)。


盆盆推測,到了Windows容器時代,相似於活動目錄這類比較笨重的驗證協議可能會逐漸退出歷史舞臺。畢竟活動目錄須要開放那麼多端口,須要藉助ADFS等手段才能穿透Internet。

不過Windows容器的驗證並不會存在問題,Azure AD和證書等都是很合適的辦法。


容器的優點


容器很是適合開發的快速迭代、快速回滾。Taylor作了一個簡單的演示,對前面所述的代碼進行修改,調用私有的msvcr120.dll文件裏的_snwprintf函數。

wKioL1VhwhnwYqW_AAC5W_oOXgE378.jpg


可是在docker build的時候,Taylor沒有修改Dockerfile,沒有像Mark以前的demo那樣把私有的msvcr120.dll拷貝到容器映像中,生成新的映像Layer。

wKioL1VhwjLxJDDYAADtSLmnNpM049.jpg


結果因爲容器的目標宿主機上沒有安裝Visual Studio,因此新Build的容器運行失敗,提醒缺乏msvcr120.dll文件。

wKiom1VhwLPC-RVmAAERGGVks1A250.jpg


解決辦法很簡單,要麼修復這個Bug,要麼根據先前的映像快速生成新的容器,這隻須要花費幾秒鐘時間!


解決這個問題很簡單,能夠根據先前的映像快速生成新的容器,這大概只須要幾秒鐘時間。這樣就能夠有充足的時間去調試修改了。

相關文章
相關標籤/搜索