Kubernetes muhitida OOMKilled sabablari tahlili

Kubernetes muhitida OOMKilled sabablari tahlili

Umumiy ma'lumotlar

Loyihada ishlayotganda OOM yoki OOMKilled bilan duch kelishingiz mumkin. Ayniqsa, Kubernetes muhitida, "Pod OOMKilled sababli qayta ishga tushirildi" holatlariga duch kelish odatiy hol.

OOMKilled oddiy serverni qayta ishga tushirishdek ko'rinishi mumkin, lekin sababi aniqlanmasa, bu yuqori xizmat yukida takrorlanishi mumkin va bu muammolar jiddiy muvaffaqiyatsizliklarga olib kelishi mumkin.

Ushbu hujjat OOMKilled nima ekanligini, uning sabablarini va loyihaning rivojlanishi davomida yuzaga kelgan holatlarga asoslanib uni qanday tahlil qilish va hal qilishni o'rganish va ko'rib chiqishni jamlaydi.

OOM va OOMKilled o'rtasidagi farq

OOM va OOMKilled xotira ajratish bilan bog'liq muammolar. Biroq, ularning kelib chiqishi va operativ mexanizmlari jihatidan farq qiladi.

OOM (Out Of Memory Error) JVM ichida sodir bo'ladi. Agar heap xotira to'lib qolsa va yangi ob'ektlar ajratish imkoni bo'lmasa, JVM java.lang.OutOfMemoryError xatosini qaytaradi va jarayonni tugatadi. Boshqacha aytganda, JVM o'z chegarasini tan oladi va xato qaytaradi.

OOMKilled JVMdan tashqarida, Kubernetes kabi konteyner muhitlarida sodir bo'ladi. Konteyner uchun belgilangan xotira chegarasidan oshganda, Kubernetes ushbu jarayonni kuch bilan tugatadi. U JVM xatoni tan olishidan oldin tashqaridan o'ldirilgani uchun, OOMdan farqli o'laroq, alohida xato jurnalari qolmaydi, shuning uchun sababi aniqlash qiyin.

Tasniflash

OOM

OOMKilled

Vujudga kelishining sababini keltirib chiqaruvchi sub'ekt

JVM ichida

Kubernetes (cgroup)

Sabab

Xotira xotirasining tugashi

Konteyner chegarasi oshib ketdi

Xato jurnal

OutOfMemoryError jurnalini saqlab qoldi

Jurnalisiz majburan to‘xtatish

Chiqarish kodi

1

137

Ma'lumotlar uchun xotira

Xotira maydoni

Xotira + No-Xotira + O'zi Xotira jami

Agar OOMKilled sodir bo'lsa, Pod avtomatik ravishda Kubernetes'ning qayta ishga tushirish siyosatiga muvofiq qayta ishga tushiriladi. Agar bu kam trafik davrida yuz bersa, bu katta muammo emas. Ammo, agar OOMKilled katta yuk sharoitida sodir bo'lsa, vaziyat jiddiy bo'lishi mumkin. Podning holatiga qarab, xizmat qayta ishga tushirish paytida to'xtatilishi mumkin va agar qayta ishga tushirishdan keyin trafik darhol oshsa, xotira tezda to'lib qolishi mumkin, bu esa OOMKilled voqealarining takrorlanishiga olib keladi. Oxir-oqibat, CPU va xotira yuklari oshgani sari, bu butun xizmat uchun jiddiy muvaffaqiyatsizliklarga olib kelishi mumkin.

Xotira farqi

OOMKilled bilan bog'liq xotira haqida gapirganda, nafaqat Xotira xotira taqsimotini, balki Konteyner, JVM va boshqa aniqroq xotira tafsilotlarini tushunish muhimdir.

Konteyner xotirasi

Kubernetes muhitida hisobga olish kerak bo'lgan bir muhim fakt — bu xotira sozlamalari oralig'i. Konteyner uchun belgilangan xotira cheklovlari faqat JVM uchun emas, balki butun konteyner uchun amal qiladi.
Boshqacha qilib aytganda, konteyner xotirasi JVM xotirasidan katta bo'lgan munosabatni tan olish muhimdir.

Container 메모리 
│
├── JVM 프로세스 메모리
│   ├── Heap
│   ├── Non-Heap
│   └── Off-Heap (Direct Buffer)
│
├── OS 및 시스템 라이브러리
└── 사이드카 Container (Istio sidecar 등) 등 기타…

JVM xotirasi

JVM xotirasi keng tarqalgan holda uchta sohalarga bo'linadi.

Heap maydoni

Bu joy Java dasturlari tomonidan yaratilgan ob'ektlar saqlanadigan joydir. Bu shuningdek GC (Garbage Collection) tomonidan maqsad qilingan maydondir.

Metrikalar

Tavsif

Heap ishlatilgan

Hozirda ishlatilayotgan xotira

Heap tayinlangan

JVM OS dan oldindan ajratilgan xotira. Bu GC dan keyin darhol chiqarilmaydi.

