Follow

Sunucularda Kaynak QoS’u: cgroups v2 ile CPU/Memory/IO Sınırlandırması ve Pratik Senaryolar

🎧 Bu yazıyı dinleyebilirsiniz

Uzun yıllardır altyapı işlerindeyim; en sinir bozucu şeylerden biri, bir sunucuda tek bir işlem veya görev yüzünden tüm servislerin yavaşlamasıdır. Bu yazıda, Linux’ta cgroups v2 kullanarak CPU, bellek ve disk I/O için nasıl güvenilir QoS (Quality of Service) sağlayabileceğinizi, gerçek senaryolarda hangi adımları uyguladığımı ve dikkat etmeniz gerekenleri paylaşacağım.

cgroups v2 nedir, neden tercih etmeliyiz?

cgroups (control groups), işletim sistemine hangi süreçlerin ne kadar kaynak kullanabileceğini sınırlama yeteneği verir. cgroups v2, önceki sürüme göre daha tutarlı bir arayüz ve işler arasında kaynak kontrolünde daha az sürpriz sunar. Özellikle paylaşılan altyapıda “noisy neighbor” (gürültü yapan komşu) problemini azaltmak için iyi bir araç setidir.

Temel kavramlar: CPUWeight, MemoryMax, io.max / io.weight

  • CPUWeight: CPU zamanını göreli olarak dağıtır. 100 ile 10000 arası değer alır; yüksek olan daha çok CPU zamanı alır.
  • MemoryMax: cgroup içindeki süreçlerin kullanabileceği maksimum bellek (ör. 2G, 512M).
  • io.max / io.weight: Blok cihazlara yönelik I/O sınırlamaları. io.max ile belirli cihaz için maksimum IOPS veya throughput kısıtlanır; io.weight ile paylaşılan I/O üzerinden paylaştırma yapılır.

Nasıl başlayalım — hazırlık ve ölçüm

Her değişiklikten önce ölçmek şart. Ben önce şu araçlarla problemi tespit ediyorum:

  • iostat -x 1 — disk kullanımını ve beklemeleri görmek için
  • iotop -aoP — hangi süreçlerin I/O yaptığını tespit etmek için
  • pidstat -r -u 1 — süreç bazlı CPU ve bellek kullanımı

Bu veriler hangi kaynağın sınırlandırılacağına karar verir. Örneğin backup süreci yüksek I/O; arka planda çalışan raporlama ise CPU tüketiyor olabilir.

Pratik: Basit bir cgroup v2 oluşturup sınır koyma (komut örnekleri)

Çoğu dağıtımda cgroups v2 ya aktiftir ya da kolayca etkinleştirilebilir. Örnek adımlar (root olarak):

# cgroups v2 mount noktası kontrolü
mount | grep cgroup2

# Yeni bir cgroup dizini oluştur
mkdir -p /sys/fs/cgroup/limited_jobs

# Bellek sınırı (2GB)
echo "2G" > /sys/fs/cgroup/limited_jobs/memory.max

# CPU göreli ağırlık (normalden daha az):
echo 100 > /sys/fs/cgroup/limited_jobs/cpu.weight

# IO için belirli bir blok aygıtına (ör. /dev/sda) throughput limiti: (ör. 20MB/s)
# önce major:minor değerini bulun
stat -c "%t:%T" /dev/sda
# veya
ls -l /dev/sda
# sonra io.max yazın (örnek: 8:0 20480 rbps)
echo "8:0 rbps=20480 wbps=20480" > /sys/fs/cgroup/limited_jobs/io.max

# Bir süreci cgroup'a taşımak (PID 12345 örneği)
echo 12345 > /sys/fs/cgroup/limited_jobs/cgroup.procs

Not: dosya yazımıyla doğrudan müdahale birçok durumda işe yarar, ama servisleri yönetmek için systemd veya uygun runtime API’lerini kullanmak genelde daha güvenlidir.

systemd ile entegrasyon (kısaca)

Eğer servisleriniz systemd ile çalışıyorsa, unit seviyesinde kaynak ayarı koymak en temiz yol. Örneğin bir dilim (slice) tanımlayıp üstünde görevleri çalıştırabilirsiniz:

# Geçici olarak bir komut çalıştırıp sınırlama koyma
systemd-run --slice=limited.slice -p MemoryMax=1G -p CPUWeight=100 --unit=backup-job /usr/local/bin/backup.sh

# Kalıcı bir unit dosyası kullanmak isterseniz /etc/systemd/system/limited.slice.d/override.conf içinde ayarlar yapabilirsiniz.

Container ortamlarında pratik yaklaşımlar

Docker veya Podman kullanıyorsanız runtime flag’leri ile limit koyabilirsiniz:

# Docker örnekleri
docker run --cpus=1.5 --memory=1g --device-write-bps /dev/sda:20mb my-image

# Podman için benzer flag'ler
podman run --cpus=1.5 --memory=1g --device-write-bps /dev/sda:20mb my-image

Ancak konteyner orkestra katmanında (kubernetes gibi) bu ayarlar farklı yerlere taşınır; kubelet veya containerd konfigürasyonlarına bakmak gerekir.

Pratik öneriler — benim uyguladıklarım

  • Ölçmeden sınır koymayın: İlk başta temkinli limitler koyun, prod performans testleri yapın.
  • Batch işlerini dış saatlere taşıyın: Backup/replication işleri için ayrı slice oluşturup düşük öncelik verin.
  • IO kısıtını cihaz bazında ayarlayın: SSD ile NVMe farklı davranır; throughput yerine IOPS sınırlamak gerekebilir.
  • OOM yönetimi: MemoryMax çok sıkı olursa OOM oluşur; memory.high ve swap kullanımı ile dengeli yaklaşın.
  • Monitoring ve alarm: iostat/iotop verilerini Prometheus + node_exporter ile toplayıp I/O latency eşiği koyun.
  • Belirli süreçleri izolasyon için yeni kullanıcılara/işlemsel hesaplara koyun: OS seviyesinde ayrışma, limitlerin uygulanmasını kolaylaştırır.

Kapanış — küçük hikaye

Bir defasında gece gelen tam disk yedeği, sabah vakti veritabanı sorgularını 10 kata kadar yavaşlatmıştı. İki saatlik panikten sonra IO weight ile backup job’u %10 önceliğe çekip, veritabanını normale döndürdüm. Sonra aynı hatayı tekrar etmemek için bu işi otomatik bir slice içinde çalıştırıp kalıcı limitler koydum. İşin özü: doğru ölçü, küçük katmanlı kısıt ve izlemeyle, “bütün sunucu çöktü” hikayeleri çok daha nadir oluyor.

Uygulamak istediğin belirli bir senaryo varsa (yüksek IOPS yapan bir yedek, veritabanı iş yükü, VM host vs.) yaz; birlikte hangi kontrolleri koyacağımızı adım adım planlayalım.

Comments
Join the Discussion and Share Your Opinion
Add a Comment

Bir yanıt yazın

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


Newsletter
Join Design Community
Get the latest updates, creative tips, and exclusive resources straight to your inbox. Let’s explore the future of design and innovation together.