关于云服务:跨主机的pod之间是如何通信的

48次阅读

共计 4964 个字符,预计需要花费 13 分钟才能阅读完成。

微信公众号:LinuGo,欢送关注

Pod 是怎么找到申请的 Pod 的,pod 之间又是怎么负载平衡的(iptables 模式下)

想晓得这个问题,首先须要理解一些 iptables 常识。

iptables 常识

五条链

iptables 是 linux 内核集成的 IP 信息过滤规定,负责将发往主机的网络包进行散发,转换等。当客户端申请服务器的某个服务时,申请信息会先通过网卡进入服务器内核,这时 iptables 会对包进行过滤,决定这些包是发往用户态的服务过程或是转发进来到别的主机。而决定这些门路的形式在 iptables 中称为链,刚进入内核的申请流会通过 PREROUTING 链,依据路由规定判断是是不是发往本机申请,是则走 INPUT 链进入本机用户态过程,否则会走 FORWARD 链并匹配对应的规定最初流出本机;如果是本机收回的申请会走 OUTPUT 链并进一步到 POSTROUTINE 链流出本机,或转发到其余机器或回复信息给客户端。

总结上述几条链:

  • PREROUTINE:流入本机路由前
  • POSTROUTINE:流出本机路由前
  • FORWARD:转发门路
  • OUTPUT:由本机用户程序收回的
  • INPUT:发送至本机用户程序的

两个动作

SNAT

源地址转换,是指将报文发送方的 ip 地址转换,这样当相应方回复申请时,回复的是发送方的地址。

示例了解

当 client 发送申请给 server 时,须要通过 gateway,如果 gateway 不对包进行源地址转换 (SNAT),发往 server 的网络包携带的源地址仍然是 client,server 会对该源地址响应,但 client 并不辨认 server 的地址,会导致该条申请呈现谬误。

DNAT

指标地址转换,是将报文的指标地址转换,起到申请转发到别的目的地的作用。

k8s 基础知识

上面理解 k8s 中的几种 IP 类型。

虚构 IP

虚 IP(下文称 VIP) 有 ClusterIP(即 serviceIP),是集群本人生成的,ping 不通,并和 PodIP 不处于同一网段,防止申请产生凌乱。当创立一个 service 时,k8s 会为该 service 指派一个 IP 地址,并会被集群中的所有 kube-proxy 察看到,kube-proxy 从而会装置一系列的 iptables 规定到宿主机,kube-dns 也会相应的插入一条域名解析 IP 的规定。申请到来的时候,如果合乎规定,iptables 会将 VIP 转化为理论的 IP 并应用。

理论 IP

实 IP 别离有 PodIP 等,该 IP 是由 CNI 插件调配的,在 k8s 集群启动时候,须要装置 CNI 插件,通常是一个 DaemonSet 控制器管制,保障每台节点都有该过程。他的作用是在集群外部产生一套网络,并给每个 pod 插上”网线”,保障 pod 与节点,pod 与 pod 是互通的。

Pod 之间通信的形式能够通过理论的 PodIP,然而该 IP 会随着 pod 的变动而变动,不适宜用该形式,也能够通过 ClusterIP 的形式通信,比较稳定,然而不容易被记住,还能够通过 svc.ns 这种域名的格局,该办法申请 kube-dns 域名解析失去域名对应的 IP。


案例学习

接下来依据一个案例探讨一下。

案例介绍

  • 集群中有两个 gateway-pod,service 类型为 NodePort,裸露端口给集群内部,接管外界申请并负载平衡,并将申请转发到上游 pod。
  • 有一个 basedao pod,负责接管 gateway pod 发来的申请并响应,对应的 service 名称是 sts-basedao,命名空间名称是 basedao。
  • Kube-dns pod 将域名解析成 IP 地址,并返回给发送方。

查看一下各个 pod 的 IP,该 IP 是理论的 IP。

[centos@guozhao-50 ~]$ kubectl get pod --all-namespaces -owide
NAMESPACE     NAME                                IP                    
basedao       sts-basedao-0                      10.34.0.2
gateway       sts-gateway-59d5fdbc54-4d6kv       10.40.0.0
gateway       sts-gateway-59d5fdbc54-dmncq       10.34.0.1 
kube-system   coredns-6c76c8bb89-kztxk           10.32.0.4

查看一下三种 pod 对应 service 的 IP,能够看到 gateway service 代理的 30001 端口映射到了内部的 31001 端口。

[centos@guozhao-50 ~]$ kubectl get svc --all-namespaces
NAMESPACE     NAME                   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                  AGE
basedao       svc-basedao            ClusterIP   10.111.143.223   <none>        30003/TCP                70m
gateway       svc-gateway            NodePort    10.102.103.1     <none>        30001:31001/TCP          70m
kube-system   kube-dns               ClusterIP   10.96.0.10       <none>        53/UDP,53/TCP,9153/TCP   14d 

1.client 发动申请

通过 iptables-save 命令能够查看到所有的 iptables 规定。

当 client 发动申请时,会申请服务器对应的端口,对应 NodePort 端口,咱们来查看对应的 iptables 规定,会通过 PREROUTING,跳转到 KUBE-SERVICES 规定。

-A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES

