全部產品
Search
文件中心

Container Service for Kubernetes:通過CNFS自動收集異常退出的JVM轉儲檔案

更新時間:Jul 24, 2025

當您的業務是使用Java開發,且設定的JVM堆空間過小時,程式會發生OOM(Out Of Memory)的問題。此時您可以使用CNFS(Container Network File System)作為記錄日誌的載體,掛載到容器內相應目錄中,當JVM發生OOM時,CNFS可以將日誌記錄到相應的目錄裡。本文介紹如何使用CNFS自動收集異常退出的JVM轉儲檔案。

前提條件

注意事項

  • Java設定的最大Heap值(Xmx)應小於Pod Memory的Limit值,防止JVM未發生OOM,但Pod發生OOM的情況。

  • 在使用Java轉儲時,建議建立個新的CNFS,將業務使用的CNFS與Java轉儲的CNFS分開,防止.hprof檔案過大,轉儲時佔用大量業務資源,影響業務。

  • 樣本中的鏡像 docker.io/filebrowser/filebrowser:v2.18.0 可能因網路訪問限制會拉取失敗,您需要通過訂閱海外源鏡像同步至您的 ACR 企業版執行個體。具體配置如下:

    • 製品來源:Docker Hub

    • 源端倉庫座標:filebrowser/filebrowser

    • 訂閱策略:v2.18.0

      完成鏡像訂閱後,您需配置 ACR 企業版執行個體 與 ACK叢集 的免密拉取策略,詳情請參見同帳號拉取鏡像

