1 背景

当在 K8S 中运行使用 C/C++ 程序的容器时,我们除了需要关注程序产出日志外,还需注意随时可能产生的 core 文件。

对于一般实体环境部署 C/C++ 程序,预期中的异常处理流程为:程序宕掉后,生成一个 core 文件,通过进程监控发现异常报警,我们通过查看日志,分析 core 文件定位问题,解决问题后重启服务。

但对于 K8S 容器环境,事情就变得复杂起来,不得不面对以下问题:

  1. 容器内的 C/C++ 程序产生的 core 文件在容器重启后会消失,该文件需要持久化。
  2. 程序挂掉后,容器会因为存活探针等因素重启,不断地产生 core 文件,直至磁盘空间告警。
  3. 应用支持多副本,不同的副本可能有不同的负责领域,因此发生问题的位置不一定相同。

2 方案

针对上述问题 ,目前采用的方法是通过 k8s 的 local-path 方法,将 core 文件持久化到宿主机中,并对 core 文件生成规则、程序启动规则进行了规范。当然,持久化部分使用 NFS 可以更好的达成目的,但会造成额外的网络开销。

规范要求所有宿主机允许生成 core 文件,并将 core 文件的名称规范为 core-${hostname}(命名方法见 core-设置core文件名和路径并手动触发coredump),路径方面则要求统一在 /corefile 目录下生成。

规范要求应用容器必须是 Statefulset,将容器内的 /corefile 映射到统一的 core 文件目录,同时在每个 C/C++ 程序的启动脚本中包含以下逻辑:

graph TD
A(开始)-->B{是否存在\ncore-hostname\n文件}
B--是-->C[获取core文件\n编辑日期]-->D[重命名文件为\ncore-hostname-日期]-->E(结束)
B--否-->E

注意

因为 statefulset 的 pod 名称是从 0 开始往后依次编号,重复启动不改变,且 pod 的 hostname 与 podname 相同,因此可以使用此类方法。 但 deployment 的 podname 是尾部带随机字母,每次启动会重新随机生成,因此不适用。

如此规范可以解决上述的问题:

  • 每个自然日、每个应用的副本最多只有 1 个 core 文件
  • core 文件能持久化