Kubernetes v1.37: etcd RangeStream ile Bellek Dostu Liste
Kubernetes v1.37 ile birlikte etcd RangeStream özelliği beta aşamasına geçiyor. etcd v3.7 ile eşleştirildiğinde bu yenilik, API sunucusunun ve etcd’nin büyük koleksiyonları okurken kullandığı belleği belirgin biçimde düşürüyor; daha da önemlisi, tepe bellek tüketimini çok daha öngörülebilir kılıyor. Bu yazıda RangeStream’in ne yaptığını, nasıl devreye girdiğini ve doğru çalıştığını nasıl doğrulayacağınızı ele alıyoruz.
Büyük okumaların maliyeti
API sunucusu, list ve watch isteklerinin çoğunu bellek içindeki watch cache üzerinden karşılar. Ama bu önbelleği doldurmak için ilgili kaynağın tüm durumunun etcd’den okunması gerekir; bu okuma yalnızca başlangıçta değil, her yeniden başlatmada da yapılır. Nesne sayısının yüksek veya nesne boyutunun büyük olduğu kaynaklarda, özellikle Pod gibi, işlem oldukça maliyetli.
API sunucusu bu okumaları zaten sayfalıyordu; koleksiyonun tamamını etcd’den bir kerede istemek yerine sabit sayıda anahtarı sayfa sayfa çekiyordu. Sorun şu ki yalnızca anahtar sayısına bağlı bir sayfalama, nesnelerin boyutundan habersizdir. Büyük nesnelerden oluşan bir sayfa hala çok büyük olabilir. Bu da bellek kullanımının tahmin edilmesini zorlaştırır; kötü bir nesne boyutu ve eşzamanlı okuma kombinasyonu OOM tetiklemeye yetebilir.
Öte yandan etcd’nin tekli Range çağrısı her sayfayı tam olarak hazırlayıp gönderiyor, API sunucusu da bu sayfayı çözerken bellekte tutuyordu. Sonuçta aynı veri yükü, aynı anda hem etcd hem de API sunucusu tarafında bellekte duruyordu. Bu maliyetin büyük kısmı etcd tarafına düşüyordu; streaming yaklaşımının en çok fayda sağladığı yer de tam olarak burasıydı.
RangeStream ile akışlı okumalar
etcd v3.7, bu okumanın akışlı bir sürümünü ekliyor: RangeStream RPC’si. Bu çağrı, klasik Range ile aynı RangeRequest‘i alır ve aynı sonuç kümesini döner. Ancak yanıtı baştan sona hazırlayıp göndermek yerine etcd sonucu parçalara böler ve akış halinde iletir.
Parça boyutu dönen değerlere göre uyarlanır. Böylece büyük nesnelerden oluşan bir koleksiyon, anahtar sayısıyla değil bayt cinsinden sınırlanır. Bellek de sayfanın tamamı toplanana kadar tutulmak yerine akış ilerledikçe serbest bırakılır.
Özellik etkinken API sunucusu, bütün bir koleksiyonu etcd’den okuduğu her yerde RangeStream‘i kullanır. Buna watch cache başlatma süreçleri ve bir list isteğinin önbellekten karşılanamayıp doğrudan etcd’ye düştüğü fallback yolları da dahil. Her iki durumda da API sunucusu, gelen her parçayı ayrıştırır ve bir sonraki parçayı çekmeden önce onu serbest bırakır. Böylece hiçbir taraf koleksiyonun tamamını aynı anda bellekte tutmaz.
Gereksinimler ve devreye alma
RangeStream’i kullanabilmek için iki temel bileşen gerekir:
- Kubernetes v1.37 veya sonrası
- etcd v3.7 veya sonrası
RangeStream, kube-apiserver üzerinde EtcdRangeStream feature gate’i etkinken ve etcd v3.7 ya da daha yeni bir sürüm kullanıldığında devreye girer. v1.37’de bu geçit beta seviyesinde ve varsayılan olarak açık.
API sunucusu, etcd’nin bu özelliği destekleyip desteklemediğini başlangıçta çözümler; çalışma zamanında bir çağrı Unimplemented döndürürse eski yola geri düşer. Bu sayede eski bir etcd sürümüyle eşleştirilmiş bir API sunucusu, kendi başına sayfalı Range yolunu kullanmaya devam eder.
Özelliği kapatmak isterseniz geçidi devre dışı bırakmanız yeterli:
--feature-gates=EtcdRangeStream=false
RangeStream’in kullanıldığını doğrulama
API sunucusu, akış halinde yapılan okumaları etcd metriklerinde ayrı bir operasyon etiketi altında kaydeder. Aşağıdaki metriğin sıfırdan farklı bir değer göstermesi, RangeStream‘in aktif kullanıldığı anlamına gelir:
etcd_request_duration_seconds_count{operation="listStream"}
Bu sayaç sıfırda kalmaya devam ediyorsa API sunucusu hala sayfalı Range yolunu kullanıyor demektir. En olası neden, etcd’nin v3.7’den eski bir sürümde olması.
Neden önemli?
RangeStream’in getirdiği kazanım yalnızca “daha az bellek” değil, aynı zamanda daha öngörülebilir bellek davranışı. Büyük Pod koleksiyonlarının bulunduğu kümelerde watch cache yeniden başlatmaları veya önbellek dışı list istekleri, bugüne kadar tahmin edilmesi zor tepe bellek kullanımlarına yol açabiliyordu. Akışlı okuma, bu yükü hem etcd hem de API sunucusu tarafında zamana yayarak kontrol altına alıyor.
Kaynaklar ve İleri Okuma
- Kubernetes Blog: Kubernetes v1.37: etcd RangeStream Cuts Memory Use on Large List Reads
- KEP-5966: etcd RangeStream
- etcd API Rehberi: RangeStream
- Announcing etcd v3.7
- SIG etcd
- Kubernetes Slack (#sig-etcd)
- etcd v3.7.0 Çıktı: RangeStream Devri ve v2store’a Elveda
- Announcing etcd 3.7.0-beta.0
- Kubernetes 1.36 Ön İzleme: Neler Geliyor, Neler Gidiyor?







3 comments