Heap maksimum

JVM uchun mavjud maksimal heap hajmi.

Uchta metrika o'rtasidagi munosabat har doim Used ≤ Committed ≤ Max va Committed Full GC davomida tozalanadi.

Non-Heap hududi

JVMning o'z operatsiyasi uchun hudud, GCga duch kelmaydi.

Hudud

Tavsif

Metaspace

Sinf metamalari va statik o'zgaruvchilarni saqlaydi.

Metaspace nazariy jihatdan -XX:MaxMetaspaceSize belgilangan bo'lmasa cheksiz o'sishi mumkin.

Off-Heap hududi (To'g'ridan-to'g'ri bufer)

Heap yoki Non-Heap emas, operatsion tizimdan JVM tomonidan to'g'ridan-to'g'ri ajratilgan xotira hududi. Asosan NIO asosidagi faylni qayta ishlash yoki tarmoq I/O uchun ishlatiladi.

Bu GCga duch kelmagani sababli, agar aniq ozod qilinmasa to'planishi mumkin va -XX:MaxDirectMemorySize bilan cheklov belgilanmasa cheksiz o'sishi mumkin.

Konteyner xotirasi va JVM xotirasi o'rtasidagi munosabat

Agar JVMning Heap hajmi Konteyner cheklovidan past belgilangan bo'lsa, yaxshi ko'rinishi mumkin. Biroq, nafaqat Heap, balki Non-Heap va Off-Heap ham Konteyner cheklovi ichida birgalikda boshqarilsa, uchta hududni hisoblashda ehtiyotkorlik bilan hisoblash kerak. Ayniqsa, tizimning tabiati bo'yicha ko'p fayllarni qayta ishlovchi xizmatlar Off-Heapdan ko'p foydalanishi mumkin, o'zgaruvchilarning ko'pini yuklovchi xizmatlar esa Non-Heapdan ko'proq foydalanadi, shuning uchun xotira dizaynidan oldin tizim xususiyatlarini to'liq tushunish zarur.

Agar 200MB Non-Heap, 100MB Off-Heap va 50MB boshqa JVM bilan bog'liq xotira ishlatiladigan tizimda Konteyner cheklovi 1Gi ga va -XX:MaxRAMPercentage=80 ga belgilangan bo'lsa, quyidagi holat yuzaga keladi.

Heap Max (80%)  :  819MB  ← JVM이 사용 가능하다고 인식하는 Heap 한도
Non-Heap        :  200MB
Off-Heap        :  100MB
JVM 외 기타      :   50MB
─────────────────────────
Heap 외 합계     :  350MB
실질적으로 Heap에 허용되는 메모리 : 1,024MB - 350MB = 674MB

JVM 819MB gacha Heapdan foydalanishi mumkinligini tan oladi va to'liq GCsiz xotira ajratishni davom ettiradi. Biroq, Kubernetes Heap + Non-Heap + Off-Heap + boshqalarni yig'ib, bu Konteyner cheklovi bilan solishtirgach, Heapdan foydalanish 674MBni oshganda, bu 1Gi ga teng Konteyner cheklovidan oshadi va Kubernetes jarayonni JVM bunga anglamasdan oldin majburiy ravishda tugatadi. Bu OOMKilled deb ataladi.

JVM sozlamalari

JVM opsiyalari OOMKilled bilan bogʻliq qisqacha ta'rifi quyida keltirilgan.

MaxRAMPercentage

  • Yig‘ma joyning maksimal o‘lchamini konteyner cheklovining foizi sifatida belgilaydi. Uni juda past belgilash xotirani isrof qilishga olib kelishi mumkin, juda yuqori belgilash esa Non-Heap va Off-Heap iste'moli bilan birga konteyner cheklovini oshirishga olib kelishi mumkin.

MaxMetaspaceSize

  • Non-Heap hududida Metaspace maksimal o‘lchamini cheklaydi. Agar o‘rnatilmasa, Metaspace nazariy jihatdan cheksiz oshishi mumkin. Hozirgi foydalanishga asoslangan holda biroz buffer bilan cheklov o‘rnatish tavsiya etiladi.

MaxDirectMemorySize

  • Off-Heap (Direct Buffer) maksimal o‘lchamini cheklaydi. NIO asosidagi fayl qayta ishlash yoki tarmoq I/O ni jiddiy ishlatadigan xizmatlarda, agar o‘rnatilmasa, Direct Buffer cheksiz o‘sishi va konteyner cheklovini oshishi mumkin. Ushbu opsiyani o‘rnatish, shuningdek, chegaralanganida OutOfMemoryError: Direct buffer memory xato xabarini qayd etish orqali sababi aniqlashni osonlashtiradi.

OOMKilled server tahlil holati

Quyida OOMKilled sodir bo‘lgan xizmatning xotira holati tahlilidan olingan qisqacha ma'lumot keltirilgan. OOMKilled masalasi oxirgi JVM opsiya o‘zgartirishlarini qo‘llashdan so‘ng hal etildi.

