すべてのプロダクト
Search
ドキュメントセンター

Container Service for Kubernetes:CNFS を使用した異常終了時の JVM ヒープダンプの収集

最終更新日:Jun 19, 2026

CNFS をバックエンドとする NAS ボリュームをマウントすることで、OOM による Pod の再起動後も永続化される .hprof ヒープダンプをキャプチャします。

前提条件

以下を確認してください。

注意事項

JVM の最大ヒープを Pod のメモリ制限よりも低く設定してください。 -Xmx は Pod のメモリ制限よりも低く設定してください。JVM ヒープが先に Pod の制限に達した場合、JVM がダンプを書き込む前に Linux の OOM Killer が Pod を終了させてしまいます。

ヒープダンプには専用の CNFS を使用してください。 1 回の OOM イベントで数ギガバイトの .hprof ファイルが生成される可能性があり、共有クォータを使い果たして運用に支障をきたす恐れがあります。

開始する前に File Browser イメージを同期してください。 docker.io/filebrowser/filebrowser:v2.18.0 は、ネットワークの制限によりプルに失敗する可能性があります。「中国以外からのイメージのサブスクライブ」を参照して、ご利用の ACR Enterprise Edition インスタンスに同期してください。

フィールド
アーティファクトソース Docker Hub
ソースリポジトリ座標 filebrowser/filebrowser
サブスクリプションポリシー v2.18.0
同期後、ACR Enterprise Edition インスタンスと ACK クラスター間でパスワードなしのイメージプルを設定します。

Java アプリケーションのデプロイ

ヒープダンプの保存先として CNFS をバックエンドとするストレージを持つ Java Deployment をデプロイします。サンプルイメージ registry.cn-hangzhou.aliyuncs.com/acs1/java-oom-test:v1.0 は、80 MiB のヒープ制限で Mycode を実行します。

この Deployment は subPathExpr: $(POD_NAMESPACE).$(POD_NAME) を使用して、共有 NAS ボリューム内に Pod ごとのサブディレクトリを作成します。これにより、Pod が再起動しても互いのダンプが上書きされるのを防ぎます。

subPathExpr は、波括弧ではなく丸括弧 — $(POD_NAME) — を使用します。値は、Downward API の環境変数 POD_NAMEPOD_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          # Downward API 経由で Pod 名を挿入
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.name
        - name: POD_NAMESPACE     # Downward API 経由で Pod の名前空間を挿入
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.namespace
        args:
        - java
        - -Xms80m                         # 最小ヒープサイズ
        - -Xmx80m                         # 最大ヒープサイズ (Pod のメモリ制限より低く設定)
        - -XX:HeapDumpPath=/mnt/oom/logs  # CNFS をバックエンドとするマウント先にヒープダンプを書き込む
        - -XX:+HeapDumpOnOutOfMemoryError # OOM 時にヒープダンプをトリガー
        - Mycode
        volumeMounts:
        - name: java-oom-pv
          mountPath: "/mnt/oom/logs"
          subPathExpr: $(POD_NAMESPACE).$(POD_NAME)  # 波括弧ではなく丸括弧
      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  # ディレクトリクォータが有効な場合、サブディレクトリを 70 GiB に制限
---
EOF

OOM イベントの確認

Deployment が開始されると、Mycode は JVM が 80 MiB のヒープを使い果たして OOM をトリガーするまでメモリを割り当てます。Pod が再起動し、ACK はイベントセンターに back-off restarting アラートを記録します。

OOM が発生したことを確認するには:

  1. ACK コンソールにログインします。左側のナビゲーションウィンドウで、[クラスター] をクリックします。

  2. 対象のクラスターを見つけて、その名前をクリックします。左側のナビゲーションウィンドウで、[運用] > [イベントセンター] を選択します。

  3. イベントリストで、java-application Pod の back-off restarting アラートを確認します。

    3e0492283c067026c9cfd348a898ecb1

ヒープダンプファイルの参照

ヒープダンプを参照してダウンロードするために、同じ CNFS PVC を rootDir にマウントした File Browser をデプロイします。

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
        # filebrowser/filebrowser:v2.18.0 を同期した後、ご利用の ACR イメージアドレスに置き換えてください
        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  # java-application Deployment と同じ PVC
EOF

期待される出力:

configmap/filebrowser unchanged
deployment.apps/filebrowser configured

サービスの作成

  1. ACK コンソールにログインします。左側のナビゲーションウィンドウで、[クラスター] をクリックします。

  2. 対象のクラスターを見つけて、その名前をクリックします。左側のナビゲーションウィンドウで、[ネットワーク] > [サービス] を選択します。

  3. サービスページで、default 名前空間を選択し、[作成] をクリックします。以下のパラメーターを設定します:

    詳細については、「NLB の課金概要」をご参照ください。
    パラメーター
    名前 filebrowser
    サービスタイプ SLB > SLB タイプ: CLB[リソースの作成] を選択し、[アクセスメソッド][パブリックアクセス] に設定します。
    バックエンド [+ワークロードラベルの参照] をクリックします。[リソースタイプ]Deployments に、[リソース]filebrowser に設定します。
    ポートマッピング サービスポート8080コンテナポート80プロトコルTCP
  4. 構成を送信します。

File Browser へのアクセス

  1. サービスページからエンドポイントアドレスをコピーします。

  2. ブラウザで <endpoint-address>:8080 を開きます。File Browser のログインページが表示されます。

  3. デフォルトの認証情報でログインします:ユーザー名 admin、パスワード admin

    20fe4dcde1759ebc64cbe0b1bb3168da

  4. [rootdir] をダブルクリックして、NAS のマウントポイントに入ります。

    image

結果

rootdir 内では、各 Pod のダンプディレクトリは subPathExpr: $(POD_NAMESPACE).$(POD_NAME) のルールに従って命名されます。例: default.java-application-76d8cd95b7-prrl2

image

ディレクトリを開くと java_pid1.hprof が見つかります。ダウンロードして Eclipse Memory Analyzer (MAT) で分析し、OOM の原因となったコードを特定します。

lQLPJxMFSGyoLcnNAqTNB2awoAbbe3-kh8AIV2X4pMttAA_1894_676

仕組み

3 つのメカニズムが連携して、Pod の再起動後もヒープダンプを永続化します:

  • `ReadWriteMany` を持つ CNFS PVC: NAS をバックエンドとする PVC は、java-application Pod と File Browser Pod の両方にマウントされます。NAS は Pod のライフサイクルとは独立してファイルを永続化するため、ダンプファイルは Pod のクラッシュ後も残ります。

  • Downward API を使用した `subPathExpr`: 各 Pod は NAS のルートではなく、自身のサブディレクトリ (<namespace>.<pod-name>) にマウントされます。これにより、再起動時にダンプが上書きされるのを防ぎ、ダンプから Pod を簡単にトレースできるようになります。

  • `-XX:+HeapDumpOnOutOfMemoryError`: JVM は OOM で終了する前に、ヒープの状態を -XX:HeapDumpPath に書き込みます。そのパスは NAS をバックエンドとしているため、ファイルは Pod の終了後も残ります。