Kubernetes 對Windows的支持

2022-06-01 11:30 更新

Kubernetes 對 Windows 的支持

在很多組織中,其服務(wù)和應(yīng)用的很大比例是 Windows 應(yīng)用。 Windows 容器提供了一種對進(jìn)程和包依賴關(guān)系 進(jìn)行封裝的現(xiàn)代方式,這使得用戶更容易采用 DevOps 實(shí)踐,令 Windows 應(yīng)用同樣遵從 云原生模式。 Kubernetes 已經(jīng)成為事實(shí)上的標(biāo)準(zhǔn)容器編排器,Kubernetes 1.14 發(fā)行版本中包含了將 Windows 容器調(diào)度到 Kubernetes 集群中 Windows 節(jié)點(diǎn)上的生產(chǎn)級支持,從而使得巨大 的 Windows 應(yīng)用生態(tài)圈能夠充分利用 Kubernetes 的能力。 對于同時(shí)投入基于 Windows 應(yīng)用和 Linux 應(yīng)用的組織而言,他們不必尋找不同的編排系統(tǒng) 來管理其工作負(fù)載,其跨部署的運(yùn)維效率得以大幅提升,而不必關(guān)心所用操作系統(tǒng)。

kubernetes 中的 Windows 容器 

若要在 Kubernetes 中啟用對 Windows 容器的編排,可以在現(xiàn)有的 Linux 集群中 包含 Windows 節(jié)點(diǎn)。在 Kubernetes 上調(diào)度 Pods 中的 Windows 容器與調(diào)用基于 Linux 的容器類似。

為了運(yùn)行 Windows 容器,你的 Kubernetes 集群必須包含多個(gè)操作系統(tǒng),控制面 節(jié)點(diǎn)運(yùn)行 Linux,工作節(jié)點(diǎn)則可以根據(jù)負(fù)載需要運(yùn)行 Windows 或 Linux。 Windows Server 2019 是唯一被支持的 Windows 操作系統(tǒng),在 Windows 上啟用 Kubernetes 節(jié)點(diǎn) 支持(包括 kubelet, 容器運(yùn)行時(shí)、 以及 kube-proxy)。關(guān)于 Windows 發(fā)行版渠道的詳細(xì)討論,可參見  Microsoft 文檔。

Note: Kubernetes 控制面,包括主控組件, 繼續(xù)在 Linux 上運(yùn)行。 目前沒有支持完全是 Windows 節(jié)點(diǎn)的 Kubernetes 集群的計(jì)劃。

Note: 在本文中,當(dāng)我們討論 Windows 容器時(shí),我們所指的是具有進(jìn)程隔離能力的 Windows 容器。具有 Hyper-V 隔離能力 的 Windows 容器計(jì)劃在將來發(fā)行版本中推出。

支持的功能與局限性 

支持的功能 

Windows 操作系統(tǒng)版本支持 

參考下面的表格,了解 Kubernetes 中支持的 Windows 操作系統(tǒng)。 同一個(gè)異構(gòu)的 Kubernetes 集群中可以同時(shí)包含 Windows 和 Linux 工作節(jié)點(diǎn)。 Windows 容器僅能調(diào)度到 Windows 節(jié)點(diǎn),Linux 容器則只能調(diào)度到 Linux 節(jié)點(diǎn)。

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

關(guān)于不同的 Windows Server 版本的服務(wù)渠道,包括其支持模式等相關(guān)信息可以在 Windows Server servicing channels 找到。

我們并不指望所有 Windows 客戶都為其應(yīng)用頻繁地更新操作系統(tǒng)。 對應(yīng)用的更新是向集群中引入新代碼的根本原因。 對于想要更新運(yùn)行于 Kubernetes 之上的容器中操作系統(tǒng)的客戶,我們會在添加對新 操作系統(tǒng)版本的支持時(shí)提供指南和分步的操作指令。 該指南會包含與集群節(jié)點(diǎn)一起來升級用戶應(yīng)用的建議升級步驟。 Windows 節(jié)點(diǎn)遵從 Kubernetes 版本偏差策略(節(jié)點(diǎn)到控制面的 版本控制),與 Linux 節(jié)點(diǎn)的現(xiàn)行策略相同。

Windows Server 主機(jī)操作系統(tǒng)會受 Windows Server 授權(quán)策略控制。Windows 容器鏡像則遵從 Windows 容器的補(bǔ)充授權(quán)條款 約定。

帶進(jìn)程隔離的 Windows 容器受一些嚴(yán)格的兼容性規(guī)則約束, 其中宿主 OS 版本必須與容器基準(zhǔn)鏡像的 OS 版本相同。 一旦我們在 Kubernetes 中支持帶 Hyper-V 隔離的 Windows 容器, 這一約束和兼容性規(guī)則也會發(fā)生改變。

Pause 鏡像 

Kubernetes 維護(hù)著一個(gè)多體系結(jié)構(gòu)鏡像,其中包括對 Windows 的支持。 對于 Kubernetes v1.22,推薦的 pause 鏡像是 ?k8s.gcr.io/pause:3.5?。 源代碼可在 GitHub 上找到。

Microsoft 維護(hù)了一個(gè)支持 Linux 和 Windows amd64 的多體系結(jié)構(gòu)鏡像: ?mcr.microsoft.com/oss/kubernetes/pause:3.5?。 此鏡像與 Kubernetes 維護(hù)的鏡像是從同一來源構(gòu)建,但所有 Windows 二進(jìn)制文件 均由 Microsoft 簽名。 當(dāng)生產(chǎn)環(huán)境需要被簽名的二進(jìn)制文件時(shí),建議使用 Microsoft 維護(hù)的鏡像。

計(jì)算 

從 API 和 kubectl 的角度,Windows 容器的表現(xiàn)在很大程度上與基于 Linux 的容器 是相同的。不過也有一些與關(guān)鍵功能相關(guān)的差別值得注意,這些差別列舉于 局限性小節(jié)中。

關(guān)鍵性的 Kubernetes 元素在 Windows 下與其在 Linux 下工作方式相同。我們在本節(jié)中 討論一些關(guān)鍵性的負(fù)載支撐組件及其在 Windows 中的映射。

  • Pods
  • Pod 是 Kubernetes 中最基本的構(gòu)造模塊,是 Kubernetes 對象模型中你可以創(chuàng)建或部署的 最小、最簡單元。你不可以在同一 Pod 中部署 Windows 和 Linux 容器。 Pod 中的所有容器都會被調(diào)度到同一節(jié)點(diǎn)(Node),而每個(gè)節(jié)點(diǎn)代表的是一種特定的平臺 和體系結(jié)構(gòu)。Windows 容器支持 Pod 的以下能力、屬性和事件:

    • 在帶進(jìn)程隔離和卷共享支持的 Pod 中運(yùn)行一個(gè)或多個(gè)容器
    • Pod 狀態(tài)字段
    • 就緒態(tài)(Readiness)和活躍性(Liveness)探針
    • postStart 和 preStop 容器生命周期事件
    • ConfigMap、Secrets:用作環(huán)境變量或卷
    • emptyDir 卷
    • 從宿主系統(tǒng)掛載命名管道
    • 資源限制
  • 控制器(Controllers)
  • Kubernetes 控制器處理 Pod 的期望狀態(tài)。Windows 容器支持以下負(fù)載控制器:

    • ReplicaSet
    • ReplicationController
    • Deployment
    • StatefulSet
    • DaemonSet
    • Job
    • CronJob
  • 服務(wù)(Services)
  • Kubernetes Service 是一種抽象對象,用來定義 Pod 的一個(gè)邏輯集合及用來訪問這些 Pod 的策略。Service 有時(shí)也稱作微服務(wù)(Micro-service)。你可以使用服務(wù)來實(shí)現(xiàn) 跨操作系統(tǒng)的連接。在 Windows 系統(tǒng)中,服務(wù)可以使用下面的類型、屬性和能力:

    • Service 環(huán)境變量
    • NodePort
    • ClusterIP
    • LoadBalancer
    • ExternalName
    • 無頭(Headless)服務(wù)

