Senin, 12 Oktober 2026

Mengidentifikasi VM Resource Usage di Compute OpenStack (RHOSP 17.1)

Halo guys, Ridwan di sini.

Datang lagi dengan update catatan terbaru!

Singkat cerita, beberapa waktu lalu saya dapat issue salah satu compute node di cluster RHOSP 17.1 saya lihat load CPU-nya tinggi banget. Pas saya cek pakai top di hypervisor-nya, hasilnya kurang lebih begini:

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
 800657 qemu      20   0  133.4g 127.4g  22924 S 703.8   4.2 288630:18 qemu-kvm
 723367 qemu      20   0 5426160   3.9g  22528 S 393.3   0.1 576238:50 qemu-kvm
 713851 qemu      20   0 3463432   2.1g  22420 S 293.0   0.1  24130,09 qemu-kvm

Nah, di sinilah masalahnya: semua proses cuma terlihat sebagai qemu-kvm. Kita tahu ada VM yang "rakus" CPU (noisy neighbor), tapi VM siapa? Instance yang mana? Project apa? Dari tp saja kita buta total.

Di catatan kali ini saya mau share script sederhana untuk memetakan PID qemu-kvm di compute node langsung ke UUID instance Nova, lengkap dengan nama instance, flavor, project, sampai user pemiliknya — semua dijalankan cukup dari node Director.


Konsepnya: PID qemu-kvm Ternyata Sudah Bawa UUID Nova

Kuncinya sederhana. Setiap proses qemu-kvm yang dilahirkan libvirt ternyata membawa identitas instance di argumen command line-nya. Coba saja intip salah satu PID:

cat /proc/<PID>/cmdline | tr '\0' '\n' | grep -A1 -E '^-uuid|^-name'

Outputnya kurang lebih:

-name
guest=instance-0000138e,debug-threads=on
-uuid
f791078d-c0fd-46a6-a82b-c80e6d18b7dc

Nah, nilai -uuid itulah UUID instance di Nova. Jadi alurnya:

  1. Ambil top 10 proses qemu-kvm berdasarkan %CPU pakai ps di compute node.
  2. Petakan setiap PID ke UUID via /proc/<pid>/cmdline.
  3. Tanyakan detail UUID tersebut ke Nova API (openstack server show) — nama, flavor, project, user.

Tiga kali "translasi": PID → UUID → identitas Nova → identitas Keystone. Simple kan?


Tantangan di RHOSP: Dua Dunia yang Terpisah

Di RHOSP 17.1 (TripleO), ada "pemisahan kekuasaan" yang bikin kita nggak bisa jalankan semuanya di satu tempat:

  • Compute node: punya data utilisasi (proses qemu-kvm, /proc), tapi tidak punya CLI openstack maupun kredensial — dan memang by design begitu (security best practice).
  • Director: punya kredensial admin overcloud (~/overcloudrc) dan CLI lengkap, tapi tidak bisa lihat proses di compute node.

Jadi solusinya: script dijalankan dari Director, lalu Tahap 1 (pengumpulan data) dieksekusi remote via SSH ke compute node pakai user tripleo-admin, dan Tahap 2 (query Nova API) jalan lokal di Director.

+----------------------+          SSH           +------------------------+
|   DIRECTOR (stack)   | ---------------------> |   COMPUTE NODE         |
|                      |   Tahap 1: ps + /proc  |                        |
|  - overcloudrc       | <--------------------- |  - proses qemu-kvm     |
|  - openstack CLI     |   hasil: cpu,ram,uuid  |  - /proc/<pid>/cmdline |
|                      |                        |  - TIDAK ada CLI/creds |
|  Tahap 2:            |                        +------------------------+
|  openstack server    |
|  show <uuid>  -----> |  Keystone/Nova API (overcloud endpoint)
+----------------------+


1. Siapkan Script-nya di Node Director

Login ke Director sebagai user stack, lalu buat file check-top10-instances.sh: 

Jangan lupa kasih permission execute:

chmod +x check-top10-instances.sh

