Yazılara geri dön
Yazı

Linux Yüksek CPU: Kernel Space Sorun Giderme Rehberi

top yüksek CPU gösteriyor ama süreç yoksa sorun kernel'da. Üretim sunucularında kernel-space CPU kullanımını nasıl profiliyorum?

SistemLinuxkernel troubleshootingCPU usageperfperformance tuningsysadmin

top %90 CPU kullanımı gösteriyor ama hiçbir kullanıcı süreci buna sebep değilse, kernel-space CPU tüketimiyle karşı karşıyasınız demektir. Benim ortamımda bu, sanılandan daha sık yaşanır — softirq fırtınaları, lock çakışmaları, I/O bekleme süresi veya bir sürücü hatası sessizce CPU döngülerini yakar. Linux yüksek CPU kullanımı kernel sorun giderme işi, süreç listesinin ötesine bakıp kernel'in zamanını nerede harcadığını profilleme meselesidir. İşte olağan şüpheliler temiz çıktığında buna nasıl yaklaştığım.

top ve htop Sizi Nasıl Yanıltabilir

Klasik hata: top'u açarsınız, CPU'ya göre sıralarsınız ve bir sürü süreci %1-2'de görürsünüz. Ama sistem %95 yükte ve SSH dial-up gibi hissettirir. Sorun şu ki, top varsayılan olarak user-space CPU'yu gösterir. Kernel zamanı — syscall'lerde, interrupt işlemlerinde, softirq işlemlerinde ve scheduler yükünde harcanan zaman — genellikle tek bir sürece temiz şekilde atfedilmez.

top'taki %Cpu(s) satırına bakın. sy (system) değerini %60 ve us (user) değerini %5 görüyorsanız, o sizin kırmızı bayrağınızdır. Ağır işi kernel yapıyor, uygulamanız değil.

%Cpu(s):  3.2 us, 71.5 sy,  0.0 ni, 12.1 id, 13.2 wa,  0.0 hi,  0.0 si,  0.0 st

Bu çıktıda %71.5 olan sy bana kernel'in CPU'yu yaktığını söylüyor. %13.2 olan wa ise I/O bekleme süresinin de katkıda bulunduğu anlamına geliyor. Hiçbir tek süreç bunu açıklamayacak.

Önce softirq ve Donanım Interrupt'larını Kontrol Edin

Softirq'lar ertelenmiş interrupt işleyicileridir. Ağ paket işleme (NET_RX), timer tick'leri ve block I/O tamamlama işlemlerinin hepsi burada çalışır. Yüksek ağ veri hacmine sahip yoğun e-ticaret sunucularında, NIC interrupt'ları CPU'lar arasında dağıtmadığı için ksoftirqd'in bütün bir çekirdeği tükettiğini gördüm.

Şununla başlayın:

cat /proc/interrupts
watch -n1 "cat /proc/softirqs"

NET_RX tek bir CPU'da hızla artarken diğerleri boştaysa, bir interrupt affinity sorununuz var demektir. NIC'nizde RSS (Receive Side Scaling) etkin mi kontrol edin:

ethtool -l eth0
ethtool -L eth0 combined 4

