沈天真
作者沈天真2020-11-25 20:55
售前支持, IPS

K8S集群中某个worker节点上无法通过域名访问服务 ?

字数 2696阅读 6949评论 0赞 1

最近在K1 Power上和ISV进行测试,测试环境如下。

在一台服务器上,创建了3个虚拟机,在这3个虚拟机上部署了一个K8S集群,K8S版本是 1.14 。

当ISV把服务都部署上去后,发现在 cn01 节点上的一个容器内部,无法直接通过服务的域名访问运行在同样在cn01节点上,但是运行在另外一个容器中的服务。然而在cn02节点上,进行类似的测试,发现是可以通过域名访问的,所以这个问题比较奇怪。经过一番搜索,发现问题的原因, 是因为在 cn01 节点上没有启动 bridge-nf-call-iptables,由于cn01 安装的是 Centos 7.5 ,所以在 /etc/sysctl.conf 中设置

net.bridge.bridge-nf-call-iptables = 1

设置之后,果然问题解决了。当然,查看了 cn02 的配置,发现 cn02 上面果然已经是1。

问题虽然解决,但是这个值的设置为什么会影响域名访问呢 ? 在网上找到了这么一段话。

『I can't say for certain on your network/system. But I do know that k8s installer tools such as kubeadm will warn you if for example net.bridge.bridge-nf-call-iptables is not set to 1 when initializing the cluster. This is, based on my weak understanding, required to allow bridged packets to traverse iptables rules. In k8s the Cluster IPs "exist" only as a set of iptables forwarding rules, that forward packets to the pod ips. Without it set, it seems that the returning packets don’t get routed through the iptables rules, and therefore their source IPs are not changed.』

翻译过来就是『虽然我不太确认你的网络/系统。但是我确实知道一些K8S安装工具,例如 kubeadm 在初始化集群时会给出警告,如果你没有设置 net.bridge.bridge-nf-call-iptables 的值为1。要求这样做,基于我的肤浅理解,是允许桥接的数据包能够遍历iptables rules 的前提。在K8S集群中,Cluster IP地址 ”仅仅” 是作为iptables的转发规则存在的,这些转发规则把数据包送到对应的pod上。如果不设置这个值,那么pod返回的数据包就不会遍历iptables rules,所以他们的源IP地址就没有改变(NAT就不起作用了)。』

这就引申出来,还是要理解K8S集群中 Node IP,Service IP 和 Pod IP 的概念。

Node IP:Node节点的IP地址,即物理网卡的IP地址。

Pod IP:Pod的IP地址,即docker容器的IP地址,此为虚拟IP地址。

Cluster IP:Service的IP地址,此为虚拟IP地址。

Node IP

可以是物理机的IP(也可能是虚拟机IP)。每个Service都会在Node节点上开通一个端口,外部可以通过外部可以通过NodeIP:NodePort即可访问Service里的Pod,和我们访问服务器部署的项目一样,IP:端口/项目名。

在Kubernetes查询Node IP

1.kubectl get nodes。

2.kubectl describe node #nodeName。

3.显示出来的InternalIP就是Node IP。

Pod IP

Pod IP是每个Pod的IP地址,他是Docker Engine根据docker网桥的IP地址段进行分配的,通常是一个虚拟的二层网络。

同Service下的pod可以直接根据Pod IP相互通信

不同Service下的pod在集群间pod通信要借助于 Cluster IP

pod和集群外通信,要借助于Node IP

在Kubernetes查询Pod IP

1.kubectl get pods

2.kubectl describe pod #podName

Cluster IP

Service的IP地址,此为虚拟IP地址。外部网络无法ping通,只有Kubernetes集群内部访问使用。

在Kubernetes查询Cluster IP

kubectl -n 命名空间 get Service即可看到Cluster IP。

Cluster IP是一个虚拟的IP,但更像是一个伪造的IP网络,原因有以下几点

Cluster IP仅仅作用于Kubernetes Service这个对象,并由Kubernetes管理和分配P地址。

Cluster IP无法被ping,他没有一个“实体网络对象”来响应

Cluster IP只能结合Service Port组成一个具体的通信端口,单独的Cluster IP不具备通信的基础,并且他们属于Kubernetes集群这样一个封闭的空间。

在不同Service下的pod节点在集群间相互访问可以通过Cluster IP。

Cluster IP是由kube-proxy使用iptables规则重新定向到其本地端口,再均衡到后端Pod的。Cluster IP从service-cluster-ip-range参数指定的地址池中分配,比如–service-cluster-ip-range=10.0.0.0/16。假设这个service的端口是1234。集群内的所有kube-proxy都会注意到这个Service。当kube-proxy发现一个新的service后,它会在本地节点打开一个任意端口,建相应的iptables规则,重定向服务的IP和port到这个新建的端口,开始接受到达这个服务的连接。

当一个客户端访问这个service时,这些iptables规则就开始起作用,客户端的流量被重定向到kube-proxy为这个service打开的端口上,kube-proxy随机选择一个后端pod来服务客户。这个流程如下图所示。

如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

1

添加新评论0 条评论

Ctrl+Enter 发表

作者其他文章

相关文章

相关问题

相关资料

X社区推广