· kaynak dev.to (home feed)
Kubernetes 512m değerini bellek limiti olarak kabul ediyor — bu da yarım bayt demek
dev.to üzerindeki bir deney, 512Mi, 512M ve 512m değerlerinin tümünün kubectl apply tarafından kabul edildiğini ama sırasıyla 536.870.912 bayt, 512.000.000 bayt ve 0,512 bayt anlamına geldiğini gösteriyor. Hata biçimleri arasında sessizce yanlış kapasite planlaması da var.

dev.to'da yayımlanan bir yazı, Kubernetes kaynak sözdiziminde gizli bir tuzağa dikkat çekiyor: bir manifest içinde neredeyse aynı görünen üç bellek değeri — 512Mi, 512M ve 512m — kubectl apply tarafından kabul ediliyor ama sırasıyla 536.870.912 bayt, 512.000.000 bayt ve 0,512 bayt anlamına geliyor. Yazar, dokümantasyondan hareketle tartışmak yerine, containerd ve cgroup v2 ile Kubernetes 1.37 çalıştıran bir kullan-at kind cluster kurdu ve aklına gelen tüm bozuk quantity değerlerini uygulayarak gerçekte ne olduğunu gözlemledi.
İkili ve ondalık son ekler birbirinin yerine kullanılamaz
Kubernetes quantity'leri hem ikili (Ki, Mi, Gi — ikinin kuvvetleri) hem de ondalık (k, M, G — onun kuvvetleri) son ekleri kabul eder. dev.to yazısına göre aradaki fark birim büyüdükçe artıyor: M, Mi'den %4,6 küçük; G ise Gi'den %6,9 küçük. 4Gi heap için ayarlanmış bir JVM, 4G limiti aldığında sessizce 281 MiB pay kaybediyor — tam da yalnızca yoğun yük altında, bir cuma günü, kimsenin dokunmadığı bir serviste ortaya çıkan OOMKill türünden.
Laboratuvar ortamı bu farkı görünür kılıyor. 7,65 GiB'lik bir kind node üzerinde 4G bellek limitli bir pod normal şekilde başlarken, 4Gi isteyen aynı pod bellek yetersizliği nedeniyle hiç planlanamadı. Cgroup düzeyinde containerd, 500M değerini 499.998.720 bayt (4 KiB'lik sayfaya aşağı yuvarlanmış) ve 500Mi değerini 524.288.000 bayt olarak yazdı; 4G limit ise 3.999.997.952 bayta dönüştü. Yazar, hatırlanmaya değer bir görüntüleme uyumsuzluğuna da dikkat çekiyor: kubectl describe node kapasiteyi Ki cinsinden raporluyor, bulut sağlayıcıları RAM'i GiB cinsinden satıyor ve birçok dashboard GB gösteriyor — bu yüzden tavsiye, ikili son ekleri seçip onlara sadık kalmak.
Küçük harf m, bellek için bile milli demektir
CPU alanlarında m standart birimdir — 500m yarım çekirdektir. Belleğe uygulandığında da hâlâ milli anlamına gelir, yani 512m kabaca yarım bayttır. Kubernetes 1.37, kesirli bayt değerinin geçersiz olduğu ve tam sayı olması gerektiği konusunda bir uyarı verdi ve ardından pod'u yine de oluşturdu. Bu uyarı --dry-run=client ile görünmediği için bir CI log'unda veya Helm upgrade sırasında kolayca gözden kaçıyor ve nesne yazıldığı haliyle tam olarak saklanıyor. Daha da tuhafı, memory: 2000m hiç uyarı vermiyor çünkü tam sayı bayta çözümleniyor — iki bayt yani.
Yarım bayt pratikte ne yapar
Yazar, limitsiz bir request olarak kullanıldığında pod'un saniyeler içinde başladığını buldu: scheduler bunu sıfır olarak sayıyor ve cgroup hiç bellek tavanı almıyor, tek belirti sessizce yanlış olan kapasite planlaması. Tuhaf bir yan etki daha: tek bir 512m pod'u, kubectl describe node çıktısında node'un tüm bellek satırını milli-bayt cinsinden gösteriyor — testte 304087041536m, yani yaklaşık %3 — ve bu, birinin küçük harf m yazdığının güvenilir bir işareti.
Limit olarak kullanıldığında ise OOMKill yok, çünkü öldürülecek bir şey yok. Pod'un cgroup'u sıfır değerinde bir memory.max alıyor ve pod, yaklaşık 2 KB'lık bir sertifika dosyası yazarken ContainerCreating durumunda FailedMount hatasıyla — cihazda yer kalmadı — takılı kalıyor. Service-account token volume bir tmpfs, tmpfs yazmaları pod'un bellek cgroup'una yükleniyor ve o bütçe sıfır bayt. Token automount devre dışı bırakıldığında hata container runtime'a kayıyor; cgroup yapılandırmasını uygulayamıyor ve node journal'ında bellek tahsis hatası loglanıyor. Bu mesajların hiçbiri YAML dosyasına işaret etmiyor.
CPU yukarı yuvarlanıyor, bellek bozuk kalıyor
Yazı yaygın bir inanışı da düzeltiyor: Kubernetes, 1m'den ince CPU hassasiyetini kabul ediyor — sessizce yukarı yuvarlıyor. Yazarın testleri 0,0001 değerinin 1m, 0,0015'in 2m ve 100,5m'in 101m olarak saklandığını gösteriyor. CPU için zararsız, ama 512m belleği yazıldığı gibi tutan aynı parser. Kanonikleştirme diff gürültüsü ekliyor: 0,5Gi 512Mi olarak, 0,5G 500M olarak saklanıyor ve 512,5Mi 524800Ki olarak geri geliyor — canlı nesneleri Git ile karşılaştırıyorsanız bu önemli.
Bunu önceden yakalamanın yolları
Önerilen savunmalar: CI'da bellek alanları altında rakamdan sonra gelen m için lint çalıştırmak (tek satırlık bir grep ya da admission anında bir Kyverno veya Gatekeeper policy'si); 512m pod'unu engelleyecek olan --warnings-as-errors ile kubectl apply çalıştırmak; ve katkı kılavuzunda bellek için Mi ve Gi standartlarını belirleyip linter ile zorunlu kılmak. Bir pod şaşırtıcı bir depolama hatasıyla ContainerCreating'de takılı kaldığında yazarın tavsiyesi, diske bakmadan önce bellek limitini kontrol etmek.
Neden önemli
Bu yazım hataları incelemelerden geçiyor, çünkü aradaki fark insan gözüne görünmez ve API server tarafından hoşgörülür. Sonuçlar dolaylı ve gecikmeli: yüzde birkaç az sağlanmış ve yalnızca yoğun trafik altında başarısız olan iş yükleri, kapasite hesabı sessizce yanlış olan node'lar ya da hata mesajı disk alanından yakınırken hiç başlamayan bir container. Dry run ve özensiz inceleme uyarıyı gözden kaçırdığı için önlemin otomatikleştirilmesi gerekiyor — bir lint kuralı, bir admission policy'si veya uyarılarda CI'ı başarısız kılmak. Bir ekibi ikili son eklere alıştırmak katkı kılavuzunda tek satıra mal oluyor; üretimde yarım baytlık bir bellek limitini hata ayıklamaksa çok daha pahalıya.
- #kubernetes
- #devops
- #cloud
- #containers
- #yaml
İlgili yazılar
- Inngest kesintisi: yeniden başlatılan servisler, kesintinin devre dışı bıraktığı veritabanına ihtiyaç duydu
- Vercel, deployment'lar arasında dependency doğrulamasını yeniden kullanarak pnpm install sürelerini %14 kısalttı
- Docker'ın Agent CLI eklentisi, yapay zeka ajanlarını OCI artifact olarak paketleyip push, pull ve run işlemlerini mümkün kılıyor