Windows Server 2019 的6处变化,提升您的 Windows 容器体验(二)-阿里云开发者社区

开发者社区> 开发与运维> 正文

Windows Server 2019 的6处变化,提升您的 Windows 容器体验(二)

简介: Swarm 通过 DNS 提供服务发现,因此容器可以通过服务名称相互引用,Docker 将其解析为容器的 IP 地址。这是一种使用现有技术连接服务的非常简单的方法,因此它对于在容器中运行的应用程序是透明的。

screenshot

出品丨Docker公司(ID:docker-cn)
编译丨小东
每周一、三、五,与您不见不散!


目前,有大量的应用程序以 Docker 容器的形式运行在 Windows Server 2016 上,但 Windows 容器一直与 Linux 容器在性能方面存在着一些细小的差距。但是,在已经到来的 Windows Server 2019 中,它弥补了大部分的性能差距,因此现在的 Windows Docker 容器几乎与 Linux 容器旗鼓相当。接下来,我将介绍余下的内容,点击下列标题了解前一部分内容:


使用 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 端口上的投票应用程序,并且四个投票应用程序容器中的一个容器将处理该请求:

screenshot

做出选择后,应用程序将向运行在容器中的 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 PM            1,894 License.txt 
10/22/2018 01:01 PM       mount [\\?\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 AM            5,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 页面:

screenshot

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章