Pods、控制器和服務(wù)是在 Kubernetes 上管理 Windows 負(fù)載的關(guān)鍵元素。 不過,在一個(gè)動態(tài)的云原生環(huán)境中,這些元素本身還不足以用來正確管理 Windows 負(fù)載的生命周期。我們?yōu)榇颂砑恿巳缦鹿δ芴匦裕?/p>

  • Pod 和容器的度量(Metrics)
  • 對水平 Pod 自動擴(kuò)展的支持
  • 對 kubectl exec 命令的支持
  • 資源配額
  • 調(diào)度器搶占

容器運(yùn)行時(shí) 

Docker EE

FEATURE STATE: Kubernetes v1.14 [stable]

Docker EE-basic 19.03+ 是建議所有 Windows Server 版本采用的容器運(yùn)行時(shí)。 該容器運(yùn)行時(shí)能夠與 kubelet 中的 dockershim 代碼協(xié)同工作。

CRI-ContainerD

FEATURE STATE: Kubernetes v1.20 [stable]

ContainerD 1.4.0+ 也可作為 Windows Kubernetes 節(jié)點(diǎn)上的容器運(yùn)行時(shí)。

持久性存儲 

使用 Kubernetes 卷,對數(shù)據(jù)持久性和 Pod 卷 共享有需求的復(fù)雜應(yīng)用也可以部署到 Kubernetes 上。 管理與特定存儲后端或協(xié)議相關(guān)的持久卷時(shí),相關(guān)的操作包括:對卷的配備(Provisioning)、 去配(De-provisioning)和調(diào)整大小,將卷掛接到 Kubernetes 節(jié)點(diǎn)或從節(jié)點(diǎn)上解除掛接, 將卷掛載到需要持久數(shù)據(jù)的 Pod 中的某容器或從容器上卸載。 負(fù)責(zé)實(shí)現(xiàn)為特定存儲后端或協(xié)議實(shí)現(xiàn)卷管理動作的代碼以 Kubernetes 卷 插件的形式發(fā)布。 Windows 支持以下大類的 Kubernetes 卷插件:

樹內(nèi)卷插件 

與樹內(nèi)卷插件(In-Tree Volume Plugin)相關(guān)的代碼都作為核心 Kubernetes 代碼基 的一部分發(fā)布。樹內(nèi)卷插件的部署不需要安裝額外的腳本,也不需要額外部署獨(dú)立的 容器化插件組件。這些插件可以處理:對應(yīng)存儲后端上存儲卷的配備、去配和尺寸更改, 將卷掛接到 Kubernetes 或從其上解掛,以及將卷掛載到 Pod 中各個(gè)容器上或從其上 卸載。以下樹內(nèi)插件支持 Windows 節(jié)點(diǎn):

  • ?awsElasticBlockStore ?
  • ?azureDisk ?
  • ?azureFile ?
  • ?gcePersistentDisk ?
  • ?vsphereVolume?
FlexVolume 插件 

與 FlexVolume 插件相關(guān)的代碼是作為 樹外(Out-of-tree)腳本或可執(zhí)行文件來發(fā)布的,因此需要在宿主系統(tǒng)上直接部署。 FlexVolume 插件處理將卷掛接到 Kubernetes 節(jié)點(diǎn)或從其上解掛、將卷掛載到 Pod 中 各個(gè)容器上或從其上卸載等操作。對于與 FlexVolume 插件相關(guān)聯(lián)的持久卷的配備和 去配操作,可以通過外部的配置程序來處理。這類配置程序通常與 FlexVolume 插件 相分離。下面的 FlexVolume  插件 可以以 PowerShell 腳本的形式部署到宿主系統(tǒng)上,支持 Windows 節(jié)點(diǎn):

CSI 插件 

FEATURE STATE: Kubernetes v1.22 [stable]

與 CSI 插件相關(guān)聯(lián)的代碼作為 樹外腳本和可執(zhí)行文件來發(fā)布且通常發(fā)布為容器鏡像形式,并使用 DaemonSet 和 StatefulSet 這類標(biāo)準(zhǔn)的 Kubernetes 構(gòu)造體來部署。 CSI 插件處理 Kubernetes 中的很多卷管理操作:對卷的配備、去配和調(diào)整大小, 將卷掛接到 Kubernetes 節(jié)點(diǎn)或從節(jié)點(diǎn)上解除掛接,將卷掛載到需要持久數(shù)據(jù)的 Pod 中的某容器或從容器上卸載,使用快照和克隆來備份或恢復(fù)持久數(shù)據(jù)。

來支持;csi-proxy 是一個(gè)社區(qū)管理的、獨(dú)立的可執(zhí)行文件,需要預(yù)安裝在每個(gè) Windows 節(jié)點(diǎn)之上。請參考你要部署的 CSI 插件的部署指南以進(jìn)一步了解其細(xì)節(jié)。

CSI 插件與執(zhí)行本地存儲操作的 CSI 節(jié)點(diǎn)插件通信。 在 Windows 節(jié)點(diǎn)上,CSI 節(jié)點(diǎn)插件通常調(diào)用處理本地存儲操作的 csi-proxy 公開的 API, csi-proxy 由社區(qū)管理。

有關(guān)安裝的更多詳細(xì)信息,請參閱你要部署的 Windows CSI 插件的環(huán)境部署指南。 你也可以參考以下安裝步驟 。

聯(lián)網(wǎng) 

Windows 容器的聯(lián)網(wǎng)是通過 CNI 插件 來暴露出來的。Windows 容器的聯(lián)網(wǎng)行為與虛擬機(jī)的聯(lián)網(wǎng)行為類似。 每個(gè)容器有一塊虛擬的網(wǎng)絡(luò)適配器(vNIC)連接到 Hyper-V 的虛擬交換機(jī)(vSwitch)。 宿主的聯(lián)網(wǎng)服務(wù)(Host Networking Service,HNS)和宿主計(jì)算服務(wù)(Host Compute Service,HCS)協(xié)同工作,創(chuàng)建容器并將容器的虛擬網(wǎng)卡連接到網(wǎng)絡(luò)上。 HCS 負(fù)責(zé)管理容器,HNS 則負(fù)責(zé)管理網(wǎng)絡(luò)資源,例如:

  • 虛擬網(wǎng)絡(luò)(包括創(chuàng)建 vSwitch)
  • 端點(diǎn)(Endpoint)/ vNIC
  • 名字空間(Namespace)
  • 策略(報(bào)文封裝、負(fù)載均衡規(guī)則、訪問控制列表、網(wǎng)絡(luò)地址轉(zhuǎn)譯規(guī)則等等)

支持的服務(wù)規(guī)約類型如下:

  • NodePort
  • ClusterIP
  • LoadBalancer
  • ExternalName
網(wǎng)絡(luò)模式 

Windows 支持五種不同的網(wǎng)絡(luò)驅(qū)動/模式:二層橋接(L2bridge)、二層隧道(L2tunnel)、 覆蓋網(wǎng)絡(luò)(Overlay)、透明網(wǎng)絡(luò)(Transparent)和網(wǎng)絡(luò)地址轉(zhuǎn)譯(NAT)。 在一個(gè)包含 Windows 和 Linux 工作節(jié)點(diǎn)的異構(gòu)集群中,你需要選擇一種對 Windows 和 Linux 兼容的聯(lián)網(wǎng)方案。下面是 Windows 上支持的一些樹外插件及何時(shí)使用某種 CNI 插件的建議:

