Kubernetes kaynak limitleri: requests ve limits adım adım belirleme
Kubernetes'te CPU ve bellek request, limit değerlerinin nasıl belirleneceği: ölçüm yöntemi, OOMKilled, kısıtlama, QoS sınıfları, LimitRange ve ResourceQuota.
Request ve limit: iki ayrı söz
Kubernetes'te bir konteynerin kaynak ihtiyacı request ve limit alanlarıyla ifade edilir. Request (istek), konteynerin çalışmak için ayrılmasını istediği miktardır; scheduler pod'u hangi düğüme koyacağına bu değere bakarak karar verir. Limit (sınır) ise konteynerin kullanabileceği üst sınırdır; bu sınırı kubelet uygular.
Kubernetes belgesi farkı şöyle özetler: scheduler, pod'u yerleştirirken request değerlerini kullanır; limit tanımlıysa kubelet, çalışan konteynerin bu miktarı aşmasına izin vermez ve ayrıca request kadar kaynağı konteyner için ayırır. Konteyner, düğümde boş kaynak varsa request'ini aşabilir; bu mümkündür ve izin verilen bir davranıştır.
Özetle request yerleştirme ve ayırma için, limit ise zarar kontrolü içindir. İkisini karıştırmak, kümede ya israfa ya da beklenmedik kesintilere yol açar.
CPU ve bellek farklı davranır
İki kaynak, limit aşıldığında aynı sonucu vermez. CPU limitleri kısıtlama (throttling) ile uygulanır: konteyner limitine yaklaştığında çekirdek, onun CPU'ya erişimini kısar. Konteyner öldürülmez, yalnızca yavaşlar. Bu yüzden gecikme duyarlı bir uygulamada gereğinden sıkı bir CPU limiti, kaynak boşta durmasına rağmen yanıt sürelerinin artmasına neden olur.
Bellek limitleri ise çekirdeğin bellek yetersizliği (OOM) nedeniyle konteyneri sonlandırmasıyla uygulanır. Belge bunun tepkisel olduğunu belirtir: yalnızca çekirdek bellek baskısı algıladığında devreye girer; konteyner limitini bir süre aşabilir ama aşarsa öldürülebilir. Kullanıcı tarafında bu durum konteynerin yeniden başlaması olarak görünür; kubectl describe pod çıktısında son durum OOMKilled olarak yer alır.
Pratik sonuç: CPU için limiti gevşek tutmak ya da bilinçli olarak koymamak tartışılan bir tercihtir, bellek için ise limit koymak ve değeri uygulamanın gerçek kullanımına göre belirlemek neredeyse her zaman gereklidir.
Birimler ve manifestte yazımı
CPU çekirdek cinsinden ifade edilir. Bir çekirdeğin binde birini temsil eden m soneki sık kullanılır; örneğin 500m yarım çekirdek demektir. Bellek ve geçici depolama bayt cinsindendir; Mi ve Gi gibi ikili tabanlı ön ekler yaygındır, örneğin 128Mi. Aşağıdaki örnek kurguseldir; değerleri kendi ölçümünüzden almalısınız:
apiVersion: v1 kind: Pod metadata: name: uygulamam spec: containers: - name: kapsayici image: kayit.ornek.com/uygulamam:etiket resources: requests: cpu: <ölçülen tipik kullanım> memory: <ölçülen tipik kullanım> limits: memory: <ölçülen tepe kullanım ve pay>
Birden çok konteyneri olan pod'larda pod'un toplam request ve limit değeri, konteynerlerin toplamıdır. Bir kaynak için yalnız limit yazıp request yazmazsanız ve başka bir mekanizma varsayılan atamıyorsa Kubernetes, limiti request olarak da kopyalar; bu, beklenenden büyük bir ayırma anlamına gelebilir.
Doğru değerler nasıl bulunur?
Rakam tahmin etmek yerine ölçmek gerekir. Sağlam bir yöntem şu adımlarla ilerler:
- Temsili yükü uygulayın: Üretime benzer bir test ya da canlı trafik altında uygulamayı çalıştırın. Boşta ölçülen değer yanıltıcıdır.
- Kullanımı izleyin: kubectl top pod komutu anlık değeri verir, ama zaman içinde değişimi görmek için metrik sistemi (örneğin Prometheus tabanlı bir panel) gerekir. Tipik ve tepe kullanımı ayrı ayrı not edin.
- Request'i tipik kullanıma göre koyun: Çok düşük request, düğümün fazla pod almasına ve rekabet yüzünden yavaşlamaya yol açar; çok yüksek request kaynağı boşa ayırır ve pod'ların Pending'de kalmasına neden olur.
- Bellek limitini tepe kullanımın üzerine pay bırakarak koyun: Bellek sızıntısı ya da geçici sıçrama için güvenlik payı bırakın, ama sınırsız bırakmayın.
- Birkaç gün gözlemleyin ve ayarlayın: OOMKilled olayları, CPU kısıtlama oranı ve düğüm doluluğu, değerleri düzeltmenizi gösterir.
Java gibi kendi bellek yönetimine sahip çalışma zamanlarında, çalışma zamanının yığın ayarını konteyner limitiyle uyumlu yapmak gerekir; aksi halde uygulama limit ile çakışarak öldürülür. Otomatik öneri üreten araçlar da vardır; yine de önerileri doğrulamak sizin işinizdir.
QoS sınıfları ve baskı altındaki davranış
Kubernetes pod'ları, request ve limit tanımlarına göre hizmet kalitesi (QoS) sınıflarına ayırır. Genel kural şöyledir: her konteyneri için CPU ve bellek request'i limitine eşit olan pod Guaranteed sınıfındadır; hiçbir konteynerinde request ya da limit olmayan pod BestEffort'tur; bu uçların arasında kalanlar Burstable olur. Düğümde bellek baskısı oluştuğunda tahliye sırası bu sınıflara göre değişir ve en savunmasız olan BestEffort pod'lardır.
Bu sınıflandırma kritik uygulamalarınızı korumanın bir yoludur: veritabanı ve ödeme gibi hassas iş yüklerini Guaranteed yapmak, deneme ve toplu işleri ise daha düşük sınıfta tutmak mantıklı olabilir. Ancak her şeyi Guaranteed yapmak küme kapasitesini verimsiz kullanır. Sınıf seçimi, uygulamanın önemi ile maliyet arasındaki bir karardır. Ayrıntılı kuralları Kubernetes belgesindeki QoS sayfasından kontrol edin.
Namespace düzeyinde sınır: LimitRange ve ResourceQuota
Tek tek pod'lara güvenmek her zaman yeterli olmaz; yeni bir geliştirici request yazmayı unutabilir. Bunun için iki nesne yardımcı olur.
LimitRange, bir ad alanındaki konteynerlere varsayılan request ve limit değerleri atayabilir ve izin verilen alt-üst sınırı belirler. Böylece kaynak tanımsız gelen bir pod, ad alanının kurallarını otomatik devralır ve BestEffort sınıfında kalmaz.
ResourceQuota ise ad alanının toplam tüketimini sınırlar: toplam CPU ve bellek istekleri, pod sayısı gibi nesne sayıları için tavan koyar. Çok ekipli kümelerde bir ekibin tüm kapasiteyi tüketmesini önler. Bir ad alanında kota tanımlıysa, kaynak değeri belirtilmeyen pod'ların oluşturulması reddedilebilir; bu yüzden LimitRange ile birlikte kullanılır.
Bu iki nesne, platform ekibi için bir yönetişim aracıdır: geliştiricilere serbestlik verirken küme genelinde öngörülebilirlik sağlar.
Sık hatalar
- Hiç kaynak tanımlamamak: Pod'lar BestEffort olur, düğüm aşırı dolar ve ilk baskıda tahliye edilir.
- Request ile limiti kopyalayıp bırakmak: Kimse ölçmeden aynı değeri yazar; sonuç ya israf ya da OOM olur.
- CPU limitini fazla sıkı tutmak: Düğümde boş CPU olduğu halde uygulama kısılır, gecikme artar.
- Bellek limitini çok düşük koymak: Yük altında OOMKilled ve yeniden başlama döngüsü başlar.
- Çalışma zamanı ayarını konteynerle uyumlamamak: Yığın ayarı limitten büyükse uygulama sürekli öldürülür.
- Ölçümü tek bir zaman noktasında yapmak: Sabah yükü ile kampanya günü yükü farklıdır.
- Değerleri bir kez yazıp unutmak: Uygulama büyüdükçe request değerleri eskir; düzenli gözden geçirme gerekir.
Kaynak yönetimi bir kereliğine ayarlanan değil, sürekli gözlemle iyileştirilen bir pratiktir. Otomatik ölçekleme (HPA) kullanıyorsanız request değeri ölçekleme kararını da etkiler; bu yüzden iki konuyu birlikte düşünün.
Bu beceriyi Mindset programlarında nerede çalışırsınız?
Mindset kataloğundaki "Kubernetes Scheduler ve Kaynak Yönetimi İncelikleri" programı bu konunun ayrıntılı karşılığıdır: scheduler karar mekanizması, request, limit ve QoS sınıfları, node seçimi, taint ve toleration, öncelik, tahliye ile kapasite verimliliği ve politika modüllerini içerir. Küme maliyetini ve kararlılığını yöneten platform ve SRE ekipleri için uygundur. "Kubernetes ile Orkestrasyon" programındaki "Ölçekleme ve Kaynak Yönetimi" modülü ise konuya temel düzeyde giriş yapar ve kümeyle yeni tanışan mühendisler için daha uygun başlangıç noktasıdır.
İlgili Mindset programı
Kubernetes Scheduler ve Kaynak Yönetimi İncelikleri
Sık sorulan sorular
Limit koymamak sorun olur mu?
Bellek için çoğu zaman olur: sınırsız bırakılan bir konteyner düğümün belleğini tüketip diğer pod'ları etkileyebilir. CPU için tartışmalıdır; bazı ekipler gecikmeyi artırdığı için CPU limiti koymaz ve yalnızca request ile çalışır. Hangi yolun uygun olduğu uygulamanın doğasına ve kümenin kullanıcı modeline bağlıdır; ama ad alanı düzeyinde bir koruma katmanı bırakmak akıllıca olur.
OOMKilled hatasını nasıl anlarım ve gideririm?
kubectl describe pod çıktısında konteynerin son durumunda OOMKilled görürsünüz. Çözüm yolu: gerçek bellek kullanımını ölçün, uygulamada sızıntı olup olmadığına bakın, çalışma zamanının bellek ayarlarını limitle uyumlayın ve gerekiyorsa limiti artırın. Yalnızca limiti büyütmek, sızıntı varsa sorunu erteler.
Request değeri ile ölçekleme arasında bağ var mı?
Evet. Yatay pod ölçekleyici kullanımı çoğunlukla request'e oranla hesaplar; request gerçek ihtiyaçtan çok düşükse ölçekleme erken ve gereksiz, çok yüksekse geç tetiklenir. Ölçeklemeyi kurmadan önce request değerlerini ölçerek düzeltmek gerekir.
LimitRange ile ResourceQuota ne farkı var?
LimitRange tek bir konteyner ya da pod için varsayılan ve alt-üst sınır belirler. ResourceQuota ise ad alanının toplam tüketimine tavan koyar. Biri bireysel, diğeri toplu kontroldür. Birlikte kullanıldıklarında kaynak tanımlamayı unutan pod'lar varsayılan alır ve ad alanı genel kotayı aşmaz.
Guaranteed QoS sınıfını nasıl elde ederim?
Pod'un her konteynerinde CPU ve bellek için hem request hem limit yazılmalı ve her kaynak için request limite eşit olmalıdır. Bu eşitlik koşulu sağlandığında pod Guaranteed olur ve baskı altında en son tahliye edilenler arasında yer alır. Kritik iş yükleri için tercih edilir, ancak kaynak ayırma maliyeti de yüksektir.
İlgili rehberler
İlgili eğitimler
Kategori: DevOps ve Bulut Teknolojileri