Bali, Indonesia
Insights

Ketika Saran AI Gagal di Puncak Beban: Debugging Starvation I/O Firecracker dan Cgroup v2

October 13, 2026
0:00
Pada kuartal pertama 2026, implementasi agen AI dalam siklus diagnostik infrastruktur telah menjadi standar de facto di banyak tim platform. Model bahasa besar dan asisten otomatis sering kali diandalkan untuk menelaah log, merangkum metrik Prometheus, dan menyarankan patch operasional saat insiden terjadi. Namun, mesin probabilitas tetaplah mesin probabilitas; AI tidak memahami mekanika fisik transfer paket di kernel ring buffer atau lock contention di driver Ceph RBD ketika 15.000 Firecracker microVM dieksekusi serentak dalam satu bare-metal hypervisor. Ketika asisten AI menyarankan solusi generik seperti 'menaikkan vm.dirty_ratio' atau 'menambahkan vCPU quota', rekomendasi tersebut justru memicu starvation memori dan membuat host freeze selama 94 detik. Kejadian ini menegaskan prinsip fundamental: AI hanyalah alat bantu akselerasi sintaksis dan pencarian korelasi awal, sedangkan pemecahan masalah bottleneck latensi ekstrem pada sistem bare-metal tetap menuntut pemahaman mendalam atas interaksi kernel Linux, subsistem cgroup v2, dan arsitektur micro-virtualization.
Platform kami menjalankan sandbox komputasi aman multi-tenant untuk eksekusi kode dinamis. Setiap runner diisolasi menggunakan kombinasi Firecracker microVM (untuk tenant berisiko tinggi) dan unprivileged LXC container (untuk worker internal berlatensi ultra-rendah). Semua node komputasi menggunakan CPU dual-socket AMD EPYC 9654 (192 core, 384 thread), RAM 1,5 TB DDR5, dan dual 100GbE NIC dengan storage back-end Ceph Quincy via NVMe-oF/RBD. Alur eksekusi sandbox dirancang seringkas mungkin untuk mengejar start time di bawah 15 milidetik:
TEXT
+-------------------------------------------------------------+
|                        Bare-Metal Host                      |
|                                                             |
|  +--------------------+             +--------------------+  |
|  | Firecracker microVM|             |  Unprivileged LXC  |  |
|  | (Customer Code)    |             |  (Internal Task)   |  |
|  +---------+----------+             +---------+----------+  |
|            | tapX                             | vethX       |
|            v                                  v             |
|  +-------------------------------------------------------+  |
|  |             Linux Bridge (br-isolated)                |  |
|  +---------------------------+---------------------------+  |
|                              |                              |
|                              v                              |
|                 Kernel TCP/IP & XDP/eBPF Filter             |
|                              |                              |
|  +---------------------------+---------------------------+  |
|  |              Storage Block Driver (Ceph RBD)          |  |
|  +-------------------------------------------------------+  |
+-------------------------------------------------------------+
Ketika volume request melonjak hingga 45.000 runner per cluster dalam kurun waktu 3 menit, metrik p99 runtime execution time meledak dari 85ms menjadi 4.200ms. Agen AI operasional yang kami integrasikan ke incident channel mengidentifikasi metrik node_cpu_utilization sebesar 72% dan segera merekomendasikan penyesuaian cgroup limit: cpu.max dinaikkan ke nilai 'max' dan alokasi vm.dirty_background_ratio dinaikkan dari 5% ke 20%. Langkah ini salah kaprah. Root cause bukan kekurangan jatah siklus CPU, melainkan kombinasi softirq backlog di network device TAP dan antrean I/O yang tersumbat di level Ceph RBD client cache.
Asisten AI gagal membedakan antara CPU yang sibuk mengeksekusi instruksi pengguna dengan CPU yang terkunci di status softirq handling (ksoftirqd). Saat ribuan antarmuka TAP dibuat dan dihancurkan oleh Firecracker jailer dalam hitungan detik, alokasi buffer sk_buff di subsistem networking memicu lock contention hebat. Pemeriksaan awal menggunakan toolchain diagnostik kernel mengungkap anomali mendasar yang diabaikan oleh ringkasan log otomatis:
BASH
# Memeriksa distribusi softirq per-core saat insiden berlangsung
watch -n 1 'cat /proc/softirqs | grep -E "NET_RX|NET_TX|BLOCK"'

