當您的業務是使用Java開發,且設置的JVM堆空間過小時,程序會發生OOM(Out Of Memory)的問題。此時您可以使用CNFS(Container Network File System)作為記錄日志的載體,掛載到容器內相應目錄中,當JVM發生OOM時,CNFS可以將日志記錄到相應的目錄里。本文介紹如何使用CNFS自動收集異常退出的JVM轉儲文件。
前提條件
已創建Kubernetes集群,且存儲插件選擇為CSI。具體操作,請參見創建ACK托管集群。
已創建容器鏡像服務企業版實例。具體操作,請參見創建企業版實例。
已使用CNFS托管NAS文件系統。具體操作,請參見通過CNFS方式使用NAS文件系統。
背景信息
阿里云容器服務使用容器網絡文件系統CNFS,將阿里云的文件存儲抽象為一個K8s對象(CRD)進行獨立管理,包括創建、刪除、描述、掛載,監控及擴容等運維操作。更多信息,請參見容器網絡文件系統CNFS概述。
阿里云容器鏡像服務ACR(Alibaba Cloud Container Registry)是面向容器鏡像、Helm Chart等符合OCI標準的云原生制品安全托管及高效分發平臺。更多信息,請參見什么是容器鏡像服務ACR。
注意事項
Java設置的最大Heap值(Xmx)應小于Pod Memory的Limit值,防止JVM未發生OOM,但Pod發生OOM的情況。
在使用Java轉儲時,建議創建個新的CNFS,將業務使用的CNFS與Java轉儲的CNFS分開,防止.hprof文件過大,轉儲時占用大量業務資源,影響業務。
操作步驟
您可以使用registry.cn-hangzhou.aliyuncs.com/acs1/java-oom-test:v1.0鏡像作為模擬OOM的Java程序,用于觸發JVM的OOM。
關于如何構建鏡像,請參見使用企業版實例構建鏡像。
使用以下示例,創建一個名稱為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。 EOF
通過容器服務管理控制臺的事件中心,查看到該Pod發生了Back-off restarting的告警事件,說明java-application應用發生了OOM。
登錄容器服務管理控制臺。
在控制臺左側導航欄,單擊集群。
在集群列表頁面,單擊目標集群名稱或者目標集群右側操作列下的詳情。
在集群管理頁左側導航欄中,選擇 。
由于NAS目前沒有瀏覽、上傳、下載文件的功能,您可以使用File Browser作為Web端的訪問工具。首先將NAS的掛載點掛載到File Browser的rootDir上,然后通過
kubectl port-forward
命令,將File Browser的容器端口映射到本地,再通過瀏覽器訪問存放在NAS上的文件。使用以下模板,創建File Browser的Deployment和File Browser需要使用的ConfigMap,默認開啟80端口。
cat << EOF | kubectl apply -f - apiVersion: v1 data: .filebrowser.json: | { "port": 80 } 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: 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
將File Browser的80端口轉發到本地。
kubectl port-forward deployment/filebrowser 8080:80
預期輸出:
Forwarding from 127.0.0.1:8080 -> 80 Forwarding from [::1]:8080 -> 80
打開瀏覽器,在地址欄輸入127.0.0.1:8080,可以看到File Browser的登錄界面,輸入默認賬號(admin)和密碼(admin),進入到容器內部。
由于File Browser將名稱為cnfs-nas-pvc的PVC掛載到rootDir下,雙擊rootDir進入到NAS掛載點。
執行結果
在File Browser中可以看到名稱為default.java-application-76d8cd95b7-prrl2的目錄,這個目錄是java-application的subPathExpr: $(POD_NAMESPACE).$(POD_NAME)
作為規則生成的目錄。
然后進入此目錄,可以看到目錄中的轉儲文件java_pid1.hprof。如果您需要定位到程序發生OOM的代碼行數,可以將java_pid1.hprof下載到本地,通過MAT(Eclipse Memory Analyzer Tools)進一步分析JVM堆棧信息。