Part 12 · Kubernetes · 12.1.04

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.

Mental model: scheduler quyết định đặt Pod ở đâu từ declarations + cluster state hiện tại; runtime/kernel quyết định Pod được tiêu thụ đến đâu sau khi placement hoàn tất. Scheduler không dự đoán chính xác future actual usage của ứng dụng.

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 declarationscluster 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ĩaVí dụ điều kiện
FilterLoại node không khả thi.Resources, node affinity/selector, taints/tolerations, topology, volume constraints.
ScoreXếp hạng các node đã qua Filter.Ưu tiên placement phù hợp với policy và phân bố workload.
Reserve / PermitGiữ state tạm và có thể cho phép, trì hoãn hoặc từ chối trước bind.Plugin-specific coordination.
BindGắn Pod vào node được chọn.Pod chuyển sang lifecycle startup trên node đó.
Failure window: một Pod Pending lâu không đồng nghĩa scheduler “hỏng”. Hãy đọc 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, BurstableBestEffort. 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.

SignalTriệu chứngĐiều cần quan sát
CPU saturation / throttlingLatency tăng, throughput giảmCPU usage, throttled time/periods, request/limit ratio
Memory pressure / OOMContainer restart, OOMKilledWorking set, RSS, restart reason, node MemoryPressure
Disk / ephemeral storageEviction, write failurenodefs/imagefs/containerfs capacity, inode pressure, log/temp growth
PID / FD exhaustionFork/open socket/file thất bạiPIDPressure, 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.

Anti-pattern: dùng taint+toleration rồi giả định đó là “dedicated placement”. Nếu cần workload phải chạy trên nhóm node cụ thể, thường phải kết hợp toleration với label + node affinity/selector phù hợp.

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.

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.

Checklist chẩn đoán: Pending? → xem events/eligible nodes. Running nhưng chậm? → xem throttling và downstream. Restart/OOM? → xem memory limit + node pressure. Evicted? → xem QoS và pressure signal. Replica lệch zone/node? → xem topology/affinity và capacity thực tế.

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 đó.

Tài liệu: Kube Scheduler · Scheduling Framework · Resource Management · Pod QoS · Node-pressure Eviction · Taints and Tolerations · Topology Spread Constraints · Local Ephemeral Storage · Kubernetes 1.37