網(wǎng)絡(luò)驅(qū)動 描述 容器報(bào)文更改 網(wǎng)絡(luò)插件 網(wǎng)絡(luò)插件特點(diǎn)
L2bridge 容器掛接到外部 vSwitch 上。容器掛接到下層網(wǎng)絡(luò)之上,但由于容器的 MAC 地址在入站和出站時(shí)被重寫,物理網(wǎng)絡(luò)不需要這些地址。 MAC 地址被重寫為宿主系統(tǒng)的 MAC 地址,IP 地址也可能依據(jù) HNS OutboundNAT 策略重寫為宿主的 IP 地址。 win-bridge、 Azure-CNI、 Flannel 宿主網(wǎng)關(guān)(host-gateway)使用 win-bridge win-bridge 使用二層橋接(L2bridge)網(wǎng)絡(luò)模式,將容器連接到下層宿主系統(tǒng)上, 從而提供最佳性能。需要用戶定義的路由(User-Defined Routes,UDR)才能 實(shí)現(xiàn)節(jié)點(diǎn)間的連接。
L2Tunnel 這是二層橋接的一種特殊情形,但僅被用于 Azure 上。 所有報(bào)文都被發(fā)送到虛擬化環(huán)境中的宿主機(jī)上并根據(jù) SDN 策略進(jìn)行處理。 MAC 地址被改寫,IP 地址在下層網(wǎng)絡(luò)上可見。 Azure-CNI Azure-CNI 使得容器能夠與 Azure vNET 集成,并允許容器利用 [Azure 虛擬網(wǎng)絡(luò)](https://azure.microsoft.com/en-us/services/virtual-network/) 所提供的功能特性集合。例如,可以安全地連接到 Azure 服務(wù)上或者使用 Azure NSG。 你可以參考 [azure-cni](https://docs.microsoft.com/en-us/azure/aks/concepts-network#azure-cni-advanced-networking) 所提供的一些示例。
覆蓋網(wǎng)絡(luò)(Kubernetes 中為 Windows 提供的覆蓋網(wǎng)絡(luò)支持處于 *alpha* 階段) 每個(gè)容器會獲得一個(gè)連接到外部 vSwitch 的虛擬網(wǎng)卡(vNIC)。 每個(gè)覆蓋網(wǎng)絡(luò)都有自己的、通過定制 IP 前綴來定義的 IP 子網(wǎng)。 覆蓋網(wǎng)絡(luò)驅(qū)動使用 VxLAN 封裝。 封裝于外層包頭內(nèi)。 Win-overlay、 Flannel VXLAN(使用 win-overlay) 當(dāng)(比如出于安全原因)期望虛擬容器網(wǎng)絡(luò)與下層宿主網(wǎng)絡(luò)隔離時(shí), 應(yīng)該使用 win-overlay。如果你的數(shù)據(jù)中心可用 IP 地址受限, 覆蓋網(wǎng)絡(luò)允許你在不同的網(wǎng)絡(luò)中復(fù)用 IP 地址(每個(gè)覆蓋網(wǎng)絡(luò)有不同的 VNID 標(biāo)簽)。 這一選項(xiàng)要求在 Windows Server 2009 上安裝 [KB4489899](https://support.microsoft.com/help/4489899) 補(bǔ)丁。
透明網(wǎng)絡(luò)([ovn-kubernetes](https://github.com/openvswitch/ovn-kubernetes) 的特殊用例) 需要一個(gè)外部 vSwitch。容器掛接到某外部 vSwitch 上,該 vSwitch 通過邏輯網(wǎng)絡(luò)(邏輯交換機(jī)和路由器)允許 Pod 間通信。 報(bào)文或者通過 [GENEVE](https://datatracker.ietf.org/doc/draft-gross-geneve/) 來封裝, 或者通過 [STT](https://datatracker.ietf.org/doc/draft-davie-stt/) 隧道來封裝, 以便能夠到達(dá)不在同一宿主系統(tǒng)上的每個(gè) Pod。
報(bào)文通過 OVN 網(wǎng)絡(luò)控制器所提供的隧道元數(shù)據(jù)信息來判定是轉(zhuǎn)發(fā)還是丟棄。
北-南向通信通過 NAT 網(wǎng)絡(luò)地址轉(zhuǎn)譯來實(shí)現(xiàn)。
ovn-kubernetes [通過 Ansible 來部署](https://github.com/openvswitch/ovn-kubernetes/tree/master/contrib)。 所發(fā)布的 ACL 可以通過 Kubernetes 策略來應(yīng)用實(shí)施。支持 IPAM 。 負(fù)載均衡能力不依賴 kube-proxy。 網(wǎng)絡(luò)地址轉(zhuǎn)譯(NAT)也不需要 iptables 或 netsh。
NAT(未在 Kubernetes 中使用 容器獲得一個(gè)連接到某內(nèi)部 vSwitch 的 vNIC 接口。 DNS/DHCP 服務(wù)通過名為 [WinNAT](https://blogs.technet.microsoft.com/virtualization/2016/05/25/windows-nat-winnat-capabilities-and-limitations/) 的內(nèi)部組件來提供。 MAC 地址和 IP 地址都被重寫為宿主系統(tǒng)的 MAC 地址和 IP 地址。 nat 列在此表中僅出于完整性考慮

如前所述,Flannel CNI meta 插件 在 Windows 上也是 被支持 的,方法是通過 VXLAN 網(wǎng)絡(luò)后端 (alpha 階段 :委托給 win-overlay)和 主機(jī)-網(wǎng)關(guān)(host-gateway)網(wǎng)絡(luò)后端 (穩(wěn)定版本;委托給 win-bridge 實(shí)現(xiàn))。 此插件支持將操作委托給所引用的 CNI 插件(win-overlay、win-bridge)之一, 從而能夠與 Windows 上的 Flannel 守護(hù)進(jìn)程(Flanneld)一同工作,自動為節(jié)點(diǎn) 分配子網(wǎng)租期,創(chuàng)建 HNS 網(wǎng)絡(luò)。 該插件讀入其自身的配置文件(cni.conf),并將其與 FlannelD 所生成的 subnet.env 文件中的環(huán)境變量整合,之后將其操作委托給所引用的 CNI 插件之一以完成網(wǎng)絡(luò)發(fā)現(xiàn), 并將包含節(jié)點(diǎn)所被分配的子網(wǎng)信息的正確配置發(fā)送給 IPAM 插件(例如 host-local)。

對于節(jié)點(diǎn)、Pod 和服務(wù)對象,可針對 TCP/UDP 流量支持以下網(wǎng)絡(luò)數(shù)據(jù)流:

  • Pod -> Pod (IP 尋址)
  • Pod -> Pod (名字尋址)
  • Pod -> 服務(wù)(集群 IP)
  • Pod -> 服務(wù)(部分限定域名,僅適用于名稱中不包含“.”的情形)
  • Pod -> 服務(wù)(全限定域名)
  • Pod -> 集群外部(IP 尋址)
  • Pod -> 集群外部(DNS 尋址)
  • 節(jié)點(diǎn) -> Pod
  • Pod -> 節(jié)點(diǎn)
IP 地址管理(IPAM) 

Windows 上支持以下 IPAM 選項(xiàng):

  • host-local
  • HNS IPAM (Inbox 平臺 IPAM,未指定 IPAM 時(shí)的默認(rèn)設(shè)置)
  • Azure-vnet-ipam(僅適用于 azure-cni )
負(fù)載均衡與服務(wù) 

在 Windows 系統(tǒng)上,你可以使用以下配置來設(shè)定服務(wù)和負(fù)載均衡行為:

功能特性 描述 所支持的 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 設(shè)置為 "ClientIP"
直接服務(wù)器返回(DSR) 這是一種負(fù)載均衡模式,IP 地址的修正和負(fù)載均衡地址轉(zhuǎn)譯(LBNAT) 直接在容器的 vSwitch 端口上處理;服務(wù)流量到達(dá)時(shí),其源端 IP 地址 設(shè)置為來源 Pod 的 IP。 v1.20+ Windows Server 2019 為 kube-proxy 設(shè)置標(biāo)志:`--feature-gates="WinDSR=true" --enable-dsr=true`
保留目標(biāo)地址 對服務(wù)流量略過 DNAT 步驟,這樣就可以在到達(dá)后端 Pod 的報(bào)文中保留目標(biāo)服務(wù)的 虛擬 IP 地址。還要禁止節(jié)點(diǎn)之間的轉(zhuǎn)發(fā)。 v1.20+ Windows Server 1903 或更高版本 在服務(wù)注解中設(shè)置 `"preserve-destination": "true"` 并啟用 kube-proxy 中的 DSR 標(biāo)志。
IPv4/IPv6 雙棧網(wǎng)絡(luò) 在集群內(nèi)外同時(shí)支持原生的 IPv4-到-IPv4 和 IPv6-到-IPv6 通信。 v1.19+ Windows Server 2004 或更高版本 參見 [IPv4/IPv6 雙棧網(wǎng)絡(luò)](#ipv4ipv6-dual-stack)
保留客戶端 IP 確保入站流量的源 IP 地址被保留。同樣要禁止節(jié)點(diǎn)之間的轉(zhuǎn)發(fā)。 v1.20+ Windows Server 2019 或更高版本 將 service.spec.externalTrafficPolicy 設(shè)置為 "Local", 并在 kube-proxy 上啟用 DSR。

IPv4/IPv6 雙棧支持 

你可以通過使用 ?IPv6DualStack ?特性門控 來為 ?l2bridge ?網(wǎng)絡(luò)啟用 IPv4/IPv6 雙棧聯(lián)網(wǎng)支持。

對 Windows 而言,在 Kubernetes 中使用 IPv6 需要 Windows Server 2004 (內(nèi)核版本 10.0.19041.610)或更高版本。

目前 Windows 上的覆蓋網(wǎng)絡(luò)(VXLAN)還不支持雙協(xié)議棧聯(lián)網(wǎng)。

局限性 

在 Kubernetes 架構(gòu)和節(jié)點(diǎn)陣列中僅支持將 Windows 作為工作節(jié)點(diǎn)使用。 這意味著 Kubernetes 集群必須總是包含 Linux 主控節(jié)點(diǎn),零個(gè)或者多個(gè) Linux 工作節(jié)點(diǎn)以及零個(gè)或者多個(gè) Windows 工作節(jié)點(diǎn)。

資源處理

Linux 上使用 Linux 控制組(CGroups)作為 Pod 的邊界,以實(shí)現(xiàn)資源控制。 容器都創(chuàng)建于這一邊界之內(nèi),從而實(shí)現(xiàn)網(wǎng)絡(luò)、進(jìn)程和文件系統(tǒng)的隔離。 控制組 CGroups API 可用來收集 CPU、I/O 和內(nèi)存的統(tǒng)計(jì)信息。 與此相比,Windows 為每個(gè)容器創(chuàng)建一個(gè)帶有系統(tǒng)名字空間過濾設(shè)置的 Job 對象, 以容納容器中的所有進(jìn)程并提供其與宿主系統(tǒng)間的邏輯隔離。 沒有現(xiàn)成的名字空間過濾設(shè)置是無法運(yùn)行 Windows 容器的。 這也意味著,系統(tǒng)特權(quán)無法在宿主環(huán)境中評估,因而 Windows 上也就不存在特權(quán)容器。 歸咎于獨(dú)立存在的安全賬號管理器(Security Account Manager,SAM),容器也不能 獲得宿主系統(tǒng)上的任何身份標(biāo)識。

資源預(yù)留 

內(nèi)存預(yù)留 

Windows 不像 Linux 一樣有一個(gè)內(nèi)存耗盡(Out-of-memory)進(jìn)程殺手(Process Killer)機(jī)制。Windows 總是將用戶態(tài)的內(nèi)存分配視為虛擬請求,頁面文件(Pagefile) 是必需的。這一差異的直接結(jié)果是 Windows 不會像 Linux 那樣出現(xiàn)內(nèi)存耗盡的狀況, 系統(tǒng)會將進(jìn)程內(nèi)存頁面寫入磁盤而不會因內(nèi)存耗盡而終止進(jìn)程。 當(dāng)內(nèi)存被過量使用且所有物理內(nèi)存都被用光時(shí),系統(tǒng)的換頁行為會導(dǎo)致性能下降。

使用 kubelet 參數(shù) ?--kubelet-reserve? 與/或 ?-system-reserve? 可以統(tǒng)計(jì) 節(jié)點(diǎn)上的內(nèi)存用量(各容器之外),進(jìn)而可能將內(nèi)存用量限制在一個(gè)合理的范圍,。 這樣做會減少節(jié)點(diǎn)可分配內(nèi)存。

在你部署工作負(fù)載時(shí),對容器使用資源限制(必須僅設(shè)置 limits 或者讓 limits 等于 requests 值)。這也會從 NodeAllocatable 中耗掉部分內(nèi)存量,從而避免在節(jié)點(diǎn) 負(fù)荷已滿時(shí)調(diào)度器繼續(xù)向節(jié)點(diǎn)添加 Pods。

避免過量分配的最佳實(shí)踐是為 kubelet 配置至少 2 GB 的系統(tǒng)預(yù)留內(nèi)存,以供 Windows、Docker 和 Kubernetes 進(jìn)程使用。

CPU 預(yù)留 

為了統(tǒng)計(jì) Windows、Docker 和其他 Kubernetes 宿主進(jìn)程的 CPU 用量,建議 預(yù)留一定比例的 CPU,以便對事件作出相應(yīng)。此值需要根據(jù) Windows 節(jié)點(diǎn)上 CPU 核的個(gè)數(shù)來調(diào)整,要確定此百分比值,用戶需要為其所有節(jié)點(diǎn)確定 Pod 密度的上線,并監(jiān)控系統(tǒng)服務(wù)的 CPU 用量,從而選擇一個(gè)符合其負(fù)載需求的值。

使用 kubelet 參數(shù) ?--kubelet-reserve? 與/或 ?-system-reserve? 可以統(tǒng)計(jì) 節(jié)點(diǎn)上的 CPU 用量(各容器之外),進(jìn)而可能將 CPU 用量限制在一個(gè)合理的范圍,。 這樣做會減少節(jié)點(diǎn)可分配 CPU。

功能特性限制 
  • 終止寬限期(Termination Grace Period):未實(shí)現(xiàn)
  • 單文件映射:將用 CRI-ContainerD 來實(shí)現(xiàn)
  • 終止消息(Termination message):將用 CRI-ContainerD 來實(shí)現(xiàn)
  • 特權(quán)容器:Windows 容器當(dāng)前不支持
  • 巨頁(Huge Pages):Windows 容器當(dāng)前不支持
  • 現(xiàn)有的節(jié)點(diǎn)問題探測器(Node Problem Detector)僅適用于 Linux,且要求使用特權(quán)容器。 一般而言,我們不設(shè)想此探測器能用于 Windows 節(jié)點(diǎn),因?yàn)?nbsp;Windows 不支持特權(quán)容器。
  • 并非支持共享名字空間的所有功能特性(參見 API 節(jié)以了解詳細(xì)信息)

與 Linux 相比參數(shù)行為的差別

以下 kubelet 參數(shù)的行為在 Windows 節(jié)點(diǎn)上有些不同,描述如下:

  • ?--kubelet-reserve?、?--system-reserve? 和 ?--eviction-hard? 標(biāo)志 會更新節(jié)點(diǎn)可分配資源量
  • 未實(shí)現(xiàn)通過使用 ?--enforce-node-allocable? 來完成的 Pod 驅(qū)逐
  • 未實(shí)現(xiàn)通過使用 ?--eviction-hard? 和 ?--eviction-soft? 來完成的 Pod 驅(qū)逐
  • ?MemoryPressure ?狀況未實(shí)現(xiàn)
  • ?kubelet ?不會采取措施來執(zhí)行基于 OOM 的驅(qū)逐動作
  • Windows 節(jié)點(diǎn)上運(yùn)行的 kubelet 沒有內(nèi)存約束。 ?--kubelet-reserve? 和 ?--system-reserve? 不會為 kubelet 或宿主系統(tǒng)上運(yùn)行 的進(jìn)程設(shè)限。這意味著 kubelet 或宿主系統(tǒng)上的進(jìn)程可能導(dǎo)致內(nèi)存資源緊張, 而這一情況既不受節(jié)點(diǎn)可分配量影響,也不會被調(diào)度器感知。
  • 在 Windows 節(jié)點(diǎn)上存在一個(gè)額外的參數(shù)用來設(shè)置 kubelet 進(jìn)程的優(yōu)先級,稱作 ?--windows-priorityclass?。此參數(shù)允許 kubelet 進(jìn)程獲得與 Windows 宿主上 其他進(jìn)程相比更多的 CPU 時(shí)間片。 關(guān)于可用參數(shù)值及其含義的進(jìn)一步信息可參考 Windows Priority Classes。 為了讓 kubelet 總能夠獲得足夠的 CPU 周期,建議將此參數(shù)設(shè)置為 ?ABOVE_NORMAL_PRIORITY_CLASS ?或更高。

存儲 

Windows 上包含一個(gè)分層的文件系統(tǒng)來掛載容器的分層,并會基于 NTFS 來創(chuàng)建一個(gè) 拷貝文件系統(tǒng)。容器中的所有文件路徑都僅在該容器的上下文內(nèi)完成解析。

  • Docker 卷掛載僅可針對容器中的目錄進(jìn)行,不可針對獨(dú)立的文件。 這一限制不適用于 CRI-containerD。
  • 卷掛載無法將文件或目錄投射回宿主文件系統(tǒng)。
  • 不支持只讀文件系統(tǒng),因?yàn)?nbsp;Windows 注冊表和 SAM 數(shù)據(jù)庫總是需要寫訪問權(quán)限。 不過,Windows 支持只讀的卷。
  • 不支持卷的用戶掩碼和訪問許可,因?yàn)樗拗髋c容器之間并不共享 SAM,二者之間不存在 映射關(guān)系。所有訪問許可都是在容器上下文中解析的。

因此,Windows 節(jié)點(diǎn)上不支持以下存儲功能特性:

  • 卷的子路徑掛載;只能在 Windows 容器上掛載整個(gè)卷。
  • 為 Secret 執(zhí)行子路徑掛載;
  • 宿主掛載投射;
  • 默認(rèn)訪問模式 defaultMode(因?yàn)樵撎匦砸蕾?nbsp;UID/GID);
  • 只讀的根文件系統(tǒng);映射的卷仍然支持 ?readOnly?;
  • 塊設(shè)備映射;
  • 將內(nèi)存作為存儲介質(zhì);
  • 類似 UUID/GUID、每用戶不同的 Linux 文件系統(tǒng)訪問許可等文件系統(tǒng)特性;
  • 基于 NFS 的存儲和卷支持;
  • 擴(kuò)充已掛載卷(resizefs)。

聯(lián)網(wǎng) 

Windows 容器聯(lián)網(wǎng)與 Linux 聯(lián)網(wǎng)有著非常重要的差別。 Microsoft documentation for Windows Container Networking 中包含額外的細(xì)節(jié)和背景信息。

Windows 宿主聯(lián)網(wǎng)服務(wù)和虛擬交換機(jī)實(shí)現(xiàn)了名字空間隔離,可以根據(jù)需要為 Pod 或容器 創(chuàng)建虛擬的網(wǎng)絡(luò)接口(NICs)。不過,很多類似 DNS、路由、度量值之類的配置數(shù)據(jù)都 保存在 Windows 注冊表數(shù)據(jù)庫中而不是像 Linux 一樣保存在 ?/etc/...? 文件中。 Windows 為容器提供的注冊表與宿主系統(tǒng)的注冊表是分離的,因此類似于將 /etc/resolv.conf 文件從宿主系統(tǒng)映射到容器中的做法不會產(chǎn)生與 Linux 系統(tǒng)相同的效果。 這些信息必須在容器內(nèi)部使用 Windows API 來配置。 因此,CNI 實(shí)現(xiàn)需要調(diào)用 HNS,而不是依賴文件映射來將網(wǎng)絡(luò)細(xì)節(jié)傳遞到 Pod 或容器中。

Windows 節(jié)點(diǎn)不支持以下聯(lián)網(wǎng)功能:

  • Windows Pod 不能使用宿主網(wǎng)絡(luò)模式;
  • 從節(jié)點(diǎn)本地訪問 NodePort 會失?。ǖ珡钠渌?jié)點(diǎn)或外部客戶端可訪問)
  • Windows Server 的未來版本中會支持從節(jié)點(diǎn)訪問服務(wù)的 VIP;
  • 每個(gè)服務(wù)最多支持 64 個(gè)后端 Pod 或獨(dú)立的目標(biāo) IP 地址;
  • kube-proxy 的覆蓋網(wǎng)絡(luò)支持是 Beta 特性。此外,它要求在 Windows Server 2019 上安裝 KB4482887 補(bǔ)??;
  • 非 DSR(保留目標(biāo)地址)模式下的本地流量策略;
  • 連接到覆蓋網(wǎng)絡(luò)的 Windows 容器不支持使用 IPv6 協(xié)議棧通信。 要使得這一網(wǎng)絡(luò)驅(qū)動支持 IPv6 地址需要在 Windows 平臺上開展大量的工作, 還需要在 Kubernetes 側(cè)修改 kubelet、kube-proxy 以及 CNI 插件。
  • 通過 win-overlay、win-bridge 和 Azure-CNI 插件使用 ICMP 協(xié)議向集群外通信。 尤其是,Windows 數(shù)據(jù)面 (VFP) 不支持轉(zhuǎn)換 ICMP 報(bào)文。這意味著:
    • 指向同一網(wǎng)絡(luò)內(nèi)目標(biāo)地址的 ICMP 報(bào)文(例如 Pod 之間的 ping 通信)是可以工作的, 沒有局限性;
    • TCP/UDP 報(bào)文可以正常工作,沒有局限性;
    • 指向遠(yuǎn)程網(wǎng)絡(luò)的 ICMP 報(bào)文(例如,從 Pod 中 ping 外部互聯(lián)網(wǎng)的通信)無法被轉(zhuǎn)換, 因此也無法被路由回到其源點(diǎn);
    • 由于 TCP/UDP 包仍可被轉(zhuǎn)換,用戶可以將 ?ping <目標(biāo)>? 操作替換為 ?curl <目標(biāo)>? 以便能夠調(diào)試與外部世界的網(wǎng)絡(luò)連接。

Kubernetes v1.15 中添加了以下功能特性:

  • ?kubectl port-forward ?
CNI 插件 
  • Windows 參考網(wǎng)絡(luò)插件 win-bridge 和 win-overlay 當(dāng)前未實(shí)現(xiàn) CNI spec v0.4.0, 原因是缺少檢查(CHECK)用的實(shí)現(xiàn)。

  • Windows 上的 Flannel VXLAN CNI 有以下局限性:
    1. 其設(shè)計(jì)上不支持從節(jié)點(diǎn)到 Pod 的連接。 只有在 Flannel v0.12.0 或更高版本后才有可能訪問本地 Pods。
    2. 我們被限制只能使用 VNI 4096 和 UDP 端口 4789。 VNI 的限制正在被解決,會在將來的版本中消失(開源的 Flannel 更改)。 參見官方的 Flannel VXLAN 后端文檔以了解關(guān)于這些參數(shù)的詳細(xì)信息。
DNS
  • 不支持 DNS 的 ClusterFirstWithHostNet 配置。Windows 將所有包含 “.” 的名字 視為全限定域名(FQDN),因而不會對其執(zhí)行部分限定域名(PQDN)解析。
  • 在 Linux 上,你可以有一個(gè) DNS 后綴列表供解析部分限定域名時(shí)使用。 在 Windows 上,我們只有一個(gè) DNS 后綴,即與該 Pod 名字空間相關(guān)聯(lián)的 DNS 后綴(例如 ?mydns.svc.cluster.local?)。 Windows 可以解析全限定域名、或者恰好可用該后綴來解析的服務(wù)名稱。 例如,在 default 名字空間中生成的 Pod 會獲得 DNS 后綴 ?default.svc.cluster.local?。在 Windows Pod 中,你可以解析 ?kubernetes.default.svc.cluster.local? 和 ?kubernetes?,但無法解析二者 之間的形式,如 ?kubernetes.default? 或 ?kubernetes.default.svc?。
  • 在 Windows 上,可以使用的 DNS 解析程序有很多。由于這些解析程序彼此之間 會有輕微的行為差別,建議使用 ?Resolve-DNSName? 工具來完成名字查詢解析。
IPv6

Windows 上的 Kubernetes 不支持單協(xié)議棧的“只用 IPv6”聯(lián)網(wǎng)選項(xiàng)。 不過,系統(tǒng)支持在 IPv4/IPv6 雙協(xié)議棧的 Pod 和節(jié)點(diǎn)上運(yùn)行單協(xié)議家族的服務(wù)。

會話親和性 

不支持使用 ?service.spec.sessionAffinityConfig.clientIP.timeoutSeconds? 來為 Windows 服務(wù)設(shè)置最大會話粘滯時(shí)間。

安全性 

Secret 以明文形式寫入節(jié)點(diǎn)的卷中(而不是像 Linux 那樣寫入內(nèi)存或 tmpfs 中)。 這意味著客戶必須做以下兩件事:

  1. 使用文件訪問控制列表來保護(hù) Secret 文件所在的位置
  2. 使用 BitLocker 來執(zhí)行卷層面的加密

用戶可以為 Windows Pods 或 Container 設(shè)置 ?RunAsUserName ?以便以非節(jié)點(diǎn)默認(rèn)用戶來執(zhí)行容器中的進(jìn)程。這大致等價(jià)于設(shè)置 ?RunAsUser?。

不支持特定于 Linux 的 Pod 安全上下文特權(quán),例如 SELinux、AppArmor、Seccomp、 權(quán)能字(POSIX 權(quán)能字)等等。

此外,如前所述,Windows 不支持特權(quán)容器。

API

對 Windows 而言,大多數(shù) Kubernetes API 的工作方式?jīng)]有變化。 一些不易察覺的差別通常體現(xiàn)在 OS 和容器運(yùn)行時(shí)上的不同。 在某些場合,負(fù)載 API (如 Pod 或 Container)的某些屬性在設(shè)計(jì)時(shí)假定其 在 Linux 上實(shí)現(xiàn),因此會無法在 Windows 上運(yùn)行。

