Kubernetes: (1.17) 网卡故障后 Kubelet 不会重新连接到 Apiserver(使用关闭的网络连接)

创建于 2020-01-28  ·  123评论  ·  资料来源: kubernetes/kubernetes

我们刚刚将生产集群升级到 1.17.2。

自周六更新以来,我们遇到了这种奇怪的中断:在 NIC 绑定失败后(不久之后恢复),Kubelet 将断开所有连接,除非手动重新启动,否则不会重新尝试重新建立它们。

这是上次发生的时间线:

01:31:16:内核识别出绑定接口失败。 它会持续一段时间。 最终它会恢复。

Jan 28 01:31:16 baremetal044 kernel: bond-mngmt: link status definitely down for interface eno1, disabling it
...
Jan 28 01:31:37 baremetal044  systemd-networkd[1702]: bond-mngmt: Lost carrier
Jan 28 01:31:37 baremetal044  systemd-networkd[1702]: bond-mngmt: Gained carrier
Jan 28 01:31:37 baremetal044  systemd-networkd[1702]: bond-mngmt: Configured

正如预期的那样,所有手表都关闭了。 消息对他们来说都是一样的:

...
Jan 28 01:31:44 baremetal044 kubelet-wrapper[2039]: W0128 04:31:44.352736    2039 reflector.go:326] object-"namespace"/"default-token-fjzcz": watch of *v1.Secret ended with: very short watch: object-"namespace"/"default-token-fjzcz": Unexpected watch close - watch lasted less than a second and no items received
...

所以这些消息开始:

`Jan 28 01:31:44 baremetal44 kubelet-wrapper[2039]: E0128 04:31:44.361582 2039 desired_state_of_world_populator.go:320] Error processing volume "disco-arquivo" for pod "pod-bb8854ddb-xkwm9_namespace(8151bfdc-ec91-48d4-9170-383f5070933f)": error processing PVC namespace/disco-arquivo: failed to fetch PVC from API server: Get https://apiserver:443/api/v1/namespaces/namespace/persistentvolumeclaims/disco-arquivo: write tcp baremetal44.ip:42518->10.79.32.131:443: use of closed network connection`

我猜这在一段时间内应该不成问题。 但它永远不会恢复。 我们的事件发生在上午 01:31,必须在 9 点左右手动重启 Kubelet 以使内容正常化。

# journalctl --since '2020-01-28 01:31'   | fgrep 'use of closed' | cut -f3 -d' ' | cut -f1 -d1 -d':' | sort | uniq -dc
   9757 01
  20663 02
  20622 03
  20651 04
  20664 05
  20666 06
  20664 07
  20661 08
  16655 09
      3 10

Apiserver 启动并运行,所有其他节点都启动并运行,其他一切都很顺利。 这是(今天)唯一受此问题影响的人。

有没有办法减轻这种事件?

这会是一个错误吗?

kinsupport siapi-machinery sinode

最有用的评论

我通过每 5 分钟运行一次这个 bash 脚本来修复它:

#!/bin/bash
output=$(journalctl -u kubelet -n 1 | grep "use of closed network connection")
if [[ $? != 0 ]]; then
  echo "Error not found in logs"
elif [[ $output ]]; then
  echo "Restart kubelet"
  systemctl restart kubelet
fi

所有123条评论

/sig 节点
/sig api 机器

查看代码,错误发生在这里

代码的解释是它假定它可能是 EOF (IsProbableEOF) 而在这种情况下这似乎不是。

/assign @caesarxuchao

@rikatz你能详细说明你是如何追踪到你粘贴的代码的吗?

我的想法是,无论反射器如何处理错误(代码),它都会重新启动手表,因此它不能解释无法恢复的原因。

正是@caesarxuchao,所以这是我们的问题。

我已经跟踪了错误,基本上是通过代码 grep 并与 kubelet 那时正在做的事情(观察秘密)交叉以进入该部分。

不是一种高级方法,通过这似乎是错误代码的确切点。

问题是,因为连接已关闭,是否有某处标记这是手表 EOF 而不是理解这是一个错误?

除了我们有另一个节点以同样的方式失败,将发生次数从过去 4 天增加到 4 天之外,我没有其他更聪明的东西可以添加。

将尝试映射其他节点上是否正在发生绑定断开事件以及 kubelet 是否正在恢复 - 某些恢复可能是运气不好,而不是 100% 事件。

我想我们也看到了这一点,但我们没有绑定,我们只看到 Calico cali*接口的这些网络“运营商丢失”消息,并且它们是本地 veth 设备。

我也遇到过这种情况,不涉及任何债券。 重新启动节点可以解决问题,但仅重新启动 Kubelet 服务并不能解决问题(所有 API 调用都失败并显示“未授权”)。

我也遇到过这种情况,不涉及任何债券。 重新启动节点可以解决问题,但仅重新启动 Kubelet 服务并不能解决问题(所有 API 调用都失败并显示“未授权”)。

更新:在允许通过足够的时间(1 小时?)后重新启动 Kubelet 确实解决了问题。

我看到了同样的行为。 Ubuntu 18.04.3 LTS 全新安装。 用rancher 2.3.4构建的集群。 我最近看到这种情况定期发生,只是重新启动 kubelet 往往会为我修复它。 昨晚,我的所有 3 个工作节点都表现出相同的行为。 我更正了 2 以启动我的集群。 第三个仍然处于这种状态,而我正在挖掘。

我们在 CentOS 7 上看到了同样的问题,集群是用 Rancher (1.17.2) 新构建的。 我们正在使用编织。 所有 3 个工作节点都显示此问题。 重启 kubelet 对我们不起作用,我们必须重启整个节点

/sig 节点
/sig api 机器

查看代码,错误发生在这里

代码的解释是它假定它可能是 EOF (IsProbableEOF) 而在这种情况下这似乎不是。

我们也看到了同样的问题。 从日志中,我们发现问题发生后,所有后续请求仍然在同一个连接上发送。 看起来虽然客户端将请求重新发送到 apiserver,但是底层 http2 库仍然保持旧连接,因此所有后续请求仍然在此连接上发送并收到相同的错误use of closed connection

那么问题来了,为什么 http2 还保持着一个已经关闭的连接呢? 也许它维护的连接确实还活着,但一些中间连接意外关闭了?

我经常在使用 k8s 1.17.3 的 Raspberry Pi 集群上遇到同样的问题。 基于一些较旧的问题,我已将 kube API 服务器 http 连接限制设置为 1000“- --http2-max-streams-per-connection=1000”,在它现在再次启动后两周以上都很好。

是否可以重建 kube-apiserver https://github.com/kubernetes/apiserver/blob/b214a49983bcd70ced138bd2717f78c0cff351b2/pkg/server/secure_serving.go#L50
默认情况下将s.DisableHTTP2true
是否有官方图像的 dockerfile ( k8s.gcr.io/kube-apiserver:v1.17.3 )?

