解密:READY與STATUS列的計算邏輯與排障實戰(zhàn))
剛接手 Kubernetes 那陣我對kubectl get pod的輸出基本是無條件信任的STATUS 是 RunningREADY 是 1/1就覺得這 Pod 穩(wěn)了。直到有一次線上事故所有 Pod 看起來全是 Running 1/1結(jié)果業(yè)務(wù)錯誤率猛漲最后定位到根因是進程活著但業(yè)務(wù)線程池已經(jīng)掛了而那個服務(wù)壓根沒配就緒探針。從那時候起我開始較真kubectl get pod里的 READY 和 STATUS 這兩列到底是從哪來的先說結(jié)論它們都不是 API Server 里某個現(xiàn)成字段的直接透傳而是 kubectl 客戶端把 Pod 對象里一堆狀態(tài)字段匯總之后按照一定優(yōu)先級當場算出來的展示值。這篇文章我?guī)惆堰@套計算邏輯徹底拆開——分別看它們讀的是哪些底層字段、STATUS 列各種顯示值背后的決策樹是什么、以及怎么利用這套機制把排障效率提上去。適合所有被0/1、CrashLoopBackOff、ContainerCreating折磨過的 K8s 使用者和運維同學(xué)。1. 先把 kubectl get pod 的輸出和底層數(shù)據(jù)對上號kubectl get pod默認展示的列是 NAME、READY、STATUS、RESTARTS、AGE。加-o wide之后會多出 IP、NODE、NOMINATED NODE、READINESS GATES 這幾列。但不管顯示幾列它們的源頭都是同一個東西API Server 返回的 Pod 對象 JSON。想看到完整的原始數(shù)據(jù)最直接的方式是kubectl get pod pod-name -o json這段 JSON 里包含一個龐大的status結(jié)構(gòu)。我們只挑和本文相關(guān)的字段列出來JSON 字段含義影響哪一列metadata.deletionTimestampPod 被標記刪除的時間戳STATUSTerminatingmetadata.deletionGracePeriodSeconds優(yōu)雅刪除寬限期STATUSTerminatingstatus.phasePod 生命周期的大階段STATUS基礎(chǔ)值Pending/Running/Failed 等status.reason節(jié)點或控制器上報的具體原因STATUS如 Evicted、NodeLoststatus.conditions[]Pod 級別的條件集合包括 Ready、ContainersReady、Initialized、PodScheduled與 READY 列間接相關(guān)status.containerStatuses[]每個業(yè)務(wù)容器的詳細狀態(tài)state、ready、restartCount、lastStateREADY 列、STATUS 列status.initContainerStatuses[]每個初始化容器的詳細狀態(tài)READY 列初始化期間、STATUS 列Init 相關(guān)這里面最關(guān)鍵的一個認知是kubectl get 顯示的是客戶端渲染出來的視圖不是服務(wù)端存了一個顯示用字段。你進 etcd 里翻 Pod 對象找不到一個叫 STATUS 列 的東西能找到的只有上面這些結(jié)構(gòu)化字段。換句話說kubectl get pod的打印邏輯本質(zhì)上是把 Pod 狀態(tài)翻譯成人話的過程。kubectl 的這套打印邏輯對應(yīng)源碼里的staging/src/k8s.io/kubectl/pkg/printers/internalversion/printers.go核心函數(shù)是printPod。接下來我按 READY 和 STATUS 兩條線分別拆。2. READY 列容器就緒狀態(tài)的聚合統(tǒng)計READY 列的格式是X/Y比如1/1、0/2。很多人以為它表示Pod 里有多少容器在運行其實不準確它統(tǒng)計的是容器的 Ready 字段也就是就緒狀態(tài)和進程是否活著是兩個維度。2.1 X 和 Y 分別是怎么算出來的Y 的分母很簡單spec.containers數(shù)組的長度也就是普通業(yè)務(wù)容器的數(shù)量。注意Init 容器不算在內(nèi)這個后面細說。X 的算法大概是這樣的readyContainers : 0 for _, cs : range pod.Status.ContainerStatuses { if cs.Ready { readyContainers } } totalContainers : len(pod.Spec.Containers) // 如果 Pod 還在初始化階段READY 列固定顯示 0/N所以1/1表示Pod 里定義了 1 個業(yè)務(wù)容器且這個容器的ContainerStatuses[*].Ready為 true。這里有個容易踩的坑Pod 在初始化的過程中即使業(yè)務(wù)容器已經(jīng)創(chuàng)建了READY 也會顯示0/N。因為初始化階段有個硬邏輯——只要 Init 容器還沒全部跑完kubectl 就不去統(tǒng)計普通容器的就緒數(shù)直接輸出0/業(yè)務(wù)容器總數(shù)。所以看到0/2別急著下結(jié)論先看 STATUS 列是不是Init:1/2或者PodInitializing。2.2 容器 Ready 到底由誰決定一個容器的 Ready 屬性由 kubelet 維護具體判斷方式取決于你有沒有配探針沒配任何探針容器啟動進入 Running 狀態(tài)后kubelet 會很快把 Ready 置為 true。進程活著就等于就緒。配了 readinessProbe就緒探針容器進程活著還不夠必須探針連續(xù)成功一次Ready 才會變 true。探針一旦失敗Ready 立刻變 false。配了 startupProbe啟動探針容器啟動后先跑 startupProbe成功之前 readinessProbe 根本不生效Ready 保持 false。這就解釋了最常見的詭異現(xiàn)象STATUS 是 RunningREADY 卻是 0/1。容器確實在跑但 readinessProbe 一直失敗kubelet 只負責(zé)執(zhí)行探針并同步 Ready 狀態(tài)并不會因為你業(yè)務(wù)沒就緒就把 STATUS 改成別的。所以 READY 列本質(zhì)上是一個業(yè)務(wù)是否被判定為可服務(wù)的開關(guān)聚合而不是進程是否存活的聚合。真正決定這個開關(guān)的是 Kubelet 的探針機制這也是為什么很多正式環(huán)境強制要求核心服務(wù)必須配 readinessProbe 的原因——沒有探針一個依賴下游超時的服務(wù)依然會對外顯示 1/1但請求進來全掛在等待上。2.3 readinessGatesPod 級別的另類就緒門控除了容器自身的 ReadyPod 還可以通過spec.readinessGates聲明額外的就緒條件。比如spec: readinessGates: - conditionType: example.com/healthy如果聲明了這個 gatePod 的 Ready condition 必須同時滿足所有容器 Ready和所有 gate 對應(yīng)的 condition 為 True才能算 Pod 就緒。這個機制常被用來讓自定義控制器參與就緒判定比如某些網(wǎng)絡(luò)組件會在 CNI 配置沒就緒時寫一個 False 的 condition。不過要注意一個細節(jié)readinessGates 影響的是 Pod 的 Ready condition不一定直接影響 READY 列的數(shù)字。因為 READY 列統(tǒng)計的是容器級containerStatuses[*].Ready而不是 Pod 級 Ready 條件。你可能會看到 READY 1/1 但 Pod Ready condition 是 False 的情況此時這個 Pod 依然不會進 Service 的 Endpoints。這種顯示正常但實際不服務(wù)的場景排查時很容易被忽略。2.4 restarts 對 READY 的短暫影響容器重啟期間舊容器被終止、新容器在創(chuàng)建新容器的 Ready 會短暫為 false。所以 CrashLoopBackOff 里 Pod 的 READY 長期是 0/1一旦某個周期內(nèi)容器能撐夠時間READY 會短暫跳到 1/1然后又掉回 0/1。這個變化用kubectl get pod -w看得非常清楚。3. STATUS 列一套客戶端決策樹算出來的印象分STATUS 列是所有 K8s 新手最先看的列也是誤解最多的列。先說個讓人意外的事實STATUS 顯示什么并不是 API Server 告訴 kubectl 的而是 kubectl 自己根據(jù) Pod 的一堆字段按優(yōu)先級現(xiàn)場決策的。3.1 printPod 的決策優(yōu)先級把printPod的邏輯簡化成一個決策樹大概是這樣的1. 如果滿足刪除中條件 - Terminating節(jié)點失聯(lián)場景可能顯示 Unknown而不是 Terminating 2. 如果 Init 容器還沒全部成功退出 - 某個 init 容器失敗Init:Error / Init:ExitCode:x / Init:Signal:x - 某個 init 容器正在運行Init:N/MN已成功退出數(shù)M總數(shù) - 某個 init 容器在等待PodInitializing 3. 上面都不滿足時遍歷普通容器但只看第一個容器 - 如果它處于 Waiting 且 reason 非空用這個 reason 當作 STATUS 比如 ContainerCreating、CrashLoopBackOff、ErrImagePull - 如果它處于 Terminated 且 reason 非空用這個 reason 當作 STATUS 比如 Completed、Error、OOMKilled 4. 如果上面都沒拿到有意義的 reason退回 Pod.Status.Reason再退回 Pod.Status.Phase - phase Succeeded - Completed - phase Failed - Error - phase Running - Running - phase Pending - Pending這個順序里最容易被忽略的兩點STATUS 列只看第一個普通容器。如果 Pod 里有多個容器第二個、第三個容器即使 CrashLoopBackOff只要第一個容器在 RunningSTATUS 依然可能是 Running。這種多容器 Pod 的狀態(tài)顯示盲區(qū)是排障時最坑的細節(jié)。容器處于 Running 但 readiness 失敗時STATUS 不會顯示 NotReady。kubectl 沒有為readiness 失敗單獨設(shè)計一種顯示值所以 Running 0/1 是同時出現(xiàn)的。很多人看到 Running 就覺得 OK其實問題就藏在這里。3.2 各種 STATUS 顯示值到底對應(yīng)什么底層狀態(tài)我整理了一張速查表基本覆蓋日常最常見的 STATUS 值STATUS 顯示底層狀態(tài)常見誘因PendingphasePending沒有其他 reason 覆蓋調(diào)度失敗、資源不足、等待存儲ContainerCreating第一個容器 Waiting reasonContainerCreating鏡像拉取、sandbox 創(chuàng)建、CNI 配置ErrImagePull容器 Waiting reasonErrImagePull鏡像不存在、倉庫認證失敗、地址錯誤ImagePullBackOff容器 Waiting reasonImagePullBackOff鏡像拉取連續(xù)失敗后的退避階段CrashLoopBackOff容器 Waiting reasonCrashLoopBackOff容器啟動后反復(fù)崩潰kubelet 退避重啟Running第一個容器處于 Running 狀態(tài)正?;蛘咛结樜磁渲?探針失敗但容器存活Completed容器 Terminated reasonCompleted 且 phaseSucceededJob 正常結(jié)束Error容器 Terminated reasonError或 phaseFailed啟動腳本出錯、探針失敗導(dǎo)致重啟等OOMKilled容器 Terminated reasonOOMKilled內(nèi)存超過 cgroup 限制被內(nèi)核殺掉TerminatingdeletionTimestamp 已設(shè)置執(zhí)行了 delete等待優(yōu)雅退出或卡刪除Unknown節(jié)點失聯(lián)且 Pod 設(shè)置了 NodeLost 相關(guān) reasonkubelet 長時間不上報狀態(tài)Evictedstatus.reasonEvicted節(jié)點資源壓力驅(qū)逐這個表里的值不是隨便拍的它們要么直接來自containerStatuses[*].state.waiting.reason要么來自state.terminated.reason要么來自status.reason/status.phase。所以你會發(fā)現(xiàn)STATUS 列其實是一個第一個異常狀態(tài)的快速入口——它的設(shè)計目標是讓你一眼看出最值得關(guān)注的容器問題而不是告訴你整個 Pod 的健康全貌。3.3 一個補充STATUSRunning 但 READY0/1 的官方解釋回到開頭那個現(xiàn)象。容器狀態(tài)機里有一個獨立的維度叫State分為 Waiting、Running、Terminated 三態(tài)。readiness 是另一個獨立的布爾維度。kubectl 在渲染 STATUS 列時看的是 State 相關(guān)字段在渲染 READY 列時看的是 Ready 布爾值。兩邊各行其是所以會出現(xiàn)容器 StateRunningReadyfalse - STATUSRunningREADY0/1容器 StateWaiting(reasonCrashLoopBackOff)Readyfalse - STATUSCrashLoopBackOffREADY0/1理解了這個兩套維度各算各的設(shè)計很多所謂的詭異顯示就都能解釋通了。比如容器剛被 OOM 殺掉State 變成 Terminated reasonOOMKilled但 kubelet 正在重啟它STATUS 可能短時間閃過 OOMKilled 然后變成 CrashLoopBackOff。4. 三層狀態(tài)模型phase、conditions、containerState 的關(guān)系如果你覺得上一節(jié)的決策樹有點繞那可能是因為還沒建立 Pod 狀態(tài)的整體模型。我習(xí)慣把 Pod 狀態(tài)拆成三層來看排障時一層一層剝。4.1 第一層Pod Phase階段status.phase是 Pod 生命周期最粗粒度的描述只有五個值PendingPod 已被 API Server 接受但還沒有完成調(diào)度或者某些容器還沒啟動。RunningPod 已綁定節(jié)點所有容器已被創(chuàng)建且至少有一個容器在運行或正在啟動。Succeeded所有容器都以退出碼 0 正常結(jié)束且不會被重啟。Failed所有容器都已終止至少有一個容器以非 0 退出碼結(jié)束。UnknownAPI Server 長時間無法從 kubelet 獲取 Pod 狀態(tài)一般是節(jié)點失聯(lián)。Phase 是一個控制面視角的粗分類你不會從這里知道鏡像拉到了沒有探針過了沒有它太粗了。4.2 第二層Pod Conditions條件status.conditions是一組更細的布爾條件標準的有四個PodScheduledPod 是否已成功調(diào)度到節(jié)點。Initialized所有 Init 容器是否已執(zhí)行完成。ContainersReady所有業(yè)務(wù)容器是否都 Ready。Ready整個 Pod 是否就緒等價于 ContainersReady 且所有 readinessGates 滿足。每個 condition 都有statusTrue/False/Unknown、reason和message。查看方式kubectl get pod pod-name -o jsonpath{.status.conditions[*].type}{.status.conditions[*].status}{\n}或者看 YAMLkubectl get pod pod-name -o yaml | grep -A 12 conditions如果你的 Pod 被寫入了自定義 condition比如某些控制器會寫example.com/healthy那它也會出現(xiàn)在這個數(shù)組里。Pod 的 Ready condition 是控制器、Service Endpoints 是否收錄該 Pod 的依據(jù)之一。4.3 第三層Container State容器狀態(tài)容器層狀態(tài)是排障時信息量最大的一層。每個容器在status.containerStatuses[]里都有一個state字段三選一state : { waiting: { reason, message } running: { startedAt } terminated: { exitCode, reason, signal, startedAt, finishedAt } }值得專門做一張 reason 速查表state 字段的 reason含義ContainerCreatingkubelet 正在創(chuàng)建容器可能卡在 sandbox 或卷掛載CrashLoopBackOff容器啟動后崩潰kubelet 正在退避等待下一次重啟ErrImagePull首次拉取鏡像失敗ImagePullBackOff鏡像拉取連續(xù)失敗進入退避CreateContainerConfigError容器配置有問題比如 ConfigMap/Secret 不存在StartError容器運行時啟動失敗OOMKilled容器因超限被殺Completed容器正常退出退出碼 0Error容器異常退出除此之外lastState字段很有價值。它記錄的是容器上一次的狀態(tài)快照。當容器處于 CrashLoopBackOff 時當前 state 多半是 waiting但上一次的 terminated 信息里能看到 exitCode 和 OOMKilled 標志這是定位崩潰根因的鑰匙。kubectl get pod pod-name -o json | jq .status.containerStatuses[0].lastState三層之間是遞進關(guān)系容器 State 決定容器的 Ready 和 Phase 的走向容器 Ready 聚合出 ContainersReadyContainersReady 加上 readinessGates 得出 Pod Ready。所以當你看到 STATUS 列異常時往下一層找容器 State 的 reason往往比盯住 STATUS 文案更高效。5. 從這兩列出發(fā)的實戰(zhàn)排障鏈路知道數(shù)據(jù)來源之后排障思路就清晰了。下面按最常見的 5 個狀態(tài)場景給出一步步的排查命令鏈。5.1 STATUS 是 ContainerCreatingREADY 是 0/1先看完整事件別急著看日志kubectl describe pod pod-name | tail -30 kubectl get pod pod-name -o json | jq .status.containerStatuses[0].state.waiting kubectl get events --sort-by.lastTimestamp | tail -30這個狀態(tài)最常見的兩個原因創(chuàng)建 sandbox 失敗事件里會看到類似failed to create pod sandbox: rpc error: code unknown desc failed to create...的信息。這種一般是容器運行時或 CNI 網(wǎng)絡(luò)插件的問題需要上節(jié)點看 containerd 日志。鏡像拉取慢或被限流事件里會有Failed to pull image ...或exceeded retry limit, last status: 429 too many requests之類。429 這類限流在鏡像倉庫層很常見排查時留意 registry mirror、拉取憑證是否配置。5.2 STATUS 是 CrashLoopBackOffREADY 是 0/1這個狀態(tài)說明容器已經(jīng)啟動過但反復(fù)崩潰kubelet 進入退避。核心動作是看兩樣?xùn)|西# 看上一次退出時的日志 kubectl logs pod-name --previous # 看終止時的退出碼和 reason kubectl get pod pod-name -o json | jq .status.containerStatuses[0].lastState.terminated退出碼很能說明問題127啟動命令或依賴找不到檢查 image 里的可執(zhí)行文件路徑。137SIGKILL通常是 OOMKilled或者被系統(tǒng) cgroup 殺掉的信號檢查內(nèi)存 limit 和實際占用。143SIGTERM常見于探針失敗觸發(fā) kill或者業(yè)務(wù)收到終止信號后沒正常退出。退出碼是 0 但仍在重啟大概率是 livenessProbe 失敗kubelet 認為容器不健康主動重啟。這時候要去看探針配置kubectl get pod pod-name -o json | jq .spec.containers[0].livenessProbe5.3 STATUS 是 Running但 READY 是 0/1這就是我們前面講的假健康狀態(tài)。第一件事確認是不是探針問題# 查看就緒探針配置 kubectl get pod pod-name -o json | jq .spec.containers[0].readinessProbe # 查看容器就緒條件 kubectl get pod pod-name -o json | jq .status.conditions[] | select(.typeReady) # 手動模擬探針請求按你探針配置的協(xié)議來 kubectl exec -it pod-name -- curl -sf http://127.0.0.1:8080/healthz如果探針地址確實不通那是應(yīng)用沒就緒去查應(yīng)用日志。如果應(yīng)用地址通但 READY 還是 0/1檢查一下探針的initialDelaySeconds和periodSeconds是否設(shè)置合理以及探針是否寫錯了端口或路徑。另一個可能被忽略的情況是 readinessGates如果 Pod 里定義了 gate但對應(yīng)的 condition 一直沒被外部控制器置為 True那 Pod Ready 也是 False。這時候去查kubectl get pod pod-name -o json | jq .spec.readinessGates kubectl get pod pod-name -o json | jq .status.conditions[]5.4 STATUS 是 Terminating一直在刪除中Pod 設(shè)置了 deletionTimestamp但遲遲沒消失。先用一條命令看清全貌kubectl get pod pod-name -o json | jq {finalizers: .metadata.finalizers, deletionTimestamp: .metadata.deletionTimestamp, grace: .metadata.deletionGracePeriodSeconds, phase: .status.phase}常見的卡刪除原因容器主進程不響應(yīng) SIGTERM超過 grace 期只能等 SIGKILL但 SIGKILL 后還卡住一般是容器運行時問題。有 finalizer 掛在 metadata 上需要對應(yīng)的控制器清理完成后才會移除。底層卷還沒完成 detach或者節(jié)點失聯(lián)導(dǎo)致狀態(tài)更新停滯。如果業(yè)務(wù)可以允許強刪再考慮兜底命令kubectl delete pod pod-name --grace-period0 --force但要清楚強刪可能造成容器進程殘留、卷鎖不釋放等后遺癥生產(chǎn)環(huán)境慎用。更穩(wěn)妥的方式是先查 finalizer 歸屬等對應(yīng) controller 清理或者先把節(jié)點的問題處理掉。5.5 STATUS 是 Pending一直沒有 RunningPending 最常見的是調(diào)度階段就出問題。重點看調(diào)度事件kubectl describe pod pod-name | grep -A 20 Events kubectl get events --field-selector involvedObject.namepod-name --sort-by.lastTimestamp如果事件里持續(xù)刷FailedScheduling跟著 message 走常見的幾類Insufficient cpu/memory節(jié)點資源不夠擴容或減小 request。node(s) had taint節(jié)點有污點Pod 沒有對應(yīng)容忍。didnt match node selector / affinity rules調(diào)度約束無法滿足。如果調(diào)度已經(jīng)成功Pod 卻還停在 Pending那說明問題轉(zhuǎn)移到卷掛載或容器創(chuàng)建階段。這時再去翻 containerStatuses 的 message看是不是FailedMount之類的問題。5.6 用 custom-columns 直接拿原始狀態(tài)排障時如果不想被 STATUS 列的展示值誤導(dǎo)可以繞過它直接輸出原始字段kubectl get pods -o custom-columns\ NAME:.metadata.name,\ PHASE:.status.phase,\ POD_READY:.status.conditions[?(.typeReady)].status,\ CONTAINER_READY:.status.containerStatuses[*].ready,\ WAIT_REASON:.status.containerStatuses[*].state.waiting.reason,\ RESTARTS:.status.containerStatuses[*].restartCount,\ DELETION:.metadata.deletionTimestamp這能讓你同時看到容器級 Ready 數(shù)組、Pod 級 Ready 條件、等待 reason 和刪除時間戳多容器 Pod 的狀態(tài)盲區(qū)也一覽無余。6. 平時最容易忽略的細節(jié)和我的實操建議最后聊幾個分散在細節(jié)里的經(jīng)驗都是我在實際維護中踩過或見過別人踩的。多容器 Pod 的 STATUS 列盲區(qū)前面提過值得再強調(diào)一次kubectl 在選代表容器時只挑第一個普通容器排在后面的容器就算炸了STATUS 也可能紋絲不動。所以凡是多容器 Pod我習(xí)慣直接-o json配合 jq 看全量容器狀態(tài)或者用custom-columns把所有容器的 reason 都打出來。肉眼盯著 STATUS 單列是真的會看漏。RESTARTS 列和 READY 列的關(guān)系也要理解。RESTARTS 是所有containerStatuses[*].restartCount的累加值。容器被 OOM 殺掉后重啟RESTARTS 會 1如果后端是 sandbox 或網(wǎng)絡(luò)重建可能連累 Init 容器也計一次重啟。所以看到 RESTARTS 很高別只想到業(yè)務(wù)崩潰也要看是不是基礎(chǔ)設(shè)施層在不斷重建。初始化階段 READY 恒為 0/N 這種行為偶爾會引發(fā)誤判。尤其是 Init 容器比較多、單個 Init 執(zhí)行很慢的 Pod你可能會看到 STATUS 一直是Init:2/5READY 一直是0/1持續(xù)十幾分鐘。這時候別急著重啟或強刪先看 Init 容器日志kubectl logs pod-name -c init-container-nameSTATUS 列顯示 Unknown 的時候絕大多數(shù)情況是節(jié)點失聯(lián)而不是 Pod 本身出問題。先去看節(jié)點狀態(tài)kubectl get node kubectl get node node-name -o json | jq .status.conditions[] | select(.typeReady)節(jié)點 NotReady 會連帶一堆 Pod 顯示 Unknown 或 Terminating這時候先恢復(fù)節(jié)點再處理 Pod 狀態(tài)。版本差異也要留個心眼。不同 Kubernetes 小版本之間kubectl 的打印邏輯偶爾會有細微調(diào)整比如原生 sidecar 容器K8s 1.28的 RESTARTS 統(tǒng)計方式、初始化階段 READY 的分母算法都隨版本演進改過。遇到和文檔描述不一致的輸出優(yōu)先看當前 kubectl 對應(yīng)版本的源碼而不是懷疑自己的集群壞了。還有一個老生常談但我必須再提一次的建議不要把 STATUS 和 READY 這兩列當成業(yè)務(wù)健康度的最終答案。它們的設(shè)計目標是快速概覽不是健康證明。真正判斷服務(wù)能不能接流量的指標應(yīng)該是Pod 的 Ready condition 是否為 TruePod 是否出現(xiàn)在 Service 的 Endpoints 列表里應(yīng)用自身的健康檢查接口、錯誤率、延遲是否正常。如果你有監(jiān)控系統(tǒng)我建議直接把kube-state-metrics暴露的kube_pod_status_ready、kube_pod_container_status_ready這些指標接入告警比每天對著終端刷kubectl get pod靠譜得多。這兩年排查 Kubernetes 問題下來我最大的體會是狀態(tài)列是給人快速瀏覽用的但每個奇怪的顯示背后都有一套非常機械的計算邏輯。搞清楚kubectl get pod里 READY 和 STATUS 的每一層來源之后很多玄學(xué)其實都是可預(yù)測、可復(fù)現(xiàn)的。遇到問題別盯著狀態(tài)文案猜拉著原始字段看——-o json加 jq基本能回答你 80% 的疑問。