you are better than you think

备忘

last update:

问题描述

线上A模块访问B模块,A模块部署在物理机,B模块部署在容器上。早晚高峰A访问B会出现超时报警。

问题排查

业务方找到我们排查,我首先申请了监控中提示超时的两台机器权限,看一下超时规律 timeout 登录10.167.8.25容器所在的宿主机常规排查

dmesg显示如下,联系值班同学和系统部同学硬件报修。

EDAC sbridge MC1: HANDLING MCE MEMORY ERROR

漂移容器10.167.8.252后,10.167.41.18 在两台物理机上小时级别日志中会出现近10次

阅读前准备

git: https://github.com/moby/moby.git
branch: v18.06.3-ce
ide: goland2020.2 

配置goland的build tag build tag

一起见证docker 代码中套路 exec.Command=> cmd.Start() => cmd.Wait()

进程模型

docker   
  |      
  V       
dockerd -> containerd ---> shim -> runc -> runc init -> process1
                      |--> shim -> runc -> runc init -> process2
                      +--> shim -> runc -> runc init -> process3

背景

线上很多场景可能会用到pstree,比如查看容器的所有子进程,回滚任务需要杀死正在运行中的子进程。

一个轻量级的库

我们选用的是一个轻量级的pstree。github.com/sbinet/pstree这个库比较简单,首先遍历/proc/ 获取所有PID

files, err := filepath.Glob("/proc/[0-9]*")
...
procs := make(map[int]Process, len(files))
	for _, dir := range files {
		proc, err := scan(dir)
		if err != nil {
			return nil, fmt.Errorf("could not scan %s: %w", dir, err)
		}
		if proc.Stat.Pid == 0 {
			// process vanished since Glob.
			continue
		}
		procs[proc.Stat.Pid] = proc
	}

然后,scan()是读取/proc/[pid]/stat,获取pid和相应的ppid、name等信息