Kubernetes Windows容器的調(diào)度指南

2022-06-01 11:47 更新

Kubernetes 中 Windows 容器的調(diào)度指南

Windows 應(yīng)用程序構(gòu)成了許多組織中運(yùn)行的服務(wù)和應(yīng)用程序的很大一部分。 本指南將引導(dǎo)你完成在 Kubernetes 中配置和部署 Windows 容器的步驟。

目標(biāo)

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

在開始之前

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

入門:部署 Windows 容器

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

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 直接暴露給服務(wù)。

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

    正確部署服務(wù)后,兩個(gè) Pod 都標(biāo)記為 “Ready”。要退出 watch 命令,請按 Ctrl + C。

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

Note: 由于當(dāng)前平臺(tái)對 Windows 網(wǎng)絡(luò)堆棧的限制,Windows 容器主機(jī)無法訪問在其上調(diào)度的服務(wù)的 IP。只有 Windows pods 才能訪問服務(wù) IP。

可觀測性 

抓取來自工作負(fù)載的日志

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

請遵照 LogMonitor GitHub 頁面上的指令,將其可執(zhí)行文件和配置文件復(fù)制到 你的所有容器中,并為其添加必要的入口點(diǎn)(Entrypoint),以便 LogMonitor 能夠?qū)⒛愕娜罩据敵鐾扑偷綐?biāo)準(zhǔn)輸出(stdout)。

使用可配置的容器用戶名

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

使用組托管服務(wù)帳戶管理工作負(fù)載身份

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

污點(diǎn)和容忍度

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

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

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

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

確保特定操作系統(tǒng)的工作負(fù)載落在適當(dāng)?shù)娜萜髦鳈C(jī)上

用戶可以使用污點(diǎn)和容忍度確保 Windows 容器可以調(diào)度在適當(dāng)?shù)闹鳈C(jī)上。目前所有 Kubernetes 節(jié)點(diǎn)都具有以下默認(rèn)標(biāo)簽:

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

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

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

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

向所有 Windows 節(jié)點(diǎn)添加污點(diǎn)后,Kubernetes 將不會(huì)在它們上調(diào)度任何負(fù)載(包括現(xiàn)有的 Linux Pod)。 為了使某 Windows Pod 調(diào)度到 Windows 節(jié)點(diǎn)上,該 Pod 需要 nodeSelector 和合適的匹配的容忍度設(shè)置來選擇 Windows。

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

處理同一集群中的多個(gè) Windows 版本

每個(gè) Pod 使用的 Windows Server 版本必須與該節(jié)點(diǎn)的 Windows Server 版本相匹配。 如果要在同一集群中使用多個(gè) Windows Server 版本,則應(yīng)該設(shè)置其他節(jié)點(diǎn)標(biāo)簽和 nodeSelector。

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

此標(biāo)簽反映了需要兼容的 Windows 主要、次要和內(nèi)部版本號。以下是當(dāng)前每個(gè) Windows Server 版本使用的值。

產(chǎn)品名稱 內(nèi)部編號
Windows Server 2019 10.0.17763
Windows Server version 1809 10.0.17763
Windows Server version 1903 10.0.18362

使用 RuntimeClass 簡化

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

  1. 將此文件保存到 ?runtimeClasses.yml? 文件。 它包括適用于 Windows 操作系統(tǒng)、體系結(jié)構(gòu)和版本的 ?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. 根據(jù)需要向 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


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

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號