Author:rab
一、问题分析
上一篇刚讲到《Docker 配置基础优化》,这里再补充一下。就在中秋+国庆
这段小长假里,接收到了线上服务器磁盘告警通知,线上服务器架构是一个 Docker Swarm 集群,该集群上运行了多个服务。于是就登录服务上去看个究竟,结果发现 Docker 业务日志数据量都是正常的,因此第一个想到的就是 Docker 的存储驱动目录 /<yourpath>/overlay2
占用大小,进去看结果发现有一个文件(目录)数据大小异常(这里忘记截图了 - 大概 140 多 G),然后就根据这个目录名称找到归属的具体容器,看看是哪个容器产生的数据。以下是查看命令:
docker ps -q | xargs docker inspect --format '{{.State.Pid}}, {{.Name}}, {{.GraphDriver.Data.WorkDir}}' | grep "fe9eecfd2fc5f5c2289bd19194900c0c707d67e05e54ea55721c4d3c3ba8cc03"
确定目标容器后,就进入容器去看一下,结果在运行程序(xxx.jar)主目录(即同级目录)下发现有大量的 core 文件,且每个文件的大小均为 105M,粗略统计了一下大概占用了 143G 左右的大小。
那这些 Core 文件是什么文件?又是怎么产生的呢?
首先我们要知道 core file 是什么文件?在Linux系统中,“core file”(核心文件)是指在程序异常崩溃(如段错误、非法指令等)时生成的文件,它包含了程序在崩溃瞬间的内存状态信息,帮助开发人员进行调试和分析问题,我们一般使用调试器工具(如GDB)来分析核心文件,以便定位和解决问题。
核心文件的名称通常是 “core”,并且会与崩溃的进程相关联,因此它可能具有类似于 “core.<进程ID>” 的名称,其中 “<进程ID>” 是崩溃的进程的实际ID。核心文件通常会生成在程序崩溃的当前工作目录中,但也可以通过调整系统的核心转储设置来指定其他位置。
核心文件包含了程序的内存映像,包括堆栈、寄存器的状态以及其他与程序状态相关的信息。这些文件通常很大,因此在默认情况下,许多 Linux 系统都会禁用核心文件的生成,以节省磁盘空间。要启用核心文件生成,可以使用 ulimit
命令或 /proc/sys/kernel/core_pattern
文件进行配置。
默认情况下:Host 宿主机是限制生成 core 文件的(即禁用的),但是容器中却是无限制的(因其独立的 namespace),因此当容器中程序异常时就会生成 core 文件,而且是无限制的,这样一来就会耗尽我们 Host 宿主机的磁盘空间。
接着查看该容器的资源利用情况:
可见容器的 CPU 波动非常大(非常不稳定),因为持续时间很短,所以并没有达到监控告警的条件,但是我没可以通过 core 文件来分析导致 CPU 浮动的原因。
二、解决方案
如果需要分析这些 Core 文件,可先下载到本地其他服务器进行分析,从运维角度来说,可进入容器直接删除这些 Core 文件即可。但为了避免后续的问题,应将这些 core 文件交给开发人员进行程序异常分析,并做后续优化。
1、进入容器内部
docker exec -it <容器名> bash
2、删除 core 文件
rm -rf core.*
切记!!!不要在/<yourpath>/overlay2
目录下进行任何增删操作,否则可能会导致容器内部程序异常。
其实这只是临时解决的,如果要解决根源问题,需要开发人员优化代码(解决 CPU 波动问题)或把容器中“core dump(核心转存)”
关闭,关闭步骤如下:只需在 Docker 服务的启动命令添加--default-ulimit core=0:0
选项即可。
vim /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --default-ulimit core=0:0
systemctl daemon-reload
systemctl restart docker.service
运行一个测试容器再次验证,此时的容器已经限制了 core file 了。
docker run -it --rm centos:centos7.9.2009
如果此时你想要启用 core dump,去掉 --default-ulimit core=0:0
选项即可。
扩展
1、overlay2 目录下的那些长目录说明
overlay2 目录下的那些长目录实际上对应 Docker 中运行的容器或镜像的文件系统层。每个子目录都包含容器或镜像的文件系统内容。这些子目录的名称是由一种称为 SHA256
散列的哈希函数生成的,用于唯一标识每个文件系统层。
每个子目录中包含容器或镜像的文件系统内容,以及元数据和其他相关信息。这些文件系统层会根据需要叠加在一起,以创建容器的整体文件系统视图。
2、如何配置 Linux 系统的 core file
-
启用
# 法1:ulimit命令 - 临时生效(重启失效) ulimit -c unlimited # 无限制大小 ulimit -c 100000 # 限制大小为100MB # 法2:/etc/security/limits.conf文件 - 永久生效 cat /etc/security/limits.conf * hard core unlimited * soft core unlimited
如何自定义 core 文件名及存储目录?
# 法1:/proc文件 # 自定义core文件名及存储位置 echo "/tmp/core-%e.%p" > /proc/sys/kernel/core_pattern # 或 sysctl -w kernel.core_pattern="/tmp/core-%e.%p" # 这两条任意命令会将核心文件保存在/tmp目录中,文件名格式为core-<进程名称>.<进程ID> # 法2:/etc/sysctl.conf文件 cat /etc/sysctl.conf kernel.core_pattern = /tmp/core-%e.%p kernel.core_uses_pid = 1
-
禁用
# 法1:ulimit命令 - 临时禁用 ulimit -c 0 # 法2:/etc/security/limits.conf文件 - 永久禁用 cat /etc/security/limits.conf * hard core 0 * soft core 0
—END