Windows Server 2019 的6處變化,提升您的 Windows 容器體驗(二)
出品丨Docker公司(ID:docker-cn)
編譯丨小東
每週一、三、五,與您不見不散!
目前,有大量的應用程式以 Docker 容器的形式執行在 Windows Server 2016 上,但 Windows 容器一直與 Linux 容器在效能方面存在著一些細小的差距。但是,在已經到來的 Windows Server 2019 中,它彌補了大部分的效能差距,因此現在的 Windows Docker 容器幾乎與 Linux 容器旗鼓相當。接下來,我將介紹餘下的內容,點選下列標題了解前一部分內容:
- ofollow,noindex" target="_blank">Windows Server 2019 的6處變化,提升您的Windows容器體驗(一)
使用 VIP 服務發現
接下來將介紹 Docker Swarm 模式的第二個增強功能。Swarm 通過 DNS 提供服務發現,因此容器可以通過服務名稱相互引用,Docker 將其解析為容器的 IP 地址。這是一種使用現有技術連線服務的非常簡單的方法,因此它對於在容器中執行的應用程式是透明的。
服務發現有兩種模式:VIP 和 DNSRR 模式。VIP 模式使用的是虛擬 IP 地址,當容器進行 DNS 查詢時,它在響應中獲得單個 IP 地址,該地址是虛擬地址。網路層實際上是將其路由到執行服務副本的某一個容器中。DNSRR 模式也是 DNS 迴圈,DNS 響應包含所有容器IP 地址的列表,以隨機順序提供負載均衡。
VIP 模式是更好的選擇,因為它不會對快取 DNS 響應的客戶端(幾乎每個DNS客戶端)造成任何問題。如果在服務中替換容器,則虛擬IP地址保持不變,並且客戶端請求將始終路由到活動的容器。如果客戶端快取響應,DNSRR 模式可能會出現問題,因為響應是單個容器的 IP 地址,當更換該容器時,客戶端無法訪問該服務,直到 DNS 快取過期並獲得新響應。
DNSRR 有很好的用途,特別是對於使用 DNS 發現叢集中其他節點的叢集技術。在 Docker Swarm 模式中管理負載均衡和擴充套件叢集也涵蓋了這一點。
Windows Server 2016 僅支援 DNSRR 服務發現,但 Windows Server 2019 不僅支援 DNSRR 服務發現還支援 VIP 服務發現。與入口網路一起,這意味著您可以在群集模式下執行高度可用、高度可擴充套件和彈性的服務。
我已經為 Docker 示例投票應用程式添加了 Windows 1809 版本。您可以使用此 Docker 應用棧檔案在 Windows 1809 版本的叢集上執行該應用程式,該檔案使用入口網路和 VIP 服務發現:
Docker 示例投票應用程程式碼: https://github.com/dockersamples/example-voting-app
iwr -useb -outf docker-stack-windows-1809.yml ` https://raw.githubusercontent.com/sixeyed/example-voting-app/master/docker-stack-windows-1809.yml docker stack deploy -c .\docker-stack-windows-1809.yml vote
現在,您可以在叢集中的任何節點上瀏覽到在 5000 埠上的投票應用程式,並且四個投票應用程式容器中的一個容器將處理該請求:
做出選擇後,應用程式將向執行在容器中的 CNCF-incubating NATS 訊息佇列傳送訊息,然後三個訊息處理程式容器中的一個容器將處理訊息並將資料儲存在與 mysql 相容的 TiDB 資料庫中 —— 在容器中執行。瀏覽到 5001 埠,您將看到來自投票結果應用程式的總數。
這些都是基於 1809 版本的 Windows Nano Server 基礎映象構建的小映象。
卷掛載具有可用的目錄路徑
Docker 卷(Volume)是您將儲存與容器生命週期分開的方式。您將卷附加到容器,它將作為容器檔案系統中的一個目錄出現。您的應用程式寫入“C: jenkins”(或您安裝的任何路徑)並且資料實際儲存在卷中,該卷可能儲存在 Docker 主機上。就像伺服器上的 RAID 陣列,或資料中心中的單獨儲存單元,或雲端儲存服務。
容器內的掛載應該對應用程式透明,但實際上在 Windows Server 2016 中使用的是符號連結目錄,這就導致了一些問題。
這是一個基本問題,首先執行互動式 Windows Server Core 2016 容器,Docker 卷將本地目錄掛載到容器內的目標 C: mount 中:
docker container run -it --rm ` -v C:\temp:C:\mount ` microsoft/windowsservercore:ltsc2016
檢查容器中的目錄列表,你會看到“C: mount”實際上是 SYMLINKD(符號連結目錄)型別,它對映到一個危險的檔案路徑“ [\?ContainerMappedDirectories…”:
Microsoft Windows [Version 10.0.14393] (c) 2016 Microsoft Corporation. All rights reserved. C:\>dir C:\ Volume in drive C has no label. Volume Serial Number is 5AC2-AFC5 Directory of C:\ 11/22/2016 11:45 PM1,894 License.txt 10/22/2018 01:01 PMmount [\\?\ContainerMappedDirectories\C4CCB043-FA0A-49DE-88F0-F408917EC284] 06/28/2018 07:55 PM PerfLogs 06/28/2018 08:04 PM Program Files 07/16/2016 02:18 PM Program Files (x86) 10/22/2018 01:01 PM Users 10/22/2018 01:01 PM Windows 1 File(s)1,894 bytes 6 Dir(s) 21,218,250,752 bytes free
這會導致底層語言嘗試解析符號連結並使用目標路徑的應用程式出現問題,因為它們會識別雙反斜槓和問號。
這個問題在 Windows Server 2019 中將不再是問題。在執行 Docker 的 1809 版本的機器上執行相同的命令:
docker container run -it --rm ` -v C:\temp:C:\mount ` mcr.microsoft.com/windows/servercore:1809
現在列表顯示“C: mount”作為標準目錄:
Microsoft Windows [Version 10.0.17763.1] (c) 2018 Microsoft Corporation. All rights reserved. C:\>dir C:\ Volume in drive C has no label. Volume Serial Number is 961D-F4E8 Directory of C:\ 09/15/2018 10:42 AM5,510 License.txt 10/04/2018 11:08 AM mount 09/15/2018 05:44 PM Program Files 09/15/2018 10:42 AM Program Files (x86) 09/15/2018 10:45 AM Users 10/22/2018 01:05 PM Windows 1 File(s)5,510 bytes 5 Dir(s) 21,242,155,008 bytes free
它仍然是一個使用容器外部儲存的卷,由Docker管理,但現在它對應用程式完全透明。將我的 Windows Server 2019 的 Jenkins Dockerfile 與我的 Windows Server 2016 的 Jenkins Dockerfile 進行比較,你會發現它更容易閱讀。
卷掛載可以覆蓋現有目錄
Windows Server 2016 還存在一些其它的關於卷的問題。一個是如果該目錄已經存在於 Docker 映象中,則無法使用目標目錄進行卷掛載操作。
許多應用來說都存在這個問題,,因為配置目錄附帶了映象中的預設配置檔案。在 Linux 上,您可以執行容器並使用卷的內容覆蓋 config 目錄。但在 Windows 2016 上您就不能這樣做了,您必須編寫一個 Dockerfile 來打包你的自定義配置。
或者使用 Web 伺服器,如果您想使用預設映象,又想從卷中提供自己的內容,那麼您將從 Windows Server 2016 中收到錯誤提示:
PS> docker container run -d ` -p 8041:80 ` -v C:\web:C:\nginx\html ` sixeyed/nginx:windowsservercore-ltsc2016 13f9f189ef9b5a73b700b79556aa002fd8fb3ce5f70ced21e364d5b4ac708446 C:\Program Files\Docker\docker.exe: Error response from daemon: container 13f9f189ef9b5a73b700b79556aa002fd8fb3ce5f70ced21e364d5b4ac708446 encountered an error during CreateContainer: failure in a Windows system call: The directory is not empty. (0x91) extra info:
您得到的錯誤訊息 —— 該目錄不是空的。
在 Windows Server 2019 中解決了該問題。現在,您可以在現有目錄上掛載卷並替換其內容,因此容器可以檢視卷的內容而不是映象中的內容:
PS> docker container run -d ` -p 8041:80 ` -v C:\web:C:\nginx\html ` sixeyed/nginx:windowsservercore-1809 42ed3441e2e2cebc37cac6ecac927ece45c65f877d4c072be4f5ff2dcef7ddcf
在 Windows Server 2019 中將不再出現該問題的錯誤提示了。 現在,當我瀏覽應用程式時,我會看到我的網頁,而不是預設的 Nginx 頁面: