SSD Nodes Learn Hosting plans →
Hướng dẫn Matt ConnorBởi Matt Connor · Cập nhật ngày 2026-08-23

CPU steal time trên VPS: nhận biết noisy neighbour

Hiểu CPU steal time, đọc cột st trong vmstat và phân biệt noisy neighbour với VPS quá tải của bạn bằng chỉ số scheduler ở hypervisor.

Verified Every command ran end-to-end on a fresh Ubuntu 24.04 server, August 7, 2026.

CPU steal time thực sự đo gì

CPU steal time là tỷ lệ thời gian vCPU của bạn đã sẵn sàng chạy, không phải chờ tài nguyên nào, nhưng hypervisor lại cấp core vật lý cho một guest khác. Công việc đã được đưa vào hàng đợi. Core đang được dùng ở nơi khác. Linux đếm riêng các chu kỳ này và báo cáo chúng dưới dạng st. Đây là cách phân biệt “server của tôi đang bận” với “server của tôi đang chờ đến lượt”.

Đó là lý do counter này tồn tại. Thời gian các process của bạn chạy trên CPU được báo cáo dưới dạng us (user) hoặc sy (system). Thời gian một task bị block khi chờ storage được báo cáo dưới dạng wa (I/O wait). Một vCPU (virtual CPU) có thể chạy, đang nằm trong run queue, không có I/O nào đang chờ xử lý, nhưng vẫn chưa được thực thi, được báo cáo dưới dạng st. Không thành phần nào bên trong server có thể xóa trạng thái này, vì quyết định scheduling được đưa ra ở tầng thấp hơn bạn, trên host.

Điều này bắt nguồn trực tiếp từ cách một VPS chia sẻ một máy vật lý giữa nhiều guest. Nguyên nhân thường gặp là một guest lân cận: guest khác trên cùng node đang dùng CPU cao, nên host phải chia các core cho bạn. Có một nguyên nhân thứ hai thường bị bỏ qua. Nhiều provider giới hạn shared vCPU ở một phần của core vật lý, và trên một số hypervisor, giới hạn này được áp dụng rồi tính là steal bên trong guest. Vì vậy, giá trị st cao cho biết core không được cấp cho bạn. Nó không phải lúc nào cũng cho biết ai đã lấy core đó.

Nguồn gốc của chỉ số steal

Kernel không thể tự đo steal vì không nhìn thấy host. Hypervisor cung cấp chỉ số này. Trên KVM, host ghi một counter riêng cho từng vCPU vào một page được chia sẻ với guest. Guest cộng các giá trị này khi kernel được build với CONFIG_PARAVIRT_TIME_ACCOUNTING, như mọi kernel của các distribution. Xen báo cùng thông tin qua vùng runstate. Tổng giá trị đi vào userspace tại đúng một nơi:

head -1 /proc/stat

Dòng cpu chứa 10 counter, tính theo tick USER_HZ từ lúc boot, theo thứ tự: user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice. Steal là giá trị thứ 8 sau nhãn. Mọi tool bên dưới, vmstat, top, mpstat và mọi Prometheus exporter đều đọc cùng field này rồi chuyển 2 sample thành phần trăm.

Một hệ quả quan trọng hơn các điểm còn lại: nếu hypervisor không export counter, field này sẽ giữ giá trị 0 mãi mãi. Khi đó mọi tool dựa trên nó đều báo 0.0 bình thường, dù host đang quá tải. KVM và Xen có export counter này. Guest trên VMware và Hyper-V thường luôn báo 0. Hãy kiểm tra platform trước khi tin vào giá trị 0:

systemd-detect-virt

Lệnh này in tên platform, chẳng hạn kvm, xen, vmware hoặc microsoft, và none trên bare metal. Bên trong container, lệnh báo runtime thay vào đó, chẳng hạn lxc, docker hoặc podman. Thông tin này chỉ cho biết về container, không cho biết về máy bên dưới. Trên kvm, giá trị 0 là bằng chứng thực tế rằng host đang phân bổ tài nguyên tốt cho bạn. Trên platform không bao giờ ghi field này, giá trị 0 hoàn toàn không có ý nghĩa. Khi đó phải đánh giá contention bằng cách đo thời gian chạy công việc thực tế.

Cách kiểm tra CPU steal time trên VPS

vmstat thuộc package procps. Nó có trong hầu hết image Ubuntu và Debian VPS, nhưng có thể không có trong một số container image tối giản. Vì vậy, hãy cài đặt nó trước khi phụ thuộc vào công cụ này.

sudo apt-get update
sudo apt-get install -y procps
vmstat --version
vmstat 1 5

