docker问题分析

1 问题描述

messages中有docker多种类型报错信息,可能为k8s健康检查过程中无法连接到对应容器造成,以下为messages中报错信息。

1

2 问题分析

docker 代码中查找原因。

docker问题分析_第1张图片

2

根据上面 docker 的日志,err 的错误信息为:Error running exec a72587fd3b0e74682e02201eec3d22541625f27e659174dfbb95a78923d8fcdf in container:OCI runtime exec failed: exec failed: container_linux.go:318: starting container process caused \"read init-p: connection reset by peer\": unknown"。也就是说 ContainerExecStart 返回了错误。ContainerExecStart 函数会调用到 containerd.Exec(如图4),也就是 dockerd containerd 之间进行通信。

docker问题分析_第2张图片

4

Exec函数如下图5,如果p.Start 出错,会导致内部的 fifo 关闭,从而导致 reading from a closed fifo 的问题。

docker问题分析_第3张图片

5

p.Start 调用到下面的代码,通过GRPCcontainerd通信

docker问题分析_第4张图片

6

这个GRPC调用会到达containerd 以下的代码,start中调用了runtime.Exec

docker问题分析_第5张图片

7

start中返回了OCI runtime exec failed: exec failed: container_linux.go:318: starting container process caused \"read init-p: connection reset by peer\": unknown"错误。runtime.Exec代码如下:

docker问题分析_第6张图片

8

因此是runc在运行后输出了exec failed:container_linux.go:318: starting container process caused \"read init-p: connection reset by peer\": unknown"

docker问题分析_第7张图片

9

在(图9kubelet日志中可以看到oci报错之前会有pod状态改变,这是由于k8s会更新容器的cpuset,容器的更新导致容器的state.json文件随之更新。而runc exec会读取 container state.json,因此当runc 读到了部分更新的内容时,会导致json decode失败,关闭了fifo,然后exec容器失败。在runc rc92版本中修复了这个问题,将saveState变成原子操作,这样就不会出现读取 state.json时读到部分写入的内容。

修复前:

docker问题分析_第8张图片

10

修复后:

docker问题分析_第9张图片

11

3 建议

  1. 升级runc版本至runc rc92(如果客户评估后选用此方案,该升级包可以由麒麟提供)。
  2. K8s核心组件的exec健康检查改为HTTP方式。

你可能感兴趣的:(docker,容器,运维)