eBPF ve bpftool ile Linux Çekirdek Düzeyinde Süreç Davranışını İzleme

Üretim ortamında bir süreç aniden kontrolden çıkıyor, CPU’yu eritiyor ama klasik araçlarla nedeni anlamak için yeterli görünürlüğünüz yok. top, htop, strace gibi araçlar bir noktaya kadar götürüyor sizi. Ama çekirdek düzeyinde gerçekte ne olduğunu görmek istiyorsanız, yani hangi sistem çağrıları yapılıyor, hangi dosyalara dokunuluyor, ağ bağlantıları nasıl kuruluyor, bunları düşük maliyetle ve canlı ortamda izlemek istiyorsanız, eBPF dünyasına adım atmanız gerekiyor.

Ben bu teknolojiye 2020 yılında ciddi anlamda geçiş yaptım ve açıkçası o günden bu yana Linux izleme konusundaki bakış açım köklü biçimde değişti. Bu yazıda hem eBPF’in ne olduğunu hem de bpftool ile pratik kullanımını gerçek dünya senaryolarıyla ele alacağız.

eBPF Nedir ve Neden Önemlidir

eBPF, “extended Berkeley Packet Filter” kelimelerinin kısaltmasıdır ama bu isim aslında teknolojinin ne yaptığını tam olarak yansıtmıyor. Özünde, kullanıcı alanından çekirdek kaynak kodunu değiştirmeden veya modül yüklemeden, çekirdek içinde küçük programlar çalıştırmanıza olanak tanıyan bir sanal makine mekanizmasıdır.

Geleneksel izleme araçları ya yüksek overhead yaratır (strace bir sürecin %100-200 yavaşlamasına yol açabilir) ya da çekirdek modülü gerektirir ki bu da üretim ortamında ciddi bir risk anlamına gelir. eBPF ise farklı bir denklem kurar:

  • Güvenli çalışma: Programlar çekirdeğe yüklenmeden önce bir verifier tarafından kontrol edilir. Sonsuz döngü, geçersiz bellek erişimi gibi durumlar engellenir.
  • Düşük overhead: JIT derlemesi sayesinde native koda yakın performans sağlanır.
  • Dinamik bağlama: Çalışan sistemi durdurmadan, yeniden başlatmadan programları ekleyip çıkarabilirsiniz.
  • Çok yönlülük: Ağ filtreleme, güvenlik izleme, performans analizi, hatta paket yönlendirme gibi alanlarda kullanılabilir.

Linux 4.x serisinden itibaren olgunlaşmaya başlayan eBPF, 5.x serisinde gerçek anlamda üretim kalitesine ulaştı. Cloudflare, Facebook (Meta), Netflix gibi şirketler altyapılarının kritik parçalarında eBPF kullanıyor.

Ortam Kurulumu

Başlamadan önce sisteminizin hazır olduğundan emin olalım. Ubuntu 22.04 veya RHEL 8+ üzerinde çalışıyorsanız çoğu şey hazır gelecektir.

# Kernel versiyonunu kontrol et - 5.x önerilen
uname -r

# Ubuntu/Debian için
sudo apt install -y bpfcc-tools bpftool linux-headers-$(uname -r) 
    libbpf-dev clang llvm

# RHEL/CentOS için
sudo dnf install -y bpftool bcc bcc-tools kernel-devel clang llvm

# eBPF dosya sistemini bağla (genellikle otomatik gelir)
sudo mount -t bpf bpf /sys/fs/bpf

# bpftool versiyonunu kontrol et
sudo bpftool version

eBPF programları için BTF (BPF Type Format) desteği de önemli. Çekirdeğinizin BTF ile derlenip derlenmediğini kontrol edin:

ls -la /sys/kernel/btf/vmlinux
# ya da
sudo bpftool btf list

Eğer bu dosya varsa, CO-RE (Compile Once, Run Everywhere) yaklaşımıyla yazdığınız programlar farklı çekirdek versiyonlarında da çalışabilir.

bpftool ile İlk Adımlar

bpftool, BPF objelerini (programlar, haritalar, bağlantılar) incelemenizi ve yönetmenizi sağlayan resmi araçtır. Sisteminizde halihazırda çalışan eBPF programlarını görmekle başlayalım:

# Yüklü BPF programlarını listele
sudo bpftool prog list

# Daha ayrıntılı çıktı
sudo bpftool prog list --pretty

# Belirli bir programın detaylarına bak
sudo bpftool prog show id 42

# BPF haritalarını listele
sudo bpftool map list

# Harita içeriğini dök (örneğin hash map)
sudo bpftool map dump id 15

# Sistem üzerindeki BPF bağlantılarını gör
sudo bpftool link list