在这里也一样。(ubuntu 18.04,kubernetes 1.17.3)

我们也在我们的两个集群中观察到了这一点。 不完全确定根本原因,但至少我们能够看到这种情况发生在具有非常高监视计数的集群中。 但是,我无法通过强制每个 kubelet 进行大量监视来进行复制(开始时每个 Pod 有 300 个秘密的 Pod,这也导致 Prometheus 指标中每个 Pod 有 300 个监视)。 同样设置非常低的http2-max-streams-per-connection值并没有触发这个问题,但至少我能够观察到一些意外的调度程序和控制器管理器的行为(在无休止的重新监视循环或类似的事情之后可能只是过载,尽管)。

作为解决方法,我的所有节点每晚都通过本地 cronjob 重新启动 kublet。 现在 10 天前,我可以说它对我有用,我的节点上不再有“使用封闭网络连接”。

@sbiermann
感谢您发布此信息。 您用于 cronjob 的时间间隔是多少?

24小时

我也可以确认这个问题,我们还没有到 1.17.3,目前运行的是 Ubuntu 19.10:

Linux <STRIPPED>-kube-node02 5.3.0-29-generic #31-Ubuntu SMP Fri Jan 17 17:27:26 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

NAME                  STATUS   ROLES    AGE   VERSION       INTERNAL-IP   EXTERNAL-IP   OS-IMAGE       KERNEL-VERSION     CONTAINER-RUNTIME
STRIPPED-kube-node02   Ready    <none>   43d   v1.16.6   10.6.0.12     <none>        Ubuntu 19.10   5.3.0-29-generic   docker://19.3.3

我也可以在通过 RancherOS 1.5.5 节点上的 Rancher 2.3.5 部署的 Kubernetes 1.17.4 上确认这一点。 重新启动 kubelet 似乎对我有用,我不必重新启动整个节点。

对我来说,根本原因似乎是 RAM 即将耗尽,因此 kswapd0 的 CPU 使用率高达 100%,因为我忘记将 Kubernetes 节点的 swappiness 设置为 0。 在将 swappiness 设置为 0 并向机器添加一些 RAM 后,我还没有再次出现该问题。

如果根本问题是“http2 using dead connections”,那么重新启动 kubelet 应该可以解决问题。 https://github.com/kubernetes/kubernetes/pull/48670建议减少 TCP_USER_TIMEOUT 可以缓解问题。 我已经打开了https://github.com/golang/net/pull/55 ,在http2库中添加了客户端连接健康检查,但是登陆需要更多时间。

如果重新启动 kubelet 没有解决问题,那么可能是不同的根本原因。

我在重新启动网络时与 v1.17.2 有同样的问题,但只有一个节点有这个问题(我的集群有五个节点),我无法重现它。 重启kubelet解决了这个问题。

我怎样才能避免这个问题? 升级最新版本还是有其他方法修复?

我通过每 5 分钟运行一次这个 bash 脚本来修复它:

#!/bin/bash
output=$(journalctl -u kubelet -n 1 | grep "use of closed network connection")
if [[ $? != 0 ]]; then
  echo "Error not found in logs"
elif [[ $output ]]; then
  echo "Restart kubelet"
  systemctl restart kubelet
fi

我创建了一个没有重启 kubelet 的补丁,似乎问题已经解决了。
截止日期补丁

diff --git a/staging/src/k8s.io/client-go/transport/cache.go b/staging/src/k8s.io/client-go/transport/cache.go
index 7c40848c79f..bd61b39551a 100644
--- a/staging/src/k8s.io/client-go/transport/cache.go
+++ b/staging/src/k8s.io/client-go/transport/cache.go
@@ -38,6 +38,8 @@ const idleConnsPerHost = 25

 var tlsCache = &tlsTransportCache{transports: make(map[tlsCacheKey]*http.Transport)}

+type dialFunc func(network, addr string) (net.Conn, error)
+
 type tlsCacheKey struct {
        insecure   bool
        caData     string
@@ -92,7 +94,7 @@ func (c *tlsTransportCache) get(config *Config) (http.RoundTripper, error) {
                TLSHandshakeTimeout: 10 * time.Second,
                TLSClientConfig:     tlsConfig,
                MaxIdleConnsPerHost: idleConnsPerHost,
-               Dial:                dial,
+               Dial:                setReadDeadlineAfterDial(dial, 30*time.Second),
        })
        return c.transports[key], nil
 }
@@ -111,3 +113,18 @@ func tlsConfigKey(c *Config) (tlsCacheKey, error) {
                serverName: c.TLS.ServerName,
        }, nil
 }
+
+func setReadDeadlineAfterDial(dialer dialFunc, timeout time.Duration) dialFunc {
+       return func(network, addr string) (net.Conn, error) {
+               c, err := dialer(network, addr)
+               if err != nil {
+                       return nil, err
+               }
+
+               if err := c.SetReadDeadline(time.Now().Add(timeout)); err != nil {
+                       return nil, err
+               }
+
+               return c, nil
+       }
+}

@mYmNeo你能解释一下如何重建客户端吗?

@mYmNeo你能解释一下如何重建客户端吗?

@ik9999应用此补丁,然后重建 kubelet 并替换二进制文件

@mYmNeo如何重现此问题并进行测试?

我通过每 5 分钟运行一次这个 bash 脚本来修复它

@ik9999谢谢,它有效。

抄送@liggitt

设置 SetReadDeadline 是否意味着所有手表将每 30 秒关闭一次?

设置 SetReadDeadline 是否意味着所有手表将每 30 秒关闭一次?

是的。 这是解决此问题的丑陋方法(强制关闭连接)。

只是另一种情况:

我们在 Kube 1.16.8 集群中也看到了这一点。 重新启动 VM 可用于使节点恢复到良好状态(我怀疑 kubelet 重新启动也可以)。

我们的设置 kubelet 通过 localhost 与本地 haproxy 实例通信,该实例充当多个后端主实例的 tcp 负载均衡器。 我们将调查是否添加

option clitcpka    # enables keep-alive only on client side
option srvtcpka    # enables keep-alive only on server side

我们的负载均衡器实例有助于减轻显式重启的需要,并可以导致完全恢复。 重复日志示例