在較高層面,不同的 OS 概念有:

  • 身份標(biāo)識 - Linux 使用證書類型來表示用戶 ID(UID)和組 ID(GID)。用戶和組名 沒有特定標(biāo)準(zhǔn),它們是 ?/etc/groups? 或 ?/etc/passwd? 中的別名表項(xiàng),會映射回 UID+GID。Windows 使用一個(gè)更大的二進(jìn)制安全標(biāo)識符(SID),保存在 Windows 安全訪問管理器(Security Access Manager,SAM)數(shù)據(jù)庫中。此數(shù)據(jù)庫并不在宿主系統(tǒng) 與容器間,或者任意兩個(gè)容器之間共享。
  • 文件許可 - Windows 使用基于 SID 的訪問控制列表,而不是基于 UID+GID 的訪問權(quán)限位掩碼。
  • 文件路徑 - Windows 上的習(xí)慣是使用 ?\? 而非 ?/?。Go 語言的 IO 庫同時(shí)接受這兩種文件路徑分隔符。不過,當(dāng)你在指定要在容器內(nèi)解析的路徑或命令行時(shí), 可能需要使用 ?\?。
  • 信號(Signal) - Windows 交互式應(yīng)用以不同方式來處理終止事件,并可實(shí)現(xiàn)以下方式之一或組合:
    • UI 線程處理包含 ?WM_CLOSE ?在內(nèi)的良定的消息
    • 控制臺應(yīng)用使用控制處理程序來處理 Ctrl-C 或 Ctrl-Break
    • 服務(wù)會注冊服務(wù)控制處理程序,接受 ?SERVICE_CONTROL_STOP ?控制代碼

退出代碼遵從相同的習(xí)慣,0 表示成功,非 0 值表示失敗。 特定的錯(cuò)誤代碼在 Windows 和 Linux 上可能會不同。不過,從 Kubernetes 組件 (kubelet、kube-proxy)所返回的退出代碼是沒有變化的。

  • ?v1.Container.ResourceRequirements.limits.cpu? 和 ?v1.Container.ResourceRequirements.limits.memory? - Windows 不對 CPU 分配設(shè)置硬性的限制。與之相反,Windows 使用一個(gè)份額(share)系統(tǒng)。 基于毫核(millicores)的現(xiàn)有字段值會被縮放為相對的份額值,供 Windows 調(diào)度器使用。
    • Windows 容器運(yùn)行時(shí)中沒有實(shí)現(xiàn)巨頁支持,因此相關(guān)特性不可用。 巨頁支持需要判定用戶的特權(quán) 而這一特性無法在容器級別配置。
  • ?v1.Container.ResourceRequirements.requests.cpu? 和 ?v1.Container.ResourceRequirements.requests.memory? - 請求 值會從節(jié)點(diǎn)可分配資源中扣除,從而可用來避免節(jié)點(diǎn)上的資源過量分配。 但是,它們無法用來在一個(gè)已經(jīng)過量分配的節(jié)點(diǎn)上提供資源保障。 如果操作員希望徹底避免過量分配,作為最佳實(shí)踐,他們就需要為所有容器設(shè)置資源請求值。
  • ?v1.Container.SecurityContext.allowPrivilegeEscalation? - 在 Windows 上無法實(shí)現(xiàn),對應(yīng)的權(quán)能無一可在 Windows 上生效。
  • ?v1.Container.SecurityContext.Capabilities? - Windows 上未實(shí)現(xiàn) POSIX 權(quán)能機(jī)制
  • ?v1.Container.SecurityContext.privileged? - Windows 不支持特權(quán)容器
  • ?v1.Container.SecurityContext.procMount? - Windows 不包含 ?/proc? 文件系統(tǒng)
  • ?v1.Container.SecurityContext.readOnlyRootFilesystem? - 在 Windows 上無法實(shí)現(xiàn), 要在容器內(nèi)使用注冊表或運(yùn)行系統(tǒng)進(jìn)程就必需寫訪問權(quán)限。
  • ?v1.Container.SecurityContext.runAsGroup? - 在 Windows 上無法實(shí)現(xiàn),沒有 GID 支持
  • ?v1.Container.SecurityContext.runAsNonRoot? - Windows 上沒有 root 用戶。 與之最接近的等價(jià)用戶是 ContainerAdministrator,而該身份標(biāo)識在節(jié)點(diǎn)上并不存在。
  • ?v1.Container.SecurityContext.runAsUser? - 在 Windows 上無法實(shí)現(xiàn), 因?yàn)闆]有作為整數(shù)支持的 GID。
  • ?v1.Container.SecurityContext.seLinuxOptions? - 在 Windows 上無法實(shí)現(xiàn), 因?yàn)闆]有 SELinux
  • ?V1.Container.terminationMessagePath? - 因?yàn)?nbsp;Windows 不支持單個(gè)文件的映射,這一功能 在 Windows 上也受限。默認(rèn)值 ?/dev/termination-log? 在 Windows 上也無法使用因?yàn)?nbsp;對應(yīng)路徑在 Windows 上不存在。