操作步驟

  1. 使用registry.cn-hangzhou.aliyuncs.com/acs1/java-oom-test:v1.0樣本鏡像作為類比OOM的Java程式,用於觸發JVM的OOM。

  2. 使用以下樣本,建立一個名稱為java-application的Deployment。

    本樣本在啟動Java程式Mycode時,設定申請的堆大小為80 MB,堆轉儲的目錄為/mnt/oom/logs。當JVM的堆大小不滿足時,捕獲HeapDumpOnOutOfMemoryError錯誤。

    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:                               #定義兩個索引值:POD_NAME為metadata.name,POD_NAMESPACE為metadata.namespace。
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  apiVersion: v1
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  apiVersion: v1
                  fieldPath: metadata.namespace
            args:
            - java                            #執行命令。
            - -Xms80m                         #堆記憶體的最小Heap值。
            - -Xmx80m                         #堆記憶體的最大Heap值。
            - -XX:HeapDumpPath=/mnt/oom/logs  #發生OOM時,堆記憶體轉儲的路徑。
            - -XX:+HeapDumpOnOutOfMemoryError #捕獲堆發生OOM的錯誤。
            - Mycode                          #執行程式。
            volumeMounts:
            - name: java-oom-pv
              mountPath: "/mnt/oom/logs"      #容器內部使用/mnt/oom/logs做為掛載目錄。
              subPathExpr: $(POD_NAMESPACE).$(POD_NAME)   #使用$(POD_NAMESPACE).$(POD_NAME)作為建立出子目錄,將OOM轉儲檔案產生到子目錄中。
          volumes:
          - name: java-oom-pv
            persistentVolumeClaim:
              claimName: cnfs-nas-pvc         #使用CNFS的PVC,名稱為cnfs-nas-pvc。
    ---
    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: cnfs-nas-pvc
    spec:
      accessModes:
        - ReadWriteMany
      storageClassName: alibabacloud-cnfs-nas
      resources:
        requests:
          storage: 70Gi # 如果開啟目錄限額功能,則storage欄位會生效,動態建立目錄寫入資料量最大為70 GiB。
    ---          
    EOF
  3. 通過Container Service管理主控台的事件中心,查看到該Pod發生了Back-off restarting的警示事件,說明java-application應用發生了OOM。

    1. 登入Container Service管理主控台,在左側導覽列選擇叢集列表

    2. 叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇營運管理 > 事件中心

    3. 查看對應事件。

      3e0492283c067026c9cfd348a898ecb1

  4. 由於NAS目前沒有瀏覽、上傳、下載檔案的功能,您可以使用File Browser作為Web端的訪問工具。首先將NAS的掛載點掛載到File Browser的rootDir上,然後通過建立Service,將File Browser的容器連接埠映射,再通過瀏覽器訪問存放在NAS上的檔案。

    1. 使用以下模板,建立File Browser的Deployment和File Browser需要使用的ConfigMap,預設開啟80連接埠。

      cat << EOF | kubectl apply -f -
      apiVersion: v1
      data:
        .filebrowser.json: |
          {
            "port": 80,
            "address": "0.0.0.0"
          }
      kind: ConfigMap
      metadata:
        labels:
          app.kubernetes.io/instance: filebrowser
          app.kubernetes.io/name: filebrowser
        name: filebrowser
        namespace: default
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        labels:
          app.kubernetes.io/instance: filebrowser
          app.kubernetes.io/name: filebrowser
        name: filebrowser
        namespace: default
      spec:
        progressDeadlineSeconds: 600
        replicas: 1
        revisionHistoryLimit: 10
        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:
            - image:  XXXX-registry-vpc.cn-hangzhou.cr.aliyuncs.com/test/test:v2.18.0  #樣本鏡像docker.io/filebrowser/filebrowser:v2.18.0可能因網路訪問限制會拉取失敗,請參見注意事項。
              imagePullPolicy: IfNotPresent
              name: filebrowser
              ports:
              - containerPort: 80
                name: http
                protocol: TCP
              resources: {}
              securityContext: {}
              terminationMessagePath: /dev/termination-log
              terminationMessagePolicy: File
              volumeMounts:
              - mountPath: /.filebrowser.json
                name: config
                subPath: .filebrowser.json
              - mountPath: /db
                name: rootdir
              - mountPath: /rootdir
                name: rootdir
            dnsPolicy: ClusterFirst
            restartPolicy: Always
            schedulerName: default-scheduler
            securityContext: {}
            terminationGracePeriodSeconds: 30
            volumes:
            - configMap:
                defaultMode: 420
                name: filebrowser
              name: config
            - name: rootdir
              persistentVolumeClaim:
                claimName: cnfs-nas-pvc
      EOF

      預期輸出:

      configmap/filebrowser unchanged
      deployment.apps/filebrowser configured
    2. 登入Container Service管理主控台,在左側導覽列選擇叢集列表

    3. 叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇網路 > 服務

    4. 服務頁面選擇default命名空間,單擊建立,然後根據以下參數配置。

      參數

      樣本說明

      服務名稱

      filebrowser

      服務類型

      負載平衡(LoadBalancer)

      • 負載平衡類型傳統型負載平衡 CLB

      • 選擇建立資源,單擊建立CLB資源下拉列,將訪問方式配置為公網訪問計費方式配置為隨用隨付

      關於CLB的計費說明,請參見CLB計費概述

      服務關聯

      選擇+引用工作負載標籤

      • 資源類型:Deployments

      • 資源清單:filebrowser

      連接埠映射

      • 服務連接埠:8080

      • 容器連接埠:80

      • 協議:TCP

    5. 在對話方塊中,選擇負載平衡(LoadBalancer)作為服務類型。選擇建立資源,將訪問方式配置為公網訪問計費方式配置為隨用隨付(PayByCLCU),按照頁面提示提交配置的修改。

      關於CLB的計費說明,請參見CLB計費概述
    6. 開啟瀏覽器,在地址欄輸入端點地址:8080,可以看到File Browser的登入介面,輸入預設帳號(admin)和密碼(admin),進入到容器內部。

      20fe4dcde1759ebc64cbe0b1bb3168da

    7. 由於File Browser將名稱為cnfs-nas-pvc的PVC掛載到rootDir下,雙擊rootDir進入到NAS掛載點。

      image

執行結果

在File Browser中可以看到名稱為default.java-application-76d8cd95b7-prrl2的目錄,此目錄是java-applicationsubPathExpr: $(POD_NAMESPACE).$(POD_NAME)作為規則產生的目錄。

image

然後進入此目錄,可以看到目錄中的轉儲檔案java_pid1.hprof。如果您需要定位到程式發生OOM的程式碼數,可以將java_pid1.hprof下載到本地,通過MAT(Eclipse Memory Analyzer Tools)進一步分析JVM堆棧資訊。

lQLPJxMFSGyoLcnNAqTNB2awoAbbe3-kh8AIV2X4pMttAA_1894_676