Kubernetes Windows容器的調度指南

2022-06-01 11:47 更新

Kubernetes 中 Windows 容器的調度指南

Windows 應用程序構成了許多組織中運行的服務和應用程序的很大一部分。 本指南將引導你完成在 Kubernetes 中配置和部署 Windows 容器的步驟。

目標

  • 配置一個示例 deployment 以在 Windows 節(jié)點上運行 Windows 容器
  • (可選)使用組托管服務帳戶(GMSA)為你的 Pod 配置 Active Directory 身份

在開始之前

  • 創(chuàng)建一個 Kubernetes 集群,其中包括一個控制平面和 運行 Windows 服務器的工作節(jié)點
  • 重要的是要注意,對于 Linux 和 Windows 容器,在 Kubernetes 上創(chuàng)建和部署服務和工作負載的行為幾乎相同。 與集群接口的 kubectl 命令相同。 提供以下部分中的示例只是為了快速啟動 Windows 容器的使用體驗。

入門:部署 Windows 容器

要在 Kubernetes 上部署 Windows 容器,你必須首先創(chuàng)建一個示例應用程序。 下面的示例 YAML 文件創(chuàng)建了一個簡單的 Web 服務器應用程序。 創(chuàng)建一個名為 ?win-webserver.yaml? 的服務規(guī)約,其內容如下:

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

Note: 端口映射也是支持的,但為簡單起見,在此示例中容器端口 80 直接暴露給服務。

  1. 檢查所有節(jié)點是否健康:
  2. kubectl get nodes
    
  3. 部署服務并觀察 pod 更新:
  4. kubectl apply -f win-webserver.yaml
    kubectl get pods -o wide -w

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

  5. 檢查部署是否成功。驗證:
    • Windows 節(jié)點上每個 Pod 有兩個容器,使用 ?docker ps?
    • Linux 控制平面節(jié)點列出兩個 Pod,使用 ?kubectl get pods?
    • 跨網絡的節(jié)點到 Pod 通信,從 Linux 控制平面節(jié)點 ?curl ?你的 pod IPs 的端口 80,以檢查 Web 服務器響應
    • Pod 到 Pod 的通信,使用 docker exec 或 kubectl exec 在 Pod 之間 (以及跨主機,如果你有多個 Windows 節(jié)點)進行 ping 操作
    • 服務到 Pod 的通信,從 Linux 控制平面節(jié)點和各個 Pod 中 ?curl ?虛擬服務 IP (在 ?kubectl get services? 下可見)
    • 服務發(fā)現(xiàn),使用 Kubernetes ?curl ?服務名稱 默認 DNS 后綴
    • 入站連接,從 Linux 控制平面節(jié)點或集群外部的計算機 ?curl ?NodePort
    • 出站連接,使用 kubectl exec 從 Pod 內部 curl 外部 IP

Note: 由于當前平臺對 Windows 網絡堆棧的限制,Windows 容器主機無法訪問在其上調度的服務的 IP。只有 Windows pods 才能訪問服務 IP。

可觀測性 

抓取來自工作負載的日志

日志是可觀測性的重要一環(huán);使用日志用戶可以獲得對負載運行狀況的洞察, 因而日志是故障排查的一個重要手法。 因為 Windows 容器中的 Windows 容器和負載與 Linux 容器的行為不同, 用戶很難收集日志,因此運行狀態(tài)的可見性很受限。 例如,Windows 工作負載通常被配置為將日志輸出到 Windows 事件跟蹤 (Event Tracing for Windows,ETW),或者將日志條目推送到應用的事件日志中。  LogMonitor 是 Microsoft 提供的一個開源工具,是監(jiān)視 Windows 容器中所配置的日志源 的推薦方式。 LogMonitor 支持監(jiān)視時間日志、ETW 提供者模塊以及自定義的應用日志, 并使用管道的方式將其輸出到標準輸出(stdout),以便 ?kubectl logs <pod>? 這類命令能夠讀取這些數據。

請遵照 LogMonitor GitHub 頁面上的指令,將其可執(zhí)行文件和配置文件復制到 你的所有容器中,并為其添加必要的入口點(Entrypoint),以便 LogMonitor 能夠將你的日志輸出推送到標準輸出(stdout)。

使用可配置的容器用戶名

從 Kubernetes v1.16 開始,可以為 Windows 容器配置與其鏡像默認值不同的用戶名 來運行其入口點和進程。 此能力的實現(xiàn)方式和 Linux 容器有些不同。

使用組托管服務帳戶管理工作負載身份

