K8S 中实现程序 OOM 后 dump 上传到阿里云 OSS (一)

背景

在日常工作中发现,JAVA 程序部署在 K8S 上后,若发生 OOM,程序生成的 dump 文件在 Pod 重启后会丢失,无法给开发人员分析起原因,造成了很多不便。

方案考虑

经过上网查询资料,思考,大概列出了下面这几种方式:

  1. 使用 hostPath,把 dump 挂在宿主机上。 --- 主要排除因素:K8S 节点有多个,不好管理
  2. 使用阿里云 NAS 挂载 pod 的 dump 目录。 --- 主要排除因素:每个 pod 都要挂一个目录,不好管理,引入了额外的开销
  3. 构建 JAVA 程序镜像时,配置 java 命令参数 -XX:OnOutOfMemoryError=/dumpError.sh,OOM 发生时调用 dumpError.sh 脚本,上传。 --- 改动少,只需要修改基础镜像即可,但实际测试时,发现 dump 没上传完成,POD 就重启了, 只能放弃
  4. 在 K8S 中使用 Sidecar,让 POD 中包含2个容器,并且共享 dump 所在目录,OOM时让 sidecar 容器进行 dump 上传,主容器重启也不影响。 --- 本次选择这个方案

编写 dump 上传到阿里云 OSS 的程序

该程序采用go语言编写,原因是 go 语句可以直接编译成可在Linux系统直接运行的程序,不依赖其他额外的软件环境。
可以参考阿里云的文档:https://help.aliyun.com/zh/oss/user-guide/multipart-upload?spm=5176.8466032.console-base_help.dexternal.500614501X6Zj7#12bca60a3dshn
注意!要记得创建 OSS 的 bucket 和配置对应的 RAM 的权限~
程序我是采用 Trae ,让它来帮我写,测试通过后,让他帮编译成Linux系统可运行的程序。
image

制作 Sidecar 镜像

我这里上一步生成的可执行程序是:traeAliOSS

mkdir -p /data/images/alpine-ossutil
cd /data/images/alpine-ossutil

# 上传 traeAliOSS 到该目录下

# 下面是检测和调用 traeAliOSS 程序上传 dump 的脚本,简单说明一下功能
#  判断 /tmp/ 目录下是否有 dump 且没有带时间的?
#  有:则重命名,在后面加上时间,并上传;
#  无:则继续循环。
cat dumpError.sh 
#!/bin/sh

# 每分钟执行一次检查
while true; do
    # 查找 /tmp 目录下所有 .dump 文件
    for file in /tmp/*.dump; do
        # 跳过不存在的文件(当没有.dump文件时,循环会进入一次)
        [ -e "$file" ] || continue
        
        # 提取文件名(不含路径)
        filename=$(basename "$file")
        
        # 检查文件名是否已包含时间戳格式(-YYYYMMDD_HHMM)
        if echo "$filename" | grep -qE '.*-[0-9]{8}_[0-9]{4}\.dump$'; then
            # 文件名已包含时间戳,跳过处理
            continue
        else
            # 文件名不包含时间戳,需要处理
            # 获取文件基本名(不含扩展名)
            base_name=$(echo "$filename" | sed 's/\.dump$//')
            
            # 生成时间戳(格式:年月日_时分)
            timestamp=$(date +%Y%m%d_%H%M)
            
            # 新文件名
            new_name="/tmp/${base_name}-${timestamp}.dump"
            
            # 重命名文件
            mv "$file" "$new_name"
            
            # 上传文件, 需要通过环境变了获取 ALI_OSS_BUCKET,即是 阿里云 Bucket 的值
            traeAliOSS -bucket "$ALI_OSS_BUCKET" -file "$new_name" -object "$(basename "$new_name")" > /tmp/traeAliOSS.log 2>&1
        fi
    done
    
    # 等待60秒
    sleep 60
done

chmod +x dumpError.sh
chmod +x traeAliOSS

# 编写 Dockerfile ,因为要用到 https 证书信任链,所以要安装 ca-certificates 软件
cat Dockerfile 
FROM alpine:3.23.2
RUN apk add --no-cache ca-certificates
ADD traeAliOSS /usr/bin/traeAliOSS
ADD dumpError.sh /dumpError.sh
CMD /dumpError.sh

现在目录的情况:
image

# 制作镜像并上传
# 根据自身情况进行调整:
docker build -t harbor.klvchen.com/library/alpine-ossutil:0.1

docker push harbor.klvchen.com/library/alpine-ossutil:0.1
posted @ 2026-01-08 11:43  klvchen  阅读(9)  评论(0)    收藏  举报