7.6 GB RAM’li Bir VPS’de Kubernetes Denemesi
Küçük ölçekli sunucu ortamlarında, özellikle de sadece 7.6 GB RAM’e sahip bir Virtual Private Server (VPS) üzerinde Kubernetes gibi kaynak yoğun bir platformu çalıştırmaya çalışmak, genellikle beklenmedik ve can sıkıcı sorunlara yol açabiliyor. Bu yazıda, kendi VPS’imde Kubernetes’i kurarken karşılaştığım “swap yangını” problemine ve bu sorunu nasıl aştığıma dair deneyimlerimi aktaracağım. Amacım, bu tür durumlarda neyin ters gidebileceğini, neden ters gittiğini ve en önemlisi, bu tür bir altyapı kurarken nelere dikkat etmemiz gerektiğini somut örneklerle anlatmak.
Bu deneme, tamamen öğrenme amaçlıydı. Prodüksiyon ortamları için bu kadar kısıtlı kaynaklarla Kubernetes çalıştırmak pek mantıklı olmasa da, bu süreçte edindiğim bilgiler, daha büyük sistemlerde de karşılaşılabilecek bellek yönetimi ve performans sorunlarına ışık tutuyor. Kendi sistemimde yaptığım bu deneme, karmaşık sistemlerin nasıl beklenmedik şekillerde tepki verebileceğini ve biz sistem yöneticilerine ne kadar çok şey öğretebileceğini gösteriyor.
Swap Kullanımının Derinliklerine İniş
Swap belleği, fiziksel RAM (Random Access Memory) yetersiz kaldığında işletim sisteminin geçici olarak disk üzerinde oluşturduğu bir alandır. RAM’deki verilerin bir kısmı diske taşınarak, daha fazla verinin RAM’e sığması sağlanır. Teoride harika bir çözüm gibi görünse de, disk erişiminin RAM erişimine göre çok daha yavaş olması nedeniyle, swap kullanımının artması sistem performansında ciddi düşüşlere neden olur. Özellikle Kubernetes gibi servislerin ve konteynerlerin yoğun bellek kullandığı ortamlarda, aşırı swap kullanımı tam bir performans çöküşüne yol açabilir.
Bu denememde, 7.6 GB RAM’e sahip VPS’ime birkaç temel servis ve ardından Kubernetes’i kurmaya başladım. İlk başta her şey yolunda gibi görünüyordu. Ancak servisler ve Kubernetes bileşenleri çalışmaya başladıkça, sistemin yavaşladığını fark ettim. htop komutunu çalıştırdığımda, RAM kullanımının %90’ların üzerine çıktığını ve aniden swap kullanımının da hızla arttığını gördüm. Bu durum, sistemin adeta nefes alamadığını gösteriyordu.
Swap Yangınını Başlatan Tetikleyiciler
Peki, bu “swap yangını” tam olarak nasıl başladı? Kubernetes, kendi kontrol düzlemi (control plane) bileşenleri (API server, etcd, scheduler, controller manager) ve kubelet gibi ajanları ile zaten belirli bir miktar bellek tüketir. Buna ek olarak, çalıştıracağımız uygulamalar veya servisler de kendi bellek ihtiyaçlarını karşılamak zorundadır. Benim durumumda, başlangıçta kurduğum birkaç temel servis (örneğin, bir monitoring aracı ve bir veritabanı) ve üzerine eklediğim Kubernetes bileşenleri, 7.6 GB’lık fiziksel RAM’i hızla doldurdu.
Sorunun kaynağını anlamak için dmesg komutunun çıktısını dikkatle inceledim. Sistem loglarında, bellek azlığı nedeniyle bazı işlemlerin (process) “Out Of Memory (OOM) killer” tarafından sonlandırıldığına dair mesajlar görüyordum. Bu, sistemin RAM’i tamamen tükettiğini ve kernel’in, daha fazla bellek boşaltmak için en çok bellek tüketen işlemleri zorla kapattığını gösteriyordu. Ancak bu kapatmalar, geçici bir rahatlama sağlasa da, temel sorunu çözmüyordu; sistem hala swap alanına bağımlı hale geliyordu.
Bir diğer önemli nokta ise, Kubernetes’in kendisinin de belirli bir bellek profiline sahip olmasıydı. Örneğin, etcd gibi bileşenler veritabanı benzeri bir yapıya sahip oldukları için zamanla bellek tüketimlerini artırabilirler. Kubelet da node’daki konteynerlerin durumunu izlerken bellek kullanır. Bu bileşenlerin hepsi bir araya geldiğinde, 7.6 GB RAM hızla yetersiz kalmaya başladı.
# Sunucuya ilk bağlanıp htop çıktısı
top - 14:30:00 up 1 day, 1:15, 1 user, load average: 0.50, 0.60, 0.70
Tasks: 200 total, 1 running, 199 sleeping, 0 stopped, 0 zombie
%Cpu(s): 5.0 us, 2.0 sy, 0.0 ni, 93.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 7800 total, 150 free, 6500 used, 1150 buff/cache
MiB Swap: 2048 total, 500 free, 1548 used. 1000 avail Mem
# Bellek kullanımı %83'e ulaştığında swap kullanımı da artmaya başlıyor
top - 14:35:00 up 1 day, 1:20, 1 user, load average: 1.20, 1.00, 0.90
Tasks: 210 total, 2 running, 208 sleeping, 0 stopped, 0 zombie
%Cpu(s): 10.0 us, 5.0 sy, 0.0 ni, 85.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 7800 total, 50 free, 7200 used, 550 buff/cache
MiB Swap: 2048 total, 50 free, 1998 used. 0 avail Mem <-- Swap bijna doldu!
Sorunun Kök Nedeni: Swap’a Bağımlılık
Swap belleği kullanmak, tek başına bir “kötü” değildir. Asıl sorun, sistemin sürekli olarak swap alanına dayanmak zorunda kalmasıdır. Bu durum, “swap thrashing” olarak da bilinen ve sistemin disk ile bellek arasında sürekli veri taşıdığı, CPU’nun büyük bir kısmının bu taşıma işlemleriyle meşgul olduğu ve gerçek işin yapılamadığı bir döngüye yol açar. Kubernetes gibi sistemlerde, bu durum bir düğümün (node) kararsızlaşmasına ve kümeden düşmesine neden olabilir.
Benim durumumda, swappiness parametresinin değeri de önemli bir faktördü. swappiness, kernel’in ne kadar agresif bir şekilde swap alanını kullanacağını belirleyen bir parametredir. Değeri 0 ile 100 arasında değişir. 0 değeri, kernel’in sadece RAM tamamen dolduğunda swap kullanmasını söylerken, 100 değeri ise kernel’in RAM’i dolu olmasa bile swap alanını aktif olarak kullanmasını teşvik eder. Varsayılan değer genellikle 60 civarındadır. Benim VPS’imde bu değerin yüksek olması, sistemin RAM’de yeterli boşluk varken bile swap’ı kullanmaya başlamasına neden oluyordu.
Bu bağımlılığın bir diğer göstergesi de, sistemin yanıt vermez hale gelmesiydi. ssh ile bağlanmak bile dakikalar sürebiliyor, komutlar yanıt vermiyordu. htop gibi araçları çalıştırmak bile zorlaşıyordu çünkü bu araçlar da çalışmak için belleğe ve CPU’ya ihtiyaç duyuyordu. Bu, tam anlamıyla bir performans darboğazıydı.
Çözüm: Swap Kaynaklarını Artırmak ve Swappiness’i Ayarlamak
İlk adım, sorunun aciliyetini azaltmak için swap alanını artırmak oldu. Mevcut 2 GB’lık swap alanı hızla doluyordu. Yeni bir swap dosyası oluşturdum ve boyutunu artırdım. Bu, sistemin anlık olarak daha fazla belleği disk üzerinde tutabilmesini sağlayacaktı, ancak temel sorunu çözmeyecekti.
Yeni swap dosyası oluşturma adımları genellikle şöyledir:
- Swap Dosyası Oluşturma:
fallocateveyaddkomutu ile swap dosyası için yer ayırma.# 4 GB'lık yeni bir swap dosyası oluşturalım sudo fallocate -l 4G /swapfile2 # Veya dd ile: # sudo dd if=/dev/zero of=/swapfile2 bs=1M count=4096 - Dosya İzinlerini Ayarlama: Swap dosyasına sadece root kullanıcısının erişebildiğinden emin olma.
sudo chmod 600 /swapfile2 - Swap Alanı Olarak Formatlama: Oluşturulan dosyayı swap alanı olarak işaretleme.
sudo mkswap /swapfile2 - Swap’ı Aktifleştirme: Yeni swap dosyasını sisteme ekleme.
sudo swapon /swapfile2 - Kalıcı Hale Getirme: Sistem yeniden başladığında swap dosyasının otomatik olarak aktif olması için
/etc/fstabdosyasına ekleme.echo '/swapfile2 none swap sw 0 0' | sudo tee -a /etc/fstab
Bu adımları tamamladıktan sonra htop veya free -h komutlarıyla swap alanının arttığını görebilirsiniz.
# Swap alanı artırıldıktan sonraki durum
free -h
total used free shared buff/cache available
Mem: 7.6G 7.2G 50Mi 100Mi 550Mi 100Mi
Swap: 6.0G 1.5G 4.5G
# Swappiness değerini 10'a düşürme
sudo sysctl vm.swappiness=10
# Değişikliği kalıcı hale getirme
echo 'vm.swappiness = 10' | sudo tee -a /etc/sysctl.conf
Bu adımlar, sistemin anlık olarak nefes almasını sağladı. Ancak asıl çözüm, sadece swap alanını artırmak değil, aynı zamanda swappiness değerini düşürerek kernel’in swap kullanımını azaltmasını sağlamaktı. swappiness değerini 10’a düşürmek, kernel’in RAM’de hala boş yer varken swap’a başvurma eğilimini azalttı. Bu sayede, sistem daha çok fiziksel RAM’i kullanmaya yöneldi ve disk I/O’su azaldı.
Kubernetes İçin Optimizasyonlar ve Alternatifler
Kubernetes’in küçük bir VPS’de sorunsuz çalışması için ek optimizasyonlar ve farklı yaklaşımlar gerekebilir. Öncelikle, Kubernetes’in kendisinin bellek tüketimini azaltmak için bazı ayarlar yapılabilir. Örneğin, kubelet’in bellek limitlerini ayarlamak veya etcd gibi bileşenlerin daha hafif alternatiflerini kullanmak (eğer mümkünse). Ancak bu genellikle daha karmaşık bir konudur ve dağıtık sistemlerin doğası gereği belirli bir kaynak gereksinimi vardır.
Daha pratik bir yaklaşım, çalıştırılacak application’ların (uygulamaların) bellek ayak izini küçültmek olabilirdi. Örneğin, hafif konteyner imajları kullanmak, uygulamaların bellek sızıntılarını gidermek veya daha az bellek tüketen alternatif servisler seçmek gibi. Ancak bu, benim durumumda deneyin amacından sapmak anlamına geliyordu.
Başka bir strateji ise, Kubernetes’i tamamen farklı bir şekilde kullanmaktı. Örneğin, Kubernetes yerine Docker Compose gibi daha basit bir araçla servisleri yönetmek. 7.6 GB RAM’li bir VPS için Docker Compose genellikle çok daha uygun bir çözüm olacaktır. Bu, benim denememin amacına aykırı olsa da, gerçek dünya senaryolarında kesinlikle göz önünde bulundurulması gereken bir alternatiftir.
Sonuç: Küçük VPS’lerde Kubernetes Denemesi ve Dersler
Sonuç olarak, 7.6 GB RAM’li bir VPS’de Kubernetes denemesi yapmak, bol miktarda swap kullanımı ve performans sorunlarıyla sonuçlandı. Bu deneyim bana, Kubernetes’in belirli bir minimum kaynak gereksinimi olduğunu ve bu sınırlar zorlandığında sistemin kararsız hale gelebileceğini bir kez daha gösterdi. Swap alanını artırmak ve swappiness değerini düşürmek geçici çözümler sunsa da, temel sorun kaynak yetersizliğiydi.
Bu denemeden çıkardığım en önemli derslerden biri, her teknoloji veya platformun belirli bir “minimum viable resource” gereksinimi olduğudur. Kubernetes gibi güçlü ve karmaşık bir sistem, onu çalıştırmak için yeterli kaynağa sahip olmayan bir ortamda kullanıldığında, verimlilikten çok sorun yaratır. Eğer düşük kaynaklı bir ortamda konteyner orkestrasyonu yapmanız gerekiyorsa, K3s veya MicroK8s gibi hafif alternatifleri veya Docker Compose gibi daha basit araçları değerlendirmek çok daha mantıklı olacaktır.
Bu tür denemeler, teorik bilgiyi pratik deneyimle birleştirmenin en iyi yolu. Karşılaştığım sorunlar ve bulduğum çözümler, gelecekte benzer durumlarla karşılaştığımda daha hazırlıklı olmamı sağlayacak. Unutmamak gerekir ki, her “yangın” aslında bir öğrenme fırsatıdır.
VPS migration deneyimim yazımda da bahsettiğim gibi, altyapı planlaması yaparken kaynakları doğru tahmin etmek kritik önem taşır. Bu deneme, bu gerçeği bir kez daha gözler önüne serdi.