Topologi dan Anatomi Beban Kerja
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) | |
| +-------------------------------------------------------+ |
+-------------------------------------------------------------+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.
Diagnostik Tingkat Rendah: Mengurai Kegagalan Diagnosis AI
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]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_switchO_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.
Anatomi Masalah: Network TAP vs VirtIO Buffers
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}"
fiIsolasi Cgroup v2 dan Pressure Stall Information (PSI)
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=131072INI
# /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 = 67108864BASH
sysctl --systemStorage Contention: Tuning Ceph RBD untuk Ephemeral MicroVMs
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 = 15io_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
},