SSD Nodes Learn 🎉 VPS từ $4.99/tháng
Hướng dẫn Matt ConnorBởi Matt Connor

CPU steal time trên VPS là gì? Cách đọc vmstat st

Hiểu CPU steal time, đọc cột st trong vmstat và phân biệt VPS quá tải với noisy neighbour khi vCPU sẵn sàng nhưng hypervisor chưa cấp CPU.

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

CPU steal time là tỷ lệ thời gian virtual CPU của bạn đã sẵn sàng chạy, không phải chờ gì, nhưng hypervisor lại cấp physical core cho một guest khác. Công việc đã được xếp hàng. Core đang được dùng ở nơi khác. Linux đếm riêng các chu kỳ đó 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 duy nhất counter này tồn tại. Thời gian các process của bạn thực sự chạy trên CPU được báo cáo là us (user) hoặc sy (system). Thời gian một task bị block khi chờ storage được báo cáo là wa (I/O wait). Một vCPU (virtual CPU) có thể chạy, đang nằm trong run queue, không có I/O đang chờ xử lý nhưng vẫn chưa được thực thi sẽ được báo cáo là st. Không thành phần nào bên trong server có thể tự xóa trạng thái đó, vì quyết định scheduling được thực hiện ở tầng thấp hơn bạn một lớp, 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ý cho nhiều guest. Nguyên nhân thường gặp là một guest khác trên cùng node đang chạy với tải cao, khiến host phải chia các core giữa bạn và guest đó. Có một nguyên nhân thứ hai thường bị bỏ qua. Nhiều nhà cung cấp giới hạn một vCPU dùng chung ở một phần của physical core. Trên một số hypervisor, giới hạn này được áp dụng và tính là steal bên trong guest. Vì vậy, chỉ số 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 đã sử dụng core đó.

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

Kernel không thể tự đo steal vì nó không nhìn thấy host. Hypervisor cung cấp thông tin 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 lại khi kernel được build với CONFIG_PARAVIRT_TIME_ACCOUNTING, tùy chọn này có trong mọi kernel của các bản phân phối. Xen báo cáo cùng thông tin qua vùng runstate. Tổng giá trị được đưa lên 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 kể từ khi boot, theo thứ tự sau: 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 này rồi chuyển hai mẫu đo thành phần trăm.

Có một hệ quả quan trọng hơn các hệ quả 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. Guest trên VMware và Hyper-V thường báo giá trị 0 cố định. 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 nếu chạy 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ế cho thấy host đang cấp đủ tài nguyên cho bạn. Trên platform không bao giờ điền field này, giá trị 0 hoàn toàn không có ý nghĩa, và 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 thời gian CPU steal trên VPS?

vmstat thuộc package procps. Package này có trên gần như mọi image Ubuntu và Debian 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 trước khi phụ thuộc vào nó.

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

vmstat --version in 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 bộ đếm kernel thực. Sau đó, vmstat 1 5 lấy 1 mẫu 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 cột st trong block cpu ở bên phải. Các bản procps-ng hiện tại in thêm cột gu phía sau cột đó để ghi thời gian KVM guest, vì vậy st là cột thứ hai tính từ bên phải thay vì cột cuối cùng. Hãy đọc cột theo tên trong header, vì vị trí này đã thay đổi giữa các bản phát hành.

Hai thói quen giúp kết quả phản ánh đúng thực tế. Dòng dữ liệu đầu tiên là giá trị trung bình tính từ lúc boot, vì vậy hãy bỏ qua dòng đó và đọc các dòng phía sau. Một mẫu duy nhất chưa phải là phép đo, vì steal thường xảy ra theo từng đợt: 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 số liệu trên dòng tóm tắt %Cpu(s), trong trường đượ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 dòng cho mỗi CPU, kèm cột %steal cho biết mọi vCPU đều bị ảnh hưởng hay chỉ 1 vCPU. Để có lịch sử cần cho support ticket, hãy lưu các mẫu 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 đó từ cron trong những giờ bạn nghi ngờ có vấn đề. Khi đó, file sẽ giúp bạn thay câu “tối qua máy có vẻ chậm” bằng bằng chứng chính xác về 10 phút đã xảy ra vấn đề.

Các mức steal có ý nghĩa gì?

  • 0.0 ổn định. Máy 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. Tác vụ build của máy lân cận bắt đầu chạy hoặc host đang chạy tác vụ 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ó hiện tượng chậm mà bạn có thể đo được. Bắt đầu ghi lại bằng chứng và so sánh cùng các khung giờ trong nhiều ngày.
  • Trên 10 phần trăm trong nhiều giờ liên tục. Node đang cấp phát quá mức so với workload của bạn. Đây là mức đủ để gửi ticket cho bộ phận hỗ trợ hoặc chuyển sang node khác.