Apr  8 00:04:25 kube-bnkjtdvd03sqjar31uhg-cgliksp01-cgliksp-00001442 kubelet.service[6175]: E0408 00:04:25.472682    6175 reflector.go:123] object-"ibm-observe"/"sysdig-agent": Failed to list *v1.ConfigMap: Get https://172.20.0.1:2040/api/v1/namespaces/ibm-observe/configmaps?fieldSelector=metadata.name%3Dsysdig-agent&limit=500&resourceVersion=0: write tcp 172.20.0.1:22501->172.20.0.1:2040: use of closed network connection
Apr  8 00:04:25 kube-bnkjtdvd03sqjar31uhg-cgliksp01-cgliksp-00001442 kubelet.service[6175]: E0408 00:04:25.472886    6175 reflector.go:123] object-"default"/"default-token-gvbk5": Failed to list *v1.Secret: Get https://172.20.0.1:2040/api/v1/namespaces/default/secrets?fieldSelector=metadata.name%3Ddefault-token-gvbk5&limit=500&resourceVersion=0: write tcp 172.20.0.1:22501->172.20.0.1:2040: use of closed network connection

如果这解决了我们的特定问题,将发布更新,以防在此期间帮助这里的任何人。

想知道是否有一个配置参数来设置观看时间的绝对上限? 我发现 --streaming-idle-connection-timeout 但没有特定于手表。

我们在 kube 1.17.4 中看到了这一点,因为“etcd failed: reason forheld”导致 API 服务器不健康。

嗨,大家好。 我已经用 golang 1.14 重新编译了 kubernetes 二进制文件。 问题似乎消失了

@mYmNeo golang 1.14 + kubernetes v1.17?

@mYmNeo golang 1.14 + kubernetes v1.17 ?

@pytimer我们正在使用 1.16.6,无需更改任何代码,只需重新编译即可。 我认为根本原因可能是golang。

嘿! 在这里遇到同样的问题,k8s 1.17.4 如果解决了问题,我们认为我们可以使用 go 1.14 重新编译 1.17.5 吗?

不幸的是,更新到 go1.14 需要更新几个关键组件,因此不太可能重新选择到 Kube 1.17。 您可以在https://github.com/kubernetes/kubernetes/pull/88638 中跟踪问题和进度

很高兴知道,谢谢

@callicles是否已确认使用 go 1.14 重新编译解决了该问题?

我在 1.16.8 上看到了一个相同的问题 - 每隔几天(有时每两天一次,有时每两周一次)节点变为 NotReady,原因是 Kubelet 停止发布节点状态,并且“使用封闭的网络连接”填写日志

go 处理 h2 升级可能有问题。
golang.org/x/net/http2/transport.go

    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
        }

嗨,大家好。 我已经用 golang 1.14 重新编译了 kubernetes 二进制文件。 问题似乎消失了

@mYmNeo你有没有在用 go 1.14 重新编译后重现这个问题

嗨,大家好。 我已经用 golang 1.14 重新编译了 kubernetes 二进制文件。 问题似乎消失了

@mYmNeo你有没有在用 go 1.14 重新编译后重现这个问题

AFAIN,问题不再存在。

不幸的是,更新到 go1.14 需要更新几个关键组件,因此不太可能重新选择到 Kube 1.17。 您可以在 #88638 中跟踪问题和进度

您是否已经知道 go1.14 是否会向后移植到 1.18?

您是否已经知道 go1.14 是否会向后移植到 1.18?

我不希望如此。 似乎需要对 etcd 和 bbolt 进行更改以支持 go1.14,这比通常在发布分支中所做的更改更大。

@liggitt好的谢谢。 看起来我们(至少对于我们的集群)同时需要一个缓解策略:)

此问题是否仅在 NIC 故障后发生? 我们在 v1.16.8 集群中看到相同的错误消息,但没有关联的 NIC 故障。

我们至少有一个实例,其中底层 VM 在连接到 SAN 时出现 SCSI 错误。 SCSI 问题自行解决,但kubelet从未恢复。

--goaway-chance选项是在 1.18(#88567) 中添加的。 这个选项会缓解这个问题吗?

不。这只有在 kubelet 实际上能够到达 API 服务器并得到响应时才有效。

NIC 绑定失败(不久后恢复),所有连接都会中断,除非手动重新启动,否则不会重新尝试重新建立它们。

你能告诉你使用的是什么绑定模式吗? 我无法使用主动备份绑定在我的集群上重现此问题。

升级到 Kubernetes 1.16 后,我们也开始看到use of closed network connection错误和 kubelet 没有重新连接到 apiserver,使节点卡在 NotReady 中。 我们无法通过关闭 NIC(通过关闭/打开链接)来重现该问题,但我们确实注意到这种行为仅发生在负载更重的集群上。

我们做了更多的挖掘,发现golang中的服务器端客户端默认是 1000 ,所以我的猜测是,一旦 kubelet 从 apiserver 收到错误以达到 http2 流限制,它从未尝试重新连接。 设置--http2-max-streams-per-connection=1000我们没有看到节点像最初在测试期间发现的那样卡在 NotReady 中的问题。 这并没有解决 kubelet 无法重新连接的问题,但它确实帮助我们缓解了我们所看到的问题。

升级到 Kubernetes 1.16 后,我们也开始看到use of closed network connection错误和 kubelet 没有重新连接到 apiserver,使节点卡在 NotReady 中。 我们无法通过关闭 NIC(通过关闭/打开链接)来重现该问题,但我们确实注意到这种行为仅发生在负载更重的集群上。

我们做了更多的挖掘,发现golang中的服务器端客户端默认是 1000 ,所以我的猜测是,一旦 kubelet 从 apiserver 收到错误以达到 http2 流限制,它从未尝试重新连接。 设置--http2-max-streams-per-connection=1000我们没有看到节点像最初在测试期间发现的那样卡在 NotReady 中的问题。 这并没有解决 kubelet 无法重新连接的问题,但它确实帮助我们缓解了我们所看到的问题。

您好,kube-apiserver 中默认的服务器端 https 流是 1000,这等于客户端的值。
https://github.com/kubernetes/kubernetes/blob/ae1103726f9aea1f9bbad1b215edfa47e0747dce/staging/src/k8s.io/apiserver/pkg/server/options/recommended.go#L62

@warmchang我认为这适用于 apiextensions apiservers 和示例 apiserver:
https://github.com/kubernetes/kubernetes/blob/ae1103726f9aea1f9bbad1b215edfa47e0747dce/staging/src/k8s.io/apiserver/pkg/server/options/recommended.go#L62

没有设置--http2-max-streams-per-connection curl 测试在我们的 apiserver 日志中有这个(使用 v1.16):
I0603 10:18:08.038531 1 flags.go:33] FLAG: --http2-max-streams-per-connection="0"

并且 curl 请求在响应中显示了这一点:
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!

当我使用--http2-max-streams-per-connection=1000 ,curl 请求会显示
* Connection state changed (MAX_CONCURRENT_STREAMS == 1000)!

@jmcmeek @treytabner ,你说得对。 我误读了代码。 :+1:

