news 2026/9/16 18:12:11

hcsshim 完全指南:Windows HCS 容器运行时接口、containerd shim 架构与 buildkit 中的实际应用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
hcsshim 完全指南:Windows HCS 容器运行时接口、containerd shim 架构与 buildkit 中的实际应用

hcsshim 完全指南:Windows HCS 容器运行时接口、containerd shim 架构与 buildkit 中的实际应用

【免费下载链接】buildkitconcurrent, cache-efficient, and Dockerfile-agnostic builder toolkit项目地址: https://gitcode.com/GitHub_Trending/bu/buildkit

hcsshim(Host Compute Service Shim)是微软开源的 Go 语言库,为 Windows 容器提供对 Windows 宿主计算服务(HCS)的完整 Go 接口,涵盖容器生命周期管理、宿主网络服务(HNS)封装以及支撑 Linux Hyper-V 容器的 Guest Compute Service(GCS)客户代理。本文以仓库中随 buildkit 一并 vendor 的 hcsshim 文档(vendor/github.com/Microsoft/hcsshim/README.md)为骨架,结合 vendor 目录下的源码实现,系统讲解 hcsshim 的构建方法、containerd shim V1/V2 架构演进,以及它在 buildkit 工程中被真实引用的方式,帮助读者掌握在 Windows 环境下开发、调试和扩展容器运行时所需的完整知识。

hcsshim 是什么:Windows 容器生态的核心 Go 接口层

hcsshim 包提供了用于调用 Windows Host Compute Service(HCS) 的 Golang 接口,用于启动和管理 Windows Containers。其职责边界可以概括为三块:

  1. HCS 接口层:以 Go 类型化 API 封装 HCS 的底层 WMI/COM 调用,屏蔽 Windows 平台细节;
  2. HNS 接口层:提供 Host Network Service(HNS)的 Go 封装,用于管理 Windows 容器的网络命名空间、endpoint 与策略;
  3. Guest Agent(GCS):即代码库中常称的 Guest Compute Service,负责支撑运行 Linux Hyper-V 容器(LCOW),是 Linux 容器跑在 Windows 主机上的关键组件。

该库主要被 Moby 与 Containerd 项目使用,但其他项目也可以自由引用。hcsshim 本身既可以作为调用 HCS API 的库来使用,也同时产出了几个二进制程序,最主要的两个是Linux guest agentruntime v2 containerd shim API 的实现

从源码看 hcsshim 的核心抽象

在仓库 vendor 目录中,可以找到 hcsshim 顶层 API 的直接证据。以 vendor/github.com/Microsoft/hcsshim/interface.go 为例:

  • Container接口定义了容器的完整生命周期方法:Start()Shutdown()Terminate()Wait()WaitTimeout()Pause()Resume(),以及CreateProcess()OpenProcess()Modify()等操作;
  • Process接口则抽象了容器内进程:Pid()Kill()Wait()ExitCode()ResizeConsole()Stdio()CloseStdin()
  • 配置文件类型(ContainerConfigProcessConfigLayerMappedDirMappedPipeHvRuntimeMappedVirtualDisk)统一从internal/hcs/schema1导出,注释明确说明它们"既作为 CreateContainer 的输入,也用于转换成 JSON 传给 HCS"——这正是 hcsshim 与 Windows 底层服务交互的桥接方式。

而 vendor/github.com/Microsoft/hcsshim/hcsshim.go 的包注释则点明了它的定位:"Shim for the Host Compute Service (HCS) to manage Windows Server containers and Hyper-V containers",并定义了一系列用户可见的常量,如WaitErrExecFailed = 32767TimeoutInfinite = 0xFFFFFFFF等。

在内部实现层面,vendor/github.com/Microsoft/hcsshim/internal/hcs/schema2 目录下存放着 HCS 计算系统文档的完整 Go 结构体定义,涵盖计算系统配置(compute_system.go)、容器(container.go)、虚拟机(virtual_machine.go)、内存(memory.go)、处理器(processor.go)、存储(storage.go)、网络(networking.go)等上百个类型;internal/vmcomputeinternal/hnsinternal/wclayer等目录则分别封装了 HCS 调用、HNS 网络管理和 Windows 容器层文件操作。

hcsshim 在 buildkit 中的实际应用

buildkit 作为面向 Windows 平台提供容器镜像构建能力的工具链,在go.mod中以依赖形式引入了 hcsshim:

github.com/Microsoft/hcsshim v0.15.0-rc.4

