Capturez les vidages de tas .hprof qui persistent lors des redémarrages de pods dus à une erreur de mémoire insuffisante (OOM) en montant un volume NAS pris en charge par CNFS.
Prérequis
Vérifiez les points suivants :
Un système de fichiers NAS géré par CNFS est provisionné.
Une instance Enterprise Edition de Container Registry est créée.
Notes d'utilisation
Définissez la taille maximale du tas JVM en dessous de la limite de mémoire du pod. Maintenez la valeur -Xmx inférieure à la limite de mémoire du pod. Si le tas JVM atteint d'abord la limite du pod, le tueur OOM de Linux termine le pod avant que la JVM ne puisse écrire le vidage.
Utilisez un CNFS dédié pour les vidages de tas. Un seul événement OOM peut générer un fichier .hprof de plusieurs gigaoctets, susceptible d'épuiser le quota partagé et de perturber les opérations.
Synchronisez l'image File Browser avant de commencer. L'image docker.io/filebrowser/filebrowser:v2.18.0 peut échouer au téléchargement en raison de restrictions réseau. Synchronisez-la avec votre instance ACR Enterprise Edition en vous abonnant aux images provenant de l'extérieur de la Chine :
| Champ | Valeur |
|---|---|
| Artifact source | Docker Hub |
| Source repository coordinates | filebrowser/filebrowser |
| Subscription policy | v2.18.0 |
Après la synchronisation, configurez le téléchargement d'images sans mot de passe entre l'instance ACR Enterprise Edition et votre cluster ACK.
Déploiement de l'application Java
Déployez un déploiement Java avec un stockage pris en charge par CNFS comme destination des vidages de tas. L'image d'exemple registry.cn-hangzhou.aliyuncs.com/acs1/java-oom-test:v1.0 exécute Mycode avec une limite de tas de 80 MiB.
Le déploiement utilise subPathExpr: $(POD_NAMESPACE).$(POD_NAME) pour créer des sous-répertoires par pod dans le volume NAS partagé, empêchant ainsi les redémarrages de pods d'écraser les vidages des autres.
subPathExprutilise des parenthèses —$(POD_NAME)— et non des accolades. Les valeurs proviennent des variables d'environnement Downward APIPOD_NAMEetPOD_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
Vérification de l'événement OOM
Une fois le déploiement démarré, Mycode alloue de la mémoire jusqu'à ce que la JVM épuise le tas de 80 MiB et déclenche une erreur OOM. Le pod redémarre et ACK enregistre une alerte back-off restarting dans le centre d'événements.
Pour confirmer la survenue de l'erreur OOM :
Connectez-vous à la console ACK. Dans le volet de navigation de gauche, cliquez sur Clusters.
Recherchez votre cluster et cliquez sur son nom. Dans le volet de navigation de gauche, choisissez Operations > Event Center.
-
Vérifiez la liste des événements pour détecter une alerte
back-off restartingsur le podjava-application.
Parcours des fichiers de vidage de tas
Déployez File Browser avec le même PVC CNFS monté sur rootDir pour parcourir et télécharger les vidages de tas.
Déploiement 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
Sortie attendue :
configmap/filebrowser unchanged
deployment.apps/filebrowser configured
Création d'un service
Connectez-vous à la console ACK. Dans le volet de navigation de gauche, cliquez sur Clusters.
Recherchez votre cluster et cliquez sur son nom. Dans le volet de navigation de gauche, choisissez Network > Services.
-
Sur la page Services, sélectionnez l'espace de noms
defaultet cliquez sur Create. Configurez les paramètres suivants :Consultez la présentation de la facturation NLB .
Paramètre Valeur Name filebrowserService type SLB > SLB type: CLB. Sélectionnez Create Resource, puis définissez Access method sur Public Access. Backend Cliquez sur +Reference Workload Label. Définissez Resource type sur Deploymentset Resources surfilebrowser.Port mapping Service port : 8080, Container port :80, Protocol :TCP Envoyez la configuration.
Accès à File Browser
Copiez l'adresse du point de terminaison depuis la page Services.
Ouvrez
<endpoint-address>:8080dans un navigateur. La page de connexion File Browser s'affiche.-
Connectez-vous avec les identifiants par défaut : nom d'utilisateur
admin, mot de passeadmin.
-
Double-cliquez sur rootdir pour accéder au point de montage NAS.

Résultat
Dans rootdir, le répertoire de vidage de chaque pod est nommé selon la règle subPathExpr: $(POD_NAMESPACE).$(POD_NAME) — par exemple, default.java-application-76d8cd95b7-prrl2.

Ouvrez le répertoire pour trouver java_pid1.hprof. Téléchargez-le et analysez-le avec Eclipse Memory Analyzer (MAT) pour identifier le code ayant provoqué l'erreur OOM.

Fonctionnement
Trois mécanismes permettent de conserver les vidages de tas lors des redémarrages de pods :
PVC CNFS avec
ReadWriteMany: Le PVC sauvegardé par NAS est monté dans les podsjava-applicationet File Browser. NAS conserve les fichiers indépendamment du cycle de vie des pods, de sorte que les fichiers de vidage survivent aux plantages des pods.subPathExpravec Downward API : Chaque pod monte son propre sous-répertoire (<namespace>.<pod-name>) plutôt que la racine NAS, ce qui empêche les redémarrages d'écraser les vidages et facilite le traçage des vidages vers les pods.-XX:+HeapDumpOnOutOfMemoryError: La JVM écrit l'état du tas dans-XX:HeapDumpPathavant de quitter en cas d'erreur OOM. Comme ce chemin est sauvegardé par NAS, le fichier survit à la sortie du pod.