V1.Pod
  • ?v1.Pod.hostIPC?、?v1.Pod.hostPID? - Windows 不支持共享宿主系統(tǒng)的名字空間
  • ?v1.Pod.hostNetwork? - Windows 操作系統(tǒng)不支持共享宿主網(wǎng)絡(luò)
  • ?v1.Pod.dnsPolicy? - 不支持 ?ClusterFirstWithHostNet?,因?yàn)?nbsp;Windows 不支持宿主網(wǎng)絡(luò)
  • ?v1.Pod.podSecurityContext? - 參見下面的 ?v1.PodSecurityContext?
  • ?v1.Pod.shareProcessNamespace? - 此為 Beta 特性且依賴于 Windows 上未實(shí)現(xiàn) 的 Linux 名字空間。 Windows 無法共享進(jìn)程名字空間或者容器的根文件系統(tǒng)。只能共享網(wǎng)絡(luò)。
  • ?v1.Pod.terminationGracePeriodSeconds? - 這一特性未在 Windows 版本的 Docker 中完全實(shí)現(xiàn)。 參見問題報(bào)告。 目前實(shí)現(xiàn)的行為是向 ?ENTRYPOINT ?進(jìn)程發(fā)送 ?CTRL_SHUTDOWN_EVENT ?事件,之后 Windows 默認(rèn) 等待 5 秒鐘,并最終使用正常的 Windows 關(guān)機(jī)行為關(guān)閉所有進(jìn)程。 這里的 5 秒鐘默認(rèn)值實(shí)際上保存在  容器內(nèi) 的 Windows 注冊表中,因此可以在構(gòu)造容器時(shí)重載。
  • ?v1.Pod.volumeDevices? - 此為 Beta 特性且未在 Windows 上實(shí)現(xiàn)。Windows 無法掛接 原生的塊設(shè)備到 Pod 中。
  • ?v1.Pod.volumes? - ?emptyDir?、?secret?、?configMap ?和 ?hostPath ?都可正常工作且在 TestGrid 中測試。
    • ?v1.emptyDir.volumeSource? - Windows 上節(jié)點(diǎn)的默認(rèn)介質(zhì)是磁盤。 不支持將內(nèi)存作為介質(zhì),因?yàn)?nbsp;Windows 不支持內(nèi)置的 RAM 磁盤。
  • ?v1.VolumeMount.mountPropagation? - Windows 上不支持掛載傳播。
V1.PodSecurityContext

PodSecurityContext 的所有選項(xiàng)在 Windows 上都無法工作。這些選項(xiàng)列在下面僅供參考。

  • ?v1.PodSecurityContext.seLinuxOptions? - Windows 上無 SELinux
  • ?v1.PodSecurityContext.runAsUser? - 提供 UID;Windows 不支持
  • ?v1.PodSecurityContext.runAsGroup? - 提供 GID;Windows 不支持
  • ?v1.PodSecurityContext.runAsNonRoot? - Windows 上沒有 root 用戶 最接近的等價(jià)賬號是 ?ContainerAdministrator?,而該身份標(biāo)識在節(jié)點(diǎn)上不存在
  • ?v1.PodSecurityContext.supplementalGroups? - 提供 GID;Windows 不支持
  • ?v1.PodSecurityContext.sysctls? - 這些是 Linux sysctl 接口的一部分;Windows 上 沒有等價(jià)機(jī)制。

操作系統(tǒng)版本限制 

Windows 有著嚴(yán)格的兼容性規(guī)則,宿主 OS 的版本必須與容器基準(zhǔn)鏡像 OS 的版本匹配。 目前僅支持容器操作系統(tǒng)為 Windows Server 2019 的 Windows 容器。 對于容器的 Hyper-V 隔離、允許一定程度上的 Windows 容器鏡像版本向后兼容性等等, 都是將來版本計(jì)劃的一部分。

獲取幫助和故障排查 