vmstat --version in ra một dòng như vmstat from procps-ng 4.0.4. Nếu lệnh này in ra kết quả, tool đã được cài đặt và bạn đang đọc các kernel counter thực. Sau đó, vmstat 1 5 lấy một sample mỗi giây, tổng cộng 5 lần.

procs -----------memory---------- ---swap-- -----io---- -system-- -------cpu-------
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st gu
 1  0      0 3216484  98304 1284360    0    0     4    18   62  110  3  1 96  0  0  0
 2  0      0 3216232  98304 1284360    0    0     0     0  248  431  6  2 84  0  8  0

Tìm column st trong block cpu ở bên phải. Các bản procps-ng hiện tại in thêm column gu phía sau nó để ghi thời gian của KVM guest. Vì vậy, st đứng ở vị trí thứ hai từ bên phải thay vì cuối cùng. Hãy đọc column theo tên header, vì vị trí này đã thay đổi giữa các bản release.

Có 2 nguyên tắc giúp kết quả chính xác. Dòng dữ liệu đầu tiên là giá trị trung bình từ lúc boot, nên bỏ qua dòng này và đọc các dòng phía sau. Một sample không đủ để đo lường, vì steal time thường xuất hiện theo từng đợt. Hãy chạy vmstat 1 60 và theo dõi đủ 1 phút trước khi kết luận.

top báo cáo cùng một giá trị trên summary line %Cpu(s), tại field được đánh dấu st:

%Cpu(s):  6.2 us,  2.1 sy,  0.0 ni, 83.9 id,  0.0 wa,  0.0 hi,  0.3 si,  7.5 st

Để xem chi tiết theo từng core, thêm sysstat:

sudo apt-get install -y sysstat
mpstat -P ALL 1 5

mpstat in 1 row cho mỗi CPU cùng column %steal. Column này cho biết mọi vCPU đều bị ảnh hưởng hay chỉ 1 vCPU. Nếu cần lịch sử cho support ticket, hãy lưu các sample thay vì chỉ đọc chúng trên màn hình:

date -u | tee -a ~/steal.log
mpstat -P ALL 1 5 | tee -a ~/steal.log

Hãy chạy lệnh này từ cron trong những giờ bạn nghi ngờ có vấn đề. File kết quả sẽ giúp bạn đưa cho provider dữ liệu chính xác về 10 phút xảy ra sự cố, thay vì chỉ nói rằng “tối qua máy có vẻ chậm”.

Các con số steal có ý nghĩa gì?

  • 0.0 ổn định. Hệ thống khỏe, hoặc platform hoàn toàn không báo steal. Hãy xác nhận bằng systemd-detect-virt trước khi kết luận.
  • Tăng đột biến vài phần trăm trong vài giây. Bình thường trên mọi node dùng chung. Một máy lân cận bắt đầu chạy build hoặc host đang chạy backup.
  • Duy trì ở mức 1 đến 5 phần trăm trên gói dùng chung. Có thể dự đoán được. CPU dùng chung được phản ánh trong mức giá.
  • Duy trì ở mức 5 đến 10 phần trăm. Có slowdown mà bạn có thể đo được. Bắt đầu ghi lại bằng chứng và so sánh cùng khung giờ trong vài ngày.
  • Trên 10 phần trăm trong nhiều giờ liên tục. Node đang bị phân bổ quá mức so với workload của bạn. Đây là mức đủ để mở support ticket hoặc chuyển sang node khác.

Hãy xem các khoảng này là hướng dẫn đọc số liệu, không phải specification, vì không provider nào công bố mức đảm bảo steal cho gói dùng chung. Đánh giá chúng dựa trên workload bạn đang chạy. Một batch job chạy qua đêm có thể chịu được steal 15 phần trăm mà không ai nhận thấy. Một service nhạy với latency sẽ thể hiện điều này trong p99 từ lâu trước khi giá trị trung bình trở nên đáng lo. Vì vậy, các workload nhạy với latency như trading bot nên chạy trên các core dedicated.

Steal time khiến bạn mất bao nhiêu?

Phép tính rất ngắn. Nếu một phần s thời gian CPU của bạn bị lấy đi, một job cần một lượng CPU cố định sẽ mất 1 / (1 - s) lần thời gian thực lâu hơn. Với job cần 60 giây CPU:

ChartWall clock time for a job needing 60 seconds of CPU
The data behind this chart
[
  {
    "steal_percent": 0,
    "wall_clock_seconds": "60.0"
  },
  {
    "steal_percent": 3,
    "wall_clock_seconds": "61.9"
  },
  {
    "steal_percent": 8,
    "wall_clock_seconds": "65.2"
  },
  {
    "steal_percent": 15,
    "wall_clock_seconds": "70.6"
  },
  {
    "steal_percent": 25,
    "wall_clock_seconds": "80.0"
  },
  {
    "steal_percent": 40,
    "wall_clock_seconds": "100.0"
  }
]

