Cách kiểm tra CPU steal time trên VPS và noisy neighbour
CPU steal time là thời gian vCPU bị hypervisor chặn do tranh chấp tài nguyên. Hướng dẫn đọc cột st trong vmstat để xác định server quá tải hay do hàng xóm gây ra.
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 con số steal
Kernel không thể tự đo steal vì nó không nhìn thấy host. Hypervisor cung cấp giá trị này. Trên KVM, host ghi một counter cho từng vCPU vào một page được chia sẻ với guest. Guest cộng các giá trị đó khi kernel được build với CONFIG_PARAVIRT_TIME_ACCOUNTING, tùy chọn này có trong kernel của mọi distribution. Xen báo cùng thông tin qua vùng runstate của nó. Tổng giá trị được đưa lên userspace đúng tại một nơi:
head -1 /proc/statDòng cpu đó chứa 10 counter, tính theo tick USER_HZ kể từ khi boot, theo thứ tự: user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice. Steal là giá trị thứ 8 sau label. Mọi tool bên dưới, vmstat, top, mpstat và mọi Prometheus exporter, đều đọc cùng field đó 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 này, field sẽ luôn bằng 0, và mọi tool dựa trên nó sẽ báo 0.0 bình thường trong khi host đang quá tải. KVM và Xen export counter này. Trên các platform khác, trong đó có VMware và Hyper-V, việc có thấy steal hay không phụ thuộc vào dữ liệu host expose và khả năng hỗ trợ của guest kernel. Vì vậy, giá trị 0 cố định trên các platform này không tự nó chứng minh được điều gì. Hãy kiểm tra platform trước khi tin vào giá trị 0:
systemd-detect-virtLệ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. Giá trị này cho biết thông tin về container, không phải 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 cấp tài nguyên tốt cho bạn. Trên platform không bao giờ điền field này, giá trị 0 không cung cấp bằng chứng nào cả; khi đó phải đánh giá contention bằng cách đo thời gian chạy công việc thực tế.
Làm thế nào để kiểm tra CPU steal time trên VPS?
vmstat thuộc package procps. Package này có trên hầu hết image Ubuntu và Debian dành cho VPS, nhưng có thể thiếu trong một số image container 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 5vmstat --version in ra một dòng như vmstat from procps-ng 4.0.4. Nếu lệnh in ra dòng đó, tool đã được cài đặt và bạn đang đọc các kernel counter thực tế. Sau đó vmstat 1 5 in ra 5 report: report đầu tiên là giá trị trung bình từ lúc boot, 4 report tiếp theo là các mẫu cách nhau 1 giây.
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 0Tì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 sau column này để hiển thị thời gian của KVM guest. Vì vậy, st đứng thứ 2 từ bên phải thay vì ở cuối. Hãy đọc column theo tên header, vì vị trí này đã thay đổi giữa các release.
Có 2 thói quen giúp kết quả không bị sai lệch. Dòng dữ liệu đầu tiên là giá trị trung bình từ lúc boot, vì vậy hãy bỏ qua dòng này và đọc các dòng phía sau. Một sample cũng chưa đủ để đo, vì steal time thường xuất hiện theo từng đợt. Hãy chạy vmstat 1 61. Lệnh này lấy 60 sample, mỗi sample cách nhau 1 giây, sau dòng chứa giá trị từ lúc boot. Hãy theo dõi đủ 1 phút trước khi đưa ra kết luận.
top báo cáo cùng giá trị đó trên dòng summary %Cpu(s), trong 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 5mpstat in 1 row cho mỗi CPU, kèm column %steal. Column này cho biết tất cả vCPU đều bị ảnh hưởng hay chỉ một vCPU. Để lưu lại history khi cần gửi 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.logHãy chạy lệnh đó từ cron trong những khung giờ bạn nghi ngờ có vấn đề. File kết quả sẽ giúp bạn chuyển từ việc nói với provider rằng “tối qua máy có vẻ chậm” sang việc đưa ra chính xác 10 phút bị ảnh hưởng.
Các con số steal có ý nghĩa gì?
0.0ổn định. Hệ thống khỏe, hoặc platform không báo steal. Hãy xác nhận bằngsystemd-detect-virttrước khi kết luận.- Tăng vọt vài phần trăm trong vài giây. Bình thường trên mọi shared node. Một máy hàng xóm 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 shared plan. Có thể dự kiến. Giá của gói phản ánh việc CPU được chia sẻ.
- Duy trì ở mức 5 đến 10 phần trăm. Có slowdown có thể đo được. Hãy bắt đầu ghi lại bằng chứng và so sánh cùng khung giờ trong nhiều ngày.
- Trên 10 phần trăm trong nhiều giờ liên tục. Node có thể đang oversubscribe so với workload của bạn hoặc CPU limit của plan đang được áp dụng; một số provider báo limit đó dưới dạng steal. Đâ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ố bảo đảm về steal cho shared plan. Đối chiếu chúng với workload bạn đang chạy. Một batch job chạy qua đêm có thể chịu được 15 phần trăm steal mà không ai nhận ra. Một service nhạy với latency sẽ thể hiện điều đó trong p99 từ lâu trước khi average 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 dedicated core.
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:
Dữ liệu đằng sau biểu đồ này
[
{
"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.
stcao trong khirvàusvẫn thấp: host không cấp CPU core cho bạn. Đó là steal.rcao hơn nhiều so với số vCPU của bạn,uscao vàstgầ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ánhrvới kết quả củanproc. Đâ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.wacao vàstgầ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
stvàusđề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.statnr_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ó thiết lập nào bên trong guest có thể khắc phục 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 sự được cấp cho bạn, và không thể lấy lại các CPU cycle mà neighbour đã chiếm.
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à xem mpstat cho thấy chỉ một vCPU hay tất cả vCPU bị ảnh hưởng. Một tuần sample được ghi log có giá trị hơn một screenshot.
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 khoảng thời gian đó 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à các thời điểm chính xác. Provider sẽ xử lý khi có 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 bổ sung khoảng thời gian cụ thể. Mức độ bạn có thể giao việc này cho provider là một trong những khác biệt thực tế giữa VPS managed và VPS unmanaged.
Yêu cầu migration. Chuyển guest sang node ít tải hơn là công việc thường ngày của provider và thường chỉ cần reboot nhanh. Đây là cách khắc phục không phát sinh chi phí, đồng thời giải quyết trường hợp phổ biến khi một node tình cờ chứa nhiều neighbour nặng cùng lúc.
Mua gói không bị contention. Gói dedicated vCPU reserve capacity CPU cho instance của bạn, có thể là một core đầy đủ hoặc một hardware thread đầy đủ tùy provider. Nhờ đó, neighbour không còn chiếm các CPU cycle của bạn và counter duy trì ở mức 0 hoặc gần 0. Công việc housekeeping của hypervisor vẫn có thể để lại một lượng nhỏ. Chi phí hàng 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 context switch. Chuyển batch work sang những giờ node ít tải, theo dữ liệu trong log của bạn. 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ì đoán.
FAQ
Thời gian CPU steal trên VPS ở mức nào là bình thường?
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ý giữa nhiều guest. Giá trị duy trì ở mức hai chữ số trong nhiều giờ là không bình thường và nên gửi ticket. Trên gói vCPU dedicated, giá trị kỳ vọng là ở mức hoặc rất gần 0.0, vì hypervisor vẫn có thể dùng một phần nhỏ tài nguyên cho các tác vụ quản trị. Do đó, steal duy trì cao hơn mức này là lỗi cần báo. Hãy đánh giá con số này theo workload của bạn: một batch job chạy qua đêm có thể chịu được steal mà một API nhạy với latency thì không.
Nâng cấp gói lớn hơn 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ạnh tranh cùng các core vật lý đang bị quá tải, nên phần trăm này có thể giữ nguyên. Cách gần như loại bỏ hoàn toàn steal là dùng CPU dedicated 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.
Vì 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. Điều đó xảy ra trên một số platform, tùy host và guest kernel, nên field vẫn ở mức 0 dù host đang làm gì. Chạy systemd-detect-virt để xem bạn đang dùng platform nào. Nếu không, 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 các container để phát hiện việc bị 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 mức ảnh hưởng của nó. Chạy ít worker thread hơn số vCPU hiện có để giảm lượng công việc nằm trong run queue chờ một core không sẵn sàng. Chuyển các batch job sang thời điểm node ít tải hơn. Cache kết quả để giảm số request thực sự cần CPU. Những thay đổi có thể loại bỏ steal, như migration sang node khác hoặc dùng core dedicated, phải được thực hiện ở phía provider.