在很多组织中,其服务和应用的很大比例是 Windows 应用。 Windows 容器提供了一种对进程和包依赖关系 进行封装的现代方式,这使得用户更容易采用 DevOps 实践,令 Windows 应用同样遵从 云原生模式。 Kubernetes 已经成为事实上的标准容器编排器,Kubernetes 1.14 发行版本中包含了将 Windows 容器调度到 Kubernetes 集群中 Windows 节点上的生产级支持,从而使得巨大 的 Windows 应用生态圈能够充分利用 Kubernetes 的能力。 对于同时投入基于 Windows 应用和 Linux 应用的组织而言,他们不必寻找不同的编排系统 来管理其工作负载,其跨部署的运维效率得以大幅提升,而不必关心所用操作系统。
若要在 Kubernetes 中启用对 Windows 容器的编排,可以在现有的 Linux 集群中 包含 Windows 节点。在 Kubernetes 上调度 Pods 中的 Windows 容器与调用基于 Linux 的容器类似。
为了运行 Windows 容器,你的 Kubernetes 集群必须包含多个操作系统,控制面 节点运行 Linux,工作节点则可以根据负载需要运行 Windows 或 Linux。 Windows Server 2019 是唯一被支持的 Windows 操作系统,在 Windows 上启用 Kubernetes 节点 支持(包括 kubelet, 容器运行时、 以及 kube-proxy)。关于 Windows 发行版渠道的详细讨论,可参见 Microsoft 文档。
Note: Kubernetes 控制面,包括主控组件, 继续在 Linux 上运行。 目前没有支持完全是 Windows 节点的 Kubernetes 集群的计划。
Note: 在本文中,当我们讨论 Windows 容器时,我们所指的是具有进程隔离能力的 Windows 容器。具有 Hyper-V 隔离能力的 Windows 容器计划在将来发行版本中推出。
参考下面的表格,了解 Kubernetes 中支持的 Windows 操作系统。 同一个异构的 Kubernetes 集群中可以同时包含 Windows 和 Linux 工作节点。 Windows 容器仅能调度到 Windows 节点,Linux 容器则只能调度到 Linux 节点。
Kubernetes 版本 | Windows Server LTSC 版本 | Windows Server SAC 版本 |
---|---|---|
Kubernetes v1.20 | Windows Server 2019 | Windows Server ver 1909, Windows Server ver 2004 |
Kubernetes v1.21 | Windows Server 2019 | Windows Server ver 2004, Windows Server ver 20H2 |
Kubernetes v1.22 | Windows Server 2019 | Windows Server ver 2004, Windows Server ver 20H2 |
关于不同的 Windows Server 版本的服务渠道,包括其支持模式等相关信息可以在 Windows Server servicing channels找到。
我们并不指望所有 Windows 客户都为其应用频繁地更新操作系统。 对应用的更新是向集群中引入新代码的根本原因。 对于想要更新运行于 Kubernetes 之上的容器中操作系统的客户,我们会在添加对新 操作系统版本的支持时提供指南和分步的操作指令。 该指南会包含与集群节点一起来升级用户应用的建议升级步骤。 Windows 节点遵从 Kubernetes 版本偏差策略(节点到控制面的 版本控制),与 Linux 节点的现行策略相同。
Windows Server 主机操作系统会受 Windows Server授权策略控制。Windows 容器镜像则遵从 Windows 容器的补充授权条款约定。
带进程隔离的 Windows 容器受一些严格的兼容性规则约束, 其中宿主 OS 版本必须与容器基准镜像的 OS 版本相同。 一旦我们在 Kubernetes 中支持带 Hyper-V 隔离的 Windows 容器, 这一约束和兼容性规则也会发生改变。
Kubernetes 维护着一个多体系结构镜像,其中包括对 Windows 的支持。 对于 Kubernetes v1.22,推荐的 pause 镜像是 k8s.gcr.io/pause:3.5
。 源代码可在 GitHub 上找到。
Microsoft 维护了一个支持 Linux 和 Windows amd64 的多体系结构镜像: mcr.microsoft.com/oss/kubernetes/pause:3.5
。 此镜像与 Kubernetes 维护的镜像是从同一来源构建,但所有 Windows 二进制文件 均由 Microsoft 签名。 当生产环境需要被签名的二进制文件时,建议使用 Microsoft 维护的镜像。
从 API 和 kubectl 的角度,Windows 容器的表现在很大程度上与基于 Linux 的容器 是相同的。不过也有一些与关键功能相关的差别值得注意,这些差别列举于 局限性小节中。
关键性的 Kubernetes 元素在 Windows 下与其在 Linux 下工作方式相同。我们在本节中 讨论一些关键性的负载支撑组件及其在 Windows 中的映射。
Pod 是 Kubernetes 中最基本的构造模块,是 Kubernetes 对象模型中你可以创建或部署的 最小、最简单元。你不可以在同一 Pod 中部署 Windows 和 Linux 容器。 Pod 中的所有容器都会被调度到同一节点(Node),而每个节点代表的是一种特定的平台 和体系结构。Windows 容器支持 Pod 的以下能力、属性和事件:
Kubernetes 控制器处理 Pod 的期望状态。Windows 容器支持以下负载控制器:
Kubernetes Service 是一种抽象对象,用来定义 Pod 的一个逻辑集合及用来访问这些 Pod 的策略。Service 有时也称作微服务(Micro-service)。你可以使用服务来实现 跨操作系统的连接。在 Windows 系统中,服务可以使用下面的类型、属性和能力:
Pods、控制器和服务是在 Kubernetes 上管理 Windows 负载的关键元素。 不过,在一个动态的云原生环境中,这些元素本身还不足以用来正确管理 Windows 负载的生命周期。我们为此添加了如下功能特性:
FEATURE STATE: Kubernetes v1.14 [stable]
Docker EE-basic 19.03+ 是建议所有 Windows Server 版本采用的容器运行时。 该容器运行时能够与 kubelet 中的 dockershim 代码协同工作。
FEATURE STATE: Kubernetes v1.20 [stable]
ContainerD 1.4.0+ 也可作为 Windows Kubernetes 节点上的容器运行时。
使用 Kubernetes 卷,对数据持久性和 Pod 卷 共享有需求的复杂应用也可以部署到 Kubernetes 上。 管理与特定存储后端或协议相关的持久卷时,相关的操作包括:对卷的配备(Provisioning)、 去配(De-provisioning)和调整大小,将卷挂接到 Kubernetes 节点或从节点上解除挂接, 将卷挂载到需要持久数据的 Pod 中的某容器或从容器上卸载。 负责实现为特定存储后端或协议实现卷管理动作的代码以 Kubernetes 卷 插件的形式发布。 Windows 支持以下大类的 Kubernetes 卷插件:
与树内卷插件(In-Tree Volume Plugin)相关的代码都作为核心 Kubernetes 代码基 的一部分发布。树内卷插件的部署不需要安装额外的脚本,也不需要额外部署独立的 容器化插件组件。这些插件可以处理:对应存储后端上存储卷的配备、去配和尺寸更改, 将卷挂接到 Kubernetes 或从其上解挂,以及将卷挂载到 Pod 中各个容器上或从其上 卸载。以下树内插件支持 Windows 节点:
awsElasticBlockStore
azureDisk
azureFile
gcePersistentDisk
vsphereVolume
与 FlexVolume 插件相关的代码是作为 树外(Out-of-tree)脚本或可执行文件来发布的,因此需要在宿主系统上直接部署。 FlexVolume 插件处理将卷挂接到 Kubernetes 节点或从其上解挂、将卷挂载到 Pod 中 各个容器上或从其上卸载等操作。对于与 FlexVolume 插件相关联的持久卷的配备和 去配操作,可以通过外部的配置程序来处理。这类配置程序通常与 FlexVolume 插件 相分离。下面的 FlexVolume 插件 可以以 PowerShell 脚本的形式部署到宿主系统上,支持 Windows 节点:
SMB
iSCSI
FEATURE STATE: Kubernetes v1.22 [stable]
与 CSI 插件相关联的代码作为 树外脚本和可执行文件来发布且通常发布为容器镜像形式,并使用 DaemonSet 和 StatefulSet 这类标准的 Kubernetes 构造体来部署。 CSI 插件处理 Kubernetes 中的很多卷管理操作:对卷的配备、去配和调整大小, 将卷挂接到 Kubernetes 节点或从节点上解除挂接,将卷挂载到需要持久数据的 Pod 中的某容器或从容器上卸载,使用快照和克隆来备份或恢复持久数据。
来支持;csi-proxy 是一个社区管理的、独立的可执行文件,需要预安装在每个 Windows 节点之上。请参考你要部署的 CSI 插件的部署指南以进一步了解其细节。
CSI 插件与执行本地存储操作的 CSI 节点插件通信。 在 Windows 节点上,CSI 节点插件通常调用处理本地存储操作的 csi-proxy 公开的 API, csi-proxy 由社区管理。
有关安装的更多详细信息,请参阅你要部署的 Windows CSI 插件的环境部署指南。 你也可以参考以下安装步骤 。
Windows 容器的联网是通过 CNI 插件 来暴露出来的。Windows 容器的联网行为与虚拟机的联网行为类似。 每个容器有一块虚拟的网络适配器(vNIC)连接到 Hyper-V 的虚拟交换机(vSwitch)。 宿主的联网服务(Host Networking Service,HNS)和宿主计算服务(Host Compute Service,HCS)协同工作,创建容器并将容器的虚拟网卡连接到网络上。 HCS 负责管理容器,HNS 则负责管理网络资源,例如:
支持的服务规约类型如下:
Windows 支持五种不同的网络驱动/模式:二层桥接(L2bridge)、二层隧道(L2tunnel)、 覆盖网络(Overlay)、透明网络(Transparent)和网络地址转译(NAT)。 在一个包含 Windows 和 Linux 工作节点的异构集群中,你需要选择一种对 Windows 和 Linux 兼容的联网方案。下面是 Windows 上支持的一些树外插件及何时使用某种 CNI 插件的建议:
网络驱动 | 描述 | 容器报文更改 | 网络插件 | 网络插件特点 |
---|---|---|---|---|
L2bridge | 容器挂接到外部 vSwitch 上。容器挂接到下层网络之上,但由于容器的 MAC 地址在入站和出站时被重写,物理网络不需要这些地址。 | MAC 地址被重写为宿主系统的 MAC 地址,IP 地址也可能依据 HNS OutboundNAT 策略重写为宿主的 IP 地址。 | win-bridge、 Azure-CNI、 Flannel 宿主网关(host-gateway)使用 win-bridge | win-bridge 使用二层桥接(L2bridge)网络模式,将容器连接到下层宿主系统上, 从而提供最佳性能。需要用户定义的路由(User-Defined Routes,UDR)才能 实现节点间的连接。 |
L2Tunnel | 这是二层桥接的一种特殊情形,但仅被用于 Azure 上。 所有报文都被发送到虚拟化环境中的宿主机上并根据 SDN 策略进行处理。 | MAC 地址被改写,IP 地址在下层网络上可见。 | Azure-CNI | Azure-CNI 使得容器能够与 Azure vNET 集成,并允许容器利用 [Azure 虚拟网络](https://azure.microsoft.com/en-us/services/virtual-network/) 所提供的功能特性集合。例如,可以安全地连接到 Azure 服务上或者使用 Azure NSG。 你可以参考 [azure-cni](https://docs.microsoft.com/en-us/azure/aks/concepts-network#azure-cni-advanced-networking) 所提供的一些示例。 |
覆盖网络(Kubernetes 中为 Windows 提供的覆盖网络支持处于 *alpha* 阶段) | 每个容器会获得一个连接到外部 vSwitch 的虚拟网卡(vNIC)。 每个覆盖网络都有自己的、通过定制 IP 前缀来定义的 IP 子网。 覆盖网络驱动使用 VxLAN 封装。 | 封装于外层包头内。 | Win-overlay、 Flannel VXLAN(使用 win-overlay) | 当(比如出于安全原因)期望虚拟容器网络与下层宿主网络隔离时, 应该使用 win-overlay。如果你的数据中心可用 IP 地址受限, 覆盖网络允许你在不同的网络中复用 IP 地址(每个覆盖网络有不同的 VNID 标签)。 这一选项要求在 Windows Server 2009 上安装 [KB4489899](https://support.microsoft.com/help/4489899) 补丁。 |
透明网络([ovn-kubernetes](https://github.com/openvswitch/ovn-kubernetes) 的特殊用例) | 需要一个外部 vSwitch。容器挂接到某外部 vSwitch 上,该 vSwitch 通过逻辑网络(逻辑交换机和路由器)允许 Pod 间通信。 | 报文或者通过 [GENEVE](https://datatracker.ietf.org/doc/draft-gross-geneve/) 来封装, 或者通过 [STT](https://datatracker.ietf.org/doc/draft-davie-stt/) 隧道来封装, 以便能够到达不在同一宿主系统上的每个 Pod。 报文通过 OVN 网络控制器所提供的隧道元数据信息来判定是转发还是丢弃。 北-南向通信通过 NAT 网络地址转译来实现。 | ovn-kubernetes | [通过 Ansible 来部署](https://github.com/openvswitch/ovn-kubernetes/tree/master/contrib)。 所发布的 ACL 可以通过 Kubernetes 策略来应用实施。支持 IPAM 。 负载均衡能力不依赖 kube-proxy。 网络地址转译(NAT)也不需要 iptables 或 netsh。 |
NAT(未在 Kubernetes 中使用) | 容器获得一个连接到某内部 vSwitch 的 vNIC 接口。 DNS/DHCP 服务通过名为 [WinNAT](https://blogs.technet.microsoft.com/virtualization/2016/05/25/windows-nat-winnat-capabilities-and-limitations/) 的内部组件来提供。 | MAC 地址和 IP 地址都被重写为宿主系统的 MAC 地址和 IP 地址。 | nat | 列在此表中仅出于完整性考虑 |
如前所述,Flannel CNI meta 插件 在 Windows 上也是 被支持 的,方法是通过 VXLAN 网络后端 (alpha 阶段 :委托给 win-overlay)和 主机-网关(host-gateway)网络后端 (稳定版本;委托给 win-bridge 实现)。 此插件支持将操作委托给所引用的 CNI 插件(win-overlay、win-bridge)之一, 从而能够与 Windows 上的 Flannel 守护进程(Flanneld)一同工作,自动为节点 分配子网租期,创建 HNS 网络。 该插件读入其自身的配置文件(cni.conf),并将其与 FlannelD 所生成的 subnet.env 文件中的环境变量整合,之后将其操作委托给所引用的 CNI 插件之一以完成网络发现, 并将包含节点所被分配的子网信息的正确配置发送给 IPAM 插件(例如 host-local)。
对于节点、Pod 和服务对象,可针对 TCP/UDP 流量支持以下网络数据流:
Windows 上支持以下 IPAM 选项:
host-local
在 Windows 系统上,你可以使用以下配置来设定服务和负载均衡行为:
功能特性 | 描述 | 所支持的 Kubernetes 版本 | 所支持的 Windows OS 版本 | 如何启用 |
---|---|---|---|---|
会话亲和性 | 确保来自特定客户的连接每次都被交给同一 Pod。 | v1.20+ | [Windows Server vNext Insider Preview Build 19551](https://blogs.windows.com/windowsexperience/2020/01/28/announcing-windows-server-vnext-insider-preview-build-19551/) 或更高版本 | 将 service.spec.sessionAffinitys 设置为 "ClientIP" |
直接服务器返回(DSR) | 这是一种负载均衡模式,IP 地址的修正和负载均衡地址转译(LBNAT) 直接在容器的 vSwitch 端口上处理;服务流量到达时,其源端 IP 地址 设置为来源 Pod 的 IP。 | v1.20+ | Windows Server 2019 | 为 kube-proxy 设置标志:`--feature-gates="WinDSR=true" --enable-dsr=true` |
保留目标地址 | 对服务流量略过 DNAT 步骤,这样就可以在到达后端 Pod 的报文中保留目标服务的 虚拟 IP 地址。还要禁止节点之间的转发。 | v1.20+ | Windows Server 1903 或更高版本 | 在服务注解中设置 `"preserve-destination": "true"` 并启用 kube-proxy 中的 DSR 标志。 |
IPv4/IPv6 双栈网络 | 在集群内外同时支持原生的 IPv4-到-IPv4 和 IPv6-到-IPv6 通信。 | v1.19+ | Windows Server 2004 或更高版本 | 参见 [IPv4/IPv6 双栈网络](#ipv4ipv6-dual-stack) |
保留客户端 IP | 确保入站流量的源 IP 地址被保留。同样要禁止节点之间的转发。 | v1.20+ | Windows Server 2019 或更高版本 | 将 service.spec.externalTrafficPolicy 设置为 "Local", 并在 kube-proxy 上启用 DSR。 |
你可以通过使用 IPv6DualStack
特性门控 来为 l2bridge
网络启用 IPv4/IPv6 双栈联网支持。
对 Windows 而言,在 Kubernetes 中使用 IPv6 需要 Windows Server 2004 (内核版本 10.0.19041.610)或更高版本。
目前 Windows 上的覆盖网络(VXLAN)还不支持双协议栈联网。
在 Kubernetes 架构和节点阵列中仅支持将 Windows 作为工作节点使用。 这意味着 Kubernetes 集群必须总是包含 Linux 主控节点,零个或者多个 Linux 工作节点以及零个或者多个 Windows 工作节点。
Linux 上使用 Linux 控制组(CGroups)作为 Pod 的边界,以实现资源控制。 容器都创建于这一边界之内,从而实现网络、进程和文件系统的隔离。 控制组 CGroups API 可用来收集 CPU、I/O 和内存的统计信息。 与此相比,Windows 为每个容器创建一个带有系统名字空间过滤设置的 Job 对象, 以容纳容器中的所有进程并提供其与宿主系统间的逻辑隔离。 没有现成的名字空间过滤设置是无法运行 Windows 容器的。 这也意味着,系统特权无法在宿主环境中评估,因而 Windows 上也就不存在特权容器。 归咎于独立存在的安全账号管理器(Security Account Manager,SAM),容器也不能 获得宿主系统上的任何身份标识。
Windows 不像 Linux 一样有一个内存耗尽(Out-of-memory)进程杀手(Process Killer)机制。Windows 总是将用户态的内存分配视为虚拟请求,页面文件(Pagefile) 是必需的。这一差异的直接结果是 Windows 不会像 Linux 那样出现内存耗尽的状况, 系统会将进程内存页面写入磁盘而不会因内存耗尽而终止进程。 当内存被过量使用且所有物理内存都被用光时,系统的换页行为会导致性能下降。
使用 kubelet 参数 --kubelet-reserve
与/或 -system-reserve
可以统计 节点上的内存用量(各容器之外),进而可能将内存用量限制在一个合理的范围,。 这样做会减少节点可分配内存。
在你部署工作负载时,对容器使用资源限制(必须仅设置 limits 或者让 limits 等于 requests 值)。这也会从 NodeAllocatable 中耗掉部分内存量,从而避免在节点 负荷已满时调度器继续向节点添加 Pods。
避免过量分配的最佳实践是为 kubelet 配置至少 2 GB 的系统预留内存,以供 Windows、Docker 和 Kubernetes 进程使用。
为了统计 Windows、Docker 和其他 Kubernetes 宿主进程的 CPU 用量,建议 预留一定比例的 CPU,以便对事件作出相应。此值需要根据 Windows 节点上 CPU 核的个数来调整,要确定此百分比值,用户需要为其所有节点确定 Pod 密度的上线,并监控系统服务的 CPU 用量,从而选择一个符合其负载需求的值。
使用 kubelet 参数 --kubelet-reserve
与/或 -system-reserve
可以统计 节点上的 CPU 用量(各容器之外),进而可能将 CPU 用量限制在一个合理的范围,。 这样做会减少节点可分配 CPU。
以下 kubelet 参数的行为在 Windows 节点上有些不同,描述如下:
--kubelet-reserve
、--system-reserve
和 --eviction-hard
标志 会更新节点可分配资源量--enforce-node-allocable
来完成的 Pod 驱逐--eviction-hard
和 --eviction-soft
来完成的 Pod 驱逐MemoryPressure
状况未实现kubelet
不会采取措施来执行基于 OOM 的驱逐动作--kubelet-reserve
和 --system-reserve
不会为 kubelet 或宿主系统上运行 的进程设限。这意味着 kubelet 或宿主系统上的进程可能导致内存资源紧张, 而这一情况既不受节点可分配量影响,也不会被调度器感知。--windows-priorityclass
。此参数允许 kubelet 进程获得与 Windows 宿主上 其他进程相比更多的 CPU 时间片。 关于可用参数值及其含义的进一步信息可参考 Windows Priority Classes。 为了让 kubelet 总能够获得足够的 CPU 周期,建议将此参数设置为 ABOVE_NORMAL_PRIORITY_CLASS
或更高。Windows 上包含一个分层的文件系统来挂载容器的分层,并会基于 NTFS 来创建一个 拷贝文件系统。容器中的所有文件路径都仅在该容器的上下文内完成解析。
因此,Windows 节点上不支持以下存储功能特性:
readOnly
;Windows 容器联网与 Linux 联网有着非常重要的差别。 Microsoft documentation for Windows Container Networking中包含额外的细节和背景信息。
Windows 宿主联网服务和虚拟交换机实现了名字空间隔离,可以根据需要为 Pod 或容器 创建虚拟的网络接口(NICs)。不过,很多类似 DNS、路由、度量值之类的配置数据都 保存在 Windows 注册表数据库中而不是像 Linux 一样保存在 /etc/...
文件中。 Windows 为容器提供的注册表与宿主系统的注册表是分离的,因此类似于将 /etc/resolv.conf 文件从宿主系统映射到容器中的做法不会产生与 Linux 系统相同的效果。 这些信息必须在容器内部使用 Windows API 来配置。 因此,CNI 实现需要调用 HNS,而不是依赖文件映射来将网络细节传递到 Pod 或容器中。
Windows 节点不支持以下联网功能:
ping <目标>
操作替换为 curl <目标>
以便能够调试与外部世界的网络连接。Kubernetes v1.15 中添加了以下功能特性:
kubectl port-forward
Windows 参考网络插件 win-bridge 和 win-overlay 当前未实现 CNI spec v0.4.0, 原因是缺少检查(CHECK)用的实现。
mydns.svc.cluster.local
)。 Windows 可以解析全限定域名、或者恰好可用该后缀来解析的服务名称。 例如,在 default 名字空间中生成的 Pod 会获得 DNS 后缀 default.svc.cluster.local
。在 Windows Pod 中,你可以解析 kubernetes.default.svc.cluster.local
和 kubernetes
,但无法解析二者 之间的形式,如 kubernetes.default
或 kubernetes.default.svc
。Resolve-DNSName
工具来完成名字查询解析。Windows 上的 Kubernetes 不支持单协议栈的“只用 IPv6”联网选项。 不过,系统支持在 IPv4/IPv6 双协议栈的 Pod 和节点上运行单协议家族的服务。
不支持使用 service.spec.sessionAffinityConfig.clientIP.timeoutSeconds
来为 Windows 服务设置最大会话粘滞时间。
Secret 以明文形式写入节点的卷中(而不是像 Linux 那样写入内存或 tmpfs 中)。 这意味着客户必须做以下两件事:
用户可以为 Windows Pods 或 Container 设置 RunAsUserName
以便以非节点默认用户来执行容器中的进程。这大致等价于设置 RunAsUser
。
不支持特定于 Linux 的 Pod 安全上下文特权,例如 SELinux、AppArmor、Seccomp、 权能字(POSIX 权能字)等等。
此外,如前所述,Windows 不支持特权容器。
对 Windows 而言,大多数 Kubernetes API 的工作方式没有变化。 一些不易察觉的差别通常体现在 OS 和容器运行时上的不同。 在某些场合,负载 API (如 Pod 或 Container)的某些属性在设计时假定其 在 Linux 上实现,因此会无法在 Windows 上运行。
在较高层面,不同的 OS 概念有:
/etc/groups
或 /etc/passwd
中的别名表项,会映射回 UID+GID。Windows 使用一个更大的二进制安全标识符(SID),保存在 Windows 安全访问管理器(Security Access Manager,SAM)数据库中。此数据库并不在宿主系统 与容器间,或者任意两个容器之间共享。\
而非 /
。Go 语言的 IO 库同时接受这两种文件路径分隔符。不过,当你在指定要在容器内解析的路径或命令行时, 可能需要使用 \
。WM_CLOSE
在内的良定的消息SERVICE_CONTROL_STOP
控制代码退出代码遵从相同的习惯,0 表示成功,非 0 值表示失败。 特定的错误代码在 Windows 和 Linux 上可能会不同。不过,从 Kubernetes 组件 (kubelet、kube-proxy)所返回的退出代码是没有变化的。
v1.Container.ResourceRequirements.limits.cpu
和 v1.Container.ResourceRequirements.limits.memory
- Windows 不对 CPU 分配设置硬性的限制。与之相反,Windows 使用一个份额(share)系统。 基于毫核(millicores)的现有字段值会被缩放为相对的份额值,供 Windows 调度器使用。v1.Container.ResourceRequirements.requests.cpu
和 v1.Container.ResourceRequirements.requests.memory
- 请求 值会从节点可分配资源中扣除,从而可用来避免节点上的资源过量分配。 但是,它们无法用来在一个已经过量分配的节点上提供资源保障。 如果操作员希望彻底避免过量分配,作为最佳实践,他们就需要为所有容器设置资源请求值。v1.Container.SecurityContext.allowPrivilegeEscalation
- 在 Windows 上无法实现,对应的权能无一可在 Windows 上生效。v1.Container.SecurityContext.Capabilities
- Windows 上未实现 POSIX 权能机制v1.Container.SecurityContext.privileged
- Windows 不支持特权容器v1.Container.SecurityContext.procMount
- Windows 不包含 /proc
文件系统v1.Container.SecurityContext.readOnlyRootFilesystem
- 在 Windows 上无法实现, 要在容器内使用注册表或运行系统进程就必需写访问权限。v1.Container.SecurityContext.runAsGroup
- 在 Windows 上无法实现,没有 GID 支持v1.Container.SecurityContext.runAsNonRoot
- Windows 上没有 root 用户。 与之最接近的等价用户是 ContainerAdministrator,而该身份标识在节点上并不存在。v1.Container.SecurityContext.runAsUser
- 在 Windows 上无法实现, 因为没有作为整数支持的 GID。v1.Container.SecurityContext.seLinuxOptions
- 在 Windows 上无法实现, 因为没有 SELinuxV1.Container.terminationMessagePath
- 因为 Windows 不支持单个文件的映射,这一功能 在 Windows 上也受限。默认值 /dev/termination-log
在 Windows 上也无法使用因为 对应路径在 Windows 上不存在。v1.Pod.hostIPC
、v1.Pod.hostPID
- Windows 不支持共享宿主系统的名字空间v1.Pod.hostNetwork
- Windows 操作系统不支持共享宿主网络v1.Pod.dnsPolicy
- 不支持 ClusterFirstWithHostNet
,因为 Windows 不支持宿主网络v1.Pod.podSecurityContext
- 参见下面的 v1.PodSecurityContext
v1.Pod.shareProcessNamespace
- 此为 Beta 特性且依赖于 Windows 上未实现 的 Linux 名字空间。 Windows 无法共享进程名字空间或者容器的根文件系统。只能共享网络。v1.Pod.terminationGracePeriodSeconds
- 这一特性未在 Windows 版本的 Docker 中完全实现。 参见问题报告。 目前实现的行为是向 ENTRYPOINT
进程发送 CTRL_SHUTDOWN_EVENT
事件,之后 Windows 默认 等待 5 秒钟,并最终使用正常的 Windows 关机行为关闭所有进程。 这里的 5 秒钟默认值实际上保存在 容器内 的 Windows 注册表中,因此可以在构造容器时重载。v1.Pod.volumeDevices
- 此为 Beta 特性且未在 Windows 上实现。Windows 无法挂接 原生的块设备到 Pod 中。v1.Pod.volumes
- emptyDir
、secret
、configMap
和 hostPath
都可正常工作且在 TestGrid 中测试。v1.emptyDir.volumeSource
- Windows 上节点的默认介质是磁盘。 不支持将内存作为介质,因为 Windows 不支持内置的 RAM 磁盘。v1.VolumeMount.mountPropagation
- Windows 上不支持挂载传播。PodSecurityContext 的所有选项在 Windows 上都无法工作。这些选项列在下面仅供参考。
v1.PodSecurityContext.seLinuxOptions
- Windows 上无 SELinuxv1.PodSecurityContext.runAsUser
- 提供 UID;Windows 不支持v1.PodSecurityContext.runAsGroup
- 提供 GID;Windows 不支持v1.PodSecurityContext.runAsNonRoot
- Windows 上没有 root 用户 最接近的等价账号是 ContainerAdministrator
,而该身份标识在节点上不存在v1.PodSecurityContext.supplementalGroups
- 提供 GID;Windows 不支持v1.PodSecurityContext.sysctls
- 这些是 Linux sysctl 接口的一部分;Windows 上 没有等价机制。Windows 有着严格的兼容性规则,宿主 OS 的版本必须与容器基准镜像 OS 的版本匹配。 目前仅支持容器操作系统为 Windows Server 2019 的 Windows 容器。 对于容器的 Hyper-V 隔离、允许一定程度上的 Windows 容器镜像版本向后兼容性等等, 都是将来版本计划的一部分。
Kubernetes 中日志是故障排查的一个重要元素。确保你在尝试从其他贡献者那里获得 故障排查帮助时提供日志信息。你可以按照 SIG-Windows 贡献指南和收集日志 所给的指令来操作。
start.ps1
是否已成功完成?你应该能看到节点上运行的 kubelet、kube-proxy 和(如果你选择 Flannel 作为联网方案)flanneld 宿主代理进程,它们的运行日志显示在不同的 PowerShell 窗口中。此外,你的 Windows 节点应该在你的 Kubernetes 集群 列举为 "Ready" 节点。
我可以将 Kubernetes 节点进程配置为服务运行在后台么?kubelet 和 kube-proxy 都已经被配置为以本地 Windows 服务运行, 并且在出现失效事件(例如进程意外结束)时通过自动重启服务来提供一定的弹性。 你有两种办法将这些节点组件配置为服务。
Kubelet 和 kube-proxy 可以用 sc.exe
以本地 Windows 服务的形式运行:
# 用两个单独的命令为 kubelet 和 kube-proxy 创建服务使用 nssm.exe
sc.exe create <组件名称> binPath="<可执行文件路径> -service <其它参数>"
# 请注意如果参数中包含空格,必须使用转义
sc.exe create kubelet binPath= "C:\kubelet.exe --service --hostname-override 'minion' <其它参数>"
# 启动服务
Start-Service kubelet
Start-Service kube-proxy
# 停止服务
Stop-Service kubelet (-Force)
Stop-Service kube-proxy (-Force)
# 查询服务状态
Get-Service kubelet
Get-Service kube-proxy
你也总是可以使用替代的服务管理器,例如nssm.exe,来为你在后台运行 这些进程(flanneld
、kubelet
和 kube-proxy
)。你可以使用这一 示例脚本, 利用 nssm.exe
将 kubelet
、kube-proxy
和 flanneld.exe
注册为要在后台运行的 Windows 服务。
register-svc.ps1 -NetworkMode <网络模式> -ManagementIP <Windows 节点 IP> -ClusterCIDR <集群子网> -KubeDnsServiceIP <kube-dns 服务 IP> -LogDir <日志目录>
这里的参数解释如下:
NetworkMode
:网络模式 l2bridge(flannel host-gw,也是默认值)或 overlay(flannel vxlan)选做网络方案ManagementIP
:分配给 Windows 节点的 IP 地址。你可以使用 ipconfig 得到此值ClusterCIDR
:集群子网范围(默认值为 10.244.0.0/16)KubeDnsServiceIP
:Kubernetes DNS 服务 IP(默认值为 10.96.0.10)LogDir
:kubelet 和 kube-proxy 的日志会被重定向到这一目录中的对应输出文件, 默认值为 C:\k
。若以上所引用的脚本不适合,你可以使用下面的例子手动配置 nssm.exe
。
注册 flanneld.exe:
nssm install flanneld C:\flannel\flanneld.exe
nssm set flanneld AppParameters --kubeconfig-file=c:\k\config --iface=<ManagementIP> --ip-masq=1 --kube-subnet-mgr=1
nssm set flanneld AppEnvironmentExtra NODE_NAME=<hostname>
nssm set flanneld AppDirectory C:\flannel
nssm start flanneld
注册 kubelet.exe:
nssm install kubelet C:\k\kubelet.exe
nssm set kubelet AppParameters --hostname-override=<hostname> --v=6 --pod-infra-container-image=k8s.gcr.io/pause:3.5 --resolv-conf="" --allow-privileged=true --enable-debugging-handlers --cluster-dns=<DNS-service-IP> --cluster-domain=cluster.local --kubeconfig=c:\k\config --hairpin-mode=promiscuous-bridge --image-pull-progress-deadline=20m --cgroups-per-qos=false --log-dir=<log directory> --logtostderr=false --enforce-node-allocatable="" --network-plugin=cni --cni-bin-dir=c:\k\cni --cni-conf-dir=c:\k\cni\config
nssm set kubelet AppDirectory C:\k
nssm start kubelet
注册 kube-proxy.exe(二层网桥模式和主机网关模式)
nssm install kube-proxy C:\k\kube-proxy.exe
nssm set kube-proxy AppDirectory c:\k
nssm set kube-proxy AppParameters --v=4 --proxy-mode=kernelspace --hostname-override=<hostname>--kubeconfig=c:\k\config --enable-dsr=false --log-dir=<log directory> --logtostderr=false
nssm.exe set kube-proxy AppEnvironmentExtra KUBE_NETWORK=cbr0
nssm set kube-proxy DependOnService kubelet
nssm start kube-proxy
注册 kube-proxy.exe(覆盖网络模式或 VxLAN 模式)
nssm install kube-proxy C:\k\kube-proxy.exe
nssm set kube-proxy AppDirectory c:\k
nssm set kube-proxy AppParameters --v=4 --proxy-mode=kernelspace --feature-gates="WinOverlay=true" --hostname-override=<hostname> --kubeconfig=c:\k\config --network-name=vxlan0 --source-vip=<source-vip> --enable-dsr=false --log-dir=<log directory> --logtostderr=false
nssm set kube-proxy DependOnService kubelet
nssm start kube-proxy
作为初始的故障排查操作,你可以使用在 nssm.exe中使用下面的标志 以便将标准输出和标准错误输出重定向到一个输出文件:
nssm set <服务名称> AppStdout C:\k\mysvc.log
nssm set <服务名称> AppStderr C:\k\mysvc.log
要了解更多的细节,可参见官方的 nssm 用法文档。
我的 Windows Pods 无法连接网络如果你在使用虚拟机,请确保 VM 网络适配器均已开启 MAC 侦听(Spoofing)。
我的 Windows Pods 无法 ping 外部资源Windows Pods 目前没有为 ICMP 协议提供出站规则。不过 TCP/UDP 是支持的。 尝试与集群外资源连接时,可以将 ping <IP>
命令替换为对应的 curl <IP>
命令。
如果你还遇到问题,很可能你在 cni.conf 中的网络配置值得额外的注意。你总是可以编辑这一静态文件。 配置的更新会应用到所有新创建的 Kubernetes 资源上。
Kubernetes 网络的需求之一是集群内部无需网络地址转译(NAT)即可实现通信。 为了符合这一要求,对所有我们不希望出站时发生 NAT 的通信都存在一个 ExceptionList。 然而这也意味着你需要将你要查询的外部 IP 从 ExceptionList 中移除。 只有这时,从你的 Windows Pod 发起的网络请求才会被正确地通过 SNAT 转换以接收到 来自外部世界的响应。 就此而言,你在 cni.conf
中的 ExceptionList
应该看起来像这样:
"ExceptionList": [我的 Windows 节点无法访问 NodePort 服务
"10.244.0.0/16", # 集群子网
"10.96.0.0/12", # 服务子网
"10.127.130.0/24" # 管理(主机)子网
]
从节点自身发起的本地 NodePort 请求会失败。这是一个已知的局限。 NodePort 服务的访问从其他节点或者外部客户端都可正常进行。
容器的 vNICs 和 HNS 端点被删除了这一问题可能因为 hostname-override
参数未能传递给 kube-proxy 而导致。解决这一问题时,用户需要按如下方式将主机名传递给 kube-proxy:
C:\k\kube-proxy.exe --hostname-override=$(hostname)使用 Flannel 时,我的节点在重新加入集群时遇到问题
无论何时,当一个之前被删除的节点被重新添加到集群时,flannelD 都会将为节点分配 一个新的 Pod 子网。 用户需要将将下面路径中的老的 Pod 子网配置文件删除:
Remove-Item C:\k\SourceVip.json在启动了
Remove-Item C:\k\SourceVipRequest.json
start.ps1
之后,flanneld 一直停滞在 "Waiting for the Network to be created" 状态 关于这一问题有很多的报告; 最可能的一种原因是关于何时设置 Flannel 网络的管理 IP 的时间问题。 一种解决办法是重新启动 start.ps1
或者按如下方式手动重启之:
[Environment]::SetEnvironmentVariable("NODE_NAME", "<Windows 工作节点主机名>")我的 Windows Pods 无法启动,因为缺少
C:\flannel\flanneld.exe --kubeconfig-file=c:\k\config --iface=<Windows 工作节点 IP> --ip-masq=1 --kube-subnet-mgr=1
/run/flannel/subnet.env
文件 这表明 Flannel 网络未能正确启动。你可以尝试重启 flanneld.exe 或者将文件手动地 从 Kubernetes 主控节点的 /run/flannel/subnet.env
路径复制到 Windows 工作 节点的 C:\run\flannel\subnet.env
路径,并将 FLANNEL_SUBNET
行改为一个 不同的数值。例如,如果期望节点子网为 10.244.4.1/24
:
FLANNEL_NETWORK=10.244.0.0/16我的 Windows 节点无法使用服务 IP 访问我的服务
FLANNEL_SUBNET=10.244.4.1/24
FLANNEL_MTU=1500
FLANNEL_IPMASQ=true
这是 Windows 上当前网络协议栈的一个已知的限制。 Windows Pods 能够访问服务 IP。
启动 kubelet 时找不到网络适配器Windows 网络堆栈需要一个虚拟的适配器,这样 Kubernetes 网络才能工作。 如果下面的命令(在管理员 Shell 中)没有任何返回结果,证明虚拟网络创建 (kubelet 正常工作的必要前提之一)失败了:
Get-HnsNetwork | ? Name -ieq "cbr0"
Get-NetAdapter | ? Name -Like "vEthernet (Ethernet*"
当宿主系统的网络适配器名称不是 "Ethernet" 时,通常值得更改 start.ps1
脚本中的 InterfaceName 参数来重试。否则可以查验 start-kubelet.ps1
的输出,看看是否在虚拟网络创建 过程中报告了其他错误。
检查你的 pause 镜像是与你的 OS 版本兼容的。 如果你安装的是更新版本的 Windows,比如说 某个 Insider 构造版本,你需要相应地调整要使用的镜像。 请参照 Microsoft 的 Docker 仓库了解镜像。不管怎样,pause 镜像的 Dockerfile 和示例服务都期望镜像的标签 为 :latest
。
kubectl port-forward
失败,错误信息为 "unable to do port forwarding: wincat not found" 此功能是在 Kubernetes v1.15 中实现的,pause 基础设施容器 mcr.microsoft.com/oss/kubernetes/pause:3.4.1
中包含了 wincat.exe。 请确保你使用的是这些版本或者更新版本。 如果你想要自行构造你自己的 pause 基础设施容器,要确保其中包含了 wincat
Windows 的端口转发支持需要在 pause 基础设施容器 中提供 wincat.exe。 确保你使用的是与你的 Windows 操作系统版本兼容的受支持镜像。 如果你想构建自己的 pause 基础架构容器,请确保包含 wincat。
我的 Kubernetes 安装失败,因为我的 Windows Server 节点在防火墙后面如果你处于防火墙之后,那么必须定义如下 PowerShell 环境变量:
[Environment]::SetEnvironmentVariable("HTTP_PROXY", "http://proxy.example.com:80/", [EnvironmentVariableTarget]::Machine)
[Environment]::SetEnvironmentVariable("HTTPS_PROXY", "http://proxy.example.com:443/", [EnvironmentVariableTarget]::Machine)
pause
容器是什么? 在一个 Kubernetes Pod 中,一个基础设施容器,或称 "pause" 容器,会被首先创建出来, 用以托管容器端点。属于同一 Pod 的容器,包括基础设施容器和工作容器,会共享相同的 网络名字空间和端点(相同的 IP 和端口空间)。我们需要 pause 容器来工作容器崩溃或 重启的状况,以确保不会丢失任何网络配置。
如果以上步骤未能解决你遇到的问题,你可以通过以下方式获得在 Kubernetes 中的 Windows 节点上运行 Windows 容器的帮助:
如果你遇到看起来像是软件缺陷的问题,或者你想要提起某种功能需求,请使用 GitHub 问题跟踪系统。 你可以在 GitHub 上发起 Issue 并将其指派给 SIG-Windows。你应该首先搜索 Issue 列表,看看是否 该 Issue 以前曾经被报告过,以评论形式将你在该 Issue 上的体验追加进去,并附上 额外的日志信息。SIG-Windows Slack 频道也是一个获得初步支持的好渠道,可以在 生成新的 Ticket 之前对一些想法进行故障分析。
在登记软件缺陷时,请给出如何重现该问题的详细信息,例如:
/sig windows
评论为其添加 sig/windows
标签, 进而引起 SIG-Windows 成员的注意。