Go 进程在容器中无 coredump 产生问题分析

0x01 起因

coredump 作为一种非常重要的高度手段,在日常开发中经常用到,切换到容器环境后一直没关注。最近测试了下,发现出不了 core。觉得有些奇怪,抽点时间研究了下。

0x02 实验

一开始认为是 Go 运行时的问题,做了一以下对比。以下实现已保证了 GOTRACEBACK=crash 和 ulimit 和 /proc/sys/kernel/core_pattern 配置是正常的。

1. 以 Go 进程为 init 进程启动容器。
2. 在 上述容器中,额外运行一个 Go 进程。

得到的结果是,第1个不会出 core。第2个可以出 core 。对比了两者的差异,唯一不一样就是在容器里的 pid ,前者是1,后者不是1。

通过 bpftrace 工具外加 Go 运行时抛异常时打日志等调试方法,确认了信号是发给了内核,内核的 kernel/signal.c:get_signal 函数中没有走到 coredump 的分支。又补充了以下实验。用 C 语言写了一个 demo,构造空地址写异常。放在容器中作为 init 进程启动,发现可以正常出 core。

得到的结论就是:Go 作为容器中的1号进程时,无法正常 coredump 出来。

本来是想用 bpftrace 中的 kprobe + 指令偏移,一步步找出信号是在 get_signal 函数中的哪一步被忽略的,经过几次实验后发现这样效率太低了,还要去了解内核的信号处理流程。内核这种级别的项目,如果有什么特殊处理,一定会在代码中详细说明的。果然就在 get_signal 函数中找到了。

0x03 需要特殊对待的 init 进程

注释见如下:

/*
* Global init gets no signals it doesn't want.
* Container-init gets no signals it doesn't want from same
* container.
*
* Note that if global/container-init sees a sig_kernel_only()
* signal here, the signal must have been generated internally
* or must have come
* case, the signal cannot be dropped.
*/

大意是容器里的 init 进程地位跟宿主机的 init 进程地位一样重要,所以不能被自己(自杀)和自己的子孙进程杀死( 计算机世界里的父慈子孝 ),如果收到了这类信号,就会忽略掉。你可以试下能不能把宿主的 init 进程,用 kill -6 1命令杀掉(当然是杀不掉的)。由于 Go 使用的 SIGABRT 信号属于这类信号,所以被忽略了。有了类似的注释,不难搜到当时的 patch 邮件Container-init signal semantics [LWN.net]

还有问题:为什么 C 语言就可以正常出 core 呢?它不也是自杀吗?

是不一样。细节没有研究的很清楚,大概区别如下:

Go 是自己捕获了 SIGSEGV 信号,因为它要做一层地址转换,以方便调试。之后,自己向内核报告我挂了,请杀掉我。这是明确的 suicide。

C 一般没有注册 SIGSEGV 信号的处理函数,访问非法地址后,直接被内核杀掉,不是 suicide。

内核是假定某些应用可以处理掉 SIGSEGV 的异常,所以应用可以自己捕获这个信号。但 SIGABRT 是明确主动要求终止进程的信号。

0x04 解决方法

我们不大可能改内核的行为,所以只能调整自己。只要让这个进程不是 init 进程就行了。在 k8s 下的方法就是,在 Pod Spec 中,添加 shareProcessNamespace: true,与 infra 容器共享 pid 命名空间即可,让 pause 充当 init 进程。这样就能正常 dump 出 core 了。

同事提供了另外一种方法,使用 tini 作为容器的 init 进程,tini 非常小巧,只有几十 KiB。也是一种不错的思路。

