kubectl端口转发超时问题

70

使用 kubectl port-forward 命令,我能够成功地将本地端口转发到远程端口。但是似乎在空闲几分钟后,连接会中断。不确定原因。

以下是用于端口转发的命令:

kubectl --namespace somenamespace port-forward somepodname 50051:50051

错误信息:

Forwarding from 127.0.0.1:50051 -> 50051
Forwarding from [::1]:50051 -> 50051
E1125 17:18:55.723715    9940 portforward.go:178] lost connection to pod

希望能保持连接


那个Pod的状态怎么样?如果它没有重新启动或失败,因为我认为问题与会话层有关,这受到该Pod行为的影响。 - Suresh Vishnoi
2
你有没有在 AKS(Azure Kubernetes 服务)上的机会? - itaysk
Pod的状态正常…不,我们没有使用Azure。 - Stanley
5
在AWS上的Kubernetes部署中一直看到这个问题。(奇怪的是没有更多的讨论) - akauppi
6个回答

46

将kube的streaming-connection-idle-timeout设置为0应该是一个正确的解决方案,但如果您不想改变任何东西,可以使用while-do结构

格式:while true; do <<YOUR COMMAND HERE>>; done

因此,只需在CLI中输入:while true; do kubectl --namespace somenamespace port-forward somepodname 50051:50051; done即可使kubectl在连接断开时重新连接。


2
+1 这对我来说是更好的解决方案:从跳板主机转发到 Kubernetes 仪表板,在那里没有运行 kubelet。 - KiteUp
2
@AndrewSneck PowerShell:while ($true) { kubectl port-forward your-command-here } - Simon Ness
2
kubectl进程即使超时也不会退出(出现这种类型的日志:E0621 10:11:52.183060 20798 portforward.go:340] error creating error stream for port 9191 -> 9191: Timeout occured)。因此,我怀疑当超时时,这个while循环是否会一直循环。 - Lei Yang
当我收到“与 pod 的连接丢失”消息时,kubectl 就会退出。循环可能会有一些优点。 - fiidim
在我的情况下,当超时 @user2563451 时,kubectl不存在。 - Dolphin
显示剩余3条评论

41

我通过保持连接的活跃状态来解决了这个问题,例如使用curl或nc。

转发端口:

kubectl --namespace somenamespace port-forward somepodname 50051:50051
在另一个终端中,通过每10秒钟连接到该端口,保持连接处于活动状态。
while true ; do nc -vz 127.0.0.1 50051 ; sleep 10 ; done

2
这是唯一一个在不改变服务器端任何内容的情况下保持连接活动的答案。将端口转发命令放入循环中会破坏长轮询连接,这也是我在首次出现端口转发超时问题的主要原因。 - voutasaurus
3
这个有效了!为什么?只有上帝知道……哪里还有“纯C”的日子和Unix的Pizza盒子…… - user63898
你能解释一下为什么它能工作吗?我非常好奇。@Marcel - Dolphin
@Dolphin 如果不使用端口转发命令,它会超时。第二个命令会连接到该端口并保持其活动状态。 - Marcel
很遗憾,它并没有帮助到我... - titanic

37

似乎有一个5分钟的超时限制,可以通过 kubelet 参数进行覆盖:

https://github.com/kubernetes/kubernetes/issues/19231

如果你想将超时时间设置为5分钟以上(或无限制),你可以指定 streaming-connection-idle-timeout。例如: --streaming-connection-idle-timeout=4h 将其设置为4小时。或者: --streaming-connection-idle-timeout=0 将其设置为无限制。 (已弃用:此参数应通过 Kubelet 的 --config 标志指定的配置文件进行设置。请参见https://kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file/获取更多信息。)


6
当我尝试这样做时,出现了“unknown flag: --streaming-connection-idle-timeout”的错误提示。 - magnattic
3
“@magnattic Would --request-timeout work? @RobotNerd has mentioned such in 2018 in a now deleted (by him/her) answer.” 意思是:“@magnattic,请问 --request-timeout 可以使用吗?@RobotNerd 在2018年的一个现已被他/她删除的答案中提到了这一点。” - akauppi
1
--request-timeout是一个有效的选项,但似乎不能按预期工作... - Pascal Gula

18

对于 Windows,制作这样的批处理文件(愿上帝宽恕我)。

:1
oc port-forward PODNAME 8003:8080
goto 1

20
你已经被原谅。 - abarbaneld
这仍然是我能想到的最佳解决方案,以便不间断地执行此命令。 好吧,我原谅你,但我不会为了自己而在几乎2021年的每个时候都写下这个语句。我认为这个 bug 仍然存在于 Kubernetes 方面(顺便说一下,在 Linode 上运行集群)。 - JimShapedCoding
没有名为“oc”的命令.. - FireFuro99
oc 是 OpenShift(Kubernetes 变体)的命令行,同样的命令也适用于 kubectl。 - koepalex
@abarbaneld 你不是上帝,上帝会原谅你的冒充行为。 - undefined

0

如果您在负载均衡器(如HAProxy)后运行Kubernetes集群,则可能会发生kubelet中配置的超时时间大于HAProxy中配置的超时时间的情况。

例如,默认情况下,Kubelet中的streamingConnectionIdleTimeout设置为4小时:

$ kubectl proxy --port=8001 &
$ NODE_NAME="XXXX"; curl -sSL "http://localhost:8001/api/v1/nodes/${NODE_NAME}/proxy/configz" | jq '.kubeletconfig|.kind="KubeletConfiguration"|.apiVersion="kubelet.config.k8s.io/v1beta1"' | grep streaming
  "streamingConnectionIdleTimeout": "4h0m0s",

但是如果在HAProxy(或您喜欢的负载均衡器)中,您有以下设置:

defaults
  timeout client 1m
  timeout server 1m
...

尝试执行端口转发,如果您在应用程序上没有任何活动,则会超时:
$ date; kubectl port-forward service/XXXX 1234:80
Mon Jul  5 10:58:20 CEST 2021
Forwarding ...
# after a minute
E0705 10:59:21.217577   64160 portforward.go:233] lost connection to pod

为了解决这个问题,一个解决方案就是增加超时时间(需要注意的是,根据您的集群情况,这可能会产生不良影响),或者在进行端口转发连接到API服务器时绕过LB,直接进行连接(如果您的环境允许)。

0
这是我使用的一个 Bash 函数,用于绕过端口转发和超时问题:
function pfpod(){
pod=$1
portloc=$2
portrem=$3
while true
  do
    podname=`kubectl get pods -o name | awk -F'/' '{print $2}'| grep "$pod"| head -1`
    kubectl port-forward $podname $portloc:$portrem
done
}
我已经添加了一个 kubectl 调用以匹配部分 pod 名称,以防您有多个 pods 用于部署,您只需提供部分名称即可使用顶部的 pod。否则,您也可以提供完整的 pod 名称。
示例用法:

pfpod elasticsearch 9201 9200


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接