Kubernetes 中的 Windows 容器
在许多组织中,所运行的很大一部分服务和应用是 Windows 应用。 Windows 容器提供了一种封装进程和包依赖项的方式, 从而简化了 DevOps 实践,令 Windows 应用同样遵从云原生模式。
对于同时投入基于 Windows 应用和 Linux 应用的组织而言,他们不必寻找不同的编排系统来管理其工作负载, 使其跨部署的运营效率得以大幅提升,而不必关心所用的操作系统。
Kubernetes 中的 Windows 节点
若要在 Kubernetes 中启用对 Windows 容器的编排,可以在现有的 Linux 集群中包含 Windows 节点。 在 Kubernetes 上调度 Pod 中的 Windows 容器与调度基于 Linux 的容器类似。
为了运行 Windows 容器,你的 Kubernetes 集群必须包含多个操作系统。 尽管你只能在 Linux 上运行控制平面, 你可以部署运行 Windows 或 Linux 的工作节点。
支持 Windows 节点的前提是操作系统为 Windows Server 2019 或 Windows Server 2022。
本文使用术语 Windows 容器表示具有进程隔离能力的 Windows 容器。 Kubernetes 不支持使用 Hyper-V 隔离能力来运行 Windows 容器。
兼容性与局限性
某些节点层面的功能特性仅在使用特定容器运行时时才可用; 另外一些特性则在 Windows 节点上不可用,包括:
- 巨页(HugePages):Windows 容器当前不支持。
- 特权容器:Windows 容器当前不支持。 HostProcess 容器提供类似功能。
- TerminationGracePeriod:需要 containerD。
Windows 节点并不支持共享命名空间的所有功能特性。 有关更多详细信息,请参考 API 兼容性。
有关 Kubernetes 测试时所使用的 Windows 版本的详细信息,请参考 Windows 操作系统版本兼容性。
从 API 和 kubectl 的角度来看,Windows 容器的行为与基于 Linux 的容器非常相似。 然而,在本节所概述的一些关键功能上,二者存在一些显著差异。
与 Linux 比较
Kubernetes 关键组件在 Windows 上的工作方式与在 Linux 上相同。 本节介绍几个关键的工作负载抽象及其如何映射到 Windows。
-
Pod 是 Kubernetes 的基本构建块,是可以创建或部署的最小和最简单的单元。 你不可以在同一个 Pod 中部署 Windows 和 Linux 容器。 Pod 中的所有容器都调度到同一 Node 上,每个 Node 代表一个特定的平台和体系结构。 Windows 容器支持以下 Pod 能力、属性和事件:
- 每个 Pod 有一个或多个容器,具有进程隔离和卷共享能力
- Pod
status
字段 - 就绪、存活和启动探针
- postStart 和 preStop 容器生命周期回调
- ConfigMap 和 Secret:作为环境变量或卷
emptyDir
卷- 命名管道形式的主机挂载
- 资源限制
- 操作系统字段:
.spec.os.name
字段应设置为windows
以表明当前 Pod 使用 Windows 容器。如果你将 `.spec.os.name` 字段设置为 `windows`,
则你必须不能在对应 Pod 的
.spec
中设置以下字段:spec.hostPID
spec.hostIPC
spec.securityContext.seLinuxOptions
spec.securityContext.seccompProfile
spec.securityContext.fsGroup
spec.securityContext.fsGroupChangePolicy
spec.securityContext.sysctls
spec.shareProcessNamespace
spec.securityContext.runAsUser
spec.securityContext.runAsGroup
spec.securityContext.supplementalGroups
spec.containers[*].securityContext.seLinuxOptions
spec.containers[*].securityContext.seccompProfile
spec.containers[*].securityContext.capabilities
spec.containers[*].securityContext.readOnlyRootFilesystem
spec.containers[*].securityContext.privileged
spec.containers[*].securityContext.allowPrivilegeEscalation
spec.containers[*].securityContext.procMount
spec.containers[*].securityContext.runAsUser
spec.containers[*].securityContext.runAsGroup
在上述列表中,通配符(`*`)表示列表中的所有项。
例如,
spec.containers[*].securityContext
指代所有容器的 SecurityContext 对象。 如果指定了这些字段中的任意一个,则 API 服务器不会接受此 Pod。
-
工作负载资源包括:
- ReplicaSet
- Deployment
- StatefulSet
- DaemonSet
- Job
- CronJob
- ReplicationController
-
Services
有关更多详细信息,请参考负载均衡和 Service。
Pod、工作负载资源和 Service 是在 Kubernetes 上管理 Windows 工作负载的关键元素。 然而,它们本身还不足以在动态的云原生环境中对 Windows 工作负载进行恰当的生命周期管理。
kubectl exec
- Pod 和容器度量指标
- Pod 水平自动扩缩容
- 资源配额
- 调度器抢占
kubelet 的命令行选项
某些 kubelet 命令行选项在 Windows 上的行为不同,如下所述:
--windows-priorityclass
允许你设置 kubelet 进程的调度优先级 (参考 CPU 资源管理)。--kube-reserved
、--system-reserved
和--eviction-hard
标志更新 NodeAllocatable。- 未实现使用
--enforce-node-allocable
驱逐。 - 在 Windows 节点上运行时,kubelet 没有内存或 CPU 限制。
--kube-reserved
和--system-reserved
仅从NodeAllocatable
中减去,并且不保证为工作负载提供的资源。 有关更多信息,请参考 Windows 节点的资源管理。 - 未实现
PIDPressure
条件。 - kubelet 不会执行 OOM 驱逐操作。
API 兼容性
由于操作系统和容器运行时的缘故,Kubernetes API 在 Windows 上的工作方式存在细微差异。 某些工作负载属性是为 Linux 设计的,无法在 Windows 上运行。
从较高的层面来看,以下操作系统概念是不同的:
- 身份 - Linux 使用 userID(UID)和 groupID(GID),表示为整数类型。
用户名和组名是不规范的,它们只是
/etc/groups
或/etc/passwd
中的别名, 作为 UID+GID 的后备标识。 Windows 使用更大的二进制安全标识符(SID), 存放在 Windows 安全访问管理器(Security Access Manager,SAM)数据库中。 此数据库在主机和容器之间或容器之间不共享。 - 文件权限 - Windows 使用基于 SID 的访问控制列表, 而像 Linux 使用基于对象权限和 UID+GID 的位掩码(POSIX 系统)以及可选的访问控制列表。
- 文件路径 - Windows 上的约定是使用
\
而不是/
。 Go IO 库通常接受两者,能让其正常工作,但当你设置要在容器内解读的路径或命令行时, 可能需要用\
。
- 信号 - Windows 交互式应用处理终止的方式不同,可以实现以下一种或多种:
- UI 线程处理包括
WM_CLOSE
在内准确定义的消息。 - 控制台应用使用控制处理程序(Control Handler)处理 Ctrl-C 或 Ctrl-Break。
- 服务会注册可接受
SERVICE_CONTROL_STOP
控制码的服务控制处理程序(Service Control Handler)函数。
- UI 线程处理包括
容器退出码遵循相同的约定,其中 0 表示成功,非零表示失败。 具体的错误码在 Windows 和 Linux 中可能不同。 但是,从 Kubernetes 组件(kubelet、kube-proxy)传递的退出码保持不变。
容器规约的字段兼容性
以下列表记录了 Pod 容器规约在 Windows 和 Linux 之间的工作方式差异:
- 巨页(Huge page)在 Windows 容器运行时中未实现,且不可用。 巨页需要不可为容器配置的用户特权生效。
requests.cpu
和requests.memory
- 从节点可用资源中减去请求,因此请求可用于避免一个节点过量供应。 但是,请求不能用于保证已过量供应的节点中的资源。 如果运营商想要完全避免过量供应,则应将设置请求作为最佳实践应用到所有容器。
securityContext.allowPrivilegeEscalation
- 不能在 Windows 上使用;所有权能字都无法生效。securityContext.capabilities
- POSIX 权能未在 Windows 上实现。securityContext.privileged
- Windows 不支持特权容器, 可使用 HostProcess 容器代替。securityContext.procMount
- Windows 没有/proc
文件系统。securityContext.readOnlyRootFilesystem
- 不能在 Windows 上使用;对于容器内运行的注册表和系统进程,写入权限是必需的。securityContext.runAsGroup
- 不能在 Windows 上使用,因为不支持 GID。
securityContext.runAsNonRoot
- 此设置将阻止以ContainerAdministrator
身份运行容器,这是 Windows 上与 root 用户最接近的身份。securityContext.runAsUser
- 改用runAsUserName
。securityContext.seLinuxOptions
- 不能在 Windows 上使用,因为 SELinux 特定于 Linux。terminationMessagePath
- 这个字段有一些限制,因为 Windows 不支持映射单个文件。 默认值为/dev/termination-log
,因为默认情况下它在 Windows 上不存在,所以能生效。
Pod 规约的字段兼容性
以下列表记录了 Pod 规约在 Windows 和 Linux 之间的工作方式差异:
hostIPC
和hostpid
- 不能在 Windows 上共享主机命名空间。hostNetwork
- 参见下文dnsPolicy
- Windows 不支持将 PoddnsPolicy
设为ClusterFirstWithHostNet
, 因为未提供主机网络。Pod 始终用容器网络运行。podSecurityContext
参见下文shareProcessNamespace
- 这是一个 Beta 版功能特性,依赖于 Windows 上未实现的 Linux 命名空间。 Windows 无法共享进程命名空间或容器的根文件系统(root filesystem)。 只能共享网络。
terminationGracePeriodSeconds
- 这在 Windows 上的 Docker 中没有完全实现, 请参考 GitHub issue。 目前的行为是通过 CTRL_SHUTDOWN_EVENT 发送 ENTRYPOINT 进程,然后 Windows 默认等待 5 秒, 最后使用正常的 Windows 关机行为终止所有进程。 5 秒默认值实际上位于容器内的 Windows 注册表中,因此在构建容器时可以覆盖这个值。volumeDevices
- 这是一个 Beta 版功能特性,未在 Windows 上实现。 Windows 无法将原始块设备挂接到 Pod。volumes
- 如果你定义一个
emptyDir
卷,则你无法将卷源设为memory
。
- 如果你定义一个
- 你无法为卷挂载启用
mountPropagation
,因为这在 Windows 上不支持。
hostNetwork 的字段兼容性
Kubernetes v1.26 [alpha]
现在,kubelet 可以请求在 Windows 节点上运行的 Pod 使用主机的网络命名空间,而不是创建新的 Pod 网络命名空间。
要启用此功能,请将 --feature-gates=WindowsHostNetwork=true
传递给 kubelet。
说明:
此功能需要支持该功能的容器运行时。
Pod 安全上下文的字段兼容性
Pod 的 securityContext
中只有 securityContext.runAsNonRoot
和 securityContext.windowsOptions
字段在 Windows 上生效。
节点问题检测器
节点问题检测器(参考节点健康监测)初步支持 Windows。 有关更多信息,请访问该项目的 GitHub 页面。
Pause 容器
在 Kubernetes Pod 中,首先创建一个基础容器或 “pause” 容器来承载容器。 在 Linux 中,构成 Pod 的 cgroup 和命名空间维持持续存在需要一个进程; 而 pause 进程就提供了这个功能。 属于同一 Pod 的容器(包括基础容器和工作容器)共享一个公共网络端点 (相同的 IPv4 和/或 IPv6 地址,相同的网络端口空间)。 Kubernetes 使用 pause 容器以允许工作容器崩溃或重启,而不会丢失任何网络配置。
Kubernetes 维护一个多体系结构的镜像,包括对 Windows 的支持。
对于 Kubernetes v1.32.0,推荐的 pause 镜像为 registry.k8s.io/pause:3.6
。
可在 GitHub 上获得源代码。
Microsoft 维护一个不同的多体系结构镜像,支持 Linux 和 Windows amd64,
你可以找到的镜像类似 mcr.microsoft.com/oss/kubernetes/pause:3.6
。
此镜像的构建与 Kubernetes 维护的镜像同源,但所有 Windows 可执行文件均由
Microsoft 进行了验证码签名。
如果你正部署到一个需要签名可执行文件的生产或类生产环境,
Kubernetes 项目建议使用 Microsoft 维护的镜像。
容器运行时
你需要将容器运行时安装到集群中的每个节点, 这样 Pod 才能在这些节点上运行。
以下容器运行时适用于 Windows:
ContainerD
Kubernetes v1.20 [stable]
对于运行 Windows 的 Kubernetes 节点,你可以使用 ContainerD 1.4.0+ 作为容器运行时。
说明:
将 GMSA 和 containerd 一起用于访问 Windows 网络共享时存在已知限制, 这需要一个内核补丁。
Mirantis 容器运行时
Mirantis 容器运行时(MCR) 可作为所有 Windows Server 2019 和更高版本的容器运行时。
有关更多信息,请参考在 Windows Server 上安装 MCR。
Windows 操作系统版本兼容性
在 Windows 节点上,如果主机操作系统版本必须与容器基础镜像操作系统版本匹配, 则会应用严格的兼容性规则。 仅 Windows Server 2019 作为容器操作系统时,才能完全支持 Windows 容器。
对于 Kubernetes v1.32,Windows 节点(和 Pod)的操作系统兼容性如下:
- Windows Server LTSC release
- Windows Server 2019
- Windows Server 2022
- Windows Server SAC release
- Windows Server version 20H2
也适用 Kubernetes 版本偏差策略。
硬件建议和注意事项
说明:
这里列出的硬件规格应被视为合理的默认值。 它们并不代表生产环境的最低要求或具体推荐。 根据你的工作负载要求,这些值可能需要进行调整。
- 64 位处理器,4 核或更多的 CPU,能够支持虚拟化
- 8GB 或更多的 RAM
- 50GB 或更多的可用磁盘空间
有关最新的最低硬件要求信息, 请参考微软文档:Windows Server 的硬件要求。 有关决定生产工作节点资源的指导信息, 请参考 Kubernetes 文档:生产用工作节点。
为了优化系统资源,如果图形用户界面不是必需的,最好选择一个不包含 Windows 桌面体验安装选项的 Windows Server 操作系统安装包,因为这种配置通常会释放更多的系统资源。
在估算 Windows 工作节点的磁盘空间时,需要注意 Windows 容器镜像通常比 Linux 容器镜像更大,
单个镜像的容器大小范围从 300MB 到超过 10GB。
此外,需要注意 Windows 容器中的 C:
驱动器默认呈现的虚拟剩余空间为 20GB,
这不是实际的占用空间,而是使用主机上的本地存储时单个容器可以最多占用的磁盘大小。
有关更多详细信息,
请参见在 Windows 上运行容器 - 容器存储文档。
获取帮助和故障排查
对 Kubernetes 集群进行故障排查的主要帮助来源应始于故障排查页面。
本节包括了一些其他特定于 Windows 的故障排查帮助。 日志是解决 Kubernetes 中问题的重要元素。 确保在任何时候向其他贡献者寻求故障排查协助时随附了日志信息。 遵照 SIG Windows 日志收集贡献指南中的指示说明。
报告问题和功能请求
如果你发现疑似 bug,或者你想提出功能请求,请按照 SIG Windows 贡献指南 新建一个 Issue。你应该先搜索 Issue 列表,以防之前报告过这个问题,凭你对该问题的经验添加评论, 并随附日志信息。Kubernetes Slack 上的 SIG Windows 频道也是一个很好的途径, 可以在创建工单之前获得一些初始支持和故障排查思路。
验证 Windows 集群的操作性
Kubernetes 项目提供了 Windows 操作准备规范,配备了结构化的测试套件。 这个套件分为两组测试:核心和扩展。每组测试都包含了针对特定场景的分类测试。 它可以用来验证 Windows 和混合系统(混合了 Linux 节点)的所有功能,实现全面覆盖。
要在新创建的集群上搭建此项目, 请参考项目指南中的说明。
部署工具
kubeadm 工具帮助你部署 Kubernetes 集群,提供管理集群的控制平面以及运行工作负载的节点。
Kubernetes 集群 API 项目也提供了自动部署 Windows 节点的方式。
Windows 分发渠道
有关 Windows 分发渠道的详细阐述,请参考 Microsoft 文档。
有关支持模型在内的不同 Windows Server 服务渠道的信息,请参考 Windows Server 服务渠道。
本页面中的条目引用了第三方产品或项目,这些产品(项目)提供了 Kubernetes 所需的功能。Kubernetes 项目的开发人员不对这些第三方产品(项目)负责。请参阅CNCF 网站指南了解更多细节。
在提交更改建议,向本页添加新的第三方链接之前,你应该先阅读内容指南。