Boş bir sistemde bile birkaç eBPF programı yüklü olabilir. Systemd, Docker ve bazı güvenlik araçları arka planda eBPF kullanmaya başladı. Bu çıktıları incelemek, sisteminizde hangi izleme mekanizmalarının çalıştığını anlamak açısından son derece değerli.

BCC Araçları ile Pratik Süreç İzleme

eBPF programları doğrudan C ile yazılabilir ama BCC (BPF Compiler Collection) kütüphanesi Python veya Lua kullanarak çok daha hızlı geliştirme yapmanızı sağlar. BCC ile birlikte gelen hazır araçlar ciddi zaman kazandırır.

Sistem Çağrısı İzleme

Belirli bir süreci sistem çağrısı düzeyinde izlemek için bpftrace mükemmel bir seçenek:

# Belirli bir sürecin tüm sistem çağrılarını izle
sudo bpftrace -e 'tracepoint:raw_syscalls:sys_enter /pid == 1234/ { printf("%s(%d)n", probe, args->id); }'

# open() çağrılarını tüm süreçler için izle ve dosya adını göster
sudo bpftrace -e 'tracepoint:syscalls:sys_enter_openat { printf("%s açtı: %sn", comm, str(args->filename)); }'

# Belirli bir binary'nin exec çağrılarını yakala
sudo bpftrace -e 'tracepoint:syscalls:sys_enter_execve { printf("PID %d: %s çalıştırdı: %sn", pid, comm, str(args->filename)); }'

Bu üç satırlık komut, bir SOC ekibinin saatlerce uğraşacağı soruları dakikalar içinde cevaplayabilir. Üretimde bir şüpheli süreç mi var? execve hookunu açın ve hangi komutları çalıştırdığına bakın.

Dosya Sistemi Aktivitesi İzleme

# Dosya silme işlemlerini izle (unlink/unlinkat)
sudo bpftrace -e '
tracepoint:syscalls:sys_enter_unlinkat {
    printf("SİLİNDİ - PID: %d, Komut: %s, Dosya: %sn",
        pid, comm, str(args->pathname));
}'

# Belirli bir dizindeki yazma işlemlerini izle
sudo bpftrace -e '
tracepoint:syscalls:sys_enter_write
/pid > 100/ {
    printf("YAZMA - PID: %d (%s), FD: %d, Boyut: %d bytesn",
        pid, comm, args->fd, args->count);
}'

Bir keresinde üretim sunucusunda /tmp altında sürekli büyüyen gizemli dosyalar vardı. Tam olarak hangi sürecin yazdığını bulmak için bu yaklaşımı kullandım ve sonuçta hatalı yapılandırılmış bir log rotation script’i sorumluydı. strace -f ile bulmak dakikalar alırdı ve süreci ciddi şekilde yavaşlatırdı. eBPF ile bulmak on saniye sürdü.

Ağ Düzeyinde Süreç İzleme

eBPF’in en güçlü kullanım alanlarından biri ağ gözlemlenebilirliğidir. Hangi süreç, hangi IP’ye, hangi porta bağlanıyor?

# TCP bağlantılarını izle (kaynak, hedef, süreç)
sudo bpftrace -e '
kprobe:tcp_connect {
    $sk = (struct sock *)arg0;
    printf("TCP BAĞLANTI - PID: %d (%s) -> %s:%dn",
        pid, comm,
        ntop(AF_INET, $sk->__sk_common.skc_daddr),
        $sk->__sk_common.skc_dport >> 8);
}'

# DNS sorgularını yakala (UDP port 53)
sudo bpftrace -e '
tracepoint:syscalls:sys_enter_sendto
/args->addr != 0/ {
    printf("DNS/UDP GÖNDER - PID: %d (%s)n", pid, comm);
}'

Güvenlik açısından bu çok kritik. Bir container içinde çalışan bir servis, beklenmedik bir dış adrese bağlantı kurmaya çalışıyorsa, bunu gerçek zamanlı görebilmek paha biçilmez.

Performans Analizi: CPU ve Bellek

Süreç davranışını anlamak sadece ne yaptıklarını değil, ne kadar kaynak tükettiklerini ve neden tükettiklerini anlamayı da içerir.

# On-CPU profiling - hangi fonksiyonlar CPU'yu tüketiyor
sudo bpftrace -e '
profile:hz:99 /pid == 1234/ {
    @[ustack] = count();
}
interval:s:10 {
    print(@);
    clear(@);
}'

# Bellek tahsis örüntülerini izle
sudo bpftrace -e '
uprobe:/lib/x86_64-linux-gnu/libc.so.6:malloc {
    @allocs[comm] = sum(arg0);
}
interval:s:5 {
    print(@allocs);
    clear(@allocs);
}'