Go 进程在容器中无 coredump 产生问题分析的更多相关文章

  1. Docker 容器中无ss命令解决方法

    在早期运维工作中,查看服务器连接数一般都会用netstat命令.其实,有一个命令比netstat更高效,那就是ss(Socket Statistics)命令!ss命令可以用来获取socket统计信息, ...

  2. 容器中的JVM资源该如何被安全的限制?

    前言 Java与Docker的结合,虽然更好的解决了application的封装问题.但也存在着不兼容,比如Java并不能自动的发现Docker设置的内存限制,CPU限制. 这将导致JVM不能稳定服务 ...

  3. (spring-第1回【IoC基础篇】)Spring容器中Bean的生命周期

    日出日落,春去秋来,花随流水,北雁南飞,世间万物皆有生死轮回.从调用XML中的Bean配置信息,到应用到具体实例中,再到销毁,Bean也有属于它的生命周期. 人类大脑对图像的认知能力永远高于文字,因此 ...

  4. 在 docker 容器中捕获信号

    我们可能都使用过 docker stop 命令来停止正在运行的容器,有时可能会使用 docker kill 命令强行关闭容器或者把某个信号传递给容器中的进程.这些操作的本质都是通过从主机向容器发送信号 ...

  5. 在 Docker 容器中运行应用程序

    案例说明 运行 3 个容器,实现对网站的监控. 三个容器的说明: 容器 web: 创建自 nginx 映像,使用 80 端口,运行于后台,实现 web 服务. 容器 mailer: 该容器中运行一个 ...

  6. Docker 案例: 在容器中部署静态网站

    ----------------知识点------------ 容器的端口映射: docker  run  [-P] [-p] -P,–publish-all=true | false,大写的P表示为 ...

  7. 隔离 docker 容器中的用户

    笔者在前文<理解 docker 容器中的 uid 和 gid>介绍了 docker 容器中的用户与宿主机上用户的关系,得出的结论是:docker 默认没有隔离宿主机用户和容器中的用户.如果 ...

  8. 理解 docker 容器中的 uid 和 gid

    默认情况下,容器中的进程以 root 用户权限运行,并且这个 root 用户和宿主机中的 root 是同一个用户.听起来是不是很可怕,因为这就意味着一旦容器中的进程有了适当的机会,它就可以控制宿主机上 ...

  9. 容器中的诊断与分析4——live diagnosis——LTTng

    官网地址 LTTng 简介&使用实战 使用LTTng链接内核和用户空间应用程序追踪 简介: LTTng: (Linux Trace Toolkit Next Generation),它是用于跟 ...

  10. C#WinForm窗体内Panel容器中嵌入子窗体、程序主窗体设计例子

    C#WinForm父级窗体内Panel容器中嵌入子窗体.程序主窗体设计例子 在项目开发中经常遇到父级窗体嵌入子窗体所以写了一个例子程序,顺便大概划分了下界面模块和配色,不足之处还望指点 主窗体窗体采用 ...

随机推荐

  1. 【动手学深度学习】第三章笔记:线性回归、SoftMax 回归、交叉熵损失

    这章感觉没什么需要特别记住的东西,感觉忘了回来翻一翻代码就好. 3.1 线性回归 3.1.1 线性回归的基本元素 1. 线性模型 \(\boldsymbol{x}^{(i)}\) 是一个列向量,表示第 ...

  2. Linux 内核:I2C子系统分析(0)整体框架介绍

    --- title: Linux I2C子系统分析:1-整体框架介绍 EntryName: linux-subsystem-i2c-0-about date: 2020-10-13 04:19:26 ...

  3. Java socket 获取gps定位

    1.Java socket 获取gps定位的方法 在Java中使用Socket来直接获取GPS定位信息并不直接可行,因为GPS数据通常不是通过Socket通信来获取的.GPS数据通常由设备(如智能手机 ...

  4. linux 查看crontab任务执行情况

    首先创建一个定时任务,例如: */1 * * * * /usr/bin/curl http://******/admin/Keeperclock/keeper >> /data/wwwro ...

  5. oeasy教您玩转vim - 23 - 配置文件

    配置文件 回忆上节课内容 我们上次找到配置文件的位置 ~/.vimrc 了解各种配置开关 修改配置文件并应用 这次想了解和配色方案相关的内容 colorscheme vi ~/.vimrc.old 中 ...

  6. oeasy教您玩转python - 010 - # 不换行输出

    不换行输出 回忆上次内容 \n 就是换行 他对应着 ascii 字符的代码是(10)10进制 他的英文是 LF,意思是Line Feed 这样我就可以自由的控制哪里换行了! 可以做下面这个框架标题吗? ...

  7. SUM-ACM——VJ天梯训练赛

    这次比赛我暴露了很多问题,一些模拟还有贪心思路错误. 补题如下: E - E 题解:一道模拟题,我的问题在于不知道怎么替换下一个,就从0开始遍历数组然后数组的值--,如果为零就continue下一个, ...

  8. vscode 常用设置

    vscode 常用设置   by:授客 QQ:1033553122   版本 vscode Version: 1.33.1   1.   自动保存文件设置 文件编辑一秒钟过后自动保存 2.   黏贴后 ...

  9. Fiddler+proxifier解决抓取不到客户端接口的问题

    工作中偶尔会遇到Fiddler抓不到客户端接口问题,那么就要借助第三方工具proxifier来实现了: 下载地址: 原地址:链接: https://pan.baidu.com/s/1JPJ4cILEs ...

  10. 【JavaWeb】 接口鉴权

    一年前写过一篇,叫Webservice校验机制,叫法不太对,就是接口鉴权 https://www.cnblogs.com/mindzone/p/15078436.html 这东西就是说,你提供给外部的 ...