文档首页/ 云容器引擎 CCE/ 最佳实践/ 存储/ 使用通用文件存储(SFS 3.0)自动收集异常退出的JVM转储文件
更新时间:2024-10-18 GMT+08:00
分享

使用通用文件存储(SFS 3.0)自动收集异常退出的JVM转储文件

当您使用Java开发业务时,如果设置的JVM堆空间过小,程序可能会出现OOM(Out Of Memory)问题。为了解决这个问题,您可以使用通用文件存储(SFS 3.0)作为记录日志的载体,并将其挂载到容器内的相应目录中。当JVM发生OOM时,通用文件存储(SFS 3.0)可以将日志记录到相应的目录中。

前提条件

  • 已创建CCE Standard集群,详情请参见购买Standard/Turbo集群
  • 使用通用文件存储(SFS 3.0)作为CCE 容器业务存储时,需要先配置VPC终端节点,通过VPC终端节点与通用文件存储(SFS 3.0)建立通信。详情请参见配置VPC终端节点

操作步骤

  1. 基于通用文件存储(SFS 3.0)创建一个PVC。

    cat << EOF | kubectl apply -f -
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: jvm-sfs-pvc
      namespace: default
      annotations: {}
    spec:
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 10Gi
      storageClassName: csi-sfs
    EOF

  2. 使用下面的YAML创建一个Deployment,用于模拟Java服务发生OOM,将产生的dump文件转储到绑定通用文件存储(SFS 3.0)的PV中。

    cat << EOF | kubectl apply -f -
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: java-application
      namespace: default
    spec:
      selector:
        matchLabels:
          app: java-application
      template:
        metadata:
          labels:
            app: java-application
        spec:
          containers:
          - name: java-application
            image: swr.cn-east-3.myhuaweicloud.com/container/java-oom-demo:v1  #本文中的镜像仅做示例
            imagePullPolicy: Always
            env: 
            - name: POD_NAME     #取metadata.name作为环境变量POD_NAME的值
              valueFrom:
                fieldRef:
                  apiVersion: v1
                  fieldPath: metadata.name
            - name: POD_NAMESPACE     #取metadata.namespace作为环境变量POD_NAMESPACE的值
              valueFrom:
                fieldRef:
                  apiVersion: v1
                  fieldPath: metadata.namespace
            args:
            - java                            #执行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转储文件生成到子目录中
          imagePullSecrets:
            - name: default-secret
          volumes:
          - name: java-oom-pv
            persistentVolumeClaim:
              claimName: jvm-sfs-pvc         #使用SFS的PVC,名称为jvm-sfs-pvc
    EOF

  3. 等待一会后,容器会发生OOM自动重启。

    # kubectl -n default get pod
    NAME                                READY   STATUS    RESTARTS      AGE
    java-application-84dc6f897f-hc9q7   1/1     Running   1 (31s ago)   97s

  4. 获取Java程序因为OOM产生的文件。

    1. 前往CCE控制台,单击集群名称进入集群,在左侧导航栏中选择“存储”,找到jvm-sfs-pvc的存储卷声明,单击关联的存储卷PV名称。
    2. 自动跳转到PVC对应的存储卷,单击关联的卷名称。
    3. 自动跳转到弹性文件服务控制台,复制挂载命令。

    4. 登录一台集群节点,新建挂载点并运行挂载命令,挂载此通用文件存储卷。
      mkdir /test-jvm
      mount -t nfs -o vers=3,timeo=600,noresvport,nolock,proto=tcp ***.com:/pvc-4ea9137e-4101-4610-a4d2-9f8bb37043a1 /test-jvm
    5. 查看挂载的文件系统里的文件,目录中存在转储文件java_pid1.hprof。如果您需要定位到程序发生OOM的代码行数,可以将java_pid1.hprof下载到本地,通过MAT(Eclipse Memory Analyzer Tools)进一步分析JVM堆栈信息。

相关文档