當您的業務是使用Java開發,且設定的JVM堆空間過小時,程式會發生OOM(Out Of Memory)的問題。此時您可以使用CNFS(Container Network File System)作為記錄日誌的載體,掛載到容器內相應目錄中,當JVM發生OOM時,CNFS可以將日誌記錄到相應的目錄裡。本文介紹如何使用CNFS自動收集異常退出的JVM轉儲檔案。
前提條件
-
已使用CNFS託管NAS檔案系統。具體操作,請參見通過CNFS管理NAS檔案系統。
容器網路檔案系統CNFS將阿里雲的檔案儲存體抽象為一個K8s對象(CRD)進行獨立管理,包括建立、刪除、描述、掛載,監控及擴容等營運操作。
-
已建立Container Registry企業版執行個體。具體操作,請參見建立企業版執行個體。
注意事項
-
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叢集 的免密拉取策略,詳情請參見同帳號拉取鏡像。
-
操作步驟
-
使用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。 --- kind: PersistentVolumeClaim apiVersion: v1 metadata: name: cnfs-nas-pvc spec: accessModes: - ReadWriteMany storageClassName: alibabacloud-cnfs-nas resources: requests: storage: 70Gi # 如果開啟目錄限額功能,則storage欄位會生效,動態建立目錄寫入資料量最大為70 GiB。 --- EOF -
通過Container Service管理主控台的事件中心,查看到該Pod發生了Back-off restarting的警示事件,說明java-application應用發生了OOM。
-
登入Container Service管理主控台,在左側導覽列選擇叢集列表。
-
在叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇。
-
查看對應事件。
在事件中心的事件列表(叢集資源事件)頁簽中,將命名空間設為 default,名稱篩選為
java-application-7b78d4d96f-2bszs。事件列表中可看到 Warning 層級的 BackOff 事件(描述為 Back-off restarting failed container java-application),已累計出現 4945 次,表明該 Pod 因 OOM 反覆崩潰重啟;同時存在 Normal 層級的 Pulling 和 Pulled 鏡像拉取事件。針對 Warning 事件,可單擊右側智能診斷連結進一步排查。
-
-
由於NAS目前沒有瀏覽、上傳、下載檔案的功能,您可以使用File Browser作為Web端的訪問工具。首先將NAS的掛載點掛載到File Browser的rootDir上,然後通過建立Service,將File Browser的容器連接埠映射,再通過瀏覽器訪問存放在NAS上的檔案。
-
使用以下模板,建立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 -
登入Container Service管理主控台,在左側導覽列選擇叢集列表。
-
在叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇。
-
在服務頁面選擇default命名空間,單擊建立,然後根據以下參數配置。
參數
樣本說明
服務名稱
filebrowser
服務類型
Server Load Balancer(LoadBalancer)
-
負載平衡類型:傳統型負載均衡 CLB
-
選擇建立資源,單擊建立 CLB 資源下拉列,將訪問方式配置為公網訪問,計費方式配置為隨用隨付。
關於CLB的計費說明,請參見CLB計費概述。
服務關聯
選擇+引用工作負載標籤。
-
資源類型:Deployments
-
資源清單:filebrowser
連接埠映射
-
服務連接埠:8080
-
容器連接埠:80
-
協議:TCP
-
-
在對話方塊中,選擇Server Load Balancer(LoadBalancer)作為服務類型。選擇建立資源,將訪問方式配置為公網訪問,計費方式配置為隨用隨付(PayByCLCU),按照頁面提示提交配置的修改。
關於CLB的計費說明,請參見CLB計費概述。
-
開啟瀏覽器,在地址欄輸入端點地址: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堆棧資訊。