从仓库源码中可以找到两处真实的引用场景:

  1. containerd worker 的运行时选项解析(cmd/buildkitd/main_containerd_worker_windows.go):buildkitd 在 Windows 上启动 containerd worker 时,通过getRuntimeOptionsType根据运行时类型返回空的运行时选项结构体。当运行时是plugins.RuntimeRunhcsV1时,返回的是runhcsoptions.Options——这个类型正来自github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/options包,其定义可在 vendor/github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/options/runhcs.proto 中找到。这印证了 hcsshim 文档中"runhcs shim 用于启动和管理容器生命周期"的描述在 buildkit 工程中的落地。

  2. CNI 网络命名空间管理(util/network/cniprovider/createns_windows.go):buildkit 的 CNI provider 在 Windows 平台上通过 hcsshim 的hcn包创建宿主计算网络命名空间。createNetNS调用hcn.NewNamespace(hcn.NamespaceTypeGuest)创建 guest 类型命名空间,deleteNetNS则通过hcn.GetNamespaceByID查询后删除,并将命名空间 ID 写入 OCI 运行规范的s.Windows.Network.NetworkNamespace字段。这是 hcsshim 中 HNS/HCN 网络接口在真实工程中的典型用法。

这两处引用说明:hcsshim 对于 buildkit 而言,既是 Windows 上容器运行时的"启动器",也是网络命名空间等宿主资源的管理工具。

构建 Linux Hyper-V Container Guest Agent(GCS)

根据 hcsshim 文档,构建 Linux guest agent 本身只需将GOOS设置为"linux",并在cmd/gcs目录下执行构建。在 Windows 上使用 PowerShell:

C:\> $env:GOOS="linux" C:\> go build .\cmd\gcs\

在 Linux 机器上则直接执行:

> go build ./cmd/gcs

注意:当前仓库 vendor 目录仅保留了 buildkit 实际用到的 hcsshim 子集(cmd/containerd-shim-runhcs-v1等),cmd/gcs属于 hcsshim 上游仓库的内容,未随 vendor 打包。上述命令在 hcsshim 上游源码树中有效。

将 guest agent 打包进 rootfs

如果希望把 guest agent 与其他工具一起打包进 rootfs 以便随容器引导启动,需要先提供一个可供打包的 rootfs。一个便捷的做法是导出某个容器的 rootfs:

docker pull busybox docker run --name base_image_container busybox docker export base_image_container | gzip > base.tar.gz BASE=./base.tar.gz make all

构建成功后,在./out目录下应当可以看到三个产物:

> ls ./out/ delta.tar.gz initrd.img rootfs.tar.gz
  • initrd.img:initramfs 镜像,用于引导 Linux Utility VM;
  • rootfs.tar.gz:打包了 guest agent 及相关工具的根文件系统;
  • delta.tar.gz:增量层,用于叠加到基础镜像之上。

从源码看 GCS 的支撑机制

Linux Hyper-V 容器(LCOW)的实现深度依赖 hcsshim 内部的诸多模块。虽然 guest agent 本体在cmd/gcs,但支撑它的底层能力散布在 vendor 源码中:

  • internal/hcs/schema2/linux_kernel_direct.go:定义 Linux 内核直启(kernel direct boot)所需的配置结构,这是无需完整 BIOS 引导、直接加载内核镜像启动 Utility VM 的机制;
  • internal/hcs/schema2/hv_socket.go 等文件:定义 HvSocket 配置,guest agent 与宿主之间正是通过 Hyper-V Socket(vsock)通信;
  • internal/hcs/schema2/plan9.go:定义 Plan9 共享文件系统配置,用于宿主与 Linux VM 之间的文件共享。

containerd shim(V1):containerd-shim-runhcs-v1

与 Linux 上典型的 "shim -> runc" 架构不同,Windows 上的 runhcs shim 同时负责容器的启动生命周期管理。构建它需要将GOOS设置为"windows"

C:\> $env:GOOS="windows" C:\> go build .\cmd\containerd-shim-runhcs-v1

然后将生成的二进制文件放置到环境中 containerd 所在目录。生成一份默认的 containerd 配置文件:

.\containerd.exe config default | Out-File "C:\Program Files\containerd\config.toml" -Encoding ascii

这份配置已默认将 runhcs shim 设为 CRI 交互的默认运行时。可以用ctr.exe快速试用:

C:\> ctr.exe run --runtime io.containerd.runhcs.v1 --rm mcr.microsoft.com/windows/nanoserver:2004 windows-test cmd /c "echo Hello World!"

