在 Kubernetes 中執行 Windows 容器指南

本頁面提供了在 Kubernetes 中使用 Windows 容器的一些步驟演練。本頁面還重點介紹了 Kubernetes 中一些 Windows 特有的功能。

需要注意的是,在 Kubernetes 上建立和部署服務和工作負載,對於 Linux 和 Windows 容器來說,其行為方式大體相同。與叢集互動的 kubectl 命令是相同的。本頁面中的示例旨在幫助您快速開始使用 Windows 容器。

目標

配置示例部署以在 Windows 節點上執行 Windows 容器。

準備工作

您應該已經可以訪問包含執行 Windows Server 的工作節點的 Kubernetes 叢集。

入門:部署 Windows 工作負載

下面的示例 YAML 檔案部署了一個在 Windows 容器內執行的簡單 Web 伺服器應用程式。

建立一個名為 win-webserver.yaml 的清單,其內容如下

---
apiVersion: v1
kind: Service
metadata:
  name: win-webserver
  labels:
    app: win-webserver
spec:
  ports:
    # the port that this service should serve on
    - port: 80
      targetPort: 80
  selector:
    app: win-webserver
  type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: win-webserver
  name: win-webserver
spec:
  replicas: 2
  selector:
    matchLabels:
      app: win-webserver
  template:
    metadata:
      labels:
        app: win-webserver
      name: win-webserver
    spec:
     containers:
      - name: windowswebserver
        image: mcr.microsoft.com/windows/servercore:ltsc2019
        command:
        - powershell.exe
        - -command
        - "<#code used from https://gist.github.com/19WAS85/5424431#> ; $$listener = New-Object System.Net.HttpListener ; $$listener.Prefixes.Add('http://*:80/') ; $$listener.Start() ; $$callerCounts = @{} ; Write-Host('Listening at http://*:80/') ; while ($$listener.IsListening) { ;$$context = $$listener.GetContext() ;$$requestUrl = $$context.Request.Url ;$$clientIP = $$context.Request.RemoteEndPoint.Address ;$$response = $$context.Response ;Write-Host '' ;Write-Host('> {0}' -f $$requestUrl) ;  ;$$count = 1 ;$$k=$$callerCounts.Get_Item($$clientIP) ;if ($$k -ne $$null) { $$count += $$k } ;$$callerCounts.Set_Item($$clientIP, $$count) ;$$ip=(Get-NetAdapter | Get-NetIpAddress); $$header='<html><body><H1>Windows Container Web Server</H1>' ;$$callerCountsString='' ;$$callerCounts.Keys | % { $$callerCountsString+='<p>IP {0} callerCount {1} ' -f $$ip[1].IPAddress,$$callerCounts.Item($$_) } ;$$footer='</body></html>' ;$$content='{0}{1}{2}' -f $$header,$$callerCountsString,$$footer ;Write-Output $$content ;$$buffer = [System.Text.Encoding]::UTF8.GetBytes($$content) ;$$response.ContentLength64 = $$buffer.Length ;$$response.OutputStream.Write($$buffer, 0, $$buffer.Length) ;$$response.Close() ;$$responseStatus = $$response.StatusCode ;Write-Host('< {0}' -f $$responseStatus)  } ; "
     nodeSelector:
      kubernetes.io/os: windows
  1. 檢查所有節點是否健康

    kubectl get nodes
    
  2. 部署服務並觀察 Pod 更新

    kubectl apply -f win-webserver.yaml
    kubectl get pods -o wide -w
    

    當服務正確部署後,兩個 Pod 都被標記為 Ready。要退出 watch 命令,請按 Ctrl+C。

  3. 檢查部署是否成功。驗證方法如下:

    • 從 Linux 控制平面節點列出多個 Pod,使用 kubectl get pods
    • 節點到 Pod 的網路通訊,從 Linux 控制平面節點 curl Pod IP 的 80 埠,檢查 Web 伺服器響應
    • Pod 到 Pod 通訊,使用 kubectl exec 在 Pod 之間(如果有一個以上的 Windows 節點,則跨主機)進行 ping 操作
    • 服務到 Pod 通訊,從 Linux 控制平面節點和單個 Pod curl 虛擬服務 IP(在 kubectl get services 下可見)
    • 服務發現,使用 Kubernetes 預設 DNS 字尾 curl 服務名稱
    • 入站連線,從 Linux 控制平面節點或叢集外部機器 curl NodePort
    • 出站連線,從 Pod 內部使用 kubectl exec curl 外部 IP

可觀測性

捕獲工作負載日誌

日誌是可觀察性的重要組成部分;它們使使用者能夠深入瞭解工作負載的操作方面,並且是故障排除問題的關鍵要素。由於 Windows 容器和 Windows 容器內部的工作負載與 Linux 容器的行為不同,使用者很難收集日誌,從而限制了操作可見性。例如,Windows 工作負載通常配置為記錄到 ETW(Windows 事件跟蹤)或將條目推送到應用程式事件日誌。LogMonitor 是 Microsoft 的一個開源工具,是監視 Windows 容器內配置的日誌源的推薦方法。LogMonitor 支援監視事件日誌、ETW 提供程式和自定義應用程式日誌,並將它們透過管道傳輸到 STDOUT,供 kubectl logs <pod> 使用。

按照 LogMonitor GitHub 頁面上的說明,將其二進位制檔案和配置檔案複製到所有容器中,並新增必要的入口點,以便 LogMonitor 將日誌推送到 STDOUT。

配置容器使用者

使用可配置的容器使用者名稱

Windows 容器可以配置為使用與映象預設值不同的使用者名稱來執行其入口點和程序。在此處瞭解更多資訊:此處

使用組託管服務賬戶管理工作負載身份

Windows 容器工作負載可以配置為使用組託管服務賬戶(GMSA)。組託管服務賬戶是一種特定型別的 Active Directory 賬戶,提供自動密碼管理、簡化的服務主體名稱(SPN)管理,以及將管理委派給多個伺服器上的其他管理員的能力。配置了 GMSA 的容器可以訪問外部 Active Directory 域資源,同時承載使用 GMSA 配置的身份。在此處瞭解更多關於配置和使用 Windows 容器 GMSA 的資訊:此處

汙點和容忍度

使用者需要結合使用汙點和節點選擇器,才能將 Linux 和 Windows 工作負載排程到各自的 OS 特定節點。推薦的方法如下所述,其主要目標之一是此方法不應破壞現有 Linux 工作負載的相容性。

您可以(並且應該)為每個 Pod 設定 .spec.os.name,以指示該 Pod 中的容器所設計的作業系統。對於執行 Linux 容器的 Pod,將 .spec.os.name 設定為 linux。對於執行 Windows 容器的 Pod,將 .spec.os.name 設定為 windows

排程器在將 Pod 分配給節點時不會使用 .spec.os.name 的值。您應該使用正常的 Kubernetes 機制來將 Pod 分配給節點,以確保您的叢集的控制平面將 Pod 放置在執行適當作業系統的節點上。

.spec.os.name 值對 Windows Pod 的排程沒有影響,因此仍然需要汙點和容忍度(或節點選擇器)來確保 Windows Pod 落在適當的 Windows 節點上。

確保 OS 特定工作負載落在適當的容器主機上

使用者可以使用汙點和容忍度來確保 Windows 容器可以排程到適當的主機上。所有執行 Kubernetes 1.34 的 Kubernetes 節點都具有以下預設標籤

  • kubernetes.io/os = [windows|linux]
  • kubernetes.io/arch = [amd64|arm64|...]

如果 Pod 規範未指定 nodeSelector,例如 "kubernetes.io/os": windows,則該 Pod 可能會排程到任何主機,無論是 Windows 還是 Linux。這可能會出現問題,因為 Windows 容器只能在 Windows 上執行,而 Linux 容器只能在 Linux 上執行。Kubernetes 1.34 的最佳實踐是使用 nodeSelector

然而,在許多情況下,使用者已經擁有大量現有 Linux 容器部署,以及一個現成的配置生態系統,例如社群 Helm Charts 和程式化 Pod 生成情況(例如使用操作員)。在這些情況下,您可能不願意更改配置以向所有 Pod 和 Pod 模板新增 nodeSelector 欄位。替代方法是使用汙點。由於 kubelet 可以在註冊期間設定汙點,因此可以輕鬆修改它,使其僅在 Windows 上執行時自動新增汙點。

例如:--register-with-taints='os=windows:NoSchedule'

透過向所有 Windows 節點新增汙點,將不會有任何內容排程到它們上(包括現有的 Linux Pod)。為了使 Windows Pod 能夠排程到 Windows 節點上,它既需要 nodeSelector,也需要適當匹配的容忍度來選擇 Windows。

nodeSelector:
    kubernetes.io/os: windows
    node.kubernetes.io/windows-build: '10.0.17763'
tolerations:
    - key: "os"
      operator: "Equal"
      value: "windows"
      effect: "NoSchedule"

在同一叢集中處理多個 Windows 版本

每個 Pod 使用的 Windows Server 版本必須與節點的版本匹配。如果要在同一個叢集中使用多個 Windows Server 版本,則應設定額外的節點標籤和 nodeSelector 欄位。

Kubernetes 自動新增一個標籤 node.kubernetes.io/windows-build 以簡化此操作。

此標籤反映了 Windows 的主版本、次版本和內部版本號,這些版本號需要匹配才能實現相容性。以下是每個 Windows Server 版本使用的值:

產品名稱版本
Windows Server 201910.0.17763
Windows Server 202210.0.20348

使用 RuntimeClass 簡化

RuntimeClass 可用於簡化汙點和容忍度使用過程。叢集管理員可以建立 RuntimeClass 物件,該物件用於封裝這些汙點和容忍度。

  1. 將此檔案儲存為 runtimeClasses.yml。它包含適用於 Windows 作業系統、架構和版本的 nodeSelector

    ---
    apiVersion: node.k8s.io/v1
    kind: RuntimeClass
    metadata:
      name: windows-2019
    handler: example-container-runtime-handler
    scheduling:
      nodeSelector:
        kubernetes.io/os: 'windows'
        kubernetes.io/arch: 'amd64'
        node.kubernetes.io/windows-build: '10.0.17763'
      tolerations:
      - effect: NoSchedule
        key: os
        operator: Equal
        value: "windows"
    
  2. 以叢集管理員身份執行 kubectl create -f runtimeClasses.yml

  3. 根據需要將 runtimeClassName: windows-2019 新增到 Pod 規範中

    例如

    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: iis-2019
      labels:
        app: iis-2019
    spec:
      replicas: 1
      template:
        metadata:
          name: iis-2019
          labels:
            app: iis-2019
        spec:
          runtimeClassName: windows-2019
          containers:
          - name: iis
            image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
            resources:
              limits:
                cpu: 1
                memory: 800Mi
              requests:
                cpu: .1
                memory: 300Mi
            ports:
              - containerPort: 80
     selector:
        matchLabels:
          app: iis-2019
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: iis
    spec:
      type: LoadBalancer
      ports:
      - protocol: TCP
        port: 80
      selector:
        app: iis-2019
    
上次修改時間:太平洋時間 2023 年 5 月 24 日上午 10:55:修復 Windows 使用者指南中的步驟縮排 (#41283) (f0e755caae)