iptables ping svc svcip
1 |
iptables模式下,无法ping通任何svc,包括clusterip. 所有ns下, 下面来分析原因 |
查看k8s网络模式
1 2 3 4 |
curl 127.0.0.1:10249/proxyMode [root@k8s-master01 ~]# curl 127.0.0.1:10249/proxyMode iptables |
可以看到当前我的网络模式是 iptables
那么当应用程序通过服务连接到另一个应用程序时,将发生以下事件:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
1.应用程序使用集群DNS将服务名称解析为ClusterIP(虚拟IP)和端口 例如将:redis.elk:6379 解析为 10.0.0.144:6379 2.应用程序将连接请求发送给特定端口(10.0.0.144:6379)ClusterIP 3.由于ClusterIP位于没有路由的特殊网络上,因此请求将转到默认网关 4.请求发送到集群节点的默认网关时,由节点内核处理 5.将所有集群节点配置为,捕获服务正在使用的端口6379上进入ClusterIP地址的请求 6.trap导致数据包头被重写,以便将请求重定向到特定的Pod 7.Pod接收流量并服务请求 |
问题在于,当请求前往svc服务中定义的端口上的ClusterIP时,才会发生trap。无法将ping流量发送到特定端口,因此永远不会发生trap。
why?
1 |
因为ping基于ICMP ,ICMP不能在TCP/UDP上运行,因此没有TCP/UDP端口的概念。因此,无法在配置为侦听和trap的服务的端口上使用ping。 |
为什么nc 探测是成功的?
1 |
nc 默认是基于tcp, nc -u 是基于udp 所以他探测的协议是tcp/udp 所以是可以探测成功的。 |
为什么开发语言同样可以连接成功?
以php为例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?php $redis = new Redis(); $redis->connect('blog-redis.elk', 6379); $count = $redis->exists('count') ? $redis->get('count') : 1; echo $count; //$ret = $redis->auth('junyi'); var_dump($redis->ping()); $redis->set('count', ++$count); ?> |

1 2 |
可以看到开发语言同样可以在iptables模式下使用 svc.nc 的方式连接成功,为什么? 是php连接redis是通过TCP协议形式的Socket连接。 |
为什么iptables模式下无法ping通svc? 而ipvs模式可以?
我们来查看下iptables模式下kube-proxy的iptables转发规则
查看filter:
1 |
iptables -L -n -t filter |

iptable默认策略为拒绝任何icmp端口
1 2 |
REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable |
除非你手动打开让其支持icmp协议才可以ping通
IPVS
而IPVS中的ICMP报文处理-由外到内,默认是支持的,所以可以ping通
详细可以看这里这位大佬分析的很透彻 跳转
- 本文固定链接: https://www.yoyoask.com/?p=4742
- 转载请注明: shooter 于 SHOOTER 发表