Beberapa poin desain yang sengaja saya pilih:

  1. Pengukuran real-time via /proc/<pid>/stat — %CPU dihitung dari delta CPU ticks (utime+stime) antara dua snapshot berjarak 2 detik, persis mekanisme internal top. Kedua snapshot diambil untuk SEMUA proses qemu sekaligus dalam satu pass awk (bukan loop per-PID), dan pembaginya adalah elapsed aktual dari /proc/uptime — bukan asumsi "pasti 2 detik". Tanpa dua hal ini, angka %CPU bisa melenceng jauh di host yang sibuk.
  2. Heredoc <<'REMOTE' (pakai tanda kutip!) — supaya variabel di blok remote tidak di-expand oleh shell Director, tapi dievaluasi di compute node.
  3. python3 bukan jq — di Director RHOSP, python3 pasti ada, sedangkan jq kadang tidak terinstal.
  4. -f json sekali panggil — satu call openstack server show bisa "dipetik" berkali-kali (name, flavor, project_id, user_id) tanpa memanggil API berulang per field.
  5. Deteksi orphan — kalau UUID ada di hypervisor tapi tidak dikenal Nova, itu temuan berharga: kemungkinan orphan VM sisa evacuate/delete yang gagal.


2. Cara Menjalankan

Pertama, cari tahu hostname ctlplane compute node yang mau dicek. Ini pakai kredensial undercloud (stackrc):

source ~/stackrc
openstack server list -c Name -c Networks

Lalu tinggal eksekusi (script sudah source overcloudrc sendiri di dalamnya):

./check-top10-instances.sh overcloud-novacompute-2.ctlplane


3. Contoh Output

Kurang lebih hasilnya seperti ini (nama instance, project, dan IP sudah saya samarkan ya):

== Mengambil Top 10 qemu-kvm (real-time) dari overcloud-novacompute-2.ctlplane ==
%CPU    PID      RAM(GiB)   LIBVIRT_NAME           NOVA_UUID
836.8   202001   256.2      instance-000011ea      6a88a1f7-5b1f-44ab-99be-xxxxxxxxxxxx
678.2   940635   32.1       instance-0000138e      f791078d-c0fd-46a6-a82b-xxxxxxxxxxxx
419.5   521820   16.2       instance-0000130a      883644e6-8c7a-4433-9671-xxxxxxxxxxxx
378.2   274908   16.1       instance-000014a5      840a4c83-ccd8-4321-ad19-xxxxxxxxxxxx
356.8   688699   8.1        instance-00001391      ffceed81-62f6-4b9c-b119-xxxxxxxxxxxx
350.5   899453   16.1       instance-000013df      73f82694-9f5e-40a5-b3e5-xxxxxxxxxxxx
340.9   175123   126.7      instance-00001a63      bd6bcd65-e8ac-446a-b110-xxxxxxxxxxxx
327.7   13900    8.1        instance-00001397      27fc7324-925a-4514-a758-xxxxxxxxxxxx
307.3   135182   8.1        instance-00001400      9009d9d5-e0cb-4a6e-8edb-xxxxxxxxxxxx
289.1   531769   16.2       instance-00000e3c      977b1137-d18d-4b67-8a4e-xxxxxxxxxxxx

==============================================================
 DETAIL INSTANCE (openstack server show)
==============================================================

---[ %CPU: 836.8 | RAM: 256.2 GiB | UUID: 6a88a1f7-5b1f-44ab-99be-xxxxxxxxxxxx ]---
  Name    : bigdata-vm-01
  Status  : ACTIVE
  Flavor  : s1.xxxlarge (7ac87069-beae-44c7-8ea0-xxxxxxxxxxxx)
  Host    : overcloud-novacompute-2.mydomain.net
  Libvirt : instance-000011ea
  IP      : {'vpc-tenant-a': ['172.18.0.x', '103.x.x.x']}
  Created : 2025-12-24T09:01:44Z
  >> Project : Project-BigData-App (755e3adbfb9343af9d16a390xxxxxxxx)
  >> User    : user-admin01 (833864aeacc445bc83a8ec00xxxxxxxx)

---[ %CPU: 678.2 | RAM: 32.1 GiB | UUID: f791078d-c0fd-46a6-a82b-xxxxxxxxxxxx ]---
  Name    : ingestion-worker-01
  Status  : ACTIVE
  Flavor  : s1.xlarge (01900c32-831d-4d99-a390-xxxxxxxxxxxx)
  Host    : overcloud-novacompute-2.mydomain.net
  Libvirt : instance-0000138e
  IP      : {'tenant-network-b': ['10.27.10.x', '103.x.x.x']}
  Created : 2026-02-27T07:37:05Z
  >> Project : Project-Crawler-App (f1eb159bb18c4b88b6f232eaxxxxxxxx)
  >> User    : budi.santoso (5c515a9020604dfd8357ce07xxxxxxxx)

---[ %CPU: 419.5 | RAM: 16.2 GiB | UUID: 883644e6-8c7a-4433-9671-xxxxxxxxxxxx ]---
  Name    : APP-BACKEND-PRD01
  Status  : ACTIVE
  Flavor  : e1.xlarge (8e00f588-408a-4486-8b8b-xxxxxxxxxxxx)
  Host    : overcloud-novacompute-2.mydomain.net
  Libvirt : instance-0000130a
  IP      : {'lan-internal': ['10.25.216.x'], 'vpc-drc': ['192.168.100.x']}
  Created : 2026-02-09T05:56:13Z
  >> Project : Project-DRC-App (cf860849fe0e47c4abb9c450xxxxxxxx)
  >> User    : user-ops02 (f460323345404a5f919767c8xxxxxxxx)

... (dan seterusnya sampai instance ke-10)

Nah mantap kan? Dalam sekali eksekusi kita langsung dapat jawaban lengkap: "VM bigdata-vm-01 milik project Project-BigData-App sedang membakar lebih dari 8 vCPU di compute-2 saat ini, disusul ingestion-worker-01 milik project Project-Crawler-App dengan hampir 7 vCPU". Dan karena pengukurannya real-time (delta 2 detik), angka ini mencerminkan kondisi detik ini, bukan rata-rata historis.

Dari sini keputusan remediasi jadi gampang — mau di-live-migrate untuk rebalancing, dikasih CPU pinning, atau sekadar jadi bahan diskusi dengan tim yang punya tenant tersebut.

Catatan Tambahan

Beberapa hal yang perlu kalian perhatikan:

  1. Kenapa tidak pakai %CPU dari ps saja? Karena ps menghitung %CPU sebagai rata-rata sejak proses start (total CPU time / umur proses), bukan utilisasi saat ini. VM yang sudah running 6 bulan dan baru spike hari ini tidak akan terdeteksi — rata-rata historisnya masih kecil. Makanya script ini mengukur delta sendiri dari /proc. Alternatif lain yang sama validnya: top -b -n2 (ambil iterasi kedua, karena iterasi pertama top masih berisi rata-rata ala ps).
  2. SSH user beda-beda — deployment fresh RHOSP 17.1 pakai tripleo-admin, tapi environment hasil upgrade dari 16.x sering masih heat-admin. Cek cepat: ssh tripleo-admin@<host> hostname.
  3. Hati-hati soal hostname — nama untuk SSH (.ctlplane) berbeda dengan hostname yang dikenal Nova service (biasanya FQDN internal). Jangan tertukar kalau mau pakai openstack server list --host. Cek dengan openstack compute service list.
  4. Kalau muncul "UUID tidak ditemukan di Nova" — patut dicurigai sebagai orphan VM: proses qemu masih hidup tapi record Nova sudah terhapus. Verifikasi dengan membandingkan:
ssh tripleo-admin@<compute> "sudo podman exec nova_libvirt virsh list --all"

versus 

openstack server list --all-project --host <compute-fqdn>
  1. Angka RAM di output adalah RSS dari sisi host (memori fisik yang benar-benar dipakai proses qemu), bukan ukuran flavor. Kalau RSS sudah mendekati RAM flavor, artinya guest sudah touch hampir seluruh alokasinya — perhatikan ram_allocation_ratio kalian kalau host-nya overcommit.

Sekian catatan kali ini. Script ini simpel, tapi di operasional harian terbukti sangat memangkas waktu investigasi noisy neighbor — dari yang tadinya bolak-balik antara top, virsh, dan Horizon, sekarang cukup satu perintah dari Director.

Semoga bermanfaat buat teman-teman yang lagi operate RHOSP atau OpenStack pada umumnya! Kalau ada kendala atau ide improvement (misalnya versi multi-hypervisor pakai Ansible inventory TripleO), feel free drop di kolom komentar ya.

Cheers!

Share: