標籤:

容器中生成coredump file,並對coredump file做限制

關於什麼是core,為何會產生core,如何使用core,不屬於本文要介紹的東西,網上介紹一堆。例如:happyseeker.github.io/k

首先,說下對coredump做限制,限制什麼?為什麼要限制?

core file可以很方便我們做debug,但是如果集中式的coredump,由於要寫文件,可能會造成磁碟IO被打爆;另外,如果是重複式的coredump,由於coredump出來的文件一般都比較大,可能會造成磁碟很快被寫滿,比如通過supervisor或者systemd來管理的程序或者crontab定時執行的程序,可能會不斷出現coredump。所以有必要對core生成的規則,頻率,大小等做一定限制,防止以上問題出現。

問題背景:

我們這裡先描述一下我們遇到的問題:

目前,運維會統一為機器配置core_pattern,使用core_filter程序來控制core的生成。

|/usr/local/bin/core_filter -p %p -e %e -t %t -s 102400n

此配置通過管道的方式,將core file生成的事情交給core_filter程序來處理,core_filter是自己開發的一個小程序,程序默認將core file生成在/home/coresave中。

1. 容器中程序出現coredump了,卻發現容器中沒有core file。偶然間發現宿主機的/home/coresave中生成了我們容器中程序的core file。這讓容器使用者如何是好?

於是,為了驗證core file生成到宿主機中去了,我寫了一個出core的測試程序:

(註:可以直接使用kill -s SIGSEGV $pid的方式來生成core。

一個更簡單的測試方法:

$ bash

$ kill -s SIGSEGV $$

#include <stdio.h>nnvoid main (){ntint *p = NULL;nt*p = 3;n}n

果然,core file在宿主機的/home/coresave中出現了。

2. 很自然我們想到了配置core_pattern來控制core file的生成。

修改/proc/sys/kernel/core_pattern:

echo "/tmp/core.%t.%e.%p" > /proc/sys/kernel/core_pattern

好了,這下終於將core生成在容器中了。但是問題來了,這樣配置只能控制生成路徑(大小可以通過ulimit配置),但對core的頻率限制無法做到。

所以,我們碰到的問題是,如何即讓core file在容器中生成,又可以通過管道的方式交給core_filter來對core生成進行限制?

為什麼會出現上述問題?

這裡我們要先介紹一下coredump如何生成corefile。

coredump是進程收到coredump信號後,將內存中進程的信息dump出來,寫到指定的目錄中。具體寫到哪裡由/proc/sys/kernel/core_pattern來配置。

1. core_pattern中可以指定目錄和文件格式,不指定目錄就生成在運行process的當前目錄;

例如:/tmp/core.%t.%e.%p 或 core.%t.%e.%p

如果指定目錄,那麼生成在該目錄中。此時無論當前目錄還是指定目錄,path解析都在出現core的process的mount namespace中,也就是說,容器中,就會生成在容器的path目錄中;宿主機,會生成在宿主機的path目錄中。

2. core_pattern還有一種配置方式就是:管道方式。

從內核的2.6.19版本後,開始支持管道的方式來生成core file。

例如centos默認的core_pattern是:

|/usr/libexec/abrt-hook-ccpp %s %c %p %u %g %t e %P %In

> 使用管道的時候,內核會將core內容作為管道後程序的stdin,然後通過新起一個內核線程來調用管道後的程序;此時,是以root用戶來運行管道後的程序。

> 使用管道時,dump的path目錄解析是在系統初始化namespace中,也就是宿主機的global ns中,所以默認會將文件生成在宿主機的path目錄中。

> 可以通過%P參數獲取進程在宿主機NS中的pid,也就是global pid。從而找到crash process的/proc/pid目錄。

如何讓core file生成在容器中,並對其進行限制?

根據以上的知識解釋,可以了解到為何使用管道模式時,core file被生成在宿主機的path目錄中,而可能導致容器中無法找到了。

其中提到%P是process 在宿主機的global pid(gpid),那麼通過此gpid,就可以找到該process在容器中的root directory,即/proc/gpid/root。這樣,就可以在宿主機中將core file直接dump到該rootfs中。

由於core_pattern是一個未做隔離的變數,容器中和宿主機共享此值。所以在core_filter中解析出容器或者宿主機的root directory,然後加上用戶指定的目錄path,就可以達到宿主機和容器共用同一個core_pattern, 並且各自生成core file在各自的mount namespace中(即rootfs中)。

core_pattern可以配置如下,core_filter根據%P值來解析出真正要dump的path。

|/usr/local/bin/core_filter -p %p -e %e -t %t -s 102400 -P %Pn

core(5) - Linux manual page

proc(5) - Linux manual page

推薦閱讀:

如何使用OpenDroneMap對航拍圖像快速建模
Docker 重要更新: 原生支持多階段構建(multi-stage build)
Docker 容器與鏡像的儲存
docker的網路基礎

TAG:Docker |