Scheduler, requests/limits và placement
Kube-scheduler chọn node dựa trên resource requests và các scheduling constraints; sau khi Pod đã chạy, kubelet/container runtime/kernel mới enforce các giới hạn tài nguyên. Vì vậy, “Pod có schedule được không?” và “Pod chạy ổn định không?” là hai bài toán liên quan nhưng khác nhau.
1. Scheduling
Khi một Pod chưa có spec.nodeName, kube-scheduler tìm node phù hợp rồi tạo quyết định binding. Nếu không có node nào thỏa điều kiện, Pod ở trạng thái Pending và các event thường chứa lý do unschedulable — ví dụ thiếu CPU/memory request capacity, không match affinity, không toleration được taint, hoặc volume/topology constraint không thỏa.
Điểm quan trọng là scheduler nhìn vào declarations và cluster state hiện tại, không nhìn vào “CPU mà Pod có thể sẽ dùng trong tương lai”. Vì vậy requests quá thấp có thể làm node bị overcommit; requests quá cao có thể làm Pod Pending dù usage thực tế thấp.
2. Scheduling cycle
Ở mức khái niệm, scheduler lọc node không phù hợp rồi chấm điểm các candidate còn lại. Scheduling Framework triển khai quy trình qua các extension point như Filter, Score, Reserve, Permit và Bind.
| Giai đoạn | Ý nghĩa | Ví dụ điều kiện |
|---|---|---|
| Filter | Loại node không khả thi. | Resources, node affinity/selector, taints/tolerations, topology, volume constraints. |
| Score | Xếp hạng các node đã qua Filter. | Ưu tiên placement phù hợp với policy và phân bố workload. |
| Reserve / Permit | Giữ state tạm và có thể cho phép, trì hoãn hoặc từ chối trước bind. | Plugin-specific coordination. |
| Bind | Gắn Pod vào node được chọn. | Pod chuyển sang lifecycle startup trên node đó. |
kubectl describe pod và events để phân biệt thiếu capacity, constraint mâu thuẫn, taint, volume binding hoặc admission/policy issue trước khi nới rule.3. Resources: requests và limits
CPU request tham gia scheduling và ảnh hưởng cách chia CPU khi node bị contention; nó cũng thường là input cho capacity planning và các autoscaling policy. CPU limit được enforce bằng throttling: container không bị kill chỉ vì dùng nhiều CPU, nhưng có thể tăng latency khi liên tục chạm limit.
Memory request được scheduler dùng để xác định node có đủ tài nguyên khai báo hay không. Memory limit được enforce theo kiểu reactive: khi vượt giới hạn và kernel phát hiện pressure/violation, process có thể bị OOM-kill; hành vi này khác CPU throttling.
Đơn vị phải đọc rất cẩn thận: 400m CPU nghĩa là 0.4 CPU. Với memory/storage, hậu tố m là milli-unit và có thể tạo giá trị cực nhỏ; hãy dùng các byte quantity như Mi/Gi khi đó mới là ý định. Nếu chỉ khai báo limit mà không có request, Kubernetes có thể dùng limit đó làm effective request khi không có admission-time default khác.
Ví dụ khai báo
resources:
requests:
cpu: "400m"
memory: "512Mi"
ephemeral-storage: "1Gi"
limits:
cpu: "1"
memory: "1Gi"
ephemeral-storage: "2Gi"
Local ephemeral-storage cũng có requests/limits riêng. Đây là phần thường bị bỏ quên khi container ghi nhiều log, cache hoặc temp file vào node-local storage.
4. QoS, eviction và resource pressure
Kubernetes phân Pod vào các lớp QoS Guaranteed, Burstable và BestEffort. QoS có ảnh hưởng đến eviction behavior khi node thiếu tài nguyên, nhưng QoS không thay thế application SLO: một Pod Guaranteed vẫn có thể timeout, deadlock, saturate downstream hoặc fail readiness.
Node pressure không chỉ là CPU/memory. Kubelet còn theo dõi các tín hiệu như disk/inode và PID pressure. Ngoài các biểu đồ CPU/memory quen thuộc, ứng dụng cũng có thể fail vì local ephemeral storage đầy, PID cạn hoặc process chạm file-descriptor limit của OS/runtime.
| Signal | Triệu chứng | Điều cần quan sát |
|---|---|---|
| CPU saturation / throttling | Latency tăng, throughput giảm | CPU usage, throttled time/periods, request/limit ratio |
| Memory pressure / OOM | Container restart, OOMKilled | Working set, RSS, restart reason, node MemoryPressure |
| Disk / ephemeral storage | Eviction, write failure | nodefs/imagefs/containerfs capacity, inode pressure, log/temp growth |
| PID / FD exhaustion | Fork/open socket/file thất bại | PIDPressure, process count, open-file limits |
5. Placement: selector, affinity, taints và topology
nodeSelector và node affinity dùng để chọn capability/locality phù hợp. Pod anti-affinity và topology spread constraints giúp phân tán replicas qua node/zone/failure domain để giảm correlated failure. Taints có tính chất repel; toleration chỉ cho phép Pod được xét trên node có taint tương ứng, không bắt buộc Pod phải chạy trên node đó.
Hard rule quá chặt có thể làm workload Pending khi capacity thiếu. Soft/preferred rule cho scheduler nhiều freedom hơn nhưng có thể làm giảm HA/locality khi cluster không đủ lựa chọn. Topology spread với DoNotSchedule thiên về giữ constraint; ScheduleAnyway thiên về availability bằng cách vẫn schedule nhưng ưu tiên giảm skew.
6. Capacity và operational signals
Capacity planning nên theo requests và failure domain, không chỉ nhìn average actual usage. Cần giữ headroom đủ để reschedule khi một node/AZ mất, rollout tạo surge, autoscaler chưa kịp phản ứng hoặc batch workload xuất hiện cùng lúc.
- Theo dõi tỷ lệ requested/allocatable CPU, memory và ephemeral storage theo node pool.
- Theo dõi số Pod Pending, tuổi Pending và unschedulable reason thay vì chỉ đếm tổng số Pod.
- Quan sát CPU throttling, OOM/restarts, eviction, DiskPressure/MemoryPressure/PIDPressure và skew giữa topology domains.
- Với HPA hoặc autoscaler khác, phân biệt metric dùng để scale với resource request dùng để scheduler/capacity tính placement.
7. Security và policy
Scheduling labels và taints là control input nên phải được quản trị như policy. Không nên để workload hoặc user không đáng tin tự do gắn label lên node hoặc thay taint vì điều đó có thể phá isolation intent. Với workload nhạy cảm, dùng node labels mà kubelet không thể tự sửa tùy ý, RBAC least privilege và admission policy để giới hạn các trường scheduling quan trọng.
Resource requests/limits cũng là một boundary vận hành: namespace quota và LimitRange giúp tránh một workload vô tình chiếm toàn cluster hoặc khai báo thiếu resource policy cần thiết.
8. Rollback và recovery khi placement policy gây sự cố
Nếu rollout mới làm Pods Pending, ưu tiên rollback constraint vừa thay đổi thay vì xóa ngẫu nhiên nhiều protection cùng lúc. So sánh manifest trước/sau, đọc events, xác định constraint nào loại hết node candidates rồi revert có kiểm soát.
- Capacity thiếu: scale/add node pool hoặc giảm request chỉ khi có evidence usage/SLO cho phép.
- Affinity/topology quá chặt: chuyển hard rule sang preferred hoặc mở rộng eligible topology nếu chấp nhận trade-off HA.
- Taint/toleration mismatch: sửa rule đúng ownership; không thêm wildcard toleration như “quick fix” lâu dài.
- Resource limit gây runtime failure: rollback limit/request change, sau đó right-size từ metrics và load test.
9. Version scope và tài liệu tham khảo
Nội dung nền tảng của bài giữ semantics từ source. Phần production bổ sung được đối chiếu với Kubernetes documentation hiện hành cho nhánh v1.37 (active release tại thời điểm migration). Những field/feature có trạng thái Alpha/Beta/GA có thể thay đổi giữa minor version; khi áp dụng vào cluster cũ hơn phải kiểm tra docs đúng version của cluster đó.