# Memeriksa kontensi kernel lock menggunakan perf
perf top -C 0-31 -e cycles:k --dsos=[kernel.kallsyms]
Output perf top menunjukkan bahwa 42% siklus clock pada core 0-31 terkuras di fungsi _raw_spin_lock_irqsave yang dipanggil oleh tun_net_xmit dan rbd_queue_rq. AI tidak mendeteksi ini karena metrik load average host masih tampak 'sehat' di bawah kapasitas core fisik.
TEXT
Overhead  Shared Object       Symbol
  28.14%  [kernel.kallsyms]   [k] _raw_spin_lock_irqsave
  14.22%  [kernel.kallsyms]   [k] tun_get_user
   9.18%  [kernel.kallsyms]   [k] __netif_receive_skb_core
   7.45%  [kernel.kallsyms]   [k] rbd_img_request_submit
   4.10%  [kernel.kallsyms]   [k] finish_task_switch
Masalah kedua berada di subsistem penyimpanan. Firecracker menggunakan direct I/O (O_DIRECT) secara default untuk backing file rootfs jika dikonfigurasi demikian, tetapi skrip otomatisasi yang dihasilkan oleh tim platform sebelumnya menggunakan konfigurasi cache bawaan (cache_type: Unsafe atau buffered write tanpa tuning O_SYNC). Akibatnya, jutaan dirty pages menumpuk di page cache host hypervisor, melumpuhkan garbage collection memori cgroup v2.
Secara default, Firecracker mengikat antarmuka jaringan microVM ke device TAP Linux. Saat concurrency meroket, panjang antrean txqueuelen bawaan sebesar 500 paket habis dalam hitungan mikrodetik, menyebabkan drop rate masif dan memaksa guest kernel melakukan TCP retransmit berulang kali. Untuk mengatasi hal ini, kita harus menyelaraskan txqueuelen pada TAP device, mengaktifkan multiqueue jika menggunakan vhost-net (atau mengoptimasi single ring size), dan mendistribusikan interupsi softirq ke core yang tidak bersaing dengan jailer vCPU threads. Konfigurasi pembuatan TAP device yang benar pada wrapper Firecracker:
BASH
#!/usr/bin/env bash
set -euo pipefail

TAP_DEV='tap-fc-01'
HOST_BR='br-isolated'

# Buat TAP interface tanpa perantara NetworkManager/systemd-networkd
ip tuntap add dev "${TAP_DEV}" mode tap vnet_hdr
ip link set dev "${TAP_DEV}" address 02:FC:00:00:00:01
ip link set dev "${TAP_DEV}" txqueuelen 4096
ip link set dev "${TAP_DEV}" up

# Sambungkan ke bridge dengan hairpin turned off
ip link set dev "${TAP_DEV}" master "${HOST_BR}"
bridge link set dev "${TAP_DEV}" hairpin off

# Isolasi CPU affinity untuk proses Firecracker jailer
CPU_CORE=12
JAILER_PID=$(pgrep -f "firecracker.*${TAP_DEV}" || true)
if [ -n "${JAILER_PID}" ]; then
    taskset -cp "${CPU_CORE}" "${JAILER_PID}"
fi
Alih-alih mengandalkan limitasi statis cpu.max atau memory.max yang sering diusulkan AI, kita harus memanfaatkan Pressure Stall Information (PSI) di Linux Kernel 6.6+ LTS untuk mendeteksi resource starvation sebelum latency meledak. Cgroup v2 menyediakan metrik cpu.pressure, memory.pressure, dan io.pressure. Berikut konfigurasi unit systemd slice untuk isolasi worker LXC dan microVM Firecracker guna mencegah satu tenant memonopoli bandwidth block storage Ceph:
INI
# /etc/systemd/system/microvm-workload.slice
[Unit]
Description=MicroVM and Container Sandbox Slice
Before=slices.target

