0%

use of closed network connection

问题现象

可靠性验证时,发现大约存在 1/2000 概率存在 节点 NotReady ,并且不可自愈问题
kubelet 报 use of closed network connection

现象

  • 节点NotReady
  • kubelet 日志始终打印 use of closed network connection

初步定位像连接复用没有释放
一顿搜索,关联到社区 issue https://github.com/kubernetes/kubernetes/issues/87615
看起来就是 golang 的对 h2 处理的 bug

处理方式

修复也简单,手动重启 kubelet 即可恢复
主要担心其他服务用 client-go 的,可能也有问题,连不上不自愈,但是静默了

方案 1 : 各服务添加环境变量 DISABLE_HTTP2=true, 关闭 http2

  • 影响是,http1.1 模式下建链更多,会影响管理面负载
  • 多个服务涉及修改

方案 2 : http2 中进行规避

一番定位后,找到在 golang.org/x/net/http2/transport.go 里,下面位置是错误返回的地方

1
2
3
4
5
6
upgradeFn := func(authority string, c *tls.Conn) http.RoundTripper {
addr := authorityAddr("https", authority)
if used, err := connPool.addConnIfNeeded(addr, t2, c); err != nil {
go c.Close()
return erringRoundTripper{err} <--- "use of closed network connection" rised
}

通过调试,发现此处一旦发生该错误,就无法正常工作了,由此也就有了下面修改代码
一旦一个 RoundTripper 反复失败,就退出进程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
type exitedRoundTripper struct{
err error
count int
}

func (e *exitedRoundTripper) RoundTrip(*http.Request) (*http.Response, error) {
if e.count >10 {
os.Exit(1)
}
e.count ++
return nil, e.err
}

upgradeFn := func(authority string, c *tls.Conn) http.RoundTripper {
addr := authorityAddr("https", authority)
if used, err := connPool.addConnIfNeeded(addr, t2, c); err != nil {
go c.Close()
return &exitedRoundTripper{err: err,countter: 0} <--
}