在 KUBE-SERVICE 中找到合乎的规定,–dst-type LOCAL 代表本地,会持续跳转到 KUBE-NODEPORTS

-A KUBE-SERVICES -m comment --comment "kubernetes service nodeports; NOTE: this must be the last rule in this chain" -m addrtype --dst-type LOCAL -j KUBE-NODEPORTS

该申请会跳转到 KUBE-MARK-MASQ 给申请打一个标签,并跳转到下一条规定 KUBE-SVC-4QJQIYWH2AWK2TSA。

-A KUBE-NODEPORTS -p tcp -m comment --comment "gateway/svc-gateway:gateway-port" -m tcp --dport 31001 -j KUBE-MARK-MASQ
-A KUBE-NODEPORTS -p tcp -m comment --comment "gateway/svc-gateway:gateway-port" -m tcp --dport 31001 -j KUBE-SVC-4QJQIYWH2AWK2TSA

负载平衡

追随上条规定有两条规定与其对应,–probability 0.50000000000 代表有 0.5 的概率进入下面的规定,如果没有进入下面规定,就会进入上面的规定,负载平衡也就是在 iptables 层面实现的。

-A KUBE-SVC-4QJQIYWH2AWK2TSA -m comment --comment "gateway/svc-gateway:gateway-port" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-XEQTQPKSTZECBET2
-A KUBE-SVC-4QJQIYWH2AWK2TSA -m comment --comment "gateway/svc-gateway:gateway-port" -j KUBE-SEP-OCFEUGRRJNZZEOHZ

别离查看两个规定对应的下一条规定,该规定指定了指标地址,执行了 DNAT 操作进行指标地址转发,别离对应了两个 pod 实例的理论 IP 地址,申请会追随这条规定转发到理论的 gateway。

-A KUBE-SEP-XEQTQPKSTZECBET2 -p tcp -m comment --comment "gateway/svc-gateway:gateway-port" -m tcp -j DNAT --to-destination 10.34.0.1:30001
-A KUBE-SEP-OCFEUGRRJNZZEOHZ -p tcp -m comment --comment "gateway/svc-gateway:gateway-port" -m tcp -j DNAT --to-destination 10.40.0.0:30001

在最终发出请求之前会走 POSTROUTING 链,会对该申请做一个 SNAT 操作,MASQUERADE 代表执行了 SNAT 操作批改了申请源地址。

-A POSTROUTING -m comment --comment "kubernetes postrouting rules" -j KUBE-POSTROUTING
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE

2.gateway 发动申请

此时 gateway 收到了来自 client 的申请,他会向 basedao 发动申请,申请形式是通过域名即 sts-basedao.basedao:30002 格局。该申请会发送给 dns 服务器进行解析返回一个理论 IP 地址,当然,该地址也是一个 VIP。

在 pod 被创立时候,就会在 pod 中创立 dns 服务配置文件,nameserver 代表 dns 服务器的 IP 地址,默认是集群中的 kube-dns 地址,search 代表域名拼接规定。能够看出,该地址和 kube-dns 的 VIP 是雷同的。

接下来该 pod 会发出请求到 kube-dns 的 VIP

因为是在主机上收回,会走 OUTPUT 链,进而进入到 KUBE-SERVICES

-A OUTPUT -m comment --comment "kubernetes service portals" -j KUBE-SERVICES

满足 KUBE-SERVICES 的该条规定,持续跳转到 KUBE-SVC-ERIFXISQEP7F7OF4,再次跳转到 KUBE-SEP-ZT5TVM6PMFDFQAMO。

-A KUBE-SERVICES -d 10.96.0.10/32 -p tcp -m comment --comment "kube-system/kube-dns:dns-tcp cluster IP" -m tcp --dport 53 -j KUBE-SVC-ERIFXISQEP7F7OF4
-A KUBE-SVC-ERIFXISQEP7F7OF4 -m comment --comment "kube-system/kube-dns:dns-tcp" -j KUBE-SEP-ZT5TVM6PMFDFQAMO

最终进行 DNAT 指标地址转发到 dns 理论的 pod,最终 dns 返回给 gateway 由域名解析到的 ip。

-A KUBE-SEP-ZT5TVM6PMFDFQAMO -p tcp -m comment --comment "kube-system/kube-dns:dns-tcp" -m tcp -j DNAT --to-destination 10.32.0.4:53

当 gateway 失去实在的 IP,该 IP 就是 basedao 的 VIP,gateway 会应用该 VIP 发动申请,仍然会对应到相应的 iptables 规定,实现 VIP 到 IP 的映射失去 basedao pod 的理论地址,并向理论地址发送数据包,这里便不再赘述。


总结

因为 Pod 的 IP 地址不是长久的,所以尽量倡议采纳 ClusterIP 或者域名的形式申请集群中的其余 pod,而这两种形式是通过 Linux 内核的 iptables 规定实现的。应用 iptables 规定也有毛病,当集群中有过多的服务 Pod,相应的各台宿主机 iptables 规定就会减少,这减少了网络的复杂度与跟踪难度,会给前期运维带来肯定的艰难。


参考文章

  • 《iptables 详解》http://www.zsythink.net/archives/1199
  • 《k8s 中文文档》https://v1-16.docs.kubernetes.io/zh/
  • 《深刻分析 Kubernetes》极客工夫

正文完
 0