profile:hz:99 çok değerli bir pattern. 99 Hz’de örnekleme yaparak (100 Hz’de zamanlayıcı ile etkileşimi önlemek için 99 seçilir), hangi kod yollarının CPU’yu tükettiğine dair istatistiksel bir tablo çıkarırsınız. Bunu bir flamegraph’a dönüştürürseniz, uygulamanızın performans darboğazlarını görsel olarak anlayabilirsiniz.

bpftool ile Yüklü Program İncelemesi

bpftool sadece programları listelemekle kalmaz, detaylı introspection da sağlar:

# BPF programının bytecode'unu göster
sudo bpftool prog dump xlated id 42

# JIT edilmiş native kodu göster
sudo bpftool prog dump jited id 42

# Program istatistiklerini izle (run_time, run_cnt)
sudo bpftool prog show id 42 --pretty

# Tüm BPF haritalarını ve içeriklerini JSON formatında al
sudo bpftool map dump id 7 --pretty

# BPF objelerini pin'le (dosya sistemi üzerinden erişim için)
sudo bpftool prog pin id 42 /sys/fs/bpf/my_program

# Pinlenmiş programı incele
sudo bpftool prog show pinned /sys/fs/bpf/my_program

Bu özellik özellikle güvenlik denetimleri sırasında işe yarar. Bir sistemde hangi eBPF programlarının çalıştığını ve bunların ne yaptığını anlamak, güvenlik ekipleri için önemli bir denetim noktasıdır. Bir saldırgan rootkit’ini eBPF üzerinden gizlemeye çalışıyorsa, bpftool ile bu programları tespit edebilirsiniz.

Gerçek Dünya Senaryosu: Runaway Süreci Analizi

Şimdi gerçekçi bir senaryo üzerinden gidelim. Üretimde bir Java uygulaması saatlerdir yüksek CPU kullanıyor. JVM dump almak isteğiniz ama bunu yapacak yetersiz erişiminiz var. eBPF ile dışarıdan ne öğrenebilirsiniz?

# Önce sürecin PID'ini bulalım
ps aux | grep java
# Diyelim ki PID: 8742

# Bu sürecin sistem çağrısı profilini çıkar (10 saniye)
sudo bpftrace -e '
tracepoint:raw_syscalls:sys_enter /pid == 8742/ {
    @syscalls[args->id] = count();
}
interval:s:10 {
    print(@syscalls);
    exit();
}'

# Garbage collection nedeniyle mi yavaş? mmap/mprotect çağrılarına bak
sudo bpftrace -e '
tracepoint:syscalls:sys_enter_mmap /pid == 8742/ {
    printf("mmap: boyut=%d, prot=%dn", args->len, args->prot);
}
tracepoint:syscalls:sys_enter_munmap /pid == 8742/ {
    printf("munmap: boyut=%dn", args->len);
}'

# Hangi dosyalara erişiyor?
sudo bpftrace -e '
tracepoint:syscalls:sys_enter_openat /pid == 8742/ {
    printf("AÇILAN: %sn", str(args->filename));
}' 2>/dev/null | head -50

Bu üç adım genellikle sorunun kaynağını ortaya koyar. Eğer futex sistem çağrıları baskınsa kilit çekişmesi vardır. Eğer read/write yoğunsa IO beklemesi söz konusudur. mmap/munmap yoğunluğu GC baskısına işaret edebilir.

Güvenlik İzleme: Şüpheli Davranış Tespiti

eBPF, HIDS (Host-based Intrusion Detection System) için mükemmel bir altyapı sağlar. İşte birkaç kritik kontrol noktası:

# Privilege escalation girişimlerini izle
sudo bpftrace -e '
tracepoint:syscalls:sys_enter_setuid {
    if (args->uid == 0) {
        printf("UYARI: UID 0 girişimi! PID: %d, Komut: %sn",
            pid, comm);
    }
}'

# /etc/passwd veya /etc/shadow erişimlerini yakala
sudo bpftrace -e '
tracepoint:syscalls:sys_enter_openat {
    $file = str(args->filename);
    if ($file == "/etc/passwd" || $file == "/etc/shadow") {
        printf("KRİTİK DOSYA ERİŞİMİ - PID: %d (%s): %sn",
            pid, comm, $file);
    }
}'

# Olağandışı network dinleme soket oluşturma
sudo bpftrace -e '
tracepoint:syscalls:sys_enter_bind {
    printf("BIND - PID: %d (%s), FD: %dn",
        pid, comm, args->fd);
}'

Bu tür izleme, Falco ve Tetragon gibi araçların temelinde yatan mantığın aynısıdır. Farkı, bu araçları beklemek yerine kendi ihtiyacınıza özel, minimal overhead’li bir çözümü hızla yazabilmenizdir.

