为什么 HostPort 不显示在主机的 Netstat 输出中
Why Is HostPort Not Showing in The Outputs of Netstat from Host Machine
我使用 kubectl 和 yaml 文件创建目标 pod,发现 pod 中的进程按预期正在监听目标端口。
令我惊讶的是,在主机的 netstat -tunlp
或 netstat -alp
或 netstat -an
的输出中看不到该端口。但是如果我尝试 telnet localhost targetPort 就可以了!!!
为什么会这样??谁能解释一下?
为了访问工作节点上的服务,您必须使用 NodePort 类型的服务公开工作节点上的 pod。 pods 内的进程 运行 位于不同的网络命名空间中。您可以从 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
由于 pods 中的容器 运行 在它们自己的网络命名空间中,因此 netstat
无法检测到它们。
要列出在容器内侦听的端口,请使用 nsenter
。该工具将帮助您在进程的不同命名空间(在我们的例子中是所需容器的 PID)上执行命令。
- 获取容器的 PID - SSH 到 K8s 工作节点和 运行
docker inspect <containerid>
(如果 docker 是你的容器 运行time)
并且,从上面的命令 运行
获取 PID 后
$ nsenter -t <container-PID> -n netstat -nltp
这是因为docker
。默认情况下 docker 不会将容器网络名称空间添加到 linux 运行 时间数据(/var/run 从 /运行 挂载为 tmpfs),这就是您所看到的当你 运行 ip netns
命令时。
要查看您需要使用的网络命名空间 nsenter
。
- 获取容器 ID。
docker ps
- 获取容器进程 ID。
docker inspect --format '{{ .State.Pid }}' <<container-id>>
- 现在使用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/
我使用 kubectl 和 yaml 文件创建目标 pod,发现 pod 中的进程按预期正在监听目标端口。
令我惊讶的是,在主机的 netstat -tunlp
或 netstat -alp
或 netstat -an
的输出中看不到该端口。但是如果我尝试 telnet localhost targetPort 就可以了!!!
为什么会这样??谁能解释一下?
为了访问工作节点上的服务,您必须使用 NodePort 类型的服务公开工作节点上的 pod。 pods 内的进程 运行 位于不同的网络命名空间中。您可以从 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
由于 pods 中的容器 运行 在它们自己的网络命名空间中,因此 netstat
无法检测到它们。
要列出在容器内侦听的端口,请使用 nsenter
。该工具将帮助您在进程的不同命名空间(在我们的例子中是所需容器的 PID)上执行命令。
- 获取容器的 PID - SSH 到 K8s 工作节点和 运行
docker inspect <containerid>
(如果 docker 是你的容器 运行time)
并且,从上面的命令 运行
获取 PID 后$ nsenter -t <container-PID> -n netstat -nltp
这是因为docker
。默认情况下 docker 不会将容器网络名称空间添加到 linux 运行 时间数据(/var/run 从 /运行 挂载为 tmpfs),这就是您所看到的当你 运行 ip netns
命令时。
要查看您需要使用的网络命名空间 nsenter
。
- 获取容器 ID。
docker ps
- 获取容器进程 ID。
docker inspect --format '{{ .State.Pid }}' <<container-id>>
- 现在使用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/