Ở mức 3 phần trăm, là mức thường thấy trên shared plan, job đó mất 61.9 giây thay vì 60.0 giây. Không ai mở ticket chỉ vì mức này. Ở mức 8 phần trăm, thời gian là 65.2 giây. Ở mức 40 phần trăm, cùng job đó cần 100.0 giây, và một queue trước đây được xử lý hết bắt đầu tăng dần.

Đó là các giá trị được tính toán, không phải số đo thực tế. Mô hình giả định chỉ có một thread có thể chạy và steal được phân bổ đều trong toàn bộ khoảng thời gian. Dịch vụ thực tế thường bị ảnh hưởng nặng hơn so với đường cong này, vì một phần thời gian bị lấy đi có thể rơi vào giữa một request, rồi độ trễ đó tiếp tục ảnh hưởng đến mọi thứ đang chờ request đó. Để có số liệu của riêng bạn thay vì chỉ dùng công thức, hãy benchmark VPS trong một giờ ít tải rồi thực hiện lại khi tải cao, đồng thời ghi lại st cho cả hai khoảng thời gian.

Đó là steal hay là vấn đề khác?

Rất dễ nhầm steal với các triệu chứng khác. Hãy đọc các bộ đếm cùng nhau trên cùng dòng vmstat.

  • st cao trong khi rus vẫn thấp: host không cấp CPU core cho bạn. Đó là steal.
  • r cao hơn nhiều so với số vCPU của bạn, us cao và st gần bằng 0: bạn đang chạy nhiều công việc hơn khả năng xử lý của CPU riêng. So sánh r với kết quả của nproc. Đây là tình trạng oversubscription do chính bạn gây ra, không phải do một tenant khác.
  • wa cao và st gần bằng 0: các task đang bị chặn khi truy cập storage. Đây là vấn đề khác và cần cách xử lý khác.
  • Load average cao trong khi stus đều thấp: chỉ số load cũng tính các task không thể interrupt, vì vậy nguyên nhân thường là device bị kẹt hoặc network mount bị treo, không phải CPU.

Các gói Burstable cần được lưu ý riêng. Gói này cấp cho bạn một credit balance. Balance tăng khi hệ thống idle và giảm khi hệ thống bận. Khi balance cạn, provider sẽ giới hạn bạn ở mức baseline. Trên một số platform, việc throttle này được báo cáo dưới dạng steal. Trên các platform khác, thông tin này không hiển thị từ bên trong máy, và bạn chỉ nhận được ít CPU cycle hơn mỗi giây. Hãy đọc mô tả gói trước khi kết luận rằng nguyên nhân là một tenant khác.

Vì sao container báo không có steal time

Steal là thuộc tính của máy ảo, không phải của container chạy bên trong máy ảo đó. Docker container trên VPS của bạn dùng chung /proc của host, nên giá trị st đọc bên trong container chính là steal của VPS. Đây là giá trị bạn cần. Mô hình virtualisation dựa trên container được bán dưới dạng VPS hoạt động khác. Khi đã có lxcfs, /proc/stat bên trong container được tổng hợp từ việc accounting của cgroup, nên steal mặc định bằng 0. Monitoring stack chỉ scrape dữ liệu từ bên trong có thể hiển thị số 0 phẳng và ổn định, trong khi máy vật lý bên dưới đang thiếu CPU.

Bên trong container, counter có cùng ý nghĩa là CPU quota throttling. Trên cgroup v2:

cat /sys/fs/cgroup/cpu.stat

nr_throttled đếm số enforcement period mà group chạm CPU quota, còn throttled_usec tính tổng thời gian group bị đóng băng. nr_throttled tăng nghĩa là process của bạn ở trạng thái runnable nhưng không được chạy. Trải nghiệm này giống steal, nhưng nguyên nhân là limit do chính bạn đặt. Hãy kiểm tra limit của mình trước khi đổ lỗi cho host, đặc biệt nếu bạn chạy dịch vụ trong Docker trên VPS với CPU limit trong compose file. Virtualisation nhiều lớp tạo thêm một nơi khiến thời gian bị mất, vì một VM bên trong VPS phải chịu steal của VPS cộng với độ trễ scheduling của chính nó. Hãy lưu ý điều này nếu bạn chạy nested virtualisation trên VPS.

Cần làm gì khi steal kéo dài

Không có setting nào bên trong guest có thể xử lý steal, vì scheduler đưa ra quyết định này chạy bên ngoài guest. Nâng cấp kernel cũng không thay đổi được điều đó: cơ chế scheduling nhận biết cache được thêm vào Linux kernel 7.2 chỉ sắp xếp lại các task trên những core thực tế được cấp cho bạn, và không thể khôi phục số CPU cycles mà một guest khác đã lấy. Có 4 hướng xử lý thực tế.