從 Kubernetes v1.14 開始,可以將 Windows 容器工作負載配置為使用組托管服務帳戶(GMSA)。 組托管服務帳戶是 Active Directory 帳戶的一種特定類型,它提供自動密碼管理, 簡化的服務主體名稱(SPN)管理以及將管理委派給跨多臺服務器的其他管理員的功能。 配置了 GMSA 的容器可以訪問外部 Active Directory 域資源,同時攜帶通過 GMSA 配置的身份。

污點和容忍度

目前,用戶需要將 Linux 和 Windows 工作負載運行在各自特定的操作系統(tǒng)的節(jié)點上, 因而需要結合使用污點和節(jié)點選擇算符。這可能僅給 Windows 用戶造成不便。 推薦的方法概述如下,其主要目標之一是該方法不應破壞與現(xiàn)有 Linux 工作負載的兼容性。

如果 ?IdentifyPodOS ?特性門控是啟用的, 你可以(并且應該)為 Pod 設置 ?.spec.os.name? 以表明該 Pod 中的容器所針對的操作系統(tǒng)。對于運行 Linux 容器的 Pod,設置 ?.spec.os.name? 為 ?linux?。對于運行 Windows 容器的 Pod,設置 ?.spec.os.name? 為 ?Windows?。

Note: 從 1.24 開始,?IdentifyPodOS ?功能處于 Beta 階段,默認啟用。

在將 Pod 分配給節(jié)點時,調度程序不使用 ?.spec.os.name? 的值。你應該使用正常的 Kubernetes 機制將 Pod 分配給節(jié)點, 確保集群的控制平面將 Pod 放置到適合運行的操作系統(tǒng)。 ?.spec.os.name? 值對 Windows Pod 的調度沒有影響,因此仍然需要污點、容忍度以及節(jié)點選擇器, 以確保 Windows Pod 調度至合適的 Windows 節(jié)點。

確保特定操作系統(tǒng)的工作負載落在適當的容器主機上

用戶可以使用污點和容忍度確保 Windows 容器可以調度在適當的主機上。目前所有 Kubernetes 節(jié)點都具有以下默認標簽:

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

如果 Pod 規(guī)范未指定諸如 ?"kubernetes.io/os": windows? 之類的 nodeSelector,則該 Pod 可能會被調度到任何主機(Windows 或 Linux)上。 這是有問題的,因為 Windows 容器只能在 Windows 上運行,而 Linux 容器只能在 Linux 上運行。 最佳實踐是使用 nodeSelector。

但是,我們了解到,在許多情況下,用戶都有既存的大量的 Linux 容器部署,以及一個現(xiàn)成的配置生態(tài)系統(tǒng), 例如社區(qū) Helm charts,以及程序化 Pod 生成案例,例如 Operators。 在這些情況下,你可能會不愿意更改配置添加 nodeSelector。替代方法是使用污點。 由于 kubelet 可以在注冊期間設置污點,因此可以輕松修改它,使其僅在 Windows 上運行時自動添加污點。

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

向所有 Windows 節(jié)點添加污點后,Kubernetes 將不會在它們上調度任何負載(包括現(xiàn)有的 Linux Pod)。 為了使某 Windows Pod 調度到 Windows 節(jié)點上,該 Pod 需要 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 版本必須與該節(jié)點的 Windows Server 版本相匹配。 如果要在同一集群中使用多個 Windows Server 版本,則應該設置其他節(jié)點標簽和 nodeSelector。

Kubernetes 1.17 自動添加了一個新標簽 ?node.kubernetes.io/windows-build? 來簡化此操作。 如果你運行的是舊版本,則建議手動將此標簽添加到 Windows 節(jié)點。

此標簽反映了需要兼容的 Windows 主要、次要和內部版本號。以下是當前每個 Windows Server 版本使用的值。

產品名稱 內部編號
Windows Server 2019 10.0.17763
Windows Server version 1809 10.0.17763
Windows Server version 1903 10.0.18362

使用 RuntimeClass 簡化

RuntimeClass 可用于 簡化使用污點和容忍度的過程。 集群管理員可以創(chuàng)建 ?RuntimeClass ?對象,用于封裝這些污點和容忍度。

  1. 將此文件保存到 ?runtimeClasses.yml? 文件。 它包括適用于 Windows 操作系統(tǒng)、體系結構和版本的 ?nodeSelector?。
  2. apiVersion: node.k8s.io/v1
    kind: RuntimeClass
    metadata:
      name: windows-2019
    handler: 'docker'
    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"
  3. 集群管理員執(zhí)行 ?kubectl create -f runtimeClasses.yml? 操作
  4. 根據需要向 Pod 規(guī)約中添加 ?runtimeClassName: windows-2019?,例如:
  5. 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


以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號