为什么HostPort不在主机的Netstat输出中显示

问题描述

我使用带有yaml文件的kubectl创建目标容器,发现容器中的进程正在按预期方式监听目标端口。

令我惊讶的是,在主机的netstat -tunlpnetstat -alpnetstat -an输出中未看到端口。但是,如果我尝试使用telnet localhost targetPort,它将起作用!!!

为什么会这样?有人可以解释吗?

解决方法

为了访问工作程序节点上的服务,您必须使用类型NodePort的服务在工作程序节点上公开容器。在Pod中运行的进程位于不同的网络命名空间中。您可以从Pod内部访问应用程序,但不能从没有服务对象的节点访问应用程序。有关参考,请参见以下内容:

$ kubectl create deploy nginx --image=nginx
$ kubectl expose deploy nginx --target-port 80 --port 80 --type NodePort
$ NODE_PORT=$(kubectl get svc nginx -ojsonpath='{ .spec.ports[0].nodePort }')
$ netstat -an | grep $NODE_PORT
tcp46      0      0  *.31563                *.*                    LISTEN     

$ curl localhost:$NODE_PORT
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...

HTH

,

由于Pod中的容器正在其自己的网络名称空间中运行,因此netstat无法检测到它们。

要列出监听容器内部的端口,请使用nsenter。此工具将帮助您在过程的其他名称空间(在我们的示例中为所需容器的PID)上执行命令。

  1. 获取容器的PID-SSH到K8s worker节点上并运行docker inspect <containerid>(如果docker是您的容器运行时)

,然后从上述命令运行中获取PID后

  1. $ nsenter -t <container-PID> -n netstat -nltp
,

这是因为docker。默认情况下,docker不会将容器网络名称空间添加到linux运行时数据(/ var / run从/ run作为tmpfs挂载),这是在运行ip netns命令时看到的。

要查看网络名称空间,您需要使用nsenter

  1. 获取容器ID。
docker ps
  1. 获取容器进程ID。
docker inspect --format '{{ .State.Pid }}' <<container-id>>
  1. 现在使用nsenter来显示Pods网络空间。与nsenter相比,使用docker exec的优势在于nsenter使您能够执行pod内部节点上可用的所有工具或命令,而docker exec仅允许有限或受限制的命令。
nsenter -t <<container pid>> -n netstat -tunlp 

,
nsenter -t <container-PID> -n netstat -nltp

此命令显示容器端口,而不是主机端口,现在仍然回答问题

,

传入的连接可能会使用 iptable 规则直接路由到 k8s 网络中(例如,使用 Calico CNI 时)。

你可以试试

iptable -L -t nat

看看你的主机端口是否出现在那里。

看这里的解释:

https://www.reddit.com/r/kubernetes/comments/kne734/help_demystify_hostport_networking_please/