
說真的以前我一直覺得在 Windows 上搞 Kubernetes 是件挺折騰人的事直到有一次需要緊急驗證一套服務(wù)的部署配置又不想為了這點事去云上開三臺機(jī)器就順手在本地搭了一個 mini 版本的 K8s 集群。做完之后我才發(fā)現(xiàn)這套東西其實沒有想象中復(fù)雜只要把工具選對、把環(huán)境理順半小時之內(nèi)就能跑起來一個能用的本地集群。這篇文章就把我完整的搭建過程、踩過的坑、以及一些這兩年積累下來的心得一次性寫清楚希望能幫到同樣想在 Windows 上學(xué)習(xí) K8s 或做本地開發(fā)調(diào)試的朋友。再說一下這篇文章適合誰。如果你剛學(xué) K8s想找一個不用花錢、電腦上就能跟著敲命令的環(huán)境這篇文章可以直接當(dāng)操作手冊用。如果你是有經(jīng)驗的開發(fā)想快速起一個本地集群做聯(lián)調(diào)或者跑 CI那文中的 minikube 和 kind 兩套方案也可以直接抄作業(yè)。文章會先把方案選型講明白再給一套完整的實操步驟最后把常見問題整理成速查表盡量讓你照著做就能跑通。1. Windows 上搭 K8s先把思路理清楚1.1 為什么要在 Windows 本地搭一個 Mini 版 K8s很多人一開始學(xué) K8s 都容易陷入一個誤區(qū)覺得必須搞三臺 Linux 服務(wù)器才能開始。實際上對于學(xué)習(xí)、日常開發(fā)、跑通部署流程這些場景本地一個 mini 集群完全夠用而且靈活得多。你不需要申請云資源、不需要等機(jī)器初始化、不用考慮生產(chǎn)環(huán)境的安全策略改完配置隨時可以刪除重建這對學(xué)習(xí)過程中的試錯來說太重要了。我自己最常遇到的使用場景是這三類第一類學(xué) K8s 核心概念。Pod、Deployment、Service、Ingress 這些 API 對象光看文檔容易看得云里霧里但本地起一個集群之后隨手敲幾條 yaml 就能看到調(diào)度、重建、擴(kuò)容的真實過程理解速度完全不一樣。像集群調(diào)度、故障轉(zhuǎn)移這些聽起來很抽象的東西在本地集群里是可以直接觀察到的。第二類本地聯(lián)調(diào)和開發(fā)測試。項目里用到 Redis、MySQL、Nacos 這類中間件的時候與其在 Windows 上一個一個裝不如直接在 K8s 里用 yaml 把環(huán)境拉起來用完一鍵清理不污染宿主機(jī)。這個做法在開發(fā)機(jī)上的體驗非常舒服。第三類驗證部署腳本和 CI 流程。不管是公司內(nèi)部平臺的部署模板、Helm Chart還是 GitLab Runner 里的流水線腳本先在本地 mini 集群里跑一遍能攔截掉大量低級問題。以前我改一個部署 yaml 就得等遠(yuǎn)程測試環(huán)境的隊列現(xiàn)在本地十幾秒就能看到結(jié)果。1.2 主流的四條技術(shù)路線怎么選在 Windows 平臺上目前能跑起來 mini 版 K8s 的方案其實有好幾種我做過一輪對比整理成下面這張表方案底層依賴支持的多節(jié)點資源占用適合場景復(fù)雜度Docker Desktop 內(nèi)置 KubernetesWSL2 / Hyper-V僅單節(jié)點中等快速體驗Docker 用戶低minikubeDocker / Hyper-V / VirtualBox支持需配置中等學(xué)習(xí) K8s開發(fā)調(diào)試低kindDocker支持較低CI 環(huán)境、多節(jié)點快速測試低k3sWSL2 / 虛擬機(jī)支持很低邊緣計算、性能較弱的機(jī)器中先說 Docker Desktop 內(nèi)置的 Kubernetes。這個方案最省事安裝好 Docker Desktop 之后在設(shè)置里把 Kubernetes 開關(guān)打開等幾分鐘就能用。但它的主要問題是只能提供單節(jié)點而且版本跟隨 Docker Desktop 的發(fā)布節(jié)奏想升級集群版本得等 Docker Desktop 更新。對于只體驗 Pod、Service 這些基礎(chǔ)概念來說夠用了但如果你想試試多節(jié)點調(diào)度、節(jié)點親和性這類功能它就力不從心了。minikube 是我最推薦給初學(xué)者的方案它由 K8s 官方社區(qū)維護(hù)本質(zhì)上是一個能幫你自動創(chuàng)建并管理本地集群的工具。minikube 支持多種驅(qū)動在 Windows 上最常見的用法是以 Docker 作為驅(qū)動這樣就不需要額外裝虛擬機(jī)軟件。它的優(yōu)勢是功能完整Dashboard 面板、插件管理、多節(jié)點配置都有而且文檔非常豐富遇到問題去搜解決方案基本都能找到。kind 的優(yōu)勢則體現(xiàn)在啟動速度和資源占用上。kind 的全稱是 Kubernetes in Docker它把集群的每個節(jié)點都跑成一個 Docker 容器創(chuàng)建集群就是啟動幾個容器所以整套流程非常快兩三分鐘就能得到一個集群。這個方案在 CI 環(huán)境里特別受歡迎因為流水線里直接跑kind create cluster就可以創(chuàng)建一套隔離的測試環(huán)境。我自己在本地也會用 kind 來做多節(jié)點測試配置非常靈活。k3s 則是走輕量路線的發(fā)行版由 Rancher 團(tuán)隊維護(hù)專門面向邊緣計算和資源受限的場景。它把 K8s 的很多組件做成了單二進(jìn)制文件內(nèi)存占用比標(biāo)準(zhǔn)版小很多。不過 k3s 本身是面向 Linux 的在 Windows 上跑通常需要包一層 WSL2 或者虛擬機(jī)對新手來說反而多了一道門檻。如果你的筆記本配置比較老內(nèi)存只有 8G 左右可以試試這條路但我不建議作為入門首選。1.3 我最終選擇的方案與理由我的主力電腦是 Windows 11平時已經(jīng)裝了 Docker Desktop 并且在使用 WSL2 后端所以我最終選擇的是minikube Docker 驅(qū)動這套組合同時也安裝了 kind 作為備用工具。選擇 minikube 的主要原因有三個第一minikube 對 Kubernetes 版本的支持非常靈活。我可以通過—kubernetes-version參數(shù)指定集群版本比如測試新特性時起一個最新版集群跑兼容性驗證時再起一個舊版集群切換成本很低這一點對學(xué)習(xí)和排查問題特別有優(yōu)勢。第二minikube 的多節(jié)點配置雖然比 kind 麻煩一點但依然是開箱即用的。在啟動時指定—nodes3就能得到一個一主兩從的集群可以在上面驗證節(jié)點調(diào)度、Pod 漂移等場景足以滿足大多數(shù)學(xué)習(xí)需求。第三minikube 自帶的插件體系非常實用。比如ingress插件可以讓你在本地直接體驗 Ingress 流量轉(zhuǎn)發(fā)registry插件可以跑一個本地 Docker 鏡像倉庫這些都是本地開發(fā)中會實際用到的能力。至于 kind我更多是用它來跑一些需要快速驗證的多節(jié)點場景。比如之前驗證一個 StatefulSet 在節(jié)點故障時的行為用 kind 起三個節(jié)點做了半天實驗跑完直接刪掉集群宿主機(jī)干干凈凈。兩個工具各有分工建議你按自己的實際需求來選不用貪多。2. 動手前必須搞懂的幾個關(guān)鍵點2.1 WSL2 與 DockerK8s 在 Windows 上的兩個基石不管選哪條路線Windows 上跑 K8s 基本都繞不開 WSL2 和 Docker 這兩個底層組件先把它們的關(guān)系理清楚后面操作起來會順很多否則到時候出了問題都不知道該查哪層。WSL2 是 Windows Subsystem for Linux 的第二個大版本它本質(zhì)上是一個運行在 Hyper-V 虛擬機(jī)基礎(chǔ)上的輕量 Linux 內(nèi)核。有了 WSL2你可以在 Windows 上直接運行 Linux 發(fā)行版而且性能比第一代純翻譯層好很多。K8s 的組件和容器運行時本身是為 Linux 設(shè)計的雖然 Windows 上有 Windows 容器但 K8s 生態(tài)的主流鏡像、工具鏈、網(wǎng)絡(luò)插件幾乎都優(yōu)先支持 Linux所以在 Windows 上搭 K8s 的實際做法基本都是借助 WSL2 跑一個 Linux 環(huán)境再在這個環(huán)境里部署 K8s。Docker Desktop 的 Windows 版本也充分利用了 WSL2。你可以把它的 Docker Engine 跑在 WSL2 的發(fā)行版里Windows 上的 Docker 命令通過集成方式直接操作這個 Linux Docker。這樣一來Windows、WSL2、Docker 三者就形成了一個完整的鏈路。需要注意的一個點是 WSL2 和 Hyper-V 的關(guān)系。如果你用的是 Win10 2004 以上的版本打開 WSL2 功能后系統(tǒng)默認(rèn)使用 Hyper-V 底層虛擬化這意味著你在機(jī)器上不能同時用舊版 VirtualBox5.x 之前不支持 Hyper-V 共存。新一代 VirtualBox 7 已經(jīng)做了兼容適配如果你必須要用 VirtualBox記得升級到新版本。我自己的建議是能不用虛擬機(jī)就直接用 Docker 驅(qū)動省心省事。檢查 WSL2 是否安裝可以在 PowerShell 里執(zhí)行wsl --status wsl -l -v如果VERSION列顯示為 2說明已經(jīng)開啟了 WSL2。如果顯示的是 1或者執(zhí)行命令報錯需要先更新 WSL2 內(nèi)核。方法是在管理員 PowerShell 里執(zhí)行wsl --update或者參考微軟官方的安裝說明這里不再展開。2.2 K8s 與 Docker 到底什么關(guān)系這個熱搜詞出現(xiàn)的頻率太高了我?guī)缀趺看谓o同事講 K8s 都會被問到一次。簡單說K8s 和 Docker 不是同級產(chǎn)品也不是競爭關(guān)系而是兩個不同層次的東西。Docker 本質(zhì)上是容器運行時和管理工具它解決的是“怎么把應(yīng)用打包成鏡像、怎么運行容器”的問題。你寫一個 Dockerfile構(gòu)建出鏡像然后用docker run把容器跑起來這一套流程解決的是單機(jī)層面的容器化問題。K8s 解決的是“怎么在多個機(jī)器上統(tǒng)一管理這些容器”的問題。它負(fù)責(zé)容器的編排調(diào)度、服務(wù)發(fā)現(xiàn)、負(fù)載均衡、自動擴(kuò)縮容、故障恢復(fù)等能力。一臺機(jī)器上能跑幾十個容器已經(jīng)不容易了但容器宿主機(jī)宕機(jī)了怎么辦流量大了怎么擴(kuò)容服務(wù)之間怎么互相發(fā)現(xiàn)這些才是 K8s 要解決的核心問題。打個比方Docker 是單個施工隊負(fù)責(zé)把房子按圖紙蓋好K8s 是一個物業(yè)公司負(fù)責(zé)整個小區(qū)里所有房子的管理、維修、擴(kuò)容、人員調(diào)度。你可以在沒有 Docker 的情況下用 containerd、CRI-O 等其他容器運行時跑 K8s因為 K8s 通過 CRI容器運行時接口抽象了這一層。同樣你可以用 Docker Compose 在單機(jī)上編排多個容器但那和 K8s 的多節(jié)點集群能力不在一個量級。2.3 資源規(guī)劃Mini 不是隨便跑跑就行Mini 版本的意思是“功能齊全但規(guī)模小”不是說隨便一臺老爺機(jī)就能跑。K8s 集群本身需要占用一定的資源尤其是控制面組件API Server、etcd、Controller Manager、Scheduler都有常駐內(nèi)存開銷。根據(jù)我自己的經(jīng)驗單節(jié)點 mini 集群最少需要 4G 內(nèi)存其中 WSL2 至少要分到 3GDocker 運行時和 K8s 系統(tǒng)組件加起來大概要占 2G 左右。如果你想跑多節(jié)點或者同時在集群里部署中間件做開發(fā)16G 內(nèi)存是起步32G 會更從容。這里必須重點提一下 WSL2 的內(nèi)存限制。WSL2 默認(rèn)行為是占用宿主機(jī)最多 50% 的內(nèi)存如果你的電腦是 16G 內(nèi)存WSL2 可能吃掉 8GWindows 本身再加上各種軟件會感覺很卡。解決辦法是在用戶目錄下創(chuàng)建.wslconfig文件手動限制 WSL2 的資源[wsl2] memory8GB processors4 swap2GB設(shè)置完成后在 PowerShell 里執(zhí)行wsl --shutdown重啟 WSL2 即可生效。這個配置文件對于用 Docker Desktop 跑 K8s 的環(huán)境非常關(guān)鍵我見過太多同事因為沒做這個限制Windows 直接被 WSL2 拖垮還以為是 K8s 的問題。CPU 方面雙核起步四核比較穩(wěn)。K8s 的控制面組件對 CPU 的消耗不算特別夸張但如果同時跑編譯任務(wù)或者多個應(yīng)用核心數(shù)太少會明顯變慢。磁盤方面機(jī)械硬盤就別折騰了SSD 是必需的。K8s 啟動過程要拉取大量鏡像、解壓文件機(jī)械硬盤光等啟動就能讓人崩潰。3. 從零開始完整搭建過程實錄下面進(jìn)入正題我會按我實際操作時的順序一步步帶你搭建一個單節(jié)點 mini 版本的 K8s 集群。這套流程我在兩臺 Windows 11 和一臺 Win10 的機(jī)器上都驗證過照著做基本不會出大問題。如果你之前已經(jīng)裝好 Docker Desktop 并且開啟了 WSL2可以直接跳到 3.2 節(jié)。3.1 第一步把 WSL2 和 Docker Desktop 準(zhǔn)備好首先是 WSL2 的安裝。在管理員權(quán)限的 PowerShell 中執(zhí)行wsl --install這個命令會安裝 WSL2 所需的全部組件并且默認(rèn)安裝 Ubuntu 發(fā)行版安裝完成后根據(jù)提示重啟系統(tǒng)。重啟后再用wsl -l -v確認(rèn)版本為 2如果版本是 1執(zhí)行wsl --set-version Ubuntu-22.04 2升級到 WSL2。接下來安裝 Docker Desktop。去官網(wǎng)下載 Docker Desktop for Windows 安裝包安裝過程中會詢問你使用 Windows 容器還是 Linux 容器這里直接選 Linux 容器。安裝完成后打開 Docker Desktop在 Settings 的 General 頁面確認(rèn) Use the WSL 2 based engine 是勾選狀態(tài)。Docker Desktop 啟動之后會自動把 Docker CLI 集成到 Windows 終端里。你可以在 WSL2 的 Ubuntu 終端里直接運行docker version驗證 Docker 是否可用。這里有個小技巧Docker Desktop 默認(rèn)會把 WSL2 的發(fā)行版綁定為 Docker 的后端你在 WSL2 終端里跑 Docker 命令和 Windows 終端里跑是一樣的底層是同一個 Docker Engine。如果你打算在本地網(wǎng)絡(luò)環(huán)境里拉取鏡像遇到速度問題可以在 Docker Desktop 的 Settings - Docker Engine 里配置鏡像加速地址配置后需要 Apply Restart 才能生效。這一步不是必須的但在某些場景下能節(jié)省大量等待時間。另外我建議在 WSL2 的 Ubuntu 里裝一下curl、vim這些基礎(chǔ)工具后面編輯 yaml 文件和調(diào)試會用得到。執(zhí)行sudo apt update sudo apt install -y curl vim3.2 第二步安裝 kubectl 與 minikubekubectl 是操作 K8s 集群的命令行工具minikube 是負(fù)責(zé)創(chuàng)建和管理本地集群的工具。這兩個工具是獨立的二進(jìn)制文件哪個平臺下載哪個版本自己定。先裝 kubectl。在 Windows 上我建議用直接下載二進(jìn)制的方式因為最直觀不用額外裝包管理器。去 Kubernetes 官方發(fā)布頁面下載與集群版本匹配或略高一點的 kubectl把 exe 文件放到你習(xí)慣的目錄然后把該目錄加到系統(tǒng) PATH 中。下載完驗證執(zhí)行kubectl version --client順利的話會輸出版本號。嚴(yán)格來說 kubectl 的客戶端版本和集群版本不需要完全一致但大版本之間最好保持在差異一個版本以內(nèi)避免出現(xiàn) API 兼容問題。比如集群是 v1.28kubectl 用 v1.29 通常沒什么問題但跨兩個大版本就可能出現(xiàn)不識別對象字段的情況。再裝 minikube。同樣是在官方發(fā)布頁面下載最新版Windows 下是一個 exe 文件下載后改名為minikube.exe放到 PATH 目錄下。安裝完成后在終端執(zhí)行minikube version能正常輸出版本信息就說明裝好了。這里多說一句 choco 方案。如果你裝了 Chocolatey 包管理器也可以用choco install kubernetes-cli minikube一條命令裝完但對于剛接觸 Windows 命令行環(huán)境的朋友我反而推薦手動下載因為安裝過程更透明出了問題更好排查。3.3 第三步創(chuàng)建單節(jié)點集群并驗證驅(qū)動選 Docker 的情況下啟動集群只需要一條命令minikube start --driverdocker --cpus2 --memory4096拆開看這幾個參數(shù)--driverdocker讓 minikube 把集群節(jié)點跑在 Docker 容器里不需要額外創(chuàng)建虛擬機(jī)。--cpus2指定節(jié)點容器可用的 CPU 核數(shù)按你的機(jī)器配置調(diào)整。--memory4096指定節(jié)點容器的內(nèi)存單位是 MB4G 是單節(jié)點集群比較穩(wěn)的配置。執(zhí)行過程中會拉取一些底層鏡像比如kicbase和其他 K8s 組件鏡像根據(jù)網(wǎng)絡(luò)狀況可能需要幾分鐘。看到類似Done! kubectl is now configured to use minikube的輸出說明集群啟動成功了。然后驗證集群狀態(tài)kubectl get nodes正常會輸出一個control-plane節(jié)點的信息狀態(tài)為Ready。再看一下集群里有哪些系統(tǒng)組件在運行kubectl get pods -A你會看到 kube-system 命名空間下有一堆 Pod比如 coredns、etcd、kube-apiserver、kube-controller-manager、kube-scheduler、kube-proxy、storage-provisioner 等。看到這些 Pod 處于 Running 狀態(tài)集群基本就穩(wěn)了。minikube 還自帶一個 Web 儀表盤執(zhí)行minikube dashboard會自動打開瀏覽器可以在界面上查看節(jié)點、Pod、Service 等資源的狀態(tài)。儀表盤對于不熟悉命令行操作的同學(xué)非常友好可以作為輔助觀察工具用。3.4 第四步部署一個 Nginx 測試集群可用性集群建好了空跑沒有意義部署一個實際應(yīng)用來驗證一下端到端流程。創(chuàng)建一個 Deployment指定鏡像為nginx:alpinekubectl create deployment nginx-test --imagenginx:alpine然后創(chuàng)建一個 NodePort 類型的 Service 把端口暴露出來kubectl expose deployment nginx-test --typeNodePort --port80查看 Service 信息kubectl get svc nginx-test會看到類似如下的輸出NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-test NodePort 10.109.xx.xx none 80:32468/TCP 30s其中32468就是映射到宿主機(jī)的隨機(jī)端口。執(zhí)行minikube service nginx-testminikube 會把 Service 的地址拼出來并自動打開瀏覽器訪問后能看到 nginx 的歡迎頁說明集群的 Pod 調(diào)度、Service 負(fù)載均衡、端口轉(zhuǎn)發(fā)這條鏈路已經(jīng)完全打通了。如果是在 WSL2 里操作注意不要直接用localhost:32468訪問需要取 WSL2 的 IP 地址。可以在 Ubuntu 終端里執(zhí)行hostname -I拿到 IP 后用http://WSL2-IP:32468訪問。Docker Desktop 做過端口轉(zhuǎn)發(fā)的場景下localhost 通常也能用但如果你發(fā)現(xiàn)訪問不通優(yōu)先檢查這一層。4. 玩轉(zhuǎn) Mini 集群常用操作與進(jìn)階思路4.1 日常管理集群的 8 個高頻命令本地集群跑起來之后下面這些命令是我平時用得非常頻繁的建議收藏一下命令作用使用頻率kubectl get nodes查看節(jié)點狀態(tài)極高kubectl get pods -A查看所有命名空間下的 Pod極高kubectl get svc -A查看所有 Service 和暴露端口高kubectl describe pod name查看 Pod 詳細(xì)信息排查問題極高kubectl logs -f pod查看 Pod 日志高kubectl apply -f xx.yaml用配置文件創(chuàng)建/更新資源高kubectl delete -f xx.yaml用配置文件刪除資源中minikube stop / start停止/啟動本地集群中特別想說一下kubectl describe這個命令。很多新手在遇到 Pod 啟動失敗時第一反應(yīng)是看日志但實際上很多問題看日志是看不出來的比如鏡像拉取失敗、PVC 掛載失敗、存活探針失敗這些信息都在describe輸出末尾的 Events 部分。我每次排查問題的第一步都是kubectl describe pod只有看到 Events 里的報錯信息才能對癥下藥。如果你經(jīng)常敲這幾個命令建議再加一個 kubectl 自動補全。在 bash 環(huán)境里執(zhí)行source (kubectl completion bash)這樣可以減少很多輸入量。4.2 用 kind 搭建多節(jié)點 mini 集群單節(jié)點集群能體驗的基礎(chǔ)功能很多但比如節(jié)點親和性、污點容忍、Pod 漂移這類調(diào)度相關(guān)的特性單節(jié)點是完全沒有辦法驗證的。這時候可以考慮用 kind 起一個多節(jié)點集群而且 kind 的創(chuàng)建速度比 minikube 快得多每次起集群大約只需要兩到三分鐘。創(chuàng)建一個三節(jié)點集群一個控制平面節(jié)點、兩個工作節(jié)點準(zhǔn)備一個配置文件multi-node.yamlkind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane ports: - containerPort: 30080 hostPort: 30080 protocol: TCP - role: worker - role: worker執(zhí)行kind create cluster --config multi-node.yaml --name test-cluster創(chuàng)建完成后驗證kubectl get nodes輸出會看到test-cluster-control-plane、test-cluster-worker、test-cluster-worker2三個節(jié)點狀態(tài)都為 Ready。在這個多節(jié)點集群里你就能真正體驗調(diào)度是怎么回事了。比如創(chuàng)建一個 Deployment 并設(shè)置副本數(shù)為 5觀察 Pod 是怎么被調(diào)度到不同節(jié)點的kubectl create deployment nginx-multi --imagenginx:alpine --replicas5 kubectl get pods -o wide輸出結(jié)果里會有一個NODE列顯示每個 Pod 運行在哪個節(jié)點上。在這個基礎(chǔ)上你還可以手動把某個工作節(jié)點標(biāo)記為不可調(diào)度觀察 Pod 如何被重新調(diào)度kubectl cordon test-cluster-worker kubectl drain test-cluster-worker --ignore-daemonsets --delete-emptydir-data這就是 K8s 里面節(jié)點維護(hù)的標(biāo)準(zhǔn)流程平時生產(chǎn)環(huán)境升級節(jié)點前也是這么操作的。跑完這些命令之后自己動手體驗一遍比我在這里寫一千字理論都管用。4.3 小集群里也能體驗的調(diào)度玩法即便是 mini 集群K8s 的調(diào)度機(jī)制也并不會縮小。雖然集群里可能只有兩三個節(jié)點但在學(xué)習(xí)時完全可以把每個節(jié)點想象成一個大的可用區(qū)或物理機(jī)房很多生產(chǎn)級別的調(diào)度概念都能在這里模擬一遍。比如你可以給節(jié)點打上標(biāo)簽把某些 Pod 指定到特定節(jié)點上運行。給 worker 節(jié)點打一個disktypessd的標(biāo)簽kubectl label nodes test-cluster-worker disktypessd然后創(chuàng)建一個只調(diào)度到 SSD 節(jié)點的 PodapiVersion: v1 kind: Pod metadata: name: ssd-pod spec: nodeSelector: disktype: ssd containers: - name: nginx image: nginx:alpine執(zhí)行kubectl apply -f ssd-pod.yaml后用kubectl get pods -o wide查看這個 Pod 的 NODE 列它一定會運行在打了disktypessd標(biāo)簽的節(jié)點上。這就是 nodeSelector 標(biāo)簽選擇器的作用生產(chǎn)環(huán)境里經(jīng)常用它來把計算密集型任務(wù)調(diào)度到 GPU 節(jié)點或者把存儲有要求的服務(wù)調(diào)度到高性能磁盤節(jié)點。再看一個更有意思的場景模擬節(jié)點故障。在 kind 多節(jié)點集群里直接把某個節(jié)點的 Docker 容器停下來模擬一臺服務(wù)器宕機(jī)docker stop test-cluster-worker2等上幾秒鐘然后執(zhí)行kubectl get nodes你會看到test-cluster-worker2的狀態(tài)變成了NotReady。重要的是觀察運行在這個節(jié)點上的 Pod 會發(fā)生什么。由于 K8s 控制面檢測到節(jié)點不可用后會在默認(rèn)的pod-eviction-timeout默認(rèn) 5 分鐘后把該節(jié)點上的 Pod 標(biāo)記為 Terminating然后在其他可用節(jié)點上重新創(chuàng)建。這個過程就是集群故障轉(zhuǎn)移的經(jīng)典邏輯。在本地 mini 集群里親手制造一次“宕機(jī)”觀察 K8s 如何自動恢復(fù)業(yè)務(wù)這種體驗是看多少配置文檔和原理圖都替代不了的。4.4 給新手的 K8s 學(xué)習(xí)路線建議作為過來人我給剛接觸 K8s 的朋友一個清晰的學(xué)習(xí)路徑這條路徑是踩過很多坑之后總結(jié)出來的第一階段掌握核心命令和資源對象。kubectl get、describe、logs這些高頻命令要熟練Pod、Deployment、Service 這幾個最基礎(chǔ)的資源對象必須理解透徹。這個階段就用本地 mini 集群反復(fù)創(chuàng)建、修改、刪除把 yaml 文件的常見寫法刻在腦子里。第二階段理解 Pod 的高級機(jī)制。探針就緒探針、存活探針、生命周期鉤子、資源請求與限制、配置掛載ConfigMap、Secret這些內(nèi)容建議一個一個做實驗驗證。比如配置一個錯誤的存活探針觀察 K8s 如何重啟容器這種實驗在生產(chǎn)環(huán)境可不敢做但在本地集群想怎么折騰就怎么折騰。第三階段學(xué)習(xí) Controller 和存儲相關(guān)概念。Deployment、StatefulSet、DaemonSet、Job、CronJob以及 PV、PVC 持久化存儲對工作了之后實際使用幫助很大。第四階段學(xué)習(xí)網(wǎng)絡(luò)和治理能力。Service 的幾種類型、Ingress 的配置、部署一套 Ingress Controllerminikube 里直接minikube addons enable ingress就能開再跑一跑 Prometheus 監(jiān)控整套集群。這套路徑走下來基本可以應(yīng)付工作中大部分場景了。最重要的是別貪多一個概念驗證透了再進(jìn)入下一個。5. 遇到的坑與排查技巧實錄5.1 最常見報錯與解決辦法我把自己在 Windows 上搭建過程中遇到的和身邊同事問得最多的問題整理成一張速查表報錯/問題常見原因解決方法Exiting due to PROVIDER_DOCKER_NOT_RUNNINGDocker Desktop 未啟動先手動打開 Docker Desktop等右下角圖標(biāo)變穩(wěn)定后再執(zhí)行 startkubectl get nodes卡住或連接被拒絕集群未正常啟動、kubeconfig 未配置執(zhí)行minikube status檢查必要時minikube start重新初始化拉取鏡像超時或速度極慢網(wǎng)絡(luò)問題、未配置鏡像加速為 Docker 配置鏡像加速地址后重啟minikube 可使用--image-mirror-countrycn參數(shù)The connection to the server ... was refused集群已經(jīng)停止執(zhí)行minikube start恢復(fù)集群WSL2 內(nèi)存占用過高導(dǎo)致 Windows 卡頓WSL2 默認(rèn)使用 50% 內(nèi)存配置.wslconfig限制 memory端口沖突導(dǎo)致 Service 無法訪問本地端口被占用換一個 NodePort或者在 minikube 配置里指定固定端口范圍Error: No objects passed to applyyaml 文件語法錯誤或路徑不對用kubectl apply --dry-runclient -f xx.yaml預(yù)檢查部署的 Pod 顯示ImagePullBackOff鏡像不存在或倉庫認(rèn)證問題檢查鏡像名稱拼寫登錄docker login后再拉取印象最深的一個坑是 WSL2 的 DNS 解析問題。有一次集群能啟動但 Pod 內(nèi)部的apt-get update一直失敗排查了半天發(fā)現(xiàn)是 WSL2 的 DNS 配置問題。解決辦法是在 WSL2 的/etc/resolv.conf里檢查 DNS 設(shè)置或者修改/etc/wsl.conf來固定 DNS。這個問題比較隱蔽而且每臺機(jī)器的網(wǎng)絡(luò)環(huán)境不同表現(xiàn)也不一樣。遇到報錯時我的排查思路一般是這樣先看是不是環(huán)境層面的問題比如 Docker 是否運行、wsl狀態(tài)是否正常、磁盤空間是否足夠再看是不是網(wǎng)絡(luò)問題比如鏡像拉取超時、DNS 解析異常最后才看 K8s 本身的配置問題。大多數(shù) Windows 下搭集群的報錯根源都出在前兩層。5.2 鏡像拉取慢的解決思路這個問題太普遍了尤其是第一次啟動 minikube 的時候需要拉取kicbase鏡像這個鏡像體積很大網(wǎng)絡(luò)不行的時候能卡十分鐘以上。解決方案有幾個思路按優(yōu)先級排序第一個思路是配置鏡像加速地址。在 Docker Desktop 的 Settings - Docker Engine 配置 json 文件里加入registry-mirrors配置填入適合你網(wǎng)絡(luò)環(huán)境的加速地址保存后重啟 Docker。這種方式對 Docker Hub 官方倉庫的鏡像加速效果比較明顯。第二個思路是在 minikube 啟動時指定鏡像倉庫鏡像參數(shù)。比如minikube start --driverdocker --image-mirror-countrycn這條參數(shù)會自動切換為更適合國內(nèi)網(wǎng)絡(luò)環(huán)境的鏡像源啟動過程中的下載速度會快不少。第三個思路是提前手動拉取關(guān)鍵鏡像。如果啟動過程中反復(fù)失敗可以先手動執(zhí)行docker pull把比較大的幾個基礎(chǔ)鏡像拉到本地比如registry.cn-hangzhou.aliyuncs.com/...這類鏡像源然后再啟動 minikube它會優(yōu)先復(fù)用本地已存在的鏡像層。第四個思路是最終手段換個網(wǎng)絡(luò)環(huán)境或者時間段。這個聽起來有點玄學(xué)但確實有效。早上網(wǎng)絡(luò)高峰和深夜的拉取速度差距可能很大如果條件允許盡量挑網(wǎng)絡(luò)空閑時段操作。5.3 排查問題的通用套路最后分享一套排查 K8s 問題的通用套路不管是在本地 mini 集群還是生產(chǎn)環(huán)境都適用提出問題 - 縮小范圍 - 深入細(xì)節(jié) -驗證修復(fù)四步閉環(huán)。舉個例子如果 Service 訪問不通先別急著改一波配置。第一確認(rèn) Pod 本身是否 Readykubectl get pods -o wide如果 Pod 不是 Running 狀態(tài)用kubectl describe pod name看 Events。第二確認(rèn) Service 的 Endpoints 是否有數(shù)據(jù)kubectl get endpoints svc-name如果 Endpoints 為空說明 Service 的 selector 沒有匹配到任何 Pod這個是特別常見的問題。第三確認(rèn)網(wǎng)絡(luò)策略或者端口是否正常kubectl port-forward svc/svc-name 8080:80臨時把 Service 轉(zhuǎn)發(fā)到本機(jī)試一下。這套思路的精髓在于每次都只修改一個變量觀察結(jié)果避免一次性改了一堆配置卻不知道是哪個起效的。我在生產(chǎn)環(huán)境排查問題時也基本沿用這個思路只不過多加了日志和監(jiān)控數(shù)據(jù)的輔助。在 Windows 上調(diào)試還有一個特別實用的技巧在 WSL2 內(nèi)跑tcpdump抓包比在 Windows 上用 Wireshark 更輕量而且直接看 K8s 容器網(wǎng)絡(luò)的數(shù)據(jù)包會更直觀。配合kubectl exec進(jìn)入 Pod 內(nèi)部可以定位很多網(wǎng)絡(luò)層面的問題。5.4 磁盤空間清理與集群重置本地集群用久了之后磁盤占用是個很現(xiàn)實的問題。Docker 的鏡像、容器層、日志文件會越積越多尤其是頻繁實驗的情況下幾十 G 的空間很容易就被吃光了。這里提供幾個清理思路查看 Docker 磁盤占用docker system df一鍵清理無用的鏡像、容器和構(gòu)建緩存docker system prune -a --volumes清理完 Docker 之后如果覺得集群本身的環(huán)境也亂了直接刪掉重建比反復(fù)修復(fù)快得多。minikube 刪除集群minikube deletekind 刪除集群kind delete cluster --name test-cluster刪掉之后WSL2 的 vhdx 虛擬磁盤文件可能不會自動縮容。Windows 下可以用diskpart或者直接執(zhí)行wsl --shutdown Optimize-VHD -Path $env:LOCALAPPDATA\Packages\CanonicalGroupLimited.Ubuntu...\LocalState\ext4.vhdx -Mode Full如果你用的是 Docker Desktop 方案直接使用 Docker Desktop 的 Troubleshoot - Clean / Purge data 功能也能起到清理效果。這套“刪除重建、按需清理”的思路在本地環(huán)境特別推薦。K8s 的一大賣點就是基礎(chǔ)設(shè)施即代碼所有集群狀態(tài)都能通過 yaml 文件聲明出來那環(huán)境亂了就刪掉重建幾行命令的事情不要有心理負(fù)擔(dān)。最后再分享一點個人使用心得在 Windows 上堅持用本地 mini 集群做開發(fā)和測試一段時間之后我最深的體會是環(huán)境越貼近真實越能逼著你按生產(chǎn)標(biāo)準(zhǔn)來寫配置。以前我在開發(fā)環(huán)境隨便把配置寫死在鏡像里所有服務(wù)全部用默認(rèn)的 ClusterIP遇到問題全靠進(jìn)去敲命令。后來自從把整個本地開發(fā)環(huán)境都搬進(jìn) K8s 集群之后我開始認(rèn)真對待命名空間隔離、資源配額、健康檢查這些平時不太注意的細(xì)節(jié)因為這些配置在本地集群里是能直接觀察到效果的。還有一個小技巧是平時用來切換集群上下文的。當(dāng)你在本機(jī)同時用 minikube、kind、以及公司的遠(yuǎn)程集群時kubectl 的上下文切換很容易亂。我的做法是始終用kubectl config get-contexts確認(rèn)當(dāng)前操作的是哪個集群操作前先改成顯式的寫法kubectl config use-context minikube kubectl --contextminikube get pods第一次搭好環(huán)境之后建議你刻意在上面“折騰”幾天把 Deployment 的副本數(shù)隨便調(diào)一調(diào)、刪掉正在運行的 Pod 看它怎么復(fù)活、故意寫錯鏡像名看報錯信息長什么樣。這些操作看起來沒什么實際意義但會讓你在最短時間內(nèi)積累起對 K8s 的直覺。這種直覺等到了生產(chǎn)環(huán)境遇到系統(tǒng)故障的時候是真的能救命的。