使用 kubernetes 1.17.6 和这里相同。 看起来 kubelet 正在使用无效的 http2 连接。
我确实注意到 kube-apiserver 和 kubelet 之间MAX_CONCURRENT_STREAMS默认值不一致。

只需将服务器端值设置为 1000。稍后将报告。

牧场主/RKE

添加到集群定义:

 kube-api:
      extra_args:
        http2-max-streams-per-connection: '1000'

检查主节点:

docker exec -it kubelet bash
apt update && apt-get install -y nghttp2
nghttp -nsv https://127.0.0.1:6443
#Look for SETTINGS_MAX_CONCURRENT_STREAMS

在 APIserver 上将MAX_CONCURRENT_STREAMS1000对此问题没有影响。
我认为这是由golang http2 Transport的缺陷引起的。 看上面

今晚又遇到了这个问题。
似乎设置 'MAX_CONCURRENT_STREAMS ' 没有帮助☹️

嗨,大家好。 我想我终于找到了这个问题。 我们昨晚发生了同样的问题。 但使用修改后的 kubelet 成功恢复。

这不是 Kubernetes 的错误,而是关于client-go也在使用的 golang 的标准net/http包。
我相信golang.org/x/net/http2/transport.go存在缺陷

已经向golang官方报告了这个。 等待一些讨论。
https://github.com/golang/go/issues/39750

现在我修改了代码,默认启用了https://github.com/golang/net/commit/0ba52f642ac2f9371a88bfdde41f4b4e195a37c0引入的http2: perform connection health check
它被证明对这个问题有一定的帮助。 但是反应有点慢。

kubelet v1.17.6 日志(符合自行修改的golang.org/x/net包)

它确实从写死连接问题中恢复过来,但比预期花费的时间多一点。

请注意, performing http2 healthCheck是一条日志消息,我打算留在那里以证明healthCheck func 是由readIdleTimer调用的

 Jun 23 03:14:45 vm10.company.com kubelet[22255]: E0623 03:14:45.912484 22255 kubelet_node_status.go:402] 更新节点状态时出错,将重试:获取节点“vm10”:company 时出错。 “https://vm10.company.com:8443/api/v1/nodes/vm10.company.com?timeout=10s”:写tcp 16.155.199.4:39668->16.155.199.4:8443:使用关闭的网络连接
 Jun 23 03:14:45 vm10.company.com kubelet[22255]: E0623 03:14:45.912604 22255 kubelet_node_status.go:402] 更新节点状态时出错,将重试:获取节点“vm10”:company 时出错。 “https://vm10.company.com:8443/api/v1/nodes/vm10.company.com?timeout=10s”:写tcp 16.155.199.4:39668->16.155.199.4:8443:使用关闭的网络连接
 Jun 23 03:14:45 vm10.company.com kubelet[22255]: E0623 03:14:45.912741 22255 kubelet_node_status.go:402] 更新节点状态时出错,将重试:获取节点“vm10”:company 时出错。 “https://vm10.company.com:8443/api/v1/nodes/vm10.company.com?timeout=10s”:写tcp 16.155.199.4:39668->16.155.199.4:8443:使用关闭的网络连接
 Jun 23 03:14:46 vm10.company.com kubelet[22255]: E0623 03:14:46.367046 22255 controller.go:135] 无法确保节点租约存在,将在 400 毫秒后重试,错误:获取“https:// vm10.company.com:8443/apis/coordination.k8s.io/v1/namespaces/kube-node-lease/leases/vm10.company.com?timeout=10s”:写tcp 16.155.199.4:39668->16.155。 199.4:8443:使用封闭网络连接
 Jun 23 03:14:48 vm10.company.com kubelet[22255]: E0623 03:14:47.737579 22255 controller.go:135] 无法确保节点租约存在,将在 800 毫秒后重试,错误:获取“https:// vm10.company.com:8443/apis/coordination.k8s.io/v1/namespaces/kube-node-lease/leases/vm10.company.com?timeout=10s”:写tcp 16.155.199.4:39668->16.155。 199.4:8443:使用封闭网络连接
 6 月 23 日 03:14:49 vm10.company.com kubelet[22255]: E0623 03:14:49.113920 22255 reflector.go:153] k8s.io/kubernetes/pkg/kubelet/kubelet.go: 无法列出 *458 v1.Node:获取“https://vm10.company.com:8443/api/v1/nodes?fieldSelector=metadata.name%3Dvm10.company.com&limit=500&resourceVersion=0”:写tcp 16.155.199.4:39668-> 16.155.199.4:8443:使用封闭网络连接
 6 月 23 日 03:14:49 vm10.company.com kubelet[22255]: E0623 03:14:48.744770 22255 reflector.go:153] 对象-“kube-system”/“flannel-token *zvfwn”:未能列出v1.Secret:获取“https://vm10.company.com:8443/api/v1/namespaces/kube-system/secrets?fieldSelector=metadata.name%3Dflannel-token-zvfwn&limit=500&resourceVersion=0”:写tcp 16.155 .199.4:39668->16.155.199.4:8443:使用封闭网络连接
 Jun 23 03:14:49 vm10.company.com kubelet[22255]: E0623 03:14:49.599631 22255 reflector.go:153] object-"kube-system"/"coredns":无法列出 *v1.ConfigMap:获取“https://vm10.company.com:8443/api/v1/namespaces/kube-system/configmaps?fieldSelector=metadata.name%3Dcoredns&limit=500&resourceVersion=0”:写tcp 16.155.199.4:39668->16.155。 199.4:8443:使用封闭网络连接
 Jun 23 03:14:49 vm10.company.com kubelet[22255]: E0623 03:14:49.599992 22255 controller.go:135] 无法确保节点租约存在,将在 1.6 秒后重试,错误:获取“https:// /vm10.company.com:8443/apis/coordination.k8s.io/v1/namespaces/kube-node-lease/leases/vm10.company.com?timeout=10s”:写tcp 16.155.199.4:39668->16.155 .199.4:8443:使用封闭网络连接
 6 月 23 日 03:14:49 vm10.company.com kubelet[22255]: E0623 03:14:49.600182 22255 reflector.go:153] k8s.io/kubernetes/pkg/kubelet/kubelet.go: 449 失败v1.Service:获取“https://vm10.company.com:8443/api/v1/services?limit=500&resourceVersion=0”:写tcp 16.155.199.4:39668->16.155.199.4:8443:使用封闭网络联系
 6 月 23 日 03:14:49 vm10.company.com kubelet[22255]: E0623 03:14:49.600323 22255 reflector.go:153] object-"kube-system"/"kube-flannel-cfg":无法列出 * v1.ConfigMap:获取“https://vm10.company.com:8443/api/v1/namespaces/kube-system/configmaps?fieldSelector=metadata.name%3Dkube-flannel-cfg&limit=500&resourceVersion=0”:写tcp 16.155 .199.4:39668->16.155.199.4:8443:使用封闭网络连接
六月 23 03:14:49 vm10.company.com kubelet[22255]: E0623 03:14:49.600463 22255 reflector.go:153] 对象-“核心”/“registrypullsecret”:无法列出“*v1.Secret”: https://vm10.company.com:8443/api/v1/namespaces/core/secrets?fieldSelector=metadata.name%3Dregistrypullsecret&limit=500&resourceVersion=0":写tcp 16.155.199.4:39668->16.154:8443使用封闭网络连接
 6 月 23 日 03:14:49 vm10.company.com kubelet[22255]: E0623 03:14:49.369097 22255 reflector.go:153] object-"kube-system"/"registrypullsecret":未能列出:*v1.获取“https://vm10.company.com:8443/api/v1/namespaces/kube-system/secrets?fieldSelector=metadata.name%3Dregistrypullsecret&limit=500&resourceVersion=0”:写tcp 16.155.199.4:39665->16.1 199.4:8443:使用封闭网络连接
 6 月 23 日 03:25:39 vm10.company.com kubelet[22255]: E0623 03:25:39.543880 22255 desired_state_of_world_populator.go:320] 处理 pod"deployment-log-dir" 的错误处理卷 "deployment-log-dir" for pod"fluent-dc9" -4fea-bd7f-99ac1cc6ae7a)”:错误处理 PVC core/itom-vol-claim:无法从 API 服务器获取 PVC:获取“https://vm10.company.com:8443/api/v1/namespaces/core/ persistentvolumeclaims/itom-vol-claim”:读取 tcp 16.155.199.4:41512->16.155.199.4:8443:使用关闭的网络连接
 Jun 23 03:25:39 vm10.company.com kubelet[22255]: E0623 03:25:39.666303 22255 kubelet_node_status.go:402] 更新节点状态时出错,将重试:无法修补状态“{\”status\” {\"$setElementOrder/conditions\":[{\"type\":\"MemoryPressure\"},{\"type\":\"DiskPressure\"},{\"type\":\"PIDPressure\ "},{\"type\":\"Ready\"}],\"conditions\":[{\"lastHeartbeatTime\":\"2020-06-22T19:25:29Z\",\"type\ ":\"MemoryPressure\"},{\"lastHeartbeatTime\":\"2020-06-22T19:25:29Z\",\"type\":\"DiskPressure\"},{\"lastHeartbeatTime\": \"2020-06-22T19:25:29Z\",\"type\":\"PIDPressure\"},{\"lastHeartbeatTime\":\"2020-06-22T19:25:29Z\",\"为节点“vm10.company.com”输入\":\"Ready\"}]}}":补丁"https://vm10.company.com:8443/api/v1/nodes/vm10.company.com/ status?timeout=10s": 读取 tcp 16.155.199.4:41512->16.155.199.4:8443: 使用关闭的网络连接
 Jun 23 03:25:49 vm10.company.com kubelet[22255]: E0623 03:25:49.553078 22255 kubelet_node_status.go:402] 更新节点状态时出错,将重试:获取节点“vm10”:company 时出错。 “https://vm10.company.com:8443/api/v1/nodes/vm10.company.com?timeout=10s”:读取tcp 16.155.199.4:41718->16.155.199.4:8443:使用关闭的网络连接
 6 月 23 日 03:25:49 vm10.company.com kubelet[22255]:E0623 03:25:49.560723 22255 desired_state_of_world_populator.go:320] 处理 pod“fluentd-h7094a-cf-h704a-c204a-c-3255c -bd7f-99ac1cc6ae7a)”:错误处理 PVC 核心/itom-logging-vol:无法从 API 服务器获取 PVC:获取“https://vm10.company.com:8443/api/v1/namespaces/core/persistentvolumeclaims/ itom-logging-vol”:读取 tcp 16.155.199.4:41718->16.155.199.4:8443:使用关闭的网络连接
 6 月 23 日 03:27:29 vm10.company.com kubelet[22255]: I0623 03:27:29.961600 22255 log.go:181] 执行 http2 healthCheck
 6 月 23 日 03:31:32 vm10.company.com kubelet[22255]: I0623 03:31:31.829860 22255 log.go:181] 执行 http2 healthCheck
 6 月 23 日 03:31:44 vm10.company.com kubelet[22255]: I0623 03:31:44.570224 22255 log.go:181] 执行 http2 healthCheck
 6 月 23 日 03:32:13 vm10.company.com kubelet[22255]: I0623 03:32:12.961728 22255 log.go:181] 执行 http2 healthCheck
 6 月 23 日 03:33:16 vm10.company.com kubelet[22255]: I0623 03:33:15.441808 22255 log.go:181] 执行 http2 healthCheck
 6 月 23 日 03:33:28 vm10.company.com kubelet[22255]: I0623 03:33:28.233121 22255 log.go:181] 执行 http2 healthCheck

不再报告use of closed network connection并且 kubelet 返回就绪状态

我们在堆栈中的问题中获得了一些新的潜在见解。 有一定的信心,我们假设由于特定情况下连接数的高负载,网络/基础设施级别的连接很少出现下降,因此在我们的情况下,这不是网络接口翻转。 由于他们在客户端切换到 http2,因此我们在严重的问题。 通过将http2.Transport.ReadIdleTimeout为与golang/net#55一起实现来启用 http2 运行状况监视器完全解决了我们的联邦问题。

这些值当前未公开,因为apimachinery/pkg/util/net/http.go实例化http.Transport并将其在内部升级为 http2,在合并 golang/net#74 之前不会公开该选项。

除了 kubelet restart cron 作业之外,还有其他解决方法吗? 我们已经有一个星期的 cron 工作了,但它并没有阻止问题的发生。

我在 v1.17.3 中有同样的问题。

我发现使用特定golang.org/x/net版本的k8s版本有问题,这个包好像已经修复了。
https://go-review.googlesource.com/c/net/+/198040

有此问题的版本(v1.16.5 ~ 最新版本)
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9

修复版本(主分支)
golang.org/x/net v0.0.0-20200707034311-ab3426394381

更新golang.org/x/net包会解决这个问题吗?

是否有计划为维护的 k8s 版本 (v1,16, 1.17, v1,18..) 修复此问题?

我发现使用特定golang.org/x/net版本的k8s版本有问题,这个包好像已经修复了。
https://go-review.googlesource.com/c/net/+/198040

提到的更改仅_提供_启用 HTTP2 健康监视器的可能性,但它需要由开发人员启用(默认为关闭)。 此外,它不能真正设置,有一个拉取请求,允许开发人员访问健康监视器

我目前正在集成一个基于反射的修补程序,该修补程序可为我们自己的 Kubernetes 发行版启用运行状况监视器,希望这有助于解决问题。

——
延斯·埃拉特 \ 印记

@JensErat谢谢你的回答。
如果是这样,这个问题是否也会出现在旧版本的 k8s(1.13, 1.15, ..) 中?

一个多月前,我将节点发行版从 RancherOS(内核 4.14.138)更改为 Ubuntu 18.04(内核 5.3.0),此后问题一直没有出现。
我的一个集群留在 RancherOS 上,这个问题已经重现了 3 次。

不是 100% 舒尔,但内核版本可能很重要。

很难说。 我们肯定会观察到(d)1.16 到 1.18 的问题,但之前很少见奇怪的“kubelet 卡住事件”。 至少一年以来,我们已经深入研究了此类问题,但始终无法关联任何事情(几周内发生了一起事件,而且我们有一些四位数的 kubelet 正在运行)。 虽然自从我们安装了 1.16 后变得更糟,但目前我们更倾向于假设底层(也非常罕见且难以追踪......)网络问题更频繁地发生。 我们正在使用内核 5.3.0-46-generic 运行 Ubuntu 19.10,但受到影响(很可能你实际上获得了更新的补丁级别)。 您能否提示您正在运行的确切内核版本/补丁级别?

——
延斯·埃拉特 \ 印记

它是5.3.0-59-generic 。 但是我们只有大约 40 个 kubletes,所以这仍然可能是巧合。

正如我上面所说。 这个问题在重负载集群上发生得更频繁。 在启用 h2 传输健康检查之前,我们几乎每晚都观察到相同的问题。
根据问题上报给golang官方。 问题发生在套接字读取循环中,它应该在读取关闭的套接字时返回错误,但它永远不会返回。 另外,我建议在写入套接字时添加错误处理逻辑以主动检测连接问题。 但几天后,他们似乎并不在意这种罕见的问题。

我的意思是,这个话题有点远,因为问题是由非常接近内核的网络套接字引起的。 更新内核可能有帮助,也可能没有。 (PS:我们使用的是带有内核3.10的centos 7,在启用healthCheck之前几乎每天都会发生)
我花了大约 3 天时间阅读 net/http 的源代码,据我所知,启用 h2 传输健康检查应该有助于从此类问题中恢复,并且我们确实通过这样做摆脱了这种奇怪的情况。
@JensErat您是否有一些具体的证据可以证明启用 healthCheck 有助于解决此问题?

@JensErat您是否有一些具体的证据可以证明启用 healthCheck 有助于解决此问题?

我们正在为我们的每个 Kubernetes 集群运行 Prometheus federation。 Prometheus 2.19.0 引入了 http2(他们忘记在变更日志中提及这一点,并且将它很好地隐藏在提交消息正文中,我不得不 git bisect,部署并为每次运行等待几个小时......)我们观察到每天有十几起联邦被卡住的事件。 我首先再次修补了 http2 支持(问题消失了),然后直接在 golang/net/x/http2 中设置读取超时。 从那以后,我们再也没有发生过一次联邦关闭事件。

我目前正准备在一些集群上推出打补丁的 Kubernetes 版本,所以几天后我们应该会有数据。 一旦我们有适当的数据,我们肯定会分享我们的结果。

——
延斯·埃拉特 \ 印记

我目前正准备在一些集群上推出打补丁的 Kubernetes 版本,所以几天后我们应该会有数据。 一旦我们有适当的数据,我们肯定会分享我们的结果。

感谢您的反馈意见。 这是一个非常令人愉快的消息。
虽然根本原因还不是很清楚,但至少我们找到了一种从灾难中恢复的方法。 :D

我们在 k8s v1.14.3 上也有同样的问题,重启 kubelet 可以解决这个问题。

我知道这很愚蠢,但必须作为临时解决方法:

展开 yaml

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kubelet-face-slapper
  namespace: kube-system
spec:
  selector:
    matchLabels:
      app: kubelet-face-slapper
  template:
    metadata:
      labels:
        app: kubelet-face-slapper
    spec:
      # this toleration is to have the daemonset runnable on master nodes
      # remove it if your masters can't run pods    
      tolerations:
      - effect: NoSchedule
        key: node-role.kubernetes.io/controlplane
        operator: Equal
        value: "true"
      - effect: NoExecute
        key: node-role.kubernetes.io/etcd
        operator: Equal
        value: "true"
      containers:
      - command:
        - /bin/sh
        - -c
        - while true; do sleep 40; docker logs kubelet --since 1m 2>&1 | grep -q "use
          of closed network connection" && (docker restart kubelet ; echo "kubelet
          has been restarted due to connection error") || echo "kubelet connection
          is ok" ;done
        image: docker:stable
        name: kubelet-face-slapper
        volumeMounts:
        - mountPath: /var/run/docker.sock
          name: docker-sock
      volumes:
      - hostPath:
          path: /var/run/docker.sock
          type: File
        name: docker-sock


(这是特定于牧场主的,但可以通过使用特权容器和 journalctl/systemctl 轻松适应其他发行版)

sleep--since时间量必须小于集群的pod-eviction-timeout (默认

顺便说一句 - Rancher 工作节点上的docker pause nginx-proxy使 kubelet 产生相同的错误消息。

针对在 VMWare vSphere 上运行 K8S 的人的临时解决方法 -禁用K8S 虚拟机的

我们有一些关于使用新的 golang http2 健康检查功能缓解问题的好消息:没有问题了。 到目前为止,我们在 Prometheus、整个 Kubernetes 和几个内部组件中实现了“修复”(在 vendored x/net代码中硬编码设置值),观察:

  • 不再有普罗米修斯联盟问题
  • kubelet 有时仍会报告单个“使用关闭的连接”事件,但会在几秒钟内恢复(我们设置了约 30 秒的 http2 健康检查窗口)
  • 有时我们会遇到 kubectl 手表的问题——如果使用补丁 kubectl 也会消失
  • 我们正在运行一个扩展的 E2E 测试套件来定期验证我们的集成,并观察到零星的测试超时和不稳定。 你猜怎么着? 现在走了。

此外,我们已经能够获得有关如何触发问题的新见解。 我可以自信地确认

对于 Kubernetes 的某些用户来说,这是一个非常烦人且有些严重的问题(我猜这取决于 IaaS 层/网络的某种“破坏性”)。 尽管有关于公开接口以正确设置值的 golang 讨论——你认为有没有机会通过反射来设置这些值的 PR 合并上游(仍然比分叉 x/net 我想像我们现在所做的那样) ? 我们可以提供代码(并验证修复,我们实际上无法重现,但要经常观察它以确认修复是否有效)。

抄送@liggitt

长期问题(自我说明)

@JensErat谢谢你的回答。
如果是这样,这个问题是否也会出现在旧版本的 k8s(1.13, 1.15, ..) 中?

我可以确认看到 Kubernetes v1.16.13 的问题
我们没有看到 Kubernetes v1.15.9 的问题

当我从 etcd 快照备份恢复 kubenetes 集群v1.16.14 。 此错误出现在 kubelet 日志中。
感谢@ik9999 。 我重新启动 kubelet 然后错误消失

[root@dev-k8s-master ~]# journalctl -u kubelet -n 1 | grep "use of closed network connection"
Aug 22 11:31:10 dev-k8s-master kubelet[95075]: E0822 11:31:10.565237   95075 reflector.go:123] k8s.io/client-go/informers/factory.go:134: Failed to list *v1beta1.CSIDriver: Get https://apiserver.cluster.local:6443/apis/storage.k8s.io/v1beta1/csidrivers?limit=500&resourceVersion=0: write tcp 192.168.160.243:58374->192.168.160.243:6443: use of closed network connection
[root@dev-k8s-master ~]# systemctl restart kubelet
[root@dev-k8s-master ssh]# journalctl -u kubelet -n 1 | grep "use of closed network connection"

我们在 1.17.3 遇到了同样的问题,重启 kubelet 应该可以解决。 任何稳定的解决方法或何时修复?

v1.18.6 相同

@rxwang662001
这是由上游 golang 问题引起的。 需要确定的一件事是,这不会在 go 1.15 中修复。
与此同时,Kubernetes 社区仍在努力迁移到 1.14 LOL。

通常,go 每 6 个月发布一次。 如果一切顺利,也许我们可以在明年看到上游解决这个问题,也许再过一年,直到 kubernetes 修复 🥇 !
(开个玩笑。如果你现在真的想在你的堆栈中修复这个问题。破解 h2Transport 以启用 healthCheck 被证明是有效的。

与此同时,Kubernetes 社区仍在努力迁移到 1.14 LOL。

实际上,由于 sig-scalability 和 sig-release 在 go1.15 预发布方面的出色工作,Kubernetes 1.19 刚刚在 go1.15 上发布。 看起来在 go1.16 中公开 http/2 选项的工作正在进行中,我希望我们会尽快使用它。

实际上,由于 sig-scalability 和 sig-release 在 go1.15 预发布方面的出色工作,Kubernetes 1.19 刚刚在 go1.15 上发布。

奥普斯。 抱歉开了个尴尬的玩笑。 没有太关注 v1.19 的发布。
似乎我们在 K8S 上完全跳过了 go1.14? 哇。 这是一个很大的飞跃👍

@povsister

感谢您分享您的解决方案。 你能添加更多关于你如何使它工作的细节吗?

现在我修改了代码,默认启用了由golang/ net@0ba52f6引入的http2: perform connection health check
它被证明对这个问题有一定的帮助。 但是反应有点慢。

您对代码进行了哪些更改? 在哪里,在哪个文件中?

@KarthikRangaraju
初始化 h2Transport 时,请参考此 PR以启用 healthCheck,
或者你可以做一些反射/不安全的偏移黑客来在运行时访问未导出的字段。

而且,在做这些事情之前不要忘记更新 golang/x/net。

尽管我们不时遇到此问题,但我们无法重现此问题。

由于我们无法确定症状的根本原因,我们无论如何都会修复症状。

我们的解决方案:

  • 以下脚本每 1 小时运行一次。 它通过 kube 配置文件通过 kubectl 与 kube-api 服务器通信
    kubelet 使用(这种方式没有权限提升)。
  • 询问主节点thinks它自己的节点是否为 NotReady。 如果是,则通过在文件上运行touch命令来触发 kubelet 重启
    这是 kubelet-watcher.service 用于文件系统更改并相应地重新启动 kubelet 的watched
#!/bin/bash

while true; do
  node_status=$(KUBECONFIG=/etc/kubernetes/kubelet.conf kubectl get nodes | grep $HOSTNAME | awk '{print $2}')
  date=$(date)
  echo "${date} Node status for ${HOSTNAME}: ${node_status}"
  if [ ${node_status} == "NotReady" ]; then
    echo "${date} Triggering kubelet restart ..."
    # Running touch command on /var/lib/kubelet/config.yaml. This will trigger a kubelet restart.
    # /usr/lib/systemd/system/kubelet-watcher.path & /usr/lib/systemd/system/kubelet-watcher.service
    # are responsible for watching changes in this file
    # and will restart the kubelet process managed by systemd accordingly.
    touch /var/lib/kubelet/config.yaml
  fi

  # Runs ever 1 hour
  sleep 3600
done
# cat  /usr/lib/systemd/system/kubelet-watcher.path
[Path]
PathModified=/var/lib/kubelet/config.yaml

[Install]
WantedBy=multi-user.target

# cat /usr/lib/systemd/system/kubelet-watcher.service
[Unit]
Description=kubelet restarter

[Service]
Type=oneshot
ExecStart=/usr/bin/systemctl restart kubelet.service

[Install]
WantedBy=multi-user.target[root@den-iac-opstest-kube-node02 karthik]#

对于 Kubernetes 1.19.0,问题仍然存在,但消息略有不同。
Sep 11 18:19:39 k8s-node3 kubelet[17382]: E0911 18:19:38.745482 17382 event.go:273] Unable to write event: 'Patch "https://192.168.1.150:6443/api/v1/namespaces/fhem/events/fhem-7c99f5f947-z48zk.1633c689ec861314": read tcp 192.168.1.153:34758->192.168.1.150:6443: use of closed network connection' (may retry after sleeping)
它现在在错误消息中包含“(可能在睡眠后重试)”。

是否可以在不等待升级 golang 的情况下完全在 kubernetes 中缓解这种情况? 例如,如果遇到“使用封闭网络连接”或其他问题,是否可以让 client-go 更换传输?

或者,如果使用 HTTP 1.1,这个问题仍然会发生,还是纯粹与 HTTP 2 相关? 如果 HTTP 1.1 可以免疫并且没有巨大的缺点,那么在 kubelet、kube-proxy 和各种控制平面进程上设置GODEBUG=http2client=0 ,甚至设置GODEBUG=http2server=0在 apiserver 进程上使更改通用。

我们是否认为这些实际上会缓解这个问题,并且除了由于在不通过 HTTP2 进行多路复用时连接数的增加而导致的一些性能问题之外不会导致其他主要缺陷?

如果遇到“使用封闭网络连接”或其他问题,是否可以让 client-go 更换传输?

不是很外科手术......当前共享传输以避免面对反复构建新客户端的呼叫者的短暂端口耗尽

如果使用 HTTP 1.1,这个问题仍然会发生,还是纯粹与 HTTP 2 相关?

据我所知,HTTP 1.1 可能会遇到同样的问题,因为空闲连接会回到保持活动池中(并且由于 ping 运行状况检查机制不可用,因此检测/缓解它的选项较少)

对于使用客户端的项目,是否有好的解决方法? 我们如何确定客户端何时死亡以及修复它需要做的最少的事情(听起来像重新启动我们的进程可能是唯一的选择)?

我们如何识别客户何时死亡

当您重复收到相同 URL 的write tcp xxx use of closed network connection错误时。 这表明客户端已经死了。 Transport 中的连接池为请求的host:port缓存了一个无效的 tcp 连接。

对于使用客户端的项目,是否有好的解决方法?

据我所知,重新构建一个http.Client可以解决这个问题,而无需重新启动整个应用程序。

我们至少需要做些什么来修复它

它需要对项目进行源代码级访问。 也许你可以使用上面提到的机制来检测死客户端并在需要时重新构建一个新客户端。 如果没有人使用旧客户端,它将被垃圾收集。

我可以访问我的项目的源代码,但我们使用 kubernetes 客户端。 当我们执行 watch 时,它似乎永远不会检测 TCP 连接是否像这样被切断(并且由于 watch 正在处理 HTTP 事务,因此没有错误冒泡到我们的代码中进行处理)。

是的。 你是对的, http.Client没有被 kubernetes 客户端公开。
目前,顶级应用程序以很少的成本完成这种变通方法是没有希望的。
如果 kubernetes 客户端不使用http.DefaultClient ,可以通过重新构建整个 kubernetes 客户端来修复。

对于手表请求,情况越来越糟。 kubernetes 客户端似乎一直在重试请求,上层应用程序没有弹出错误。 我现在对这种情况没有什么好主意。

这里提出的解决方法已经为我们工作了几个星期。 我们把它变成了一个 python 脚本,在我们所有的集群中作为守护进程运行。 我们通常会看到它每周执行一两次操作(自动重启 kubelet),因此我们没有对我们的集群操作产生任何负面影响。 我们将其设置为可变的,以便它仅在 5 分钟内看到 2+ 条消息时才重新启动 kubelet。 我们看到偶尔可以看到一条消息,这不是问题。 当问题发生时,您会在 kubelet 日志中不断看到use of closed network connection错误。

请创建一个 pullrequest,我们将调查这个主题。

在单个裸机集群上,我看到这种情况每 24 小时发生 2-4 次。 1.17.12

它发生在 api-server pod 重新启动时,即使在单节点集群上也是如此。 与 apiserver 的连接丢失,因此错误号最小化方法正在解决 apiserver 重新启动的问题。

我在主节点前使用 haproxy,你认为有什么办法可以通过一些 LB 配置来防止这种情况发生吗?

@shubb30你介意和我分享你的解决方案吗?

当我遇到问题时,我可以确认我的 apiserver没有重新启动。 我正在使用 daemonset 和 shell 技巧来监视日志条目,然后重新启动 kubelet,这运行得相当好,但我认为它只是一种临时解决方法。

是一个对我们来说效果很好的修改版本,作为一种解决方法。

大家好!

我们是否可能认为这种向后移植会有所帮助?
https://github.com/golang/go/issues/40423

好消息:golang/net master 支持配置 http2 传输,现在允许设置超时! https://github.com/golang/net/commit/08b38378de702b893ee869b94b32f833e2933bd2

完毕。
PR 开放审查。

另一个好消息:Kubernetes 没有使用标准 net/http 包中捆绑的 http2,所以我们不需要等待下一个 Go 版本。 我们可以直接使用https://github.com/golang/net/commit/08b38378de702b893ee869b94b32f833e2933bd2来解决这个问题。

建议修复这里。 https://github.com/kubernetes/kubernetes/pull/95898
它将依赖更新到所需版本并默认启用 http2 传输健康检查。
它应该可以帮助使用 client-go 与 apiserver 通信的应用程序(例如:kubelet)摆脱“应用程序在写入 tcp xxx 时挂起:使用关闭连接”的问题。

随意留下任何评论。

似乎提到的 #95898 由于我们不需要讨论的原因而关闭。

关于这个问题还有其他更新吗?

https://github.com/kubernetes/kubernetes/pull/95981 (上面链接)正在进行中以引入 http/2 修复

这个问题是特定于 1.17.X 版本的 kubernetes 吗?

@krmayankk不完全确定它什么时候开始。 但是至少1.17-1.19有这个问题。 #95980 应该已经修复了它(将成为下一个 1.20 版本的一部分,昨天还没有进入测试版)

@krmayankk我们在 v1.18.9 中也看到了这个问题,但它是由一个有问题的 Rancher 版本触发的,该版本导致网络使用率非常高。 回滚到另一个版本后,未发现任何问题。

我遇到了这个问题,但我现在已经使用上面评论中的解决方法在我的小型爱好集群中“修复”了它

我写了一个小的 ansible-playbook来将解决方法部署在节点上作为系统单元和计时器,可能会在一段时间内为其他人节省类似的设置

是否有计划将 #95981 挑选到 1.17 发布分支?

此评论讨论向后移植到旧版本: https :

我认为答案是“这很艰难,可能会破坏事物,所以可能不会”。 当被问到时,我希望从运行 v1.17 的人那里得到相同的答案,那么为什么不升级到 v1.20 以获得修复呢? :笑:

将其向后移植到至少 1.19 会很棒,因为这将使修复相对较快可用。 我怀疑有些人会因为 Docker 的弃用而推迟 1.20。

将其向后移植到至少 1.19 会很棒,因为这将使修复相对较快可用。

这已经完成了。

我怀疑有些人会因为 Docker 的弃用而推迟 1.20。

除了弃用警告之外,1.20 中 docker 没有任何变化。 在弃用期结束时,将删除 dockershim 支持。

在 raspbian 10 上的 1.20 上遇到这些错误。从哪里开始修复这些错误? 运行云托管集群的成本似乎比尝试在自己的集群上运行更具成本效益

为了我自己的清楚,这看起来应该由#95981 解决,这使它成为 1.20 并重新移植到 1.19?

95981 被合并到 1.20,并在 #96770 中被挑选到 1.19。

/关闭

@caesarxuchao :关闭此问题。

在回答这个

95981 被合并到 1.20,并在 #96770 中被挑选到 1.19。

/关闭

此处提供了有关使用 PR 评论与我互动的说明。 如果您对我的行为有任何疑问或建议,请针对kubernetes/test-infra存储库提出问题。

v1.16、v1.17 或 v1.18 是否会有任何反向移植/樱桃选择?

@chilicathttps://github.com/kubernetes/kubernetes/pull/95981#issuecomment -730561539。 我不打算将它挑选到 1.18 或更旧的版本。

此页面是否有帮助?
0 / 5 - 0 等级