跳轉到

EKS NoExecute Taint Toleration Scheduling

概念概覽

EKS 節點隔離透過 Taint/Toleration + nodeSelector 雙機制實現,將特定工作負載綁定至專屬 Node Group(如 QA 環境)。核心約束是:擴充 node → label → Taint 三個動作必須連貫自動化執行;nodeSelector 與 toleration 必須同時設定缺一不可;所有隔離設定必須在 Infrastructure 層與 Application 層(含 CI/CD 腳本)兩個層次持久化。

核心知識

核心操作時序(不可違反)

擴充 node → label → Taint 三個動作必須**連貫自動化執行**,不能手動分開操作。中間有任何時間差,CA 就會偵測到低利用率 node 並提前縮減(第一次失敗的根因:ip-192-168-124-249 在 label 後未及時加 Taint 被 CA 刪除)。


Taint Effect 行為差異

Effect 阻止新 Pod 調度 驅逐已運行 Pod
NoSchedule
NoExecute

NoExecute 更嚴格:不只阻止新 Pod 調度,還會**立即驅逐**未宣告 toleration 的既有 Pod。適合強隔離場景,但代價是所有需要留在該 node 的 Pod 都必須宣告 toleration,否則會被驅逐。


nodeSelector + toleration 缺一不可

僅設其中一項會造成 Pod 無法調度,錯誤訊息同時出現兩種原因:

0/3 nodes are available:
  1 node(s) had untolerated taint(s)
  2 node(s) didn't match Pod's node affinity/selector

正確設定必須同時包含兩者:

nodeSelector:
  site: qa-test
tolerations:
- key: "site"
  value: "qa-test"
  effect: "NoExecute"
  • 只設 nodeSelector 不設 toleration → 無法調度到有 taint 的節點
  • 只設 toleration 不設 nodeSelector → Pod 可能調度到非 QA 專屬節點

遷移方式:nodeSelector patch

kubectl patch deployment -n ps <name> \
  -p '{"spec":{"template":{"spec":{"nodeSelector":{"site":"qa-test"}}}}}'

nodeSelector 是最簡單的遷移手段——patch 後 rolling update 自動觸發,新 pod 調度至目標 node,舊 pod 依序終止。


Key 一致性要求

Node label key、nodeSelector key、PDB selector key 三者必須完全一致(例如統一用 site=qa-test)。不一致會讓 PDB Current 欄位顯示 0,PDB 形同虛設。


PDB YAML 格式

PDB 必須存為**獨立 YAML 檔**再 apply,不可用 heredoc——heredoc 模式容易因 tab/space 混用導致 YAML 解析失敗。


CI/CD 持久化

手動 patch nodeSelector 只是一次性操作。必須同步更新 DeployServer.groovy,確保後續 CI/CD 觸發的部署自動帶入 nodeSelectortoleration,否則每次部署都會覆蓋手動設定使隔離失效。

Groovy Pipeline 中若 nodeSelector 被 comment 掉,補回時須同時補回 tolerations 區塊,兩者同一區塊管理。


實際除錯要點

  • kubectl describe node <node-name> 確認 Taints 欄位的 effect 是 NoSchedule 還是 NoExecute
  • 新增 Node Group 後,首次部署前先執行 helm template 渲染並 grep tolerations 確認
  • kubectl describe pdb 驗證 Current 欄位 > 0,確認 PDB selector 正確命中 pod

經驗教訓

  • 擴充 node → label → Taint 必須自動化連貫執行,手動操作的時間差會讓 CA 搶先縮減新 node

  • nodeSelector 比 NodeAffinity 語法更簡單,適合快速 patch 遷移場景

  • PDB selector key 必須與 node label key 完全一致,否則 Current=0 等於沒有保護

  • Node 隔離設計必須在 Infrastructure 層(label/taint)和 Application 層(deployment spec + CI/CD 腳本)兩個層次同時持久化

  • Windows 環境建立的 shell script 含 \r\n,腳本建立時需自動執行 sed -i 's/\r$//' 清除

  • nodeSelector 與 toleration 必須同時設定,缺一會導致 Pod Pending,且錯誤訊息同時夾雜兩種原因不易辨識

  • NoExecute taint 會驅逐已運行 Pod,適合強隔離但代價是所有 Pod 都必須宣告 toleration

  • 建立新 Node Group 後,首次部署前先 helm template 渲染並 grep tolerations 確認 toleration 是否齊全

常見陷阱

  • 第一次失敗:擴充 node 後未立即加 Taint,CA 在 Taint 設定前已縮減該 node

  • heredoc 方式寫 PDB 容易 tab/space 混用導致 YAML 解析失敗

  • CI/CD 腳本未同步更新,下次部署覆蓋 nodeSelector 使隔離完全失效

  • eksctl update nodegroup 在 v0.209.0 不支援 --cluster 旗標,擴充節點必須用 eksctl scale nodegroup

  • 僅設 nodeSelector 而忘記 toleration,Pod 會卡在 Pending 且錯誤訊息同時出現「untolerated taint」與「node affinity/selector」兩種原因,容易誤判

  • Pipeline 中因人工 comment 掉 nodeSelector 後補 toleration 時容易遺漏,兩者須視為不可分離的一組設定

最佳實踐

  • 四支腳本分工:check_qa_test_status.sh(診斷)、setup_qa_test_node.sh(建立)、migrate_qa_test_pods.sh(遷移)、final_verification.sh(驗證)

  • 操作腳本統一放置於 base_helm/AWS_EKS/ 目錄

  • 用 kubectl describe pdb 驗證 Current 欄位 > 0,確認 PDB selector 正確命中 pod

  • 不要調整 Node Group minSize 保護 qa node,讓 CA 自由伸縮,靠 safe-to-evict + PDB 阻擋

  • nodeSelector 與 toleration 同一區塊管理,避免分散後人工 comment 或修改時遺漏其中一個

  • 新增 dedicated Node Group 後加 smoke test job 驗證 Pod 確實落在正確節點(kubectl get pod -o wide 確認 NODE 欄位)

相關概念

來源 Sessions

日期 Session 貢獻摘要

| 2026-03-24 | 6faf05ec-5823-4354-9fcd-f9c48bb322ca | 記錄了為 QA 環境建立 Node 隔離的完整兩次實作,包含第一次因時序問題被 CA 刪除的失敗教訓與修正方案。 |

| 2026-04-08 | 4704b57e-d74e-48ab-811d-8bf398552c49 | 確認 NoExecute taint 下 Pod 必須同時具備 nodeSelector + toleration 的調度條件,以及 NoExecute 與 NoSchedule 的行為差異 |


本概念頁面由 Semi-Brain Wiki 系統自動維護

最後更新: 2026-04-08