NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

细说 Windows 与 Docker 之间的趣事

  • 2016-08-29
  • 本文字数:2892 字

    阅读完需:约 9 分钟

众所周知,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) 最佳讲师的光荣称号。


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

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2016-08-29 18:096705

评论

发布
暂无评论
发现更多内容

疫情下的人生百态

6979阿强

图计算 GraphScope 新冠

细思极恐!Alibaba新产SpringBoot深度历险(嵩山版)开源

Java 编程 架构 面试 架构师

区块链技术发展趋势与银行业探索实践

CECBC

在线JSON转MySQL建表语句工具

入门小站

工具

SharingSphere 源码解析 -- 真实SQL生成探索

数据库 源码

程序员应该专注技术还是转管理?

石云升

职业规划 职场经验 8月日更

百分点大数据技术团队:BI嵌入式分析实践

百分点科技技术团队

BI 百分点科技 嵌入式分析

我遇到的那些工长

escray

生活记录 8月日更

GitHub获120w+star的JDK源码剖析手册,竟出自Alibaba高管之手?

Java 架构 面试 程序人生 Alibaba

webrtc 即时带宽评估器(BitrateEstimator)

webrtc developer

WebRTC

不用手机,如何让猫给你打视频电话丨日常小技

声网

物联网 目标检测 目标跟踪

深入了解 RocketMQ 之ACL

邱学喆

签名 白名单 资源权限校验

百分点感知智能实验室:语音识别技术发展阶段探究

百分点科技技术团队

语音识别 百分点科技 感知智能

AlphaFold2“登陆”北鲲云平台,云计算助力科研大放异彩

北鲲云

数字化时代商业银行客户触达策略研究 从数据到服务 由场景到生态

CECBC

Linux之last命令

入门小站

Linux

分享 10 个高星的创意项目!

程序员鱼皮

Java Python 数据库 大前端 Go 语言

区块链盲盒游戏app软件开发|盲盒游戏软件介绍

量化系统19942438797

区块链 智能合约 盲盒

融云 X-Live 系列直播启动,遇见通信的无限可能

融云 RongCloud

开发者 音视频 通信 融云 即时通信

netty系列之:自建客户端和HTTP服务器交互

程序那些事

Java Netty 程序那些事

快手平台严管售卖“仿黄金类饰品”,直播带货在收割消费者

石头IT视角

中证协组织专题座谈会,加快推进区块链技术在证券行业应用

CECBC

ipfs矿机是什么?ipfs矿机挖出的币能交易吗?

区块链 分布式存储 ipfs挖矿 ipfs矿机 filecoin挖矿

Tapdata Cloud 版本上新!率先支持数据校验、类型映射等6大新功能

tapdata

MySQL nosql schema

算法毕业总结

Geek_Gu

模块1-作业

笑看风雨情

网络攻防学习笔记 Day122

穿过生命散发芬芳

网络安全 8月日更

架构设计-模块一

逝水流

架构

跨越AI天堑时:行动代号“盘古大模型”

脑极体

读书笔记 -《数据密集型应用系统设计》- 数据编码

KayTin

07. 图灵测试与第一次AI浪潮

数据与智能

人工智能

细说Windows与Docker之间的趣事_Windows_彭爱华_InfoQ精选文章