Hãy xem các khoảng này như hướng dẫn đọc số liệu, không phải thông số cam kết, vì không provider nào công bố mức steal bảo đảm 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 ra. Một service nhạy với latency sẽ thể hiện vấn đề trong p99 từ rấ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.

Chi phí của steal time là bao nhiêu?

Phép tính khá 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 một 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, một mức thường gặp ở 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, job mất 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 vẫn xử lý hết bắt đầu tăng dần.

Đây 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. Các service thực tế thường cho cảm giác tệ hơn đường cong này, vì một slice bị lấy đi có thể rơi đúng giữa lúc xử lý request, rồi độ trễ đó tiếp tục ảnh hưởng đến mọi request đang chờ request này. Để có số liệu riêng thay vì chỉ dùng công thức, hãy benchmark VPS trong một giờ ít tải và thực hiện lại vào giờ bận, đồng thời ghi lại st cho cả hai khoảng thời gian.

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

Steal rất dễ bị nhầm với các triệu chứng khác. Hãy đọc các bộ đếm cùng nhau trên cùng một 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 các CPU của mình. So sánh r với output của nproc. Đây là tình trạng oversubscription do chính bạn gây ra, không phải do máy lân cận.
  • 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ể ngắt, nên tình huống này thường chỉ ra thiết bị bị kẹt hoặc network mount bị treo, không phải vấn đề về CPU.

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

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 là steal của VPS, đúng với thông tin bạn cần. Mô hình ảo hóa dựa trên container được bán dưới dạng VPS hoạt động khác. Khi lxcfs được áp dụng, /proc/stat bên trong container được tổng hợp từ dữ liệu accounting của cgroup, nên steal mặc định bằng 0. Stack monitoring chỉ thu thập dữ liệu từ bên trong container có thể hiển thị giá trị 0 phẳng và ổn định, trong khi máy vật lý bên dưới đang thiếu tài nguyên CPU.

Bên trong container, counter mang ý nghĩa tương đương là CPU quota throttling. Trên cgroup v2:

cat /sys/fs/cgroup/cpu.stat

nr_throttled đếm số chu kỳ enforcement mà group chạm giới hạn CPU, 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. Đây là trải nghiệm giống steal, nhưng nguyên nhân là giới hạn do chính bạn đặt. Kiểm tra các giới hạn của bạn trước khi đổ lỗi cho host, đặc biệt nếu bạn chạy các service trong Docker trên VPS với giới hạn CPU trong file compose. Ảo hóa nhiều lớp tạo thêm một nơi khiến thời gian bị mất, vì VM bên trong VPS phải chịu cả steal của VPS lẫn độ trễ scheduling riêng của nó. Hãy ghi nhớ điều này nếu bạn chạy ảo hóa lồng nhau 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. 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 dữ liệu đã ghi 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 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à thời điểm chính xác. Nhà cung cấp có thể xử lý khi bạn chỉ ra được một khoảng thời gian tái hiện rõ ràng; ticket chỉ ghi server chậm thường sẽ nhận được yêu cầu cung cấp khoảng thời gian cụ thể. Mức độ bạn có thể giao việc này cho nhà cung cấp 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à việc thường làm đối với nhà cung cấp và thường chỉ cần reboot ngắn. Đâ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 neighbor nặng cùng lúc.

Mua thêm tài nguyên để tránh 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ẽ về 0 và duy trì ở mức đó. 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ấp nhận mức biến động này. Nếu vẫn chưa đủ, hoặc bạn cũng muốn dùng riêng memory bandwidth, bước tiếp theo là dùng dedicated server thay vì VPS.

Trong khi chờ xử lý, hãy giảm tác độ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, dựa trên thông tin trong log của chính 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ì chỉ phỏng đoán.

FAQ

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

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ờ không bình thường và 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.

Gói lớn hơn có khắc phục được steal time cao không?

Không phải cứ tăng gói là được. Có thêm vCPU trên cùng một shared node nghĩa là có thêm virtual CPU cùng tranh chấp 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à cấp 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 lý do phổ biến. Hypervisor có thể không export counter này, thường gặp trên các nền tảng VMware và Hyper-V, nên trường này luôn là 0 bất kể host đang làm gì. Chạy systemd-detect-virt để xem bạn đang dùng nền tảng 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 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 mức ảnh hưởng của nó. Chạy ít worker thread hơn số vCPU bạn có, để ít công việc nằm trong run queue chờ một core không sẵn sàng hơn. Chuyển batch job sang những giờ node ít tải hơn. Cache kết quả để giảm số request cần CPU. Các thay đổi thực sự loại bỏ steal time, như chuyển sang node khác hoặc dùng dedicated core, phải do provider thực hiện.