细说Windows与Docker之间的趣事

作者   彭爱华    发布于   2016年8月30日

众所周知,Docker能打通开发和运维的任督二脉,所谓DevOps是也。有朋友说,这符合王阳明的"知行合一"之教。而Windows Server 2016内置的Windows Docker亦已经出来一段时间,这里就来和诸公汇报一下测试结果。

Linux和Windows,Docker里各有多少进程

在安装配置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容器里的进程比较少,可以参考以下截图:

而Windows容器,则情况略有不同。

在Windows主机上启动Process Explorer,可以看到这个Windows容器的进程相对多一些:

这是因为在Windows系统中,需要给应用提供一些用户模式的系统服务,例如DNS、DHCP、RPC等服务,这样从容器的角度来看,容器获得了自己独有的服务(一般是在各自的svchost或者其他服务宿主进程里运行),构成了所谓的Container OS。

我们可以用PowerShell命令查看容器内部启动的Windows服务,大概有27个,参考附图。

很可惜,这个版本的Windows docker里,虽然有远程桌面服务,但是目前还不支持远程桌面到容器,所以无法使用容器应用的图形化界面。

容器里的应用,到底应该启动多少Windows服务?由于Windows服务的具体作用是非文档化的,所以不像Linux可以做到最精简。但是由于这些服务几乎不占用什么额外的资源,对于容器性能没有影响。

Windows容器的进程如何隔离

由于在最新的测试版本里,容器对象的权限设置有了改变,只有SYSTEM权限才能查看。所以要查看Windows容器的进程隔离,需要用SYSTEM权限启动Winobj。这可以借助Psexec来实现:

Psexec -i -d -s winobj.exe

可以看到Windows对象空间里多了一个Containers的节点,其下有若干个GUID分支,这些GUID代表系统里的容器。其下每个容器有自己独立的BaseNamedObjects等命名空间,包括互斥信号量、内存Section、事件等。

可以用PowerShell查看容器的GUID,参考附图。

每个容器节点下,有自己的Session分支,例如该容器,占据了Windows系统的Session 2。如附图所示。

这就是为什么,不管用任务管理器,还是PowerShell,抑或是Process Explorer等工具,我们都在Windows主机里看到容器里的所有进程都会标记Session为2。

借助Process Explorer,我们可以看到容器里的进程,所打开的Handle,其中就指向先前所看到的Windows容器对象命名空间。

同时还能看到,容器进程所在的WindowStation并不是WinSta0,而是Service-0x0-3e7$,3e7的10进制等于999,等于九五之尊,这是SYSTEM服务所在的窗口站。所以容器进程无法在Windows桌面上拥有图形化界面。

还可以查看一个有意义的对象,Windows容器所挂载的主机目录,类似于Linux容器的Volume。

Windows容器的文件系统如何隔离

和Linux一样,Windows容器映像采用分层的文件系统,基于映像创建容器后,相当于在只读的分层文件系统上再覆盖一层可读写的文件系统层。如果要修改的文件在最上层的可读写层里没有,则沿着分层的Layer找到目标文件后,将其用COW(Copy on write:写时复制)复制到可读写层再修改。

我们进入到Windows主机的以下目录:

C:\ProgramData\Microsoft\Windows\Hyper-V\Containers

该目录下列出所有通过PowerShell命令创建的容器文件。其下有文件夹和文件,都以容器的GUID来命名。

其中的926A300B-ACB7-4B28-9D86-45BF82C1211C.vhdx就是该容器的最上层的可读写层,是一个VHDX文件。

记住该可读写层并不是一个完整的文件系统,它需要和Image的现有文件系统组成Union File System。如果尝试双击该VHDX(只能尝试挂载停止状态的容器VHDX),试图挂载到Windows系统,会弹出以下报错信息,提示该虚拟硬盘无法挂载。

Image的文件系统位于以下路径(Windows Server Core的Container OS文件):

C:\ProgramData\Microsoft\Windows\Images\CN=Microsoft_WindowsServerCore_10.0.10586.0\Files

如果用Process Explorer查看容器进程访问的Dll,可以看到其访问的路径为Container OS文件。

如果是用docker命令创建的进程,道理类似,但是其可读写层文件系统位于以下路径:

C:\ProgramData\docker\windowsfilter

Windows容器还有注册表

和Linux不一样,Windows容器还需要考虑注册表的隔离问题。和文件系统命名空间隔离一样,注册表命名空间隔离也采用类似Union FS形式。

下面让我们进入PowerShell命令创建的Windows容器文件夹内部。

C:\ProgramData\Microsoft\Windows\Hyper-V\Containers\926A300B-ACB7-4B28-9D86-45BF82C1211C\Hives

在这个Hives文件夹下方,有很多命名为*_Delta的文件,这是容器所访问的注册表配置单元文件。

从命名方式中可以看到,容器的注册表和文件系统一样,也采用分层架构,最上层的是可读写的注册表命名空间。而Image映像也有只读部分的注册表空间,路径如下。

C:\ProgramData\Microsoft\Windows\Images\CN=Microsoft_WindowsServerCore_10.0.10586.0\Hives

在Process Explorer里可以看到可读写层、只读层注册表合并后所加载的内容。

Docker命令所创建的容器,方法类似,位于类似以下路径:

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标签页。

可以看到所有容器进程共享一个作业对象,而且该作业对象的内存限额(Job Memory Limit)为5GB。

作者简介

彭爱华 网名盆盆,微软混合云技术顾问。11届微软最有价值专家(MVP),微软高级认证讲师。出版过近20本技术图书,2005年创建ITECN博客(09年全国IT博客五十强)。微信公众号(华来四笑侃Windows):sysinternal。曾获得微软技术大会TechEd最佳讲师、中国首届IT管理技术大会(2009)最佳讲师的光荣称号。

感谢陈兴璐对本文的审校。

作者   彭爱华    发布于   2016年8月30日

众所周知,Docker能打通开发和运维的任督二脉,所谓DevOps是也。有朋友说,这符合王阳明的"知行合一"之教。而Windows Server 2016内置的Windows Docker亦已经出来一段时间,这里就来和诸公汇报一下测试结果。

Linux和Windows,Docker里各有多少进程

在安装配置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容器里的进程比较少,可以参考以下截图:

而Windows容器,则情况略有不同。

在Windows主机上启动Process Explorer,可以看到这个Windows容器的进程相对多一些:

这是因为在Windows系统中,需要给应用提供一些用户模式的系统服务,例如DNS、DHCP、RPC等服务,这样从容器的角度来看,容器获得了自己独有的服务(一般是在各自的svchost或者其他服务宿主进程里运行),构成了所谓的Container OS。

我们可以用PowerShell命令查看容器内部启动的Windows服务,大概有27个,参考附图。

很可惜,这个版本的Windows docker里,虽然有远程桌面服务,但是目前还不支持远程桌面到容器,所以无法使用容器应用的图形化界面。

容器里的应用,到底应该启动多少Windows服务?由于Windows服务的具体作用是非文档化的,所以不像Linux可以做到最精简。但是由于这些服务几乎不占用什么额外的资源,对于容器性能没有影响。

Windows容器的进程如何隔离

由于在最新的测试版本里,容器对象的权限设置有了改变,只有SYSTEM权限才能查看。所以要查看Windows容器的进程隔离,需要用SYSTEM权限启动Winobj。这可以借助Psexec来实现:

Psexec -i -d -s winobj.exe

可以看到Windows对象空间里多了一个Containers的节点,其下有若干个GUID分支,这些GUID代表系统里的容器。其下每个容器有自己独立的BaseNamedObjects等命名空间,包括互斥信号量、内存Section、事件等。

可以用PowerShell查看容器的GUID,参考附图。

每个容器节点下,有自己的Session分支,例如该容器,占据了Windows系统的Session 2。如附图所示。

这就是为什么,不管用任务管理器,还是PowerShell,抑或是Process Explorer等工具,我们都在Windows主机里看到容器里的所有进程都会标记Session为2。

借助Process Explorer,我们可以看到容器里的进程,所打开的Handle,其中就指向先前所看到的Windows容器对象命名空间。

同时还能看到,容器进程所在的WindowStation并不是WinSta0,而是Service-0x0-3e7$,3e7的10进制等于999,等于九五之尊,这是SYSTEM服务所在的窗口站。所以容器进程无法在Windows桌面上拥有图形化界面。

还可以查看一个有意义的对象,Windows容器所挂载的主机目录,类似于Linux容器的Volume。

Windows容器的文件系统如何隔离

和Linux一样,Windows容器映像采用分层的文件系统,基于映像创建容器后,相当于在只读的分层文件系统上再覆盖一层可读写的文件系统层。如果要修改的文件在最上层的可读写层里没有,则沿着分层的Layer找到目标文件后,将其用COW(Copy on write:写时复制)复制到可读写层再修改。

我们进入到Windows主机的以下目录:

C:\ProgramData\Microsoft\Windows\Hyper-V\Containers

该目录下列出所有通过PowerShell命令创建的容器文件。其下有文件夹和文件,都以容器的GUID来命名。

其中的926A300B-ACB7-4B28-9D86-45BF82C1211C.vhdx就是该容器的最上层的可读写层,是一个VHDX文件。

记住该可读写层并不是一个完整的文件系统,它需要和Image的现有文件系统组成Union File System。如果尝试双击该VHDX(只能尝试挂载停止状态的容器VHDX),试图挂载到Windows系统,会弹出以下报错信息,提示该虚拟硬盘无法挂载。

Image的文件系统位于以下路径(Windows Server Core的Container OS文件):

C:\ProgramData\Microsoft\Windows\Images\CN=Microsoft_WindowsServerCore_10.0.10586.0\Files

如果用Process Explorer查看容器进程访问的Dll,可以看到其访问的路径为Container OS文件。

如果是用docker命令创建的进程,道理类似,但是其可读写层文件系统位于以下路径:

C:\ProgramData\docker\windowsfilter

Windows容器还有注册表

和Linux不一样,Windows容器还需要考虑注册表的隔离问题。和文件系统命名空间隔离一样,注册表命名空间隔离也采用类似Union FS形式。

下面让我们进入PowerShell命令创建的Windows容器文件夹内部。

C:\ProgramData\Microsoft\Windows\Hyper-V\Containers\926A300B-ACB7-4B28-9D86-45BF82C1211C\Hives

在这个Hives文件夹下方,有很多命名为*_Delta的文件,这是容器所访问的注册表配置单元文件。

从命名方式中可以看到,容器的注册表和文件系统一样,也采用分层架构,最上层的是可读写的注册表命名空间。而Image映像也有只读部分的注册表空间,路径如下。

C:\ProgramData\Microsoft\Windows\Images\CN=Microsoft_WindowsServerCore_10.0.10586.0\Hives

在Process Explorer里可以看到可读写层、只读层注册表合并后所加载的内容。

Docker命令所创建的容器,方法类似,位于类似以下路径:

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标签页。

可以看到所有容器进程共享一个作业对象,而且该作业对象的内存限额(Job Memory Limit)为5GB。

作者简介

彭爱华 网名盆盆,微软混合云技术顾问。11届微软最有价值专家(MVP),微软高级认证讲师。出版过近20本技术图书,2005年创建ITECN博客(09年全国IT博客五十强)。微信公众号(华来四笑侃Windows):sysinternal。曾获得微软技术大会TechEd最佳讲师、中国首届IT管理技术大会(2009)最佳讲师的光荣称号。

感谢陈兴璐对本文的审校。


相关内容

  • [通用人工智能的新宇宙]OpenAI 重磅发布AGI测试训练平台Universe
  • 新智元编译 来源:openai.com 译者:王楠.刘小芹.胡祥杰 新智元启动新一轮大招聘:COO.执行总编.主编.高级编译.主笔.运营总监.客户经理.咨询总监.行政助理等 9 大岗位全面开放. 简历投递:[email protected] HR 微信:[1**********] 新智元为COO和执 ...

  • 超融合技术介绍
  • 超融合技术介绍 什么是流行?什么是火爆?对于一门IT 技术来说就是,你要是没听过或者不了解,都会不好意思出门跟人聊天-而现今的 超融合,就是这样一门技术. 超融合是超融合基础架构(HCI:Hyper-Converged Infrastructure)的简称.只要谈起Infra ,那么必然就会牵扯到数 ...

  • 如何搭建属于自己的 RSS 服务,高效精准获取信息
  • Google Reader 在 2013 年的下线似乎标志着 RSS 黄金时代的结束.在那之后,虽然陆续出现过很多替代品,但 RSS 的地位已经被无限刷新的信息流.算法推荐等新技术逐渐取代了. 不过,尽管小众,RSS 仍然是不少极客用户获取信息的首选.的确,如果对信息来源要求苛刻且善加维护,RSS ...

  • 高级JAVA工程师需要掌握哪些技术
  • 我把它分为了五大专题 工程化专题 工程化专题 git git安装使用 git日常使用:fetch/pull/push/revert/rebase git分支管理git flow Jenkins多套环境(test/pre/production)系统自动化发布 Jenkins自动发布到远程主机 Mave ...

  • 有关云架构建设和选型的思考
  • 最近在负责公司内部私有云的建设,一直在思考怎么搞云计算,怎么才能够把云架构设计得好一些.本文尽量全面的列出了云架构建设和选型的考量因素. 我们主要从五个层面逐步评估云架构的建设和选型,分别是: 行业生态 企业需求 云计算的能力 潜在的挑战 如何建设 一.行业生态 计算机云经过多年的发展,由一开始的概 ...

  • 大数据从业者市场现状:薪酬持续增长 人才缺口巨大
  • CSDN首页>云计算 大数据从业者市场现状:薪酬持续增长 人才缺口巨大 发表于2012-04-05 17:13| 47283次阅读| 来源InformationWeek| 75 条评论| 作者Doug Henschen 数据分析商业智能数据仓库web开发大数据 摘要:在大数据时代,企业之间正在 ...

  • [优秀作文]天空依旧蔚蓝
  • 坠落夜空的流星,跌入眼眸,溅得彻夜难眠,是否此夜世俗归于沉寂?是否流星划过,微风袭来,发丝间都有一种黯然的感伤?是否黑夜降临,心中的天空归于黯淡,就不会晴朗? 曾几何时,我的天空,艳阳高照. 回收遥望,在灯火阑珊深处,有两张稚嫩的脸,那是正儿时的我们.那纯真的年华,自由,欢笑.还依稀记得,上小学,你 ...

  • 最大似然估计总结笔记
  • 最大似然估计学习总结------MadTurtle 1. 作用 在已知试验结果(即是样本)的情况下,用来估计满足这些样本分布的参数,把可能性最大的那个参数 作为真实 的参数估计. 2. 离散型 设 为离散型随机变量, 为多维参数向量,如果随机变量 相互独立且概率计算式为P{ ,则可得概率函数为P{ ...

  • 细说餐饮业成本核算
  • 细说餐饮业成本核算 1.根据目标销售市场,确定目标成本率 根据餐厅所处的地理位置和自身特点,及当地市场的消费对象,制定相应的目标销售市场,然后按消费者的特点,确定餐饮目标分类成本率和综合成本率.例如目标销售市场是高档客人,其综合成本率应控制在30%-40%之间,确定的目标销售市场是中档或低档客人,其 ...