bpftool ile Map Tabanlı Veri Toplama

eBPF programları sonuçlarını BPF haritaları (maps) üzerinden kullanıcı alanına aktarır. Bu haritaları bpftool ile okuyabilirsiniz:

# Çalışan bir BPF programının haritalarını bul
sudo bpftool prog show id 42 --pretty | grep map_ids

# Harita tiplerini ve boyutlarını göster
sudo bpftool map list

# Hash map içeriğini oku
sudo bpftool map dump id 15

# Belirli bir key için değer sorgula
sudo bpftool map lookup id 15 key 0x01 0x00 0x00 0x00

# Haritaya manuel değer yaz (test amaçlı)
sudo bpftool map update id 15 key 0x01 0x00 0x00 0x00 value 0x00

# Perf event haritalarını izle (ring buffer)
sudo bpftool map event-pipe id 20

Perf event tabanlı haritalar özellikle yüksek frekanslı olayları düşük latency ile kullanıcı alanına iletmek için kullanılır. map event-pipe komutu bu haritaları gerçek zamanlı dinlemenizi sağlar.

Libbpf ile Minimal C Programı

BCC veya bpftrace kullanmadan, doğrudan libbpf ile minimal bir izleme aracı yazmak da mümkün. Bu daha fazla kontrol sağlar ve binary dağıtımı açısından avantajlıdır:

# Basit bir eBPF skeleton oluşturmak için araçları kontrol et
sudo bpftool gen skeleton my_prog.bpf.o > my_prog.skel.h

# BTF bilgisini çıkar ve incele
sudo bpftool btf dump file /sys/kernel/btf/vmlinux format raw | head -50

# Kernel struct layoutlarını göster (CO-RE için kritik)
sudo bpftool btf dump file /sys/kernel/btf/vmlinux format c | grep -A 20 "struct task_struct"

Bu son komut özellikle ilginç. task_struct Linux’ta her süreci temsil eden yapıdır ve eBPF programları bu yapıya erişerek süreç hakkında her türlü bilgiye ulaşabilir.

Overhead ve Üretim Güvenliği

eBPF güvenli olmakla birlikte, bilinçsiz kullanım overhead yaratabilir. Bazı pratik kurallar:

  • Tracepoint vs kprobe: Tracepoint’ler kararlı API’lerdir, kprobe’lar çekirdek iç fonksiyonlarını hooklar ve çekirdek güncellemeleriyle kırılabilir.
  • Örnekleme kullanın: Her olayı kaydetmek yerine profile:hz:99 gibi örnekleme tabanlı yaklaşımlar tercih edin.
  • Harita boyutlarını sınırlayın: Sınırsız büyüyen haritalar bellek sorunlarına yol açar.
  • Veriler kullanıcı alanına ne zaman: Yoğun veri akışını kernel tarafında filtreleyin, sadece ilgilendiğinizi kullanıcı alanına gönderin.
# Overhead'i ölçmek için bpftool istatistiklerini kullan
sudo sysctl kernel.bpf_stats_enabled=1
sudo bpftool prog list
# run_time_ns ve run_cnt değerlerine bakın
sudo sysctl kernel.bpf_stats_enabled=0

kernel.bpf_stats_enabled sysctl’i etkinleştirildiğinde, bpftool prog list çıktısında her programın toplam çalışma süresi ve çağrılma sayısı görünür. Bu değerler, eBPF programınızın sisteme ne kadar yük bindirdiğini anlamanızı sağlar.

Sonuç

eBPF ve bpftool, Linux sistem yöneticisi ve DevOps mühendisi olarak araç kutunuza eklemeniz gereken teknolojilerden biri haline geldi. Artık bu bir araştırma projesi değil; Kubernetes ağ politikaları (Cilium), güvenlik izleme (Falco, Tetragon) ve performans analizi (Parca, Pyroscope) gibi araçların üretim altyapısında günlük olarak kullandığı olgun bir teknoloji.

Başlangıç için önerdiğim yol: önce bpftrace one-liner’larla başlayın. Mevcut sisteminizdeki eBPF programlarını bpftool prog list ile inceleyin, Docker veya Kubernetes varsa Cilium veya Falco’nun ne tür programlar yüklediğini görün. Sonra bcc-tools paketinin içindeki hazır araçları keşfedin: execsnoop, opensnoop, tcpconnect, biolatency bunların her biri birer hazır eBPF aracıdır ve anında kullanıma hazır.

Bu teknolojiye yatırım yapmanın karşılığını ilk ciddi üretim olayında alacaksınız. O an geldiğinde, saatlerce strace ve log dosyası karıştırmak yerine, birkaç bpftrace satırıyla sorunun kaynağına indiğinizde, bu yazıyı hatırlayacaksınız.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir