当前位置: 首页 > news >正文

Windows Docker的有趣事实

提示

本文最初发表于华来四公众号,请扫描以下二维码关注。给盆盆发微信(微信号:markpah),即可要求加入Windows Docker微信群、或者微软混合云微信群。您还可以加入华来四QQ群(423730487),以参加在线视频讲座。

wKiom1cHJsuSOSxEAABp2KWmV3g491.jpg


众所周知,Docker能打通开发和运维的任督二脉,所谓DevOps是也。有朋友说,这符合王阳明的"知行合一"之教。

 

而Windows Server 2016 TP4内置的Windows Docker亦已经出来一段时间,这里就来和诸公汇报一下测试结果。

 

Linux和Windows,容器里各有多少进程?


在安装配置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 cmd


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整合等高大上的技术吧。


相关文章:

  • RSD和wlwmanifest是什么
  • 【烈日炎炎战后端】Zookeeper(0.5万字)
  • iOS 中runtime的运用原理
  • 【烈日炎炎战后端】Elecsticsearch(1.5万字)
  • TCP协议三次握手和四次挥手
  • 【烈日炎炎战后端】Nginx(0.3万字)
  • ESLint简单操作
  • 整体管理、范围管理
  • 【烈日炎炎战后端】编程题总结(13.3万字)
  • D3导出png,保存到本地
  • Yii2批量插入数据
  • Java垃圾回收机制
  • 我建了一个叫Hello World的项目
  • 上课笔记分享-1-第17课时-1-多域名-统一沟通-环境
  • 【烈日炎炎战后端の58万词の索引】
  • JS中 map, filter, some, every, forEach, for in, for of 用法总结
  • 【Amaple教程】5. 插件
  • 【剑指offer】让抽象问题具体化
  • android高仿小视频、应用锁、3种存储库、QQ小红点动画、仿支付宝图表等源码...
  • canvas 五子棋游戏
  • Docker下部署自己的LNMP工作环境
  • HTML5新特性总结
  • Java超时控制的实现
  • js写一个简单的选项卡
  • Just for fun——迅速写完快速排序
  • Linux快速复制或删除大量小文件
  • Median of Two Sorted Arrays
  • MobX
  • python_bomb----数据类型总结
  • thinkphp5.1 easywechat4 微信第三方开放平台
  • uva 10370 Above Average
  • 不上全站https的网站你们就等着被恶心死吧
  • 搭建gitbook 和 访问权限认证
  • 分享一份非常强势的Android面试题
  • 区块链技术特点之去中心化特性
  • 一起参Ember.js讨论、问答社区。
  • ionic入门之数据绑定显示-1
  • ​渐进式Web应用PWA的未来
  • ​如何在iOS手机上查看应用日志
  • ​软考-高级-系统架构设计师教程(清华第2版)【第12章 信息系统架构设计理论与实践(P420~465)-思维导图】​
  • # Java NIO(一)FileChannel
  • # MySQL server 层和存储引擎层是怎么交互数据的?
  • # 飞书APP集成平台-数字化落地
  • #100天计划# 2013年9月29日
  • #14vue3生成表单并跳转到外部地址的方式
  • #大学#套接字
  • (3)选择元素——(14)接触DOM元素(Accessing DOM elements)
  • (二)hibernate配置管理
  • (附源码)spring boot火车票售卖系统 毕业设计 211004
  • (附源码)spring boot球鞋文化交流论坛 毕业设计 141436
  • (附源码)ssm户外用品商城 毕业设计 112346
  • (免费领源码)python#django#mysql校园校园宿舍管理系统84831-计算机毕业设计项目选题推荐
  • (图)IntelliTrace Tools 跟踪云端程序
  • (五) 一起学 Unix 环境高级编程 (APUE) 之 进程环境
  • (原创)Stanford Machine Learning (by Andrew NG) --- (week 9) Anomaly DetectionRecommender Systems...