Capture volcados de heap .hprof que persisten entre reinicios de pods por OOM al montar un volumen NAS respaldado por CNFS.
Requisitos previos
Asegúrese de cumplir con lo siguiente:
Se ha aprovisionado un CNFS-managed NAS file system.
Se ha creado un Enterprise Edition instance en Container Registry.
Notas de uso
Configure el tamaño máximo del heap de JVM por debajo del límite de memoria del pod. Mantenga el parámetro -Xmx inferior al límite de memoria asignado al pod. Si el heap de JVM alcanza primero el límite del pod, el OOM killer de Linux finalizará el proceso antes de que la JVM pueda escribir el volcado.
Utilice un CNFS dedicado para los volcados de heap. Un solo evento de OOM puede generar un archivo .hprof de varios gigabytes que podría agotar la cuota compartida e interrumpir las operaciones.
Sincronice la imagen de File Browser antes de comenzar. Es posible que no se pueda extraer la imagen docker.io/filebrowser/filebrowser:v2.18.0 debido a restricciones de red. Sincronícela con su instancia de ACR Enterprise Edition mediante subscribing to images from outside China:
|
Campo |
Valor |
|
Artifact source |
Docker Hub |
|
Source repository coordinates |
|
|
Subscription policy |
|
Después de la sincronización, configure password-free image pulling entre la instancia de ACR Enterprise Edition y su clúster de ACK.
Despliegue de la aplicación Java
Despliegue un Deployment de Java con almacenamiento respaldado por CNFS como destino para los volcados de heap. La imagen de ejemplo registry.cn-hangzhou.aliyuncs.com/acs1/java-oom-test:v1.0 ejecuta Mycode con un límite de heap de 80 MiB.
El Deployment utiliza subPathExpr: $(POD_NAMESPACE).$(POD_NAME) para crear subdirectorios individuales por pod dentro del volumen NAS compartido. Esto evita que los reinicios de los pods sobrescriban los volcados de otros.
subPathExprutiliza paréntesis redondos —$(POD_NAME)— y no llaves. Los valores provienen de las variables de entorno de la Downward APIPOD_NAMEyPOD_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 # Inject pod name via Downward API
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: POD_NAMESPACE # Inject pod namespace via Downward API
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
args:
- java
- -Xms80m # Minimum heap size
- -Xmx80m # Maximum heap size (keep below pod memory limit)
- -XX:HeapDumpPath=/mnt/oom/logs # Write heap dumps to the CNFS-backed mount
- -XX:+HeapDumpOnOutOfMemoryError # Trigger heap dump on OOM
- Mycode
volumeMounts:
- name: java-oom-pv
mountPath: "/mnt/oom/logs"
subPathExpr: $(POD_NAMESPACE).$(POD_NAME) # Round brackets, not curly brackets
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 # If directory quota is enabled, limits the subdirectory to 70 GiB
---
EOF
Verificación del evento OOM
Una vez que inicia el Deployment, Mycode asigna memoria hasta que la JVM agota el heap de 80 MiB y desencadena un error OOM. El pod se reinicia y ACK registra una alerta de back-off restarting en Event Center.
Para confirmar que ocurrió el evento OOM:
Inicie sesión en la consola de ACK. En el panel de navegación izquierdo, haga clic en Clusters.
Localice su clúster y haga clic en su nombre. En el panel de navegación izquierdo, seleccione Operations > Event Center.
-
Revise la lista de eventos para buscar una alerta de
back-off restartingen el podjava-application.
Exploración de los archivos de volcado de heap
Despliegue File Browser con el mismo PVC de CNFS montado en rootDir para explorar y descargar los volcados de heap.
Despliegue de 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
# Replace with your ACR image address after syncing 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 # Same PVC as the java-application Deployment
EOF
Salida esperada:
configmap/filebrowser unchanged
deployment.apps/filebrowser configured
Creación de un Service
Inicie sesión en la consola de ACK. En el panel de navegación izquierdo, haga clic en Clusters.
Localice su clúster y haga clic en su nombre. En el panel de navegación izquierdo, seleccione Network > Services.
-
En la página Services, seleccione el namespace
defaulty haga clic en Create. Configure los siguientes parámetros:Consulte NLB billing overview .
Parámetro
Valor
Name
filebrowserService type
SLB > SLB type: CLB. Seleccione Create Resource y establezca Access method en Public Access.
Backend
Haga clic en +Reference Workload Label. Establezca Resource type en
Deploymentsy Resources enfilebrowser.Port mapping
Service port:
8080, Container port:80, Protocol:TCP Envíe la configuración.
Acceso a File Browser
Copie la dirección del endpoint desde la página de Services.
Abra
<endpoint-address>:8080en un navegador. Aparecerá la página de inicio de sesión de File Browser.-
Inicie sesión con las credenciales predeterminadas: nombre de usuario
admin, contraseñaadmin.
-
Haga doble clic en rootdir para acceder al punto de montaje de NAS.

Resultado
Dentro de rootdir, el directorio de volcado de cada pod sigue la nomenclatura definida por la regla subPathExpr: $(POD_NAMESPACE).$(POD_NAME); por ejemplo, default.java-application-76d8cd95b7-prrl2.

Abra el directorio para localizar el archivo java_pid1.hprof. Descárguelo y analícelo con Eclipse Memory Analyzer (MAT) para identificar el código que provocó el error OOM.

Funcionamiento
Tres mecanismos trabajan en conjunto para preservar los volcados de heap entre reinicios de pods:
PVC de CNFS con
ReadWriteMany: El PVC respaldado por NAS se monta tanto en el podjava-applicationcomo en el de File Browser. NAS conserva los archivos independientemente del ciclo de vida del pod, por lo que los volcados sobreviven a las caídas.subPathExprcon Downward API: Cada pod se monta en su propio subdirectorio (<namespace>.<pod-name>) en lugar de la raíz de NAS. Esto impide que los reinicios sobrescriban los volcados y facilita el rastreo hacia el pod correspondiente.-XX:+HeapDumpOnOutOfMemoryError: La JVM escribe el estado del heap en la ruta definida por-XX:HeapDumpPathantes de finalizar por OOM. Dado que dicha ruta reside en NAS, el archivo persiste tras la salida del pod.