在 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。若要結束監看命令,請按 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
    • 輸出連線能力,使用 kubectl exec 從 Pod 內部 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 設定的容器可以在攜帶以 GMSA 設定的身分時,存取外部 Active Directory 網域資源。請按這裡深入瞭解如何為 Windows 容器設定和使用 GMSA。

污點與容忍度

使用者需要結合使用污點和節點選取器,以便將 Linux 和 Windows 工作負載排程到各自特定於作業系統的節點。建議的方法概述如下,其主要目標之一是此方法不應破壞現有 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 節點上。

確保特定於作業系統的工作負載落在適當的容器主機上

使用者可以使用污點和容忍度來確保 Windows 容器可以排程在適當的主機上。所有執行 Kubernetes 1.32 的 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.32 的最佳實務是使用 nodeSelector

然而,在許多情況下,使用者已經有大量現有的 Linux 容器部署,以及現成的組態生態系統,例如社群 Helm Chart 和程式化的 Pod 產生案例,例如使用運算子。在這些情況下,您可能會猶豫是否要進行組態變更,以將 nodeSelector 欄位新增到所有 Pod 和 Pod 範本。替代方案是使用污點。由於 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 PST:修正 Windows 使用者指南中的步驟縮排 (#41283) (f0e755caae)