Kubernetes 中的 Windows 容器
在许多组织中,Windows 应用程序占据了服务和应用程序的很大一部分。Windows 容器提供了一种封装进程和打包依赖项的方式,使得 Windows 应用程序更容易采用 DevOps 实践和遵循云原生模式。
对基于 Windows 的应用程序和基于 Linux 的应用程序进行投资的组织无需寻找单独的编排器来管理其工作负载,从而无论操作系统如何,都能提高其部署的运营效率。
Kubernetes 中的 Windows 节点
为了在 Kubernetes 中编排 Windows 容器,请在现有 Linux 集群中包含 Windows 节点。在 Kubernetes 上在Pod 中调度 Windows 容器与调度基于 Linux 的容器类似。
要运行 Windows 容器,你的 Kubernetes 集群必须包含多个操作系统。虽然你只能在 Linux 上运行控制平面,但你可以部署运行 Windows 或 Linux 的工作节点。
如果操作系统是 Windows Server 2019 或 Windows Server 2022,则支持 Windows 节点。
本文档中,术语_Windows 容器_指具有进程隔离的 Windows 容器。Kubernetes 不支持运行具有 Hyper-V 隔离的 Windows 容器。
兼容性和限制
某些节点功能仅在使用特定的容器运行时时可用;其他功能在 Windows 节点上不可用,包括:
- HugePages:Windows 容器不支持
- 特权容器:Windows 容器不支持。HostProcess 容器提供类似功能。
- TerminationGracePeriod:需要 ContainerD
并非所有共享命名空间功能都受支持。有关更多详细信息,请参阅API 兼容性。
有关 Kubernetes 测试过的 Windows 版本的详细信息,请参阅Windows 操作系统版本兼容性。
从 API 和 kubectl 的角度来看,Windows 容器的行为方式与基于 Linux 的容器大致相同。但是,在关键功能方面存在一些显著差异,本节将对此进行概述。
与 Linux 的比较
Kubernetes 的关键元素在 Windows 中的工作方式与在 Linux 中相同。本节将介绍几个关键的工作负载抽象及其与 Windows 的映射关系。
Pod 是 Kubernetes 的基本构建块——你创建或部署的 Kubernetes 对象模型中最小和最简单的单元。你不能在同一个 Pod 中部署 Windows 和 Linux 容器。Pod 中的所有容器都调度到单个节点上,每个节点代表一个特定的平台和体系结构。以下 Pod 功能、属性和事件支持 Windows 容器:
每个 Pod 一个或多个具有进程隔离和卷共享的容器
Pod `status` 字段
就绪、存活和启动探针
postStart 和 preStop 容器生命周期钩子
ConfigMap、Secrets:作为环境变量或卷
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。
工作负载资源包括:
- 副本集
- 部署
- StatefulSet
- DaemonSet
- 作业
- 定时作业
- 复制控制器
Pod、工作负载资源和服务是 Kubernetes 上管理 Windows 工作负载的关键元素。但是,它们本身不足以在动态云原生环境中实现 Windows 工作负载的正确生命周期管理。
kubectl exec
- Pod 和容器指标
- 水平 Pod 自动扩缩
- 资源配额
- 调度器抢占
kubelet 命令行选项
一些 kubelet 命令行选项在 Windows 上的行为有所不同,如下所述:
--windows-priorityclass
允许你设置 kubelet 进程的调度优先级(请参阅CPU 资源管理)--kube-reserved
、--system-reserved
和--eviction-hard
标志更新节点可分配资源- 未实现使用
--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 安全访问管理器 (SAM) 数据库中。此数据库在主机和容器之间或容器之间不共享。 - 文件权限——Windows 使用基于 (SID) 的访问控制列表,而 POSIX 系统(如 Linux)使用基于对象权限和 UID+GID 的位掩码,以及_可选_的访问控制列表。
- 文件路径——Windows 上的约定是使用
\
而不是/
。Go IO 库通常同时接受两者并使其正常工作,但当你设置在容器内解释的路径或命令行时,可能需要\
。 - 信号——Windows 交互式应用程序以不同的方式处理终止,并且可以实现以下一个或多个:
- UI 线程处理明确定义的消息,包括
WM_CLOSE
。 - 控制台应用程序使用控制处理程序处理 Ctrl-C 或 Ctrl-break。
- 服务注册一个服务控制处理程序函数,该函数可以接受
SERVICE_CONTROL_STOP
控制代码。
- UI 线程处理明确定义的消息,包括
容器退出代码遵循相同的约定,其中 0 表示成功,非零表示失败。Windows 和 Linux 之间的特定错误代码可能有所不同。但是,从 Kubernetes 组件(kubelet、kube-proxy)传递的退出代码保持不变。
容器规范的字段兼容性
以下列表记录了 Pod 容器规范在 Windows 和 Linux 之间工作方式的差异:
- Windows 容器运行时未实现 Huge Pages,因此不可用。它们需要声明用户权限,这对于容器是不可配置的。
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 上不可能,因为不支持 GIDsecurityContext.runAsNonRoot
——此设置将阻止容器以ContainerAdministrator
身份运行,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
——在 Windows 上无法进行主机网络dnsPolicy
——在 Windows 上不支持将 PoddnsPolicy
设置为ClusterFirstWithHostNet
,因为未提供主机网络。Pod 始终使用容器网络运行。podSecurityContext
见下文shareProcessNamespace
——这是一个 Beta 版功能,依赖于 Linux 命名空间,而 Windows 上未实现。Windows 无法共享进程命名空间或容器的根文件系统。只能共享网络。terminationGracePeriodSeconds
——这在 Windows 上的 Docker 中尚未完全实现,请参阅GitHub issue。今天的行为是,ENTRYPOINT 进程收到 CTRL_SHUTDOWN_EVENT,然后 Windows 默认等待 5 秒,最后使用正常的 Windows 关机行为关闭所有进程。5 秒的默认值实际上位于容器内的 Windows 注册表中,因此可以在构建容器时覆盖。volumeDevices
——这是一个 Beta 版功能,在 Windows 上未实现。Windows 无法将原始块设备连接到 Pod。卷
- 如果定义
emptyDir
卷,则不能将其卷源设置为memory
。
- 如果定义
- 不能为卷挂载启用
mountPropagation
,因为 Windows 上不支持此功能。
主机网络访问
Kubernetes v1.26 到 v1.32 包含在主机网络命名空间中运行 Windows Pod 的 Alpha 支持。
Kubernetes v1.34 不包括 WindowsHostNetwork
功能门或在主机网络命名空间中运行 Windows Pod 的支持。
Pod 安全上下文的字段兼容性
仅 Pod securityContext
字段中的 securityContext.runAsNonRoot
和 securityContext.windowsOptions
在 Windows 上有效。
节点问题检测器
节点问题检测器(请参阅监控节点健康状况)对 Windows 有初步支持。有关更多信息,请访问该项目的 GitHub 页面。
暂停容器
在 Kubernetes Pod 中,首先创建一个基础结构或“暂停”容器来托管容器。在 Linux 中,构成 Pod 的 cgroups 和命名空间需要一个进程来维持其持续存在;暂停进程提供了这一点。属于同一 Pod 的容器,包括基础结构和工作容器,共享一个共同的网络端点(相同的 IPv4 和/或 IPv6 地址,相同的网络端口空间)。Kubernetes 使用暂停容器来允许工作容器崩溃或重新启动而不会丢失任何网络配置。
Kubernetes 维护一个支持 Windows 的多架构镜像。对于 Kubernetes v1.34.0,推荐的暂停镜像为 registry.k8s.io/pause:3.6
。其源代码可在 GitHub 上找到。
Microsoft 维护另一个多架构镜像,支持 Linux 和 Windows amd64,你可以在 mcr.microsoft.com/oss/kubernetes/pause:3.6
找到。此镜像与 Kubernetes 维护的镜像使用相同的源构建,但所有 Windows 二进制文件都经过 Microsoft Authenticode 签名。如果部署到生产或类似生产的环境需要签名二进制文件,Kubernetes 项目建议使用 Microsoft 维护的镜像。
容器运行时
你需要在集群中的每个节点上安装容器运行时,以便 Pod 可以在那里运行。
以下容器运行时适用于 Windows:
ContainerD
Kubernetes v1.20 [stable]
你可以使用 ContainerD 1.4.0+ 作为运行 Windows 的 Kubernetes 节点的容器运行时。
了解如何在Windows 节点上安装 ContainerD。
注意
使用 containerd 访问 Windows 网络共享时,GMSA 存在已知限制,需要内核补丁。Mirantis 容器运行时
Mirantis 容器运行时 (MCR) 可作为所有 Windows Server 2019 及更高版本的容器运行时。
有关更多信息,请参阅在 Windows Server 上安装 MCR。
Windows 操作系统版本兼容性
在 Windows 节点上,严格的兼容性规则适用,即主机操作系统版本必须与容器基础镜像操作系统版本匹配。仅完全支持容器操作系统为 Windows Server 2019 的 Windows 容器。
对于 Kubernetes v1.34,Windows 节点(和 Pod)的操作系统兼容性如下:
- Windows Server LTSC 发布
- Windows Server 2019
- Windows Server 2022
- Windows Server SAC 发布
- Windows Server 版本 20H2
Kubernetes 版本偏差策略也适用。
硬件建议和注意事项
注意
此处概述的以下硬件规范应视为合理的默认值。它们并非旨在代表生产环境的最低要求或具体建议。根据工作负载的要求,这些值可能需要调整。- 64 位处理器,4 个或更多 CPU 核,能够支持虚拟化
- 8GB 或更多内存
- 50GB 或更多可用磁盘空间
有关最低硬件要求的最新信息,请参阅Windows Server 硬件要求 Microsoft 文档。有关为生产工作节点决定资源的指南,请参阅生产工作节点 Kubernetes 文档。
为了优化系统资源,如果不需要图形用户界面,则最好使用不包括Windows 桌面体验安装选项的 Windows Server 操作系统安装,因为此配置通常会释放更多系统资源。
在评估 Windows 工作节点的磁盘空间时,请注意 Windows 容器镜像通常比 Linux 容器镜像大,单个容器镜像的大小范围从 300MB 到超过 10GB。此外,请注意,Windows 容器中的 C:
驱动器默认表示 20GB 的虚拟可用空间,这并不是实际消耗的空间,而是单个容器在使用主机上的本地存储时可以增长占用的磁盘大小。有关更多详细信息,请参阅Windows 上的容器 - 容器存储文档。
获取帮助和故障排除
故障排除 Kubernetes 集群的主要帮助来源应从故障排除页面开始。
本节包含一些额外的、特定于 Windows 的故障排除帮助。日志是故障排除 Kubernetes 问题的重要元素。在向其他贡献者寻求故障排除帮助时,请务必包含它们。请遵循 SIG Windows 贡献指南中的日志收集说明。
报告问题和功能请求
如果您发现问题或想提出功能请求,请遵循 SIG Windows 贡献指南 来创建新问题。您应该首先搜索问题列表,以防之前已报告过,并评论您对此问题的经验并添加额外的日志。Kubernetes Slack 上的 SIG Windows 频道也是在创建工单之前获得初步支持和故障排除想法的好途径。
验证 Windows 集群可操作性
Kubernetes 项目提供了一份_Windows 可操作性就绪_规范,并附带一套结构化测试套件。这套套件分为两组测试:核心测试和扩展测试,每组都包含旨在测试特定类别的测试。它可以用于全面验证 Windows 和混合系统(与 Linux 节点混合)的所有功能。
要在新创建的集群上设置该项目,请参阅项目指南中的说明。
部署工具
kubeadm 工具可帮助你部署 Kubernetes 集群,提供控制平面来管理集群,并提供节点来运行你的工作负载。
Kubernetes 集群 API 项目还提供自动化部署 Windows 节点的方法。
Windows 分发渠道
有关 Windows 分发渠道的详细说明,请参阅Microsoft 文档。
有关包括其支持模型在内的不同 Windows Server 服务渠道的信息,请参见Windows Server 服务渠道。
本页中的项目引用了提供 Kubernetes 所需功能的第三方产品或项目。Kubernetes 项目作者不对这些第三方产品或项目负责。有关更多详细信息,请参阅 CNCF 网站指南。
在提议添加额外第三方链接的更改之前,你应该阅读内容指南。