Asl notion havolasi :
https://app.notion.com/p/vizend/Pod-OOMKilled-38b35bc54c13806699e8e3ae329bf38f

Xotira holati tahlili

1. Konteyner resurs sozlamalari

Element

Qiymat

Xotira cheklovi

1Gi (1,073 MB)

Xotira so'rovi

256Mi

QoS sinfi

Burstable

2. JVM xotira holati (hozirgi vaqt)

Hudud

Qiymat

MB konversiyasi

Yig'ish ishlatilgan

376,595,248 bayt

~359 MB

Yig'ish belgilangan

512,229,376 bayt

~488 MB

Heap Max

859,308,032 bayt

~819 MB

Non-Heap Used

210,018,744 bayt

~200 MB

└ Metaspace

127,576,696 bayt

~122 MB

3. Asosiy Muammo Tahlili

Container Limit          :  1,073 MB  (1Gi)
────────────────────────────────────────
Heap Max (JVM 설정)       :    819 MB
Non-Heap Used (현재)      :    200 MB
────────────────────────────────────────
합산 최대 사용 가능       :  1,019 MB  ← 한계에 매우 근접
나머지 여유               :    ~54 MB  ← 위험 수준

Heap Max + Non-Heap JVMning o'zida Container Limitining taxminan 95%ini tashkil etadi.

JVMning ichki yuklarini (Thread Stack, GC metadata va boshqalar) qo'shganda, bu 1Gi dan oshib ketadi va OOMKilled yuzaga keladi.

4. GC Usulini Tekshiring

Aktuator javobi PS Eden Space, PS Old Gen, PS Survivor Space ni ko'rsatadi.

G1GC dan foydalanishni tavsiya etamiz.

5. Sabablar xulosasi

Sabab

Tavsif

O'rtacha max heap

819MB heap + 200MB non-heap bilan 1,019MB dan oldin limitdan oshib ketmoqda

Noqulay GC usuli

Parallel GC → konteyner xotirasining yetarlicha tan olinmasligi

JVM parametri o'rnatilmagan

Konteynerni tan olish parametrlarining yo'qligini faraz qilib -XX:MaxRAMPercentage

QoS burstable

Talab ≠ limit → Xotira kafolati yo'q, OOM ustuvorligi

MaxRAMPercentage simulyatsiya natijasi

Hozirgi 80% dan 60% gacha bo'lgan MaxRAMPercentage taqqoslandi va tahlil qilindi.

Heapdan foydalanish

Element

80%

70%

65%

60%

Konteyner cheklovi

1,073MB

1,073MB

1,073MB

1,073MB

Heap maksimal

858MB

~751MB

~698MB

~644MB

Heapdan Tashqari O'lchov

~200MB

~200MB

~200MB

~200MB

Thread Stackni o'z ichiga olgan qo'shimcha yuklamalar

~50~80MB

~50~80MB

~50~80MB

~50~80MB

Jami Baholash

~1,108~1,131MB

~1,001~1,031MB

~948~978MB

~894MB

Bepul

~42~72MB

~95~125MB

~179MB

Variant bo'yicha taqqoslash

Sozlamalar

Heap maksimal

Bepul

Baholash

Taqqoslash

Hozirgi 80%

~858MB

~15MB

Xatar

Non-Heap, Off-Heap qo'shimcha resurslardan foydalanishda muammolar

70%

~751MB

~42~72MB

Nodir

G1GC bilan konteyner chegarasini oshirish (1.5Gi)

60%

~644MB

~149~179MB

Tavsiya etilgan

G1GC ni qo'llang

50%

~536MB

~257MB

Xavfsiz, lekin heap yetarli bo'lmasligi mumkin

Ko'rib chiqishdan chiqarish

  • Eng xavfsiz yondashuv uni 60% ga o'rnatish va kuzatish, zarurat bo'lsa oshirishdir.

  • Non-Heap yoki Off-Heap 200MB qattiq qiymat emas va yuk ostidagi vaziyatlarda OOMKilled ga olib kelishi mumkin, masalan, qo'shimcha fayl yuklashda.

Tavsiya etilgan JVM variantlari (yakuniy)

# 현재
-XX:InitialRAMPercentage=25
-XX:MaxRAMPercentage=80
-XX:+UseParallelGC
# 권장
-XX:InitialRAMPercentage=25
-XX:MaxRAMPercentage=60          # Heap ~644MB로 제한
-XX:+UseG1GC                     # Container 친화적 GC
-XX:MaxMetaspaceSize=192m        # Metaspace 상한 설정 (현재 122MB 사용 중)
-XX:MaxDirectMemorySize=140m     # Direct Buffer 상한 설정 (현재 108MB 사용 중)
  • Heap maksimal: ~644MB

  • Non-Heap: ~200MB

  • Jami: ~844MB → 1Gi konteyner chegarasi ichida bufer taqdim eting

sby

Site footer