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