Tangkap dump heap .hprof yang tetap tersimpan meskipun Pod OOM direstart dengan memasang volume NAS berbasis CNFS.
Prasyarat
Pastikan hal-hal berikut:
-
Sistem file NAS yang dikelola CNFS telah disediakan.
-
Instans Container Registry Edisi Perusahaan telah dibuat.
Catatan penggunaan
Tetapkan batas maksimum heap JVM di bawah batas memori pod. Pastikan nilai -Xmx berada di bawah batas memori pod. Jika heap JVM mencapai batas pod terlebih dahulu, Linux OOM killer akan menghentikan pod sebelum JVM sempat menulis dump.
Gunakan CNFS khusus untuk dump heap. Satu kejadian OOM saja dapat menghasilkan file .hprof berukuran beberapa gigabyte yang berpotensi menghabiskan kuota bersama dan mengganggu operasi.
Sinkronkan image File Browser sebelum memulai. Image docker.io/filebrowser/filebrowser:v2.18.0 mungkin gagal ditarik karena pembatasan jaringan. Sinkronkan ke instans ACR Edisi Perusahaan Anda dengan cara berlangganan image dari luar Tiongkok:
| Field | Value |
|---|---|
| Artifact source | Docker Hub |
| Source repository coordinates | filebrowser/filebrowser |
| Subscription policy | v2.18.0 |
Setelah sinkronisasi selesai, konfigurasikan penarikan image tanpa kata sandi antara instans ACR Edisi Perusahaan dan kluster ACK Anda.
Terapkan aplikasi Java
Terapkan Deployment Java dengan penyimpanan berbasis CNFS sebagai tujuan dump heap. Image contoh registry.cn-hangzhou.aliyuncs.com/acs1/java-oom-test:v1.0 menjalankan Mycode dengan batas heap 80 MiB.
Deployment ini menggunakan subPathExpr: $(POD_NAMESPACE).$(POD_NAME) untuk membuat subdirektori khusus per-pod di dalam volume NAS bersama, sehingga restart pod tidak saling menimpa dump satu sama lain.
subPathExprmenggunakan tanda kurung biasa —$(POD_NAME)— bukan kurung kurawal. Nilainya berasal dari variabel lingkungan Downward APIPOD_NAMEdanPOD_NAMESPACE.
cat << EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: java-application
spec:
selector:
matchLabels:
app: java-application
template:
metadata:
labels:
app: java-application
spec:
containers:
- name: java-application
image: registry.cn-hangzhou.aliyuncs.com/acs1/java-oom-test:v1.0
imagePullPolicy: Always
env:
- name: POD_NAME # Masukkan nama pod melalui Downward API
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: POD_NAMESPACE # Masukkan namespace pod melalui Downward API
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
args:
- java
- -Xms80m # Ukuran heap minimum
- -Xmx80m # Ukuran heap maksimum (tetap di bawah batas memori pod)
- -XX:HeapDumpPath=/mnt/oom/logs # Tulis dump heap ke mount berbasis CNFS
- -XX:+HeapDumpOnOutOfMemoryError # Picu dump heap saat terjadi OOM
- Mycode
volumeMounts:
- name: java-oom-pv
mountPath: "/mnt/oom/logs"
subPathExpr: $(POD_NAMESPACE).$(POD_NAME) # Gunakan tanda kurung biasa, bukan kurung kurawal
volumes:
- name: java-oom-pv
persistentVolumeClaim:
claimName: cnfs-nas-pvc
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: cnfs-nas-pvc
spec:
accessModes:
- ReadWriteMany
storageClassName: alibabacloud-cnfs-nas
resources:
requests:
storage: 70Gi # Jika kuota direktori diaktifkan, batasi subdirektori hingga 70 GiB
---
EOF
Verifikasi kejadian OOM
Saat Deployment mulai berjalan, Mycode mengalokasikan memori hingga JVM menghabiskan heap 80 MiB dan memicu OOM. Pod tersebut direstart, dan ACK mencatat peringatan back-off restarting di Pusat Insiden.
Untuk memastikan OOM telah terjadi:
-
Masuk ke Konsol ACK. Di panel navigasi kiri, klik Clusters.
-
Temukan kluster Anda dan klik namanya. Di panel navigasi kiri, pilih Operations > Event Center.
-
Periksa daftar event untuk menemukan peringatan
back-off restartingpada podjava-application.
Jelajahi file dump heap
Terapkan File Browser dengan PVC CNFS yang sama dipasang di rootDir untuk menjelajahi dan mengunduh dump heap.
Terapkan File Browser
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: filebrowser
namespace: default
labels:
app.kubernetes.io/instance: filebrowser
app.kubernetes.io/name: filebrowser
data:
.filebrowser.json: |
{
"port": 80,
"address": "0.0.0.0"
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: filebrowser
namespace: default
labels:
app.kubernetes.io/instance: filebrowser
app.kubernetes.io/name: filebrowser
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/instance: filebrowser
app.kubernetes.io/name: filebrowser
template:
metadata:
labels:
app.kubernetes.io/instance: filebrowser
app.kubernetes.io/name: filebrowser
spec:
containers:
- name: filebrowser
# Ganti dengan alamat image ACR Anda setelah menyinkronkan filebrowser/filebrowser:v2.18.0
image: XXXX-registry-vpc.cn-hangzhou.cr.aliyuncs.com/test/test:v2.18.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
name: http
protocol: TCP
volumeMounts:
- mountPath: /.filebrowser.json
name: config
subPath: .filebrowser.json
- mountPath: /db
name: rootdir
- mountPath: /rootdir
name: rootdir
volumes:
- name: config
configMap:
name: filebrowser
defaultMode: 420
- name: rootdir
persistentVolumeClaim:
claimName: cnfs-nas-pvc # PVC yang sama dengan Deployment java-application
EOF
Output yang diharapkan:
configmap/filebrowser unchanged
deployment.apps/filebrowser configured
Buat Service
-
Masuk ke Konsol ACK. Di panel navigasi kiri, klik Clusters.
-
Temukan kluster Anda dan klik namanya. Di panel navigasi kiri, pilih Network > Services.
-
Pada halaman Services, pilih namespace
defaultlalu klik Create. Konfigurasikan parameter berikut:Lihat Ikhtisar penagihan NLB.
Parameter Value Name filebrowserService type SLB > SLB type: CLB. Pilih Create Resource, lalu atur Access method menjadi Public Access. Backend Klik +Reference Workload Label. Atur Resource type menjadi Deploymentsdan Resources menjadifilebrowser.Port mapping Service port: 8080, Container port:80, Protocol:TCP -
Kirimkan konfigurasi tersebut.
Akses File Browser
-
Salin alamat endpoint dari halaman Services.
-
Buka
<endpoint-address>:8080di browser. Halaman login File Browser akan muncul. -
Login dengan kredensial default: username
admin, passwordadmin.
-
Klik ganda rootdir untuk masuk ke titik mount NAS.

Hasil
Di dalam rootdir, setiap direktori dump pod dinamai sesuai aturan subPathExpr: $(POD_NAMESPACE).$(POD_NAME) — misalnya, default.java-application-76d8cd95b7-prrl2.
Buka direktori tersebut untuk menemukan java_pid1.hprof. Unduh dan analisis file tersebut dengan Eclipse Memory Analyzer (MAT) untuk mengidentifikasi kode yang menyebabkan OOM.
Cara kerja
Tiga mekanisme bekerja sama untuk menyimpan dump heap meskipun pod direstart:
-
PVC CNFS dengan `ReadWriteMany`: PVC berbasis NAS dipasang ke dalam pod
java-applicationmaupun File Browser. NAS menyimpan file secara independen dari siklus hidup pod, sehingga file dump tetap tersedia meskipun pod crash. -
`subPathExpr` dengan Downward API: Setiap pod dipasang ke subdirektori sendiri (
<namespace>.<pod-name>) alih-alih ke root NAS, sehingga restart tidak saling menimpa dump dan memudahkan pelacakan dump ke pod tertentu. -
`-XX:+HeapDumpOnOutOfMemoryError`: JVM menulis status heap ke lokasi yang ditentukan oleh
-XX:HeapDumpPathsebelum keluar akibat OOM. Karena lokasi tersebut berada di penyimpanan NAS, file tersebut tetap tersimpan meskipun pod berhenti.