Memecahkan masalah peristiwa OOM

Jika aplikasi Google Kubernetes Engine (GKE) Anda mengalami penghentian container yang tidak terduga, ketidakstabilan, atau error CrashLoopBackOff, hal ini mungkin disebabkan oleh peristiwa Kehabisan Memori (OOM). Peristiwa OOM terjadi saat container atau node kehabisan memori, sehingga Linux OOM Killer menghentikan proses untuk mengklaim kembali resource.

Gunakan halaman ini untuk mengidentifikasi apakah peristiwa OOM terjadi di tingkat container atau tingkat node, dan menerapkan strategi mitigasi yang efektif untuk mencegah terulangnya peristiwa tersebut.

Informasi ini penting bagi Developer aplikasi yang perlu memastikan bahwa aplikasi mereka dikonfigurasi dengan permintaan dan batas memori yang sesuai serta bebas dari kebocoran memori. Informasi ini juga penting bagi Admin dan operator platform yang memantau penggunaan resource node dan memastikan bahwa cluster memiliki kapasitas memori yang memadai untuk mendukung workload yang di-deploy. Untuk mengetahui informasi selengkapnya tentang peran umum dan contoh tugas yang kami referensikan dalam Cloud de Confiance by S3NS konten, lihat Peran dan tugas pengguna GKE umum.

Penyebab umum peristiwa OOM

Peristiwa OOM biasanya terjadi selama lonjakan beban atau traffic, saat penggunaan memori aplikasi melonjak dan mencapai batas memori yang dikonfigurasi untuk container.

Skenario berikut dapat menyebabkan peristiwa OOM:

  • Batas memori yang tidak memadai: setelan resources.limits.memory dalam manifes Pod terlalu rendah untuk permintaan memori puncak atau umum aplikasi.
  • Permintaan atau batas memori yang tidak ditentukan: jika resources.limits.memory dan resources.requests.memory tidak ditentukan, penggunaan memori container tidak akan dibatasi.
  • Beban tinggi atau tidak stabil: lonjakan beban yang tiba-tiba dan ekstrem dapat membebani resource sistem, termasuk memori, meskipun batasnya biasanya memadai.
  • Kebocoran memori: aplikasi mungkin memiliki cacat kode yang menyebabkan aplikasi gagal melepaskan memori dengan benar.

Peristiwa OOM dapat memulai kegagalan berjenjang, karena jumlah container yang tersisa untuk menangani traffic semakin sedikit, sehingga meningkatkan beban pada container yang tersisa. Container ini kemudian juga dapat dihentikan.

Cara Kubernetes menangani peristiwa OOM

Linux OOM Killer menangani setiap peristiwa OOM. OOM Killer adalah proses kernel yang diaktifkan saat sistem hampir kehabisan memori. Tujuannya adalah untuk mencegah error sistem total dengan menghentikan proses secara strategis untuk mengosongkan resource. Kernel menggunakan sistem penilaian untuk memilih proses mana yang akan dihentikan, dengan tujuan untuk mempertahankan stabilitas sistem dan meminimalkan kehilangan data.

Di lingkungan Kubernetes, OOM Killer beroperasi pada dua cakupan yang berbeda: grup kontrol (cgroup), yang memengaruhi satu container; dan sistem, yang memengaruhi seluruh node.

OOM kill tingkat container

OOM kill tingkat container terjadi saat container mencoba melebihi batas memori yang telah ditentukan. Kubernetes menetapkan setiap container ke cgroup tertentu dengan batas memori yang ketat. Saat penggunaan memori container mencapai batas ini, kernel akan mencoba mengklaim kembali memori dalam cgroup tersebut. Jika kernel tidak dapat mengklaim kembali memori yang cukup dengan menggunakan proses ini, OOM Killer cgroup akan dipanggil. OOM Killer akan menghentikan proses dalam cgroup tertentu tersebut untuk menerapkan batas resource.

Saat proses utama dalam container dihentikan dengan cara ini, Kubernetes akan mengamati peristiwa tersebut dan menandai status container sebagai OOMKilled. restartPolicy yang dikonfigurasi Pod kemudian akan menentukan hasilnya:

  • Always atau OnFailure: container akan dimulai ulang.
  • Never: container tidak akan dimulai ulang dan tetap dalam status dihentikan.

Dengan mengisolasi kegagalan ke container yang bermasalah, OOM Killer mencegah satu Pod yang rusak menyebabkan error pada seluruh node.

Pengaruh versi cgroup terhadap perilaku OOM Killer

Perilaku OOM kill dapat berbeda secara signifikan antara versi cgroup. Jika Anda tidak yakin versi cgroup mana yang digunakan, periksa mode cgroup node cluster.

  • Di cgroup v1, peristiwa OOM dalam cgroup memori container dapat menyebabkan perilaku yang tidak dapat diprediksi. OOM Killer dapat menghentikan proses apa pun dalam cgroup tersebut, termasuk proses turunan yang bukan proses utama container (PID 1).

    Perilaku ini menimbulkan tantangan yang signifikan bagi Kubernetes. Karena Kubernetes terutama memantau kesehatan proses container utama, Kubernetes tidak mengetahui OOM kill "parsial" ini. Proses container utama mungkin terus berjalan, meskipun proses turunan penting telah dihentikan. Perilaku ini dapat menyebabkan kegagalan aplikasi yang tidak terlihat secara langsung oleh Kubernetes atau operator, tetapi masih terlihat di jurnal sistem node (journalctl).

  • cgroup v2 menawarkan perilaku OOM Killer yang lebih dapat diprediksi.

    Untuk membantu menjamin integritas workload di lingkungan cgroup v2, OOM Killer mencegah penghentian parsial dan memastikan salah satu dari dua hasil: baik semua tugas yang termasuk dalam cgroup tersebut dan turunannya dihentikan (sehingga kegagalan terlihat oleh Kubernetes), atau saat workload tidak memiliki tugas yang menggunakan terlalu banyak memori, workload dibiarkan tidak tersentuh dan terus berjalan tanpa penghentian proses internal yang tidak terduga.

    Untuk skenario saat Anda menginginkan perilaku cgroup v1 untuk menghentikan satu proses, kubelet menyediakan flag singleProcessOOMKill untuk cgroup v2. Flag ini memberi Anda kontrol yang lebih terperinci, sehingga memungkinkan penghentian proses individual selama peristiwa OOM, bukan seluruh cgroup.

OOM kill tingkat sistem

OOM kill tingkat sistem adalah peristiwa yang lebih serius yang terjadi saat seluruh node, bukan hanya satu container, kehabisan memori yang tersedia. Peristiwa ini dapat terjadi jika penggunaan memori gabungan dari semua proses (termasuk semua Pod dan daemon sistem) melebihi kapasitas node.

Saat node ini kehabisan memori, OOM Killer global akan menilai semua proses di node dan menghentikan proses untuk mengklaim kembali memori untuk seluruh sistem. Proses yang dipilih biasanya adalah proses yang berumur pendek dan menggunakan sejumlah besar memori.

Untuk mencegah situasi OOM yang parah, Kubernetes menggunakan penghentian tekanan node untuk mengelola resource node. Proses ini melibatkan penghentian Pod yang kurang penting dari node saat resource, seperti memori atau ruang disk, menjadi sangat rendah. OOM kill tingkat sistem menunjukkan bahwa proses penghentian ini tidak dapat mengosongkan memori dengan cukup cepat untuk mencegah masalah.

Jika OOM Killer menghentikan proses container, efeknya biasanya sama dengan penghentian yang dipicu cgroup: container ditandai OOMKilled dan dimulai ulang berdasarkan kebijakannya. Namun, jika proses sistem penting dihentikan (yang jarang terjadi), node itu sendiri dapat menjadi tidak stabil.

Menyelidiki peristiwa OOM

Bagian berikut membantu Anda mendeteksi dan mengonfirmasi peristiwa OOM, dimulai dengan alat Kubernetes yang paling sederhana dan beralih ke analisis log yang lebih mendetail.

Memeriksa status Pod untuk peristiwa OOM yang terlihat

Langkah pertama dalam mengonfirmasi peristiwa OOM adalah memeriksa apakah Kubernetes mengamati peristiwa OOM. Kubernetes mengamati peristiwa saat proses utama container dihentikan, yang merupakan perilaku standar di lingkungan cgroup v2.

  • Periksa status Pod:

    kubectl describe pod POD_NAME
    

    Ganti POD_NAME dengan nama Pod yang ingin Anda selidiki.

    Jika peristiwa OOM yang terlihat terjadi, outputnya akan mirip dengan berikut ini:

    ...
      Last State:     Terminated
        Reason:       OOMKilled
        Exit Code:    137
        Started:      Tue, 13 May 2025 19:05:28 +0000
        Finished:     Tue, 13 May 2025 19:05:30 +0000
    ...
    

Jika Anda melihat OOMKilled di kolom Reason, Anda telah mengonfirmasi peristiwa tersebut. Exit Code dari 137 juga menunjukkan OOM kill. Jika kolom Reason memiliki nilai yang berbeda, atau Pod masih berjalan meskipun terjadi error aplikasi, lanjutkan ke bagian berikutnya untuk penyelidikan lebih lanjut.

Menelusuri log untuk peristiwa OOM yang tidak terlihat

OOM kill "tidak terlihat" oleh Kubernetes jika proses turunan dihentikan, tetapi proses container utama terus berjalan (skenario umum di lingkungan cgroup v1). Anda harus menelusuri log node untuk menemukan bukti peristiwa ini.

Untuk menemukan OOM kill yang tidak terlihat, gunakan Logs Explorer:

  1. Di Cloud de Confiance Konsol, buka Logs Explorer.

    Buka Logs Explorer

  2. Di panel kueri, masukkan salah satu kueri berikut:

    • Jika Anda sudah memiliki Pod yang menurut Anda mengalami peristiwa OOM, kueri Pod tertentu tersebut:

      resource.type="k8s_node"
      jsonPayload.MESSAGE:(("POD_NAME" AND "ContainerDied") OR "TaskOOM event")
      resource.labels.cluster_name="CLUSTER_NAME"
      

      Ganti kode berikut:

      • POD_NAME: nama Pod yang ingin Anda kueri.
      • CLUSTER_NAME: nama cluster tempat Pod berada.
    • Untuk menemukan Pod atau node mana yang mengalami peristiwa OOM, kueri semua workload GKE:

      resource.type="k8s_node"
      jsonPayload.MESSAGE:("ContainerDied" OR "TaskOOM event")
      resource.labels.cluster_name="CLUSTER_NAME"
      
  3. Klik Run query.

  4. Dalam output, temukan peristiwa OOM dengan menelusuri entri log yang berisi string TaskOOM.

  5. Opsional: jika Anda menelusuri peristiwa OOM untuk semua workload GKE dan ingin mengidentifikasi Pod tertentu yang mengalami peristiwa OOM, selesaikan langkah-langkah berikut:

    1. Untuk setiap peristiwa, catat ID container yang terkait dengannya.
    2. Identifikasi penghentian container dengan mencari entri log yang berisi string ContainerDied, dan yang terjadi tidak lama setelah peristiwa OOM. Cocokkan ID container dari peristiwa OOM dengan baris ContainerDied yang sesuai.

    3. Setelah Anda mencocokkan container IDs, baris ContainerDied biasanya menyertakan nama Pod yang terkait dengan container yang gagal. Pod ini terpengaruh oleh peristiwa OOM.

Menggunakan journalctl untuk informasi real-time

Jika Anda perlu melakukan analisis real-time pada sistem, gunakan perintah journalctl.

  1. Hubungkan ke node menggunakan SSH:

    gcloud compute ssh NODE_NAME --location ZONE
    

    Ganti kode berikut:

    • NODE_NAME: nama node yang ingin Anda periksa.
    • ZONE: zona Compute Engine tempat node Anda berada.
  2. Di shell, jelajahi pesan kernel dari jurnal sistem node:

    journalctl -k
    
  3. Analisis output untuk membedakan jenis peristiwa:

    • Penghentian tingkat container: entri log berisi istilah seperti memory cgroup, mem_cgroup, atau memcg, yang menunjukkan bahwa batas cgroup telah diterapkan.
    • Penghentian tingkat sistem: entri log adalah pesan umum seperti Out of memory: Killed process... tanpa menyebutkan cgroup.

Menyelesaikan peristiwa OOM

Untuk menyelesaikan peristiwa OOM, coba solusi berikut:

  • Meningkatkan batas memori: ini adalah solusi yang paling langsung. Edit manifes Pod untuk memberikan nilai resources.limits.memory yang lebih tinggi yang mengakomodasi penggunaan puncak aplikasi. Untuk mengetahui informasi selengkapnya tentang cara menetapkan batas, lihat Pengelolaan Resource untuk Pod dan Container dalam dokumentasi Kubernetes.
  • Menambahkan atau menyesuaikan permintaan memori: dalam manifes Pod, pastikan bahwa kolom resources.requests.memory ditetapkan ke nilai yang realistis untuk penggunaan umum. Setelan ini membantu Kubernetes menjadwalkan Pod ke node dengan memori yang cukup.
  • Menskalakan workload secara horizontal: untuk mendistribusikan beban traffic dan mengurangi tekanan memori pada satu Pod, tingkatkan jumlah replika. Agar Kubernetes dapat menskalakan workload secara proaktif, pertimbangkan untuk mengaktifkan penskalaan otomatis Pod horizontal.
  • Menskalakan node secara vertikal: jika banyak Pod di node mendekati batasnya, node itu sendiri mungkin terlalu kecil. Untuk meningkatkan ukuran node, migrasikan workload Anda ke node pool dengan memori yang lebih besar. Agar Kubernetes dapat menskalakan node secara proaktif, pertimbangkan untuk mengaktifkan penskalaan otomatis Pod vertikal.
  • Mengoptimalkan aplikasi: tinjau aplikasi Anda untuk mengidentifikasi dan menyelesaikan kebocoran memori serta mengoptimalkan kode yang menggunakan sejumlah besar memori selama lonjakan traffic.
  • Menghapus workload yang bermasalah: sebagai upaya terakhir untuk workload yang tidak penting hapus Pod untuk segera mengurangi tekanan pada cluster.

Langkah berikutnya