Kubernetes 中日志是故障排查的一個(gè)重要元素。確保你在嘗試從其他貢獻(xiàn)者那里獲得 故障排查幫助時(shí)提供日志信息。你可以按照 SIG-Windows 貢獻(xiàn)指南和收集日志 所給的指令來操作。

  • 我怎樣知道 ?start.ps1? 是否已成功完成?
  • 你應(yīng)該能看到節(jié)點(diǎn)上運(yùn)行的 kubelet、kube-proxy 和(如果你選擇 Flannel 作為聯(lián)網(wǎng)方案)flanneld 宿主代理進(jìn)程,它們的運(yùn)行日志顯示在不同的 PowerShell 窗口中。此外,你的 Windows 節(jié)點(diǎn)應(yīng)該在你的 Kubernetes 集群 列舉為 "Ready" 節(jié)點(diǎn)。

  • 我可以將 Kubernetes 節(jié)點(diǎn)進(jìn)程配置為服務(wù)運(yùn)行在后臺么?
  • kubelet 和 kube-proxy 都已經(jīng)被配置為以本地 Windows 服務(wù)運(yùn)行, 并且在出現(xiàn)失效事件(例如進(jìn)程意外結(jié)束)時(shí)通過自動重啟服務(wù)來提供一定的彈性。 你有兩種辦法將這些節(jié)點(diǎn)組件配置為服務(wù)。

    • 以本地 Windows 服務(wù)的形式
    • Kubelet 和 kube-proxy 可以用 ?sc.exe? 以本地 Windows 服務(wù)的形式運(yùn)行:

      # 用兩個(gè)單獨(dú)的命令為 kubelet 和 kube-proxy 創(chuàng)建服務(wù)
      sc.exe create <組件名稱> binPath="<可執(zhí)行文件路徑> -service <其它參數(shù)>"
      
      # 請注意如果參數(shù)中包含空格,必須使用轉(zhuǎn)義
      sc.exe create kubelet binPath= "C:\kubelet.exe --service --hostname-override 'minion' <其它參數(shù)>"
      
      # 啟動服務(wù)
      Start-Service kubelet
      Start-Service kube-proxy
      
      # 停止服務(wù)
      Stop-Service kubelet (-Force)
      Stop-Service kube-proxy (-Force)
      
      # 查詢服務(wù)狀態(tài)
      Get-Service kubelet
      Get-Service kube-proxy
    • 使用 nssm.exe
    • 你也總是可以使用替代的服務(wù)管理器,例如nssm.exe,來為你在后臺運(yùn)行 這些進(jìn)程(?flanneld?、?kubelet ?和 ?kube-proxy?)。你可以使用這一 示例腳本, 利用 ?nssm.exe? 將 ?kubelet?、?kube-proxy? 和 ?flanneld.exe? 注冊為要在后臺運(yùn)行的 Windows 服務(wù)。

      register-svc.ps1 -NetworkMode <網(wǎng)絡(luò)模式> -ManagementIP <Windows 節(jié)點(diǎn) IP> -ClusterCIDR <集群子網(wǎng)> -KubeDnsServiceIP <kube-dns 服務(wù) IP> -LogDir <日志目錄>
      

      這里的參數(shù)解釋如下:

      • ?NetworkMode?:網(wǎng)絡(luò)模式 l2bridge(flannel host-gw,也是默認(rèn)值)或 overlay(flannel vxlan)選做網(wǎng)絡(luò)方案
      • ?ManagementIP?:分配給 Windows 節(jié)點(diǎn)的 IP 地址。你可以使用 ipconfig 得到此值
      • ?ClusterCIDR?:集群子網(wǎng)范圍(默認(rèn)值為 10.244.0.0/16)
      • ?KubeDnsServiceIP?:Kubernetes DNS 服務(wù) IP(默認(rèn)值為 10.96.0.10)
      • ?LogDir?:kubelet 和 kube-proxy 的日志會被重定向到這一目錄中的對應(yīng)輸出文件, 默認(rèn)值為 ?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(二層網(wǎng)橋模式和主機(jī)網(wǎng)關(guān)模式)

      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(覆蓋網(wǎng)絡(luò)模式或 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 中使用下面的標(biāo)志 以便將標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸出重定向到一個(gè)輸出文件:

      nssm set <服務(wù)名稱> AppStdout C:\k\mysvc.log
      nssm set <服務(wù)名稱> AppStderr C:\k\mysvc.log

      要了解更多的細(xì)節(jié),可參見官方的 nssm 用法文檔。

  • 我的 Windows Pods 無法連接網(wǎng)絡(luò)
  • 如果你在使用虛擬機(jī),請確保 VM 網(wǎng)絡(luò)適配器均已開啟 MAC 偵聽(Spoofing)。

  • 我的 Windows Pods 無法 ping 外部資源
  • Windows Pods 目前沒有為 ICMP 協(xié)議提供出站規(guī)則。不過 TCP/UDP 是支持的。 嘗試與集群外資源連接時(shí),可以將 ?ping <IP>? 命令替換為對應(yīng)的 ?curl <IP>? 命令。

    如果你還遇到問題,很可能你在 cni.conf 中的網(wǎng)絡(luò)配置值得額外的注意。你總是可以編輯這一靜態(tài)文件。 配置的更新會應(yīng)用到所有新創(chuàng)建的 Kubernetes 資源上。

    Kubernetes 網(wǎng)絡(luò)的需求之一是集群內(nèi)部無需網(wǎng)絡(luò)地址轉(zhuǎn)譯(NAT)即可實(shí)現(xiàn)通信。 為了符合這一要求,對所有我們不希望出站時(shí)發(fā)生 NAT 的通信都存在一個(gè) ExceptionList。 然而這也意味著你需要將你要查詢的外部 IP 從 ExceptionList 中移除。 只有這時(shí),從你的 Windows Pod 發(fā)起的網(wǎng)絡(luò)請求才會被正確地通過 SNAT 轉(zhuǎn)換以接收到 來自外部世界的響應(yīng)。 就此而言,你在 ?cni.conf? 中的 ?ExceptionList ?應(yīng)該看起來像這樣:

    "ExceptionList": [
        "10.244.0.0/16",  # 集群子網(wǎng)
        "10.96.0.0/12",   # 服務(wù)子網(wǎng)
        "10.127.130.0/24" # 管理(主機(jī))子網(wǎng)
    ]
  • 我的 Windows 節(jié)點(diǎn)無法訪問 NodePort 服務(wù)
  • 從節(jié)點(diǎn)自身發(fā)起的本地 NodePort 請求會失敗。這是一個(gè)已知的局限。 NodePort 服務(wù)的訪問從其他節(jié)點(diǎn)或者外部客戶端都可正常進(jìn)行。

  • 容器的 vNICs 和 HNS 端點(diǎn)被刪除了
  • 這一問題可能因?yàn)?nbsp;?hostname-override? 參數(shù)未能傳遞給 kube-proxy 而導(dǎo)致。解決這一問題時(shí),用戶需要按如下方式將主機(jī)名傳遞給 kube-proxy:

    C:\k\kube-proxy.exe --hostname-override=$(hostname)
    
  • 使用 Flannel 時(shí),我的節(jié)點(diǎn)在重新加入集群時(shí)遇到問題
  • 無論何時(shí),當(dāng)一個(gè)之前被刪除的節(jié)點(diǎn)被重新添加到集群時(shí),flannelD 都會將為節(jié)點(diǎn)分配 一個(gè)新的 Pod 子網(wǎng)。 用戶需要將將下面路徑中的老的 Pod 子網(wǎng)配置文件刪除:

    Remove-Item C:\k\SourceVip.json
    Remove-Item C:\k\SourceVipRequest.json
  • 在啟動了 ?start.ps1? 之后,flanneld 一直停滯在 "Waiting for the Network to be created" 狀態(tài)
  • 關(guān)于這一問題有很多的報(bào)告; 最可能的一種原因是關(guān)于何時(shí)設(shè)置 Flannel 網(wǎng)絡(luò)的管理 IP 的時(shí)間問題。 一種解決辦法是重新啟動 ?start.ps1? 或者按如下方式手動重啟之:

    [Environment]::SetEnvironmentVariable("NODE_NAME", "<Windows 工作節(jié)點(diǎn)主機(jī)名>")
    C:\flannel\flanneld.exe --kubeconfig-file=c:\k\config --iface=<Windows 工作節(jié)點(diǎn) IP> --ip-masq=1 --kube-subnet-mgr=1
  • 我的 Windows Pods 無法啟動,因?yàn)槿鄙?nbsp;?/run/flannel/subnet.env? 文件
  • 這表明 Flannel 網(wǎng)絡(luò)未能正確啟動。你可以嘗試重啟 flanneld.exe 或者將文件手動地 從 Kubernetes 主控節(jié)點(diǎn)的 ?/run/flannel/subnet.env? 路徑復(fù)制到 Windows 工作 節(jié)點(diǎn)的 ?C:\run\flannel\subnet.env? 路徑,并將 ?FLANNEL_SUBNET ?行改為一個(gè) 不同的數(shù)值。例如,如果期望節(jié)點(diǎn)子網(wǎng)為 ?10.244.4.1/24?:

    FLANNEL_NETWORK=10.244.0.0/16
    FLANNEL_SUBNET=10.244.4.1/24
    FLANNEL_MTU=1500
    FLANNEL_IPMASQ=true
  • 我的 Windows 節(jié)點(diǎn)無法使用服務(wù) IP 訪問我的服務(wù)
  • 這是 Windows 上當(dāng)前網(wǎng)絡(luò)協(xié)議棧的一個(gè)已知的限制。 Windows Pods 能夠訪問服務(wù) IP。

  • 啟動 kubelet 時(shí)找不到網(wǎng)絡(luò)適配器
  • Windows 網(wǎng)絡(luò)堆棧需要一個(gè)虛擬的適配器,這樣 Kubernetes 網(wǎng)絡(luò)才能工作。 如果下面的命令(在管理員 Shell 中)沒有任何返回結(jié)果,證明虛擬網(wǎng)絡(luò)創(chuàng)建 (kubelet 正常工作的必要前提之一)失敗了:

    Get-HnsNetwork | ? Name -ieq "cbr0"
    Get-NetAdapter | ? Name -Like "vEthernet (Ethernet*"

    當(dāng)宿主系統(tǒng)的網(wǎng)絡(luò)適配器名稱不是 "Ethernet" 時(shí),通常值得更改 ?start.ps1? 腳本中的 InterfaceName 參數(shù)來重試。否則可以查驗(yàn) ?start-kubelet.ps1? 的輸出,看看是否在虛擬網(wǎng)絡(luò)創(chuàng)建 過程中報(bào)告了其他錯(cuò)誤。

  • 我的 Pods 停滯在 "Container Creating" 狀態(tài)或者反復(fù)重啟
  • 檢查你的 pause 鏡像是與你的 OS 版本兼容的。 如果你安裝的是更新版本的 Windows,比如說 某個(gè) Insider 構(gòu)造版本,你需要相應(yīng)地調(diào)整要使用的鏡像。 請參照 Microsoft 的 Docker 倉庫 了解鏡像。不管怎樣,pause 鏡像的 Dockerfile 和示例服務(wù)都期望鏡像的標(biāo)簽 為 ?:latest?。

  • ?kubectl port-forward? 失敗,錯(cuò)誤信息為 "unable to do port forwarding: wincat not found"
  • 此功能是在 Kubernetes v1.15 中實(shí)現(xiàn)的,pause 基礎(chǔ)設(shè)施容器 ?mcr.microsoft.com/oss/kubernetes/pause:3.4.1? 中包含了 wincat.exe。 請確保你使用的是這些版本或者更新版本。 如果你想要自行構(gòu)造你自己的 pause 基礎(chǔ)設(shè)施容器,要確保其中包含了 wincat

    Windows 的端口轉(zhuǎn)發(fā)支持需要在 pause 基礎(chǔ)設(shè)施容器 中提供 wincat.exe。 確保你使用的是與你的 Windows 操作系統(tǒng)版本兼容的受支持鏡像。 如果你想構(gòu)建自己的 pause 基礎(chǔ)架構(gòu)容器,請確保包含 wincat。

  • 我的 Kubernetes 安裝失敗,因?yàn)槲业?nbsp;Windows Server 節(jié)點(diǎn)在防火墻后面
  • 如果你處于防火墻之后,那么必須定義如下 PowerShell 環(huán)境變量:

    [Environment]::SetEnvironmentVariable("HTTP_PROXY", "http://proxy.example.com:80/", [EnvironmentVariableTarget]::Machine)
    [Environment]::SetEnvironmentVariable("HTTPS_PROXY", "http://proxy.example.com:443/", [EnvironmentVariableTarget]::Machine)
  • ?pause ?容器是什么?
  • 在一個(gè) Kubernetes Pod 中,一個(gè)基礎(chǔ)設(shè)施容器,或稱 "pause" 容器,會被首先創(chuàng)建出來, 用以托管容器端點(diǎn)。屬于同一 Pod 的容器,包括基礎(chǔ)設(shè)施容器和工作容器,會共享相同的 網(wǎng)絡(luò)名字空間和端點(diǎn)(相同的 IP 和端口空間)。我們需要 pause 容器來工作容器崩潰或 重啟的狀況,以確保不會丟失任何網(wǎng)絡(luò)配置。

進(jìn)一步探究 

如果以上步驟未能解決你遇到的問題,你可以通過以下方式獲得在 Kubernetes 中的 Windows 節(jié)點(diǎn)上運(yùn)行 Windows 容器的幫助:

報(bào)告問題和功能需求 

如果你遇到看起來像是軟件缺陷的問題,或者你想要提起某種功能需求,請使用 GitHub 問題跟蹤系統(tǒng)。 你可以在 GitHub 上發(fā)起 Issue 并將其指派給 SIG-Windows。你應(yīng)該首先搜索 Issue 列表,看看是否 該 Issue 以前曾經(jīng)被報(bào)告過,以評論形式將你在該 Issue 上的體驗(yàn)追加進(jìn)去,并附上 額外的日志信息。SIG-Windows Slack 頻道也是一個(gè)獲得初步支持的好渠道,可以在 生成新的 Ticket 之前對一些想法進(jìn)行故障分析。

在登記軟件缺陷時(shí),請給出如何重現(xiàn)該問題的詳細(xì)信息,例如:

  • Kubernetes 版本:kubectl 版本
  • 環(huán)境細(xì)節(jié):云平臺、OS 版本、網(wǎng)絡(luò)選型和配置情況以及 Docker 版本
  • 重現(xiàn)該問題的詳細(xì)步驟
  • 相關(guān)的日志
  • 通過為該 Issue 添加 ?/sig windows? 評論為其添加 ?sig/windows? 標(biāo)簽, 進(jìn)而引起 SIG-Windows 成員的注意。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號