参考资料:

《Kubernetes 网络模型基础指南》
https://mp.weixin.qq.com/s/7yJE7W0nuxnT4XPst1Q5FA

容器网络
K8S网络

Service

Service 是由 kube-proxy 组件,加上 iptables 来共同实现的

举个例子,对于我们前面创建的名叫 hostnames 的 Service 来说,一旦它被提交给 Kubernetes,那么 kube-proxy 就可以通过 Service 的 Informer 感知到这样一个 Service 对象的添加。
而作为对这个事件的响应,它就会在宿主机上创建这样一条 iptables 规则(你可以通过 iptables-save 看到它),如下所示:

  1. -A KUBE-SERVICES -d 10.0.1.175/32 -p tcp -m comment --comment "default/hostnames: cluster IP" -m tcp --dport 80 -j KUBE-SVC-NWV5X2332I4OT4T3

可以看到,这条 iptables 规则的含义是:凡是目的地址是 10.0.1.175、目的端口是 80 的 IP 包,都应该跳转到另外一条名叫 KUBE-SVC-NWV5X2332I4OT4T3 的 iptables 链进行处理。
而我们前面已经看到,10.0.1.175 正是这个 Service 的 VIP。所以这一条规则,就为这个 Service 设置了一个固定的入口地址。并且,由于 10.0.1.175 只是一条 iptables 规则上的配置,并没有真正的网络设备,所以你 ping 这个地址,是不会有任何响应的。

Kubernetes 的 kube-proxy 还支持一种叫作 IPVS 的模式

kube-proxy 通过 iptables 处理 Service 的过程,其实需要在宿主机上设置相当多的 iptables 规则。而且,kube-proxy 还需要在控制循环里不断地刷新这些规则来确保它们始终是正确的。
不难想到,当你的宿主机上有大量 Pod 的时候,成百上千条 iptables 规则不断地被刷新,会大量占用该宿主机的 CPU 资源,甚至会让宿主机“卡”在这个过程中。所以说,一直以来,基于 iptables 的 Service 实现,都是制约 Kubernetes 项目承载更多量级的 Pod 的主要障碍。
而 IPVS 模式的 Service,就是解决这个问题的一个行之有效的方法。

相比于 iptables,IPVS 在内核中的实现其实也是基于 Netfilter 的 NAT 模式,所以在转发这一层上,理论上 IPVS 并没有显著的性能提升。但是,IPVS 并不需要在宿主机上为每个 Pod 设置 iptables 规则,而是把对这些“规则”的处理放到了内核态,从而极大地降低了维护这些规则的代价。

在大规模集群里,我非常建议你为 kube-proxy 设置–proxy-mode=ipvs 来开启这个功能。它为 Kubernetes 集群规模带来的提升,还是非常巨大的。

ClusterIP 模式的 Service 为你提供的,就是一个 Pod 的稳定的 IP 地址,即 VIP。并且,这里 Pod 和 Service 的关系是可以通过 Label 确定的。
而 Headless Service 为你提供的,则是一个 Pod 的稳定的 DNS 名字,并且,这个名字是可以通过 Pod 名字和 Service 名字拼接出来的。

在理解了 Kubernetes Service 机制的工作原理之后,很多与 Service 相关的问题,其实都可以通过分析 Service 在宿主机上对应的 iptables 规则(或者 IPVS 配置)得到解决。

比如,当你的 Service 没办法通过 DNS 访问到的时候。你就需要区分到底是 Service 本身的配置问题,还是集群的 DNS 出了问题。一个行之有效的方法,就是检查 Kubernetes 自己的 Master 节点的 Service DNS 是否正常

  1. # 在一个Pod里执行
  2. $ nslookup kubernetes.default
  3. Server: 10.0.0.10
  4. Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
  5. Name: kubernetes.default
  6. Address 1: 10.0.0.1 kubernetes.default.svc.cluster.local

如果上面访问 kubernetes.default 返回的值都有问题,那你就需要检查 kube-dns 的运行状态和日志了。否则的话,你应该去检查自己的 Service 定义是不是有问题。