攜程開始了對 Windows container 的調研工作,目前已經有一些成果和實際應用案例,與大家分享一下,主要內容有:
- 攜程為什麼要使用 Windows container (可能國內大部分的人瞭解 Windows container 少一些,特別是具體的實踐,分享重點會偏 Windows container 細節)
- 傳統.Net 應用容器化實踐
- 容器存儲&網絡&編排
攜程為什麼要做 Windows container ?
現狀:
- 攜程是.Net 應用大戶,由技術棧決定的,早期攜程整個應用架構都放在該平臺上,線上跑了 3000 多個核心應用,覆蓋了 20 多個 BU (業務部門),這讓我們不得不關注這一龐大的系統。
- 平臺要往 java 方面轉,去分享 java 的紅利,但是.Net 線上應用不可能都重寫;
- .Net 的應用目前 90%左右的應用都跑在虛擬機上,從虛擬機自身來看,粒度太粗,對資源的使用率還不是很好。
- 持續發佈,應用上線,從拿到機器環境準備好環境上線生產,虛擬機模式下週期長,擴容慢。
新一代發佈平臺的需求,希望縮短環境準備時間,做到秒級部署, Linux 平臺的應用非常容易做到,但是 Windows .Net 應用在這方面支持比較難,另外,為了確保生產和測試環境高度一致,希望應用發佈是單一應用、單一鏡像的,最好是一個容器儘量少的包含系統進程,這樣可以把資源隔離的粒度控制在小範圍內,儘量榨取宿主機的資源,同時希望 Linux 容器和 Windows 容器的方案儘可能接近,比如網絡、存儲,不需要兩套不一樣的方案或是有大的有變化。
一些 Windows container 的技術細節
最開始的時候攜程用物理機部署應用,為了保證互不衝突,用戶在一個物理機上只部署一個應用。後來認為此舉太浪費,就部署了多個應用,但是為管理帶來了麻煩,應用之間有一定的衝突或者相互影響。之後有了虛擬機,虛擬機上可以部署更多的應用,而且隔離比較好,不過虛擬機資源隔離的粒度太粗了,於是容器走了過來,能做到把一個應用打到包裡,這個包涵蓋了環境配置等, run 起來可以只是一個進程,又具備一定的隔離性,同時把資源使用的粒度控制足夠的細。
Windows container 目前支持的系統是 Windows server 2016 ,這個版本是去年 10 月份正式發佈的(攜程是國內比較早的一批拿到了他們的 RTM 版本),支持兩類 server ,一類是 server core ,另一類是 nano server 。 nano server 是微軟比較推薦的一類服務器系統,啟動非常快,可以大幅度縮短計劃內維護宕機時間,通常幾秒鐘就起來了,不包含硬件檢測的時間,幾十秒都能夠起來。這塊攜程還沒有用於生產環境,目前只測試了用 server core 作為容器宿主機的系統的情況。需要著重提一下的是,如果宿主機打了補丁或者升級,容器也要對應的做補丁或者升級。當然不一定說立馬做補丁升級,但一定要比較精確的找到對應的版本做升級。
Windows container 有兩種 container 類型,這兩種容器都是跑到 Windows servrer 2016 的,但還有一種容器的玩法是在 Liunx 平臺跑.Net core ,這種方案我們也看過,大家很容易想到它的侷限,其實只能跑到用.Net 技術開發的 Windows 的應用,一些非.Net 的應用不支持,因此這個方案被 Pass 了。直接在 Windows server 跑容器的方案更為靠譜,該方案有兩種類型, Windows server 和 hyper - v container 。
有人會問, hyper-v 不就是一個虛擬機的技術嗎?對,其實它有點像虛擬機,但是 hyper - v 的技術略有不同,速度會明顯比虛擬機快很多,只是在申請資源或者獲取資源時,比 Windows server Container 的速度稍稍慢一點點, Windows server container 可能 3 秒,它可能 4 、 5 秒。但是資源的隔離度比較好一些,類似於虛擬機,微軟公有云 Azure 的容器服務也是採取這種容器類型,他們的考慮是公有云上面部署的應用不是受信任的,相互之間有可能“打架”的情況發生,他想隔離好一些。
另一個區別, Windows server Container 的內核是共享的,可以在宿主機上看到每個容器裡面的進程,這與 Linux 容器相似,可以直接 kill 掉。 hyper-v container 宿主機是看不見容器內進程的,像一個虛擬機一樣。此外,內存資源隔離不同, Windows server Container 內存可以 share , hyper-v container 不能 share , hyper-v container 一旦分配就不能重新進行修改。對系統應用是信任的,這種比較適合做私有云的一些產品,因為在應用上跑的什麼東西,這個應用能幹什麼壞事或者是相互之間有沒有影響,都可以控制,但是公有云不能這樣做,應用使用率很高,會把別的容器影響到。啟動速度上也會有差別,一個啟動快,一個啟動慢一點,當然並不是特別慢。
容器鏡像,這個和 Linux 容器的鏡像類似,可以分層。最下面一層是基礎鏡像,但是基礎鏡像和 Linux 有區別。 Linux 鏡像可以自己搞,弄一個系統把它做成鏡像,但是微軟沒有辦法自己做一個 Windows container base 鏡像。或者說現在只是 Windows server 2016 的鏡像,想跑一個 2012 的系統是不行的。當前系統內核只能支持 win10 ,在上面可以繼續安裝想要的東西,比如接著安裝 Framework ,然後在最上面裝應用。
鏡像構建也是一樣, Windows container 容器和 Docker 集成比較好,可以用 Docker 工具的一些命令進行 build ,用 Dockerfile 來 Build 一個鏡像。 registry 是鏡像可以直接 push 到一個平臺或者是私有的 registry 上面去,通過 Docker pull 方式拉下來, Docker run 跑起來。
Windows container 的鏡像,可以在 Docker 網站上可以找到關於 Windows container 的一些 base image, pull 下來大概有 8G 左右,在外網上下載可能要兩天。大家可以嘗試一下。也可以建私有的 registry ,攜程採用的 VMware 開源的 Harbor 方案,本身沒有做太多的修改,直接可以用。和攜程的 AD 整合以後基本上能用了, registry 可以把 Linux 和 Windows 的鏡像都放在一起,兩邊都能用,都能管,這部分省掉了很多的內容,不需要做額外的開發,這樣 Windows 和 Linux 的平臺的 image 管理方案是一致的。
傳統.Net 應用遷移
遷移背景:
之前提到攜程有 3000 多個.Net 應用,這些應用每天要不停的發佈、測試、編譯打包,是一項很大的繁瑣工程,有個叫“ build ”的項目負責這個事情。最初這些跑在虛擬機裡,資源使用率很低,白天很忙,晚上使用率很低,有一定的資源浪費,且構建環境也經常不一致。為了積攢容器應用使用的經驗,我們考慮把 build 項目先容器化,也就意味著.Net 應用自己的編譯在容器裡面編譯,看能撞出來什麼樣的火花。
原來寫幾千個應用的編譯腳本,如果改了一些東西,變更維護的代價是非常大的,儘量這個方案不要用到原來以往用的工具和使用方式,不去動它,最好能夠拿過來不怎麼修改,就跑起來。另外,重點看一下像 vs2010 和 vs201 這樣的工具能不能在容器裡跑,實踐證明是可以的。然後看 MSBuild 在容器裡面是否兼容,支持不同的.Net Framework 版本,這些都是比較通用的軟件,結果是這些功能都能夠支持,另外也包括 python 、 MVC 、 GIT 等等。
遷移收益
- 首先環境,編譯的環境高度一致,每個環境沒有太多的區別,容器拉起來直接跑,提高了編譯成功率。
- 其次資源利用率提高了,我們把虛擬機資源砍掉了一半,就只需要兩臺宿機機搞定整個攜程 3000 多個.Net 應用的編譯。
- 編譯時長也縮短了,原來用一次構建平均要幾分鐘,現在 90 秒左右基本上能構建完成。
待解決的問題:
- 圖形不支持,這個是某些企業想用 Windows container 的大問題,它本身圖形不支持。後臺程序沒有太大問題,不過有一些依賴圖像工具比較難支持。
- 舊應用兼容不是很好。比如遇到 MGwin 編譯出來的包,一旦代碼中有調用標準輸出的語句程序直接就掛了,遇到這類問題,需要把源碼拉下來重新編譯,比較有難度。
- 不支持 RDP ,遠程桌面是不能用的,那怎麼做到遠程訪問呢? 還好 Windows 現在支持 SSHD 安裝了,只需要容器內裝一個 SSHD ,然後遠程 SSH 去,當然可以用 powershell 遠程的登錄方式,兩種方案都可以用, SSH 方案更統一一些, 如果用戶當前正在 Linux 平臺上工作,突然想登一個 Windows 的容器怎麼辦?當然也可以用 linux 平臺的 powershell 工具實現遠程登陸容器。
- 不支持 D 盤。攜程遷移過來很多老的應用是要裝在 D 盤的,容器拉起來沒有 D 盤,只有一個 C 盤。本身 Docker 有一個 volume 功能,可以掛一個數據的盤,問題是這樣會導致在宿主機上留下一些東西,和宿主機產生耦合,如果容器刪除或者遷移,宿主機上就留下了髒數據。後來我們為 D 盤做一個 link ,相當於 D 盤可以快捷的方式連到 C 盤,映射到 C 盤的某個目錄,這樣數據都是落地到在容器的磁盤上,如果想在別的地方拉起來這個容器,可以直接 push register ,就可以在別的地方部署且環境一樣。
存儲&網絡&編排
接下來 Windows container 容器的存儲,網絡,編排方面的技術與大家分享一下。
Windows container 資源的隔離方式和配置管理 API 是借用 Docker 規範,設計理念和 Linux Container 類似,也支持 CPU share 的這種方式去控制資源的分配。內存可以通過 quota 的方式去分配內存, Disk 也能夠充分應用到 IO 的帶寬,這一塊還沒有做非常多嚴格的測試。關於網絡的支持,攜程做了很多測試,整體來講比較不錯,問題較少。性能也滿足需求,多個容器在一個同一個宿主機上也能儘量用到整個宿主機的帶寬。
容器的存儲
存儲有三種:一種是鏡像,鏡像本身是一個存儲,設計之初定義就不是一個永久的存儲,當前容器存儲拉掉那個存儲就沒有了,也不是設計安全的。另外一種存儲是 volume (卷) ,可以掛一個數據盤到某一個容器上,在容器裡擴展存儲空間。同時多個容器也可以掛載宿主機上的一個同一個 volume (卷目錄),這樣大家可以實現 NFS 一樣的效果。最後一類存儲是網絡存儲,比如可以用 SMB 的方式掛網絡盤在容器裡面使用,裡面如果有萬兆的帶寬支持還可以玩一下,如果沒有萬兆帶寬的話就不要玩了,它只能放一些冷數據。
容器的網絡
相對來講複雜一些, Windows 支持有四種網絡模型,第一種 NAT 模式大家比較熟悉,起一個本地或者是數據本地的 IP 地址,如果你想外網訪問的話,把 Docker 映射出來,這種方式比較適合做一個 JOB 類型的應用在上面,不需要外邊可以訪問它,但是容器裡面可以去下載東西。之前講的 build 項目就是用這個網絡模型,非常簡單,不需要考慮太多網絡的模型就可以直接用。
第二種是 transparent 網絡模型,這種模型是現在主要用於生產的模型,首先它是通過 mac 地址偽裝實現數據透傳,對網絡的性能本身折損也比較少,它也支持把多個工作網卡綁到一個交換機上,然後把這個交換機給容器用。網絡模型在容器宿主機以外的機器上看到 Windows 容器和一臺物理機沒有什麼區別。
還有一種是 L2 bridge 這種採用 openstack 網絡的 Flat 模式,所用的網絡跟宿主機的網絡是一樣的,和宿主機在同一個網段,這樣有很大的侷限性,網絡和宿主機混在一起沒有辦法做到多租戶隔離,然後網段用光了就完了,適用於比較小的集群。
最後一種是 Tunnel mode ,沒有太多研究這一種,但是微軟 Azure 用的這一種網絡模型。本身攜程為了和虛擬機的很多的品牌網絡模型一致,所以這一種沒有那麼快的推進。
hyper-v 的網絡模型
Hyper-v 宿主機是 2012 上面 hyper-v 的網絡模型,之前要求一臺宿主機儘量要 4 塊網卡,為什麼要用 4 塊網卡?兩塊給虛擬機用,另外兩塊做一些管理,比如對存儲用,虛擬機遷移等,可以做宿主機的管理。另一種方式, 2016 建議的一種網絡方式,這裡面有一個叫做 embed team ,內嵌交換機,它的好處是把下面無論是兩塊還是 N 塊網卡都可以綁在一個 bound ,然後把這個 bound 放在一個交換機裡面,每個容器 port 全部放在交換機裡面,然後容器給 port 打相應的 vlan tag ,這樣容器的網就通了。
embed team 的好處是不需要要求宿主機一定要有這麼多的網卡才可以用,另一個好處是對這些不同的 vlan 之間做一些流量的控制,攜程的 container 的網絡模型也是基於嵌入式交換機上實現的。把宿主機至少兩塊網卡做了 bound ,放在一個 embed team 裡面去,另外加一個 port 給宿主機做管理網卡。容器宿主機相比虛擬機宿主機簡單,沒有存儲和遷移的需求,就不要以額外的劃分網絡了,如果需要為容器的存儲單獨掛一個網絡的話可以加一個 Port 做這個事情。不同的網段的這種容器在上面可以再創建不同的 Docker ,加不同的 port ,然後容器在裡面可以互通,這樣的好處就是既實現了多租戶、實現了網絡隔離,同時和虛擬機包括 Linux 上面的網絡模型是一致的。
容器編排
編排這塊通常一個容器部署到多個宿主機上,同時一套應用下來有數據層、業務層、也有 web 層,這些應用要分開放,它們中間放在哪裡需要有一個地方,把整個管起來,也希望這個東西能自動化,本身做編排這些,無論是 Swarm 、 K8S 、 Mesos 都是需要解決的問題。一種方案是用 Docker compose 這種方式,適合於單宿主機管理。想編排一下容器,看如何跑,這種方式用 Docker compose 就能解決。當然,微軟現在對 Docker Swarm 支持好一些,實現成本比較低,基本上能管,但是性能方面沒有做太多的測試,目前一些基本的調度、主機分類等等都能用。
為什麼攜程選擇使用 Mesos ?
因為攜程的 Linux 平臺用的也是這套方案做的編排相關的管理,希望有一套方案能夠儘量兩種容器一致,於是我們的方案採用 Mesos 加上 Marathon 對它進行管理,本身它也有一些現成的工具,比如 UI 等現成的工具都可以用,這部分還在進行測試和研究中。官方下來的包不能直接跑到 Windows server 上面,要拿下來重新編譯才能用。最終攜程是想做到這麼簡單的一個容器的管理的架構,就是說希望 Mesos 在裡面能夠同時管 Linux 容器和 Windows 容器,對它進行統一的調度,最大限度的優化這種調度策略,提升使用率,這是最終整體的設計理念。
https://www.v2ex.com/t/335653
閱讀更多 N維時空 的文章