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不設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 觸發的部署自動帶入 nodeSelector 與 toleration,否則每次部署都會覆蓋手動設定使隔離失效。
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 欄位)
相關概念¶
- Cluster Autoscaler Node Protection
- Docker K8s Init Script Permission Inheritance
- EKS Cluster Version Upgrade
- EKS Node Group Creation with eksctl
- EKS Node Group Migration Runbook
- Helm Annotation Special Character Escaping
- Valkey Serverless External Routing
來源 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 的行為差異 |