Bu, receive interrupt'larını birden çok kuyruğa yayar. Fiziksel sunucularda ayrıca irqbalance veya manuel /proc/irq/*/smp_affinity maskelerini kullanarak IRQ'ları sabitlerim. Daha önce ağ sorun giderme yazımda (https://furkanikkan.com/urun/ag-yavasliginin-gercek-nedenini-bulmanin-7-yolu-50) belirttiğim gibi, kök neden genellikle beklediğiniz yerde olmaz — ve interrupt dağılımı o sessiz katillerden biridir.

Başka Hiçbir Şey Konuşmadığında Kernel'i perf ile Profilleyin

Softirq ve interrupt kontrolleri normal döndüğünde, direkt perf'e geçerim. Size tam olarak hangi kernel fonksiyonunun CPU'yu yaktığını söyleyen araç budur. Tahmin yok.

perf record -a -g -- sleep 30
perf report

-g bayrağı, en üst düzey kernel fonksiyonundan en uçtaki fonksiyona kadar izleyebilmeniz için çağrı grafiklerini yakalar. Aradığınız şeyler:

  • __do_softirq, net_rx_action veya tcp_v4_rcv gibi fonksiyonlar → ağ yığını baskısı
  • __blk_run_queue, blk_update_request → block I/O katmanı
  • __schedule, try_to_wake_up → scheduler çakışması veya aşırı context switching
  • futex_wait_queue_me, rwsem_down_read_slowpath → lock çakışması

Tam raporu istemediğimde kullandığım pratik bir komut:

perf top

Bu, kernel fonksiyonlarının CPU kullanımına göre canlı ve güncellenen bir görünümünü verir — kernel iç yapıları için top gibi.

İpucu: perf yüklü değilse, kernel sürümünüz için linux-tools paketini kurun. Debian/Ubuntu'da: apt install linux-tools-$(uname -r).

I/O Bekleme Süresinin Kernel CPU Olarak Gizlenmesi

Geçen yıl beni ısıran bir durum. Bir Proxmox sunucusunda top %40 sy ve %30 wa gösteriyordu. Her süreç normal görünüyordu. Meğer ZFS ARC, bir yedekleme işi dönen disklerden soğuk veri okuduğu için çalkalanıyormuş ve kernel bütün zamanını I/O tamamlanmasını bekleyerek block katmanında harcıyormuş.

Kilit tanılama:

iostat -xz 1

Belirli bir cihazda %util değerinin 100'e yakın olmasına ve yüksek await değerlerine bakın. await SSD'lerde 20-30ms'nin üzerindeyse veya HDD'lerde 100ms'nin üzerindeyse, kernel I/O'da bloke oluyor ve o bekleme kuyruğunu yönetirken CPU döngülerini yakıyor demektir.

Kontrol ettiğim diğer araçlar:

  • vmstat 1r sütunu (çalışabilir süreçler) yüksek ama CPU %100 user değilse, kernel ağır bir şekilde context-switch yapıyordur
  • sar -w 1 — context switch oranı; tek bir CPU'da saniyede 50.000'in üzerindeki her şey araştırılmalıdır
  • pidstat -w 1 — süreç başına context switch'leri gösterir, suçluyu belirlemeye yardımcı olur

Lock Çakışması ve Scheduler Yükü

Bazen kernel sadece kendini yöneterek CPU yakar. Lock çakışması, birden fazla CPU aynı spinlock veya rwsem için savaştığında olur. Bunu, yüksek syscall oranına sahip yoğun veritabanı sunucularında ve bilinen scheduler hataları olan eski kernel'leri çalıştıran sistemlerde gördüm.

perf, en üstte _raw_spin_lock, queued_spin_lock_slowpath veya rwsem_down_write_slowpath gibi fonksiyonları gösterecektir. Bu olduğunda:

  1. Kernel sürümünüzü kontrol edin — eski 4.x kernel'lerde yüksek ağ yükü altında bilinen spinlock sorunları vardı
  2. sysctl kernel.sched_migration_cost_ns değerine bakın — bunu düşürmek NUMA sistemlerinde scheduler yükünü azaltabilir
  3. Scheduler davranışını özel olarak profilleme için perf sched kullanın:
perf sched record -- sleep 10
perf sched latency --max

Bu, hangi görevlerin en yüksek zamanlama gecikmesine sahip olduğunu ve hangi CPU'ların bir scheduler perspektifinden aşırı yüklü olduğunu gösterir.

Hedeflenmiş Kernel İzleme için Ftrace

perf size fonksiyon adını verdiğinde ama ne zaman ve ne sıklıkta çağrıldığını görmeniz gerektiğinde, ftrace bir sonraki adımdır. Kernel'in içine yerleşiktir — paket gerekmez.

echo 1 > /sys/kernel/debug/tracing/events/sched/sched_switch/enable
cat /sys/kernel/debug/tracing/trace_pipe | head -50

Bu, context switch olaylarını gerçek zamanlı olarak akar. İki belirli süreç arasında saniyede binlerce switch görüyorsanız, bir zamanlama fırtınası yakalamışsınız demektir.

Fonksiyon seviyesinde izleme için:

echo function > /sys/kernel/debug/tracing/current_tracer
echo tcp_v4_rcv > /sys/kernel/debug/tracing/set_ftrace_filter
echo 1 > /sys/kernel/debug/tracing/tracing_on

Artık tcp_v4_rcv'ye yapılan her çağrı zaman damgasıyla günlüğe kaydedilir. Bunu bir keresinde, hiçbir user-space süreci dahil olmadan kernel CPU sıçramalarına neden olan bir SYN flood'u takip etmek için kullanmıştım.

Hızlı Tanılama Kontrol Listesi

Yüksek CPU için sayfa aldığımda ve süreç listesi temiz göründüğünde, sıram şöyledir:

  • top %Cpu(s) satırını kontrol edin — sy veya wa yüksek mi?
  • cat /proc/softirqs ve cat /proc/interrupts çalıştırın — tek bir CPU aşırı yüklü mü?
  • 30 saniye boyunca perf top — hangi kernel fonksiyonu baskın?
  • iostat -xz 1 — bir disk %100 util'de mi?
  • vmstat 1 — yüksek context switch'ler mi veya çalışabilir süreçler mi?
  • dmesg | tail — son saatte herhangi bir kernel uyarısı veya hatası var mı?

En sonuncusu bariz görünebilir, ama arızalı bir NIC'ı tekrar tekrar sıfırlayan bir sürücüyü gösteren tek bir dmesg çıktısıyla gizemleri çözdüm. Kernel, süreç listesinde hiçbir zaman görünmeyen hata işleme ve kurtarma döngülerinde CPU harcıyordu.

Kernel-space CPU sorunları, standart araçlar süreçler etrafında inşa edildiği için zor olur. perf, ftrace ve interrupt analiziyle kernel'in kendisini profilleme noktasına geçtiğinizde, kök neden genellikle birkaç dakika içinde ortaya çıkar. Zor olan kısım, oraya bakmayı ilk başta hatırlamaktır.


Kapak görseli: Operate, Defend, Attack, Influence! · PDM (Openverse / kamu malı) · https://www.flickr.com/photos/131622585@N06/48986472741