Thu thập bằng chứng trước. Ghi lại timestamp theo UTC, thời lượng của từng đợt, tần suất lặp lại và việc mpstat cho thấy chỉ một vCPU hay tất cả vCPU bị ảnh hưởng. Một tuần sample có log có giá trị hơn một ảnh chụp màn hình.

Mở ticket kèm dữ liệu đó. Đặt 2 câu hỏi trực tiếp: node này có bị oversubscribe trong những khung giờ đó không, và instance của tôi có thể được chuyển sang node khác không. Dán output của vmstat và thời điểm chính xác. Provider sẽ xử lý dựa trên một khoảng thời gian có thể tái hiện; ticket chỉ ghi server chậm thường sẽ nhận được yêu cầu cung cấp khoảng thời gian đó. Bạn có thể bàn giao bao nhiêu phần việc trong số này là một khác biệt thực tế giữa VPS managed và unmanaged.

Yêu cầu migration. Chuyển guest sang node ít tải hơn là việc thường lệ đối với provider và thường chỉ cần reboot nhanh. Đây là cách khắc phục không tốn thêm chi phí, đồng thời giải quyết trường hợp phổ biến: một node tình cờ chứa nhiều guest lân cận có tải cao cùng lúc.

Mua giải pháp loại bỏ contention. Gói dedicated vCPU dành riêng các core vật lý cho instance của bạn, nên counter sẽ ở mức 0 và giữ nguyên như vậy. Chi phí mỗi tháng cao hơn, nhưng đây là lựa chọn phù hợp cho workload không thể chịu được biến động. Nếu vẫn chưa đủ, hoặc bạn cũng muốn sử dụng riêng memory bandwidth, bước tiếp theo là dùng dedicated server thay vì VPS.

Trong thời gian chờ xử lý, hãy giảm mức độ ảnh hưởng của steal. Chạy ít worker thread hơn số vCPU bạn có, vì các thread không lấy được core chỉ làm tăng số lần context switch. Chuyển batch work sang những giờ node ít tải; log của bạn hiện đã cho biết các khung giờ đó. Sau đó đo lại bằng cùng command trong cùng khoảng thời gian, để xác định thay đổi có hiệu quả hay không thay vì phỏng đoán.

FAQ

Mức CPU steal time bình thường trên VPS là bao nhiêu?

Trên gói dùng chung, các đợt tăng ngắn và giá trị duy trì dưới khoảng 5 phần trăm là bình thường, vì CPU dùng chung nghĩa là host phân chia các core vật lý cho nhiều guest. Giá trị duy trì ở mức hai chữ số trong nhiều giờ là bất thường và bạn nên gửi ticket. Trên gói vCPU dedicated, giá trị dự kiến là 0.0, nên mọi giá trị khác đều là lỗi cần báo. Hãy đánh giá con số này dựa trên workload của chính bạn: một batch job chạy qua đêm có thể chịu được steal time mà một API nhạy với độ trễ thì không.

Nâng cấp gói có khắc phục được steal time cao không?

Không, nếu chỉ nâng cấp gói. Thêm vCPU trên cùng một shared node nghĩa là có thêm virtual CPU cùng tranh các core vật lý đang bị quá tải, nên phần trăm này có thể vẫn giữ nguyên. Cách loại bỏ steal time là dùng dedicated CPU allocation hoặc chuyển sang node ít tải hơn. Một phần lớn hơn của một máy đang bận vẫn chỉ là một phần của máy đang bận.

Tại sao VPS của tôi hiển thị 0 steal time dù rõ ràng đang chậm?

Có 2 nguyên nhân phổ biến. Hypervisor có thể không export counter này, đây là tình huống thường gặp trên các platform VMware và Hyper-V, nên field luôn giữ giá trị 0 bất kể host đang làm gì. Chạy systemd-detect-virt để xem bạn đang dùng platform nào. Nếu không phải nguyên nhân đó, bottleneck nằm ở nơi khác: kiểm tra wa để xem storage wait, so sánh r với nproc để kiểm tra tình trạng quá tải của chính bạn, và đọc /sys/fs/cgroup/cpu.stat bên trong container để phát hiện quota throttling.

Tôi có thể giảm steal time từ bên trong server không?

Bạn không thể thay đổi cách host lập lịch từ bên trong guest. Bạn chỉ có thể giảm tác động của nó. Chạy ít worker thread hơn số vCPU bạn có, để ít công việc nằm trên run queue chờ một core chưa có sẵn. Chuyển các batch job sang những giờ node ít bận hơn. Cache kết quả để giảm số request cần CPU. Những thay đổi thực sự loại bỏ steal time, như migration sang node khác hoặc dùng dedicated core, phải do provider thực hiện.