[Slice]
# Alokasikan bobot I/O proporsional (BFQ / blkio cgroup v2)
IOAccounting=yes
IOWeight=100

# Batasi lonjakan dirty memory per slice agar Ceph tidak tersedak
MemoryAccounting=yes
MemoryHigh=1200G
MemoryMax=1300G
MemorySwapMax=0

# Hindari starvation scheduling dengan jatah CFS runtime terkontrol
CPUAccounting=yes
CPUWeight=100

# Proteksi resource tasks
TasksAccounting=yes
TasksMax=131072
Di tingkat kernel sysctl, kita wajib membatasi page cache dirty bytes berbasis ukuran mutlak, bukan rasio persentase yang bisa bernilai ratusan gigabyte pada host berkapasitas RAM 1,5 TB:
INI
# /etc/sysctl.d/99-microvm-storage-tuning.conf
# Menghindari flush storm ke Ceph RBD
vm.dirty_background_bytes = 268435456
vm.dirty_bytes = 1073741824

# Mempercepat interval penulisan dirty pages ke storage
vm.dirty_writeback_centisecs = 100
vm.dirty_expire_centisecs = 300

# Mencegah kswapd agresif yang memicu stall pada alokasi memory microVM
vm.vfs_cache_pressure = 50
vm.swappiness = 0

# Buffer network core untuk menangani jutaan sk_buff
net.core.netdev_max_backlog = 32768
net.core.somaxconn = 16384
net.core.rmem_max = 67108864
net.core.wmem_max = 67108864
Terapkan konfigurasi tersebut secara deterministik menggunakan terminal host:
BASH
sysctl --system
Saran AI yang menyarankan penambahan Ceph OSD daemon saat storage latency naik justru memperburuk situasi karena jaringan Ceph terbebani oleh peering traffic tambahan. Masalah sebenarnya berada di sisi client-side locking dan queue depth RBD pada host hypervisor. Setiap Firecracker microVM mengakses root filesystem ephemeral yang di-clone dari golden image via RBD copy-on-write snapshot. Konfigurasi default client Ceph menggunakan parameter locking yang memicu serialized barrier saat write request melonjak bersamaan. Konfigurasi ceph.conf pada host client yang disesuaikan untuk konkurensi ekstrem:
INI
[client]
# Nonaktifkan exclusive-lock dan journaling jika disk sepenuhnya ephemeral
rbd_default_features = 3

# Perbesar memory cache per host client process
rbd_cache = true
rbd_cache_writethrough_until_flush = false
rbd_cache_size = 67108864
rbd_cache_max_dirty = 50331648
rbd_cache_target_dirty = 33554432
rbd_cache_max_dirty_age = 2.0

# Optimasi queue depth untuk menghindari blocking di driver block
rbd_concurrent_management_ops = 64
rbd_request_timeout = 15
Pada sisi Firecracker, block device harus dikonfigurasi dengan io_engine: Sync (jika backing store menggunakan page cache yang sudah di-tuning) atau io_engine: Async menggunakan io_uring pada kernel modern untuk menghindari pemanggilan syscall pwritev berulang yang memicu context switch cost masif. Contoh payload JSON pembuatan drive pada socket API Firecracker via curl:
BASH
curl --unix-socket /tmp/firecracker.socket -X PUT 'http://localhost/drives/rootfs' \\
    -H 'Accept: application/json' \\
    -H 'Content-Type: application/json' \\
    -d '{
        "drive_id": "rootfs",
        "path_on_host": "/dev/rbd0",
        "is_root_device": true,
        "is_read_only": false,
        "rate_limiter": {
            "bandwidth": {
                "size": 104857600,
                "refill_time": 100
            },