在 buildkit 中,plugins.RuntimeRunhcsV1正是上面这个运行时名称io.containerd.runhcs.v1的常量引用,buildkitd 在 Windows 上遇到该运行时类型时会构造runhcsoptions.Options,这个类型的 protobuf 定义位于 vendor/github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/options/runhcs.proto,字段包括KernelDirectVhdxVmProcessorCountVmMemorySizeInMB等与 Hyper-V 隔离虚拟机配置直接相关的选项。

containerd Shim V2:按平台拆分的运行时体系

V2 shim 是对 Windows containerd shim 的重写。V1 shim(containerd-shim-runhcs-v1)是单个单体二进制,同时处理 LCOW(Windows 上的 Linux 容器)、Hyper-V WCOW(Windows 上的 Hyper-V Windows 容器)、进程隔离 WCOW 以及宿主进程容器。在 V2 模型中,这个单体被拆分为聚焦的、按平台区分的多个 shim,每个 shim 与一个 sandbox 一一对应(1:1)。

V2 shim 的使用方式与 V1 相同,但暴露的 API 面不同:

  • V1 shim 只实现了 containerd 的 Task API,通过单个服务同时管理 sandbox 生命周期与容器/进程(task)生命周期;
  • 每个 V2 shim 则把职责拆分到 containerd 提供的两个 API 上:Sandbox API 负责管理 sandbox,Task API 负责管理其中运行的容器和进程;
  • 内部实现上,每个 V2 shim 将 sandbox 与 task 分别实现为独立服务,另附一个用于诊断的shimdiag服务。

统一的 CRI Pod 模型

三个 V2 shim 都遵循相同的 CRI pod 模型。一个带有"io.kubernetes.cri.container-type": "sandbox"注解的 task 被当作创建 pod 的 pause/infra 容器;同级的 workload task 则设置"io.kubernetes.cri.container-type": "container",并通过"io.kubernetes.cri.sandbox-id"注解关联到各自的 pause 容器。而 "sandbox" 在物理上对应什么,取决于具体的 shim。

containerd-shim-lcow-v2(LCOW)

维度说明
用途在 Windows 上运行 Linux 容器(LCOW),由一个 Linux Utility VM 承载 Linux 容器
SandboxLinux UVM。每个 shim 实例与单个 UVM 一一对应,且支持在同一个 UVM 中运行多个 pod,即单个 shim 实例可承载多个 CRI pod
TasksUVM 内运行的 Linux 容器与进程,通过上文描述的 CRI 注解标识
实现./cmd/containerd-shim-lcow-v2
Build Taglcow
平台要求Windows Server 2025(build 26100)或更高版本

containerd-shim-wcow-v2(WCOW)

维度说明
用途运行 Hyper-V 隔离的 Windows 容器(WCOW),由一个 Windows Utility VM 承载内部的进程隔离容器与宿主进程容器
SandboxWindows Utility VM(UVM),每个 shim 实例与单个 UVM 一一对应
TasksUVM 内运行的 Windows 容器与进程,通过标准 CRI 注解标识
Build Tagwcow

containerd-shim-process-v2(进程隔离)

维度说明
用途运行进程隔离的 Windows Server 容器与宿主进程容器——这些负载直接执行在宿主机上,没有 Utility VM
Sandboxpause 容器。pause 容器是最小化、长期存活的容器,持有 pod 的共享资源(如网络命名空间),在兄弟 workload 容器被启动、停止或替换期间维持这些资源存活。这是标准 Kubernetes pod 模型:pause 容器就是 pod 其余部分所依附的 sandbox
Tasks属于 pod 的实际 workload 容器,通过io.kubernetes.cri.sandbox-id注解关联回 pause 容器
Build Tagprocess

从上述对比可以看出 V2 架构的设计意图:把"沙箱生命周期"与"任务生命周期"彻底解耦,使不同隔离模型(UVM 隔离 vs 进程隔离)能够各自演进,同时维持统一的 CRI 语义。

V2 shim 的构建、单元测试与 parity 测试

V2 shim 源码由对应的 build tag 保护,因此构建时必须显式传入 tag。以 LCOW shim 为例:

C:\> $env:GOOS="windows" C:\> go build -tags lcow .\cmd\containerd-shim-lcow-v2

将生成的containerd-shim-lcow-v2.exe放置到与containerd.exe相同的目录(与 V1 shim 的做法一致)。

运行单元测试同样需要指定 shim 对应的 build tag:

C:\> go test -tags lcow ./...

仓库还提供了parity 测试(位于./test/parity),它们把完全相同的输入分别送入旧的 V1 与新的 V2 两条管线,并断言最终生成的 HCS ComputeSystem 文档是等价的。这些测试位于独立的testGo module 中,同样需要携带 build tag 运行:

C:\> cd test C:\> go test -tags lcow ./parity/...

parity 测试的价值在于:它从"输出文档等价"这一层面保证了 V2 重构不会改变容器实际提交给 HCS 的配置语义,为 shim 迁移提供了可回归验证的机制。

工程规范:Linting、Go Generate 与依赖要求

代码质量与 Linting

所有代码必须通过使用golangci-lint的 lint 阶段。由于./test是独立的 Go module,linter 需要同时在根目录与test目录下运行;此外,linter 还分别在GOOS=windowsGOOS=linux两种环境下执行,以确保跨平台代码质量。

lint 配置存放在.golangci.yaml中。若使用 VSCode,可在 workspace 或 folder 设置中添加以下配置让编辑器自动执行 lint:

"go.lintTool": "golangci-lint", "go.lintOnSave": "package",

也可以安装golangci-lint后在本地手动运行:

# 使用 . 或指定路径以只 lint 某个包 # 若需显示所有 lint 错误,加 --max-issues-per-linter=0 --max-same-issues=0 > golangci-lint run

若要跨整个仓库、同时覆盖GOOS=windowsGOOS=linux运行:

> foreach ( $goos in ('windows', 'linux') ) { foreach ( $repo in ('.', 'test') ) { pwsh -Command "cd $repo && go env -w GOOS=$goos && golangci-lint.exe run --verbose" } }

go generate 校验

CI 流水线还会检查通过go generate生成的代码是否保持最新。与 lint 阶段类似,go generate同样需要分别在根目录与test两个 Go module 中运行:

> go generate ./... > cd test && go generate ./...

这与 hcsshim 的代码生成策略直接相关:例如 hcsshim.go 顶部的//go:generate指令会调用mkwinsyscall生成zsyscall_windows.go,Windows API 调用的封装文件(如internal/vmcomputeinternal/wclayerhcn等目录下的zsyscall_windows.go)都由此类机制自动产出。

环境依赖与安全上报

  • hcsshim 要求Golang 1.18 或更高版本才能构建;
  • 系统运行要求请参考微软官方的 Windows Container 系统要求文档;
  • 安全问题与 bug 应通过邮件私下报告给 Microsoft Security Response Center(MSRC);
  • 贡献者需要签署 CLA,并按要求使用git commit --signoff/git rebase --signoff签名提交,CI 通过 DCO 应用自动校验。

小结:从 hcsshim 到 buildkit 的 Windows 容器构建链路

把整条链路串起来看:hcsshim 提供了访问 Windows HCS/HNS 宿主能力的 Go 语言通道,containerd-shim-runhcs-v1及其 V2 系列 shim 让 containerd 能够在 Windows 上以统一的 CRI 语义管理各种隔离形态的容器,而 buildkit 则通过runhcsoptionshcn两个切入点,把 hcsshim 的能力接入到自己的 containerd worker 与 CNI 网络管理中,从而在 Windows 平台上提供与 Linux 对等的容器镜像构建体验。理解 hcsshim 的架构分层与构建方法,是深入掌握 buildkit Windows 支持乃至整个 Windows 容器生态的基石。

【免费下载链接】buildkitconcurrent, cache-efficient, and Dockerfile-agnostic builder toolkit项目地址: https://gitcode.com/GitHub_Trending/bu/buildkit

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 18:10:18

从CTF信息泄露看备份文件风险:源码、bak、vim缓存与.DS_Store

CTF圈里有句老话:信息收集做得好,漏洞利用不用愁。我刷 CTFHUB 的时候,信息泄露这个模块最初是被我跳过的——总觉得"备份文件下载不就是下载个文件嘛,能有什么技术含量"。直到后来在一次线上赛里,一道最简单…

作者头像 李华
网站建设 2026/9/16 18:08:22

医疗大数据实战:癌症数据分析与可视化系统构建

1. 项目背景与核心价值癌症数据分析与可视化系统是一个典型的医疗大数据应用场景。根据世界卫生组织统计,全球每年新增癌症病例超过1900万例,这些病例背后产生的临床数据、基因组数据、影像数据等呈现爆发式增长。传统的数据处理方式已经无法满足科研和临…

作者头像 李华
网站建设 2026/9/16 18:08:22

Flutter视频解析播放器开发实战:从地址解析到下载缓存的全流程拆解

做视频解析类工具,最麻烦的从来不是“能不能跑通”,而是“跑通之后怎么让它一直好用”。LunaTV 这个项目我断断续续维护了大半年,从最初只想做一个临时自用的视频观看工具,慢慢折腾成了带完整解析、播放、下载和缓存体系的移动端应…

作者头像 李华