其他
使用 iptables 将 Kubernetes Service 流量随机发送到 Pod
本文将带大家了解 Kubernetes 的 kube-proxy 组件如何使用 iptables 将 service 流量随机发送到 Pod,目的是实现 service 所需的 iptables 规则。
注意:本文仅适用于 Linux。我使用的是 Ubuntu 19.10,但在其他 Linux 发行版上应该也可以使用。
创建一个虚拟网桥(名为 bridge_home
);创建两个网络命名空间(分别名为 netns_dustin
和netns_leah
);在网络命名空间中为 DNS 配置 8.8.8.8
;创建连接到 bridge_home
的两个 veth 对;将 10.0.0.11
分配给在netns_dustin
中运行的 veth;将 10.0.0.21
分配给在netns_leah
中运行的 veth;在网络命名空间中设置默认路由。
bridge_home
设备:netns_dustin
网络命名空间中启动一个 HTTP 服务器:netns_leah
网络命名空间中启动 HTTP 服务器:注意:你的 IP 地址可能不是 192.168.0.100,接口的名称可能也不是 enp4s0。
DUSTIN_SERVICE
的新链:PREROUTING
和 OUTPUT
链通过以下方式查看 DUSTIN-SERVICES
链:DUSTIN-SERVICES
链中创建一个规则来处理虚拟 IP。我们的虚拟 IP 为 10.100.100.100
。让我们创建一个规则,将 10.100.100.100:8080
的流量定向到 10.0.0.11:8080
。回想一下,10.0.0.11:8080
是在 netns_dustin
命名空间中运行的 python HTTP 服务器。netns_dustin
请求虚拟 IP 地址。net.bridge.bridge-nf-call-iptables
的设置,会将网桥配置为在处理流量时考虑 iptables。这还会导致一个问题:请求离开的设备同时也是被定向的设备。这恰好是上一个命令中遇到的情况!veth_dustin
,该请求的源 IP 地址为 10.0.0.11
。该请求的目的地是 10.100.100.100
。然后,iptables 规则在 10.100.100.100
到 10.0.0.11
上执行 DNAT。问题发生了:该请求需要定向到发出请求的地方!net.bridge.bridge-nf-call-iptable
是否已启用:br_netfilter
模块。之后再次运行 sysctl net.bridge.bridge-nf-call-iptables
。net.bridge.bridge-nf-call-iptables
已启用(输出 1)。如果出于某种原因将其禁用了(0),请运行以下命令:bridge_home 的 veth_dustin
上启用 Hairpin 模式。该模式允许离开设备的请求可被同一设备接收。有趣的事实: veth_dustin
被称为bridge_home
上的端口。类似于将物理以太网电缆插入物理网桥的端口,另一端插入物理计算机。
veth_dustin
上启用 Hairpin 模式:bridge_home
上启用 promiscuous mode:veth_leah
)上启用 Hairpin 模式!10.0.0.11
)的 service(10.100.100.100
)。我们在名为 DUSTIN-SERVICES
的链中创建了此规则,该链的名称与 kube-proxy 的 KUBERNETES-SERVICES
相似。kube-proxy 为每个 service 创建一个链,并使 KUBERNETES-SERVICES
根据目的地跳转到相应的服务链。DUSTIN-SVC-HTTP
链中添加一条规则,该规则将流量定向到后端(10.0.0.11
):DUSTIN-SERVICES
使用 DUSTIN-SVC-HTTP
链。通过以下方式删除在 DUSTIN-SERVICES
中创建的上一条规则:DUSTIN-SERVICES
中添加一条规则,通过以下方式跳转到匹配目标位置上的 DUSTIN-SVC-HTTP
:为 service 创建一个新链,例如 DUSTIN-SVC-HTTP
;在 service 链中创建一条规则以将流量定向到后端,例如 10.0.0.11
;向 DUSTIN-SERVICES
添加一条规则以跳至 service 链,例如DUSTIN-SVC-HTT
。
DUSTIN-SERVICES
链重构为跳转到单个服务链。现在可以重构 service 链(DUSTIN-SVC-HTTP
),以跳转到其他链来将流量定向到后端。注意:这里一直使用“后端”一词,但是在 Kubernetes 中这些也称为端点(endpoint)。通常,端点是容器的 IP 地址。
10.0.0.11
端点创建一个新链。kube-proxy 仍然会为这些链名使用哈希,但是我们将创建一个名为 DUSTIN-SEP-HTTP1
的链,代表 HTTP 的第一个服务端点(SEP)。通过以下方式创建新链:DUSTIN-SEP-HTTP1
链添加一个看起来很熟悉的规则:DUSTIN-SVC-HTTP
的规则,并在 DUSTIN-SVC-HTTP
中添加一条规则以跳至 DUSTIN-SEP-HTTP1
:netns_leah
网络命名空间中运行的第二个 HTTP 后端(10.0.0.21
)添加新的链和规则:DUSTIN-SVC-HTTP
链中添加另一个规则,以随机跳转到刚创建的 DUSTIN-SEP-HTTP2
链。可以通过运行以下命令添加此规则:DUSTIN-SVC-HTTP
链中把此规则插到了首位。iptables 会按顺序尝试规则。因此,这个规则在首位的话,我们就有 50% 的机会跳到该链上。如果成功,iptables 将跳至 DUSTIN-SEP-HTTP2
。如果失败,iptables 将转到下一条规则,该规则将始终跳转到 DUSTIN-SEP-HTTP1
。iptables 查看第一个规则(跳转至 DUSTIN-SEP-HTTP2
),假设失败了;iptables 查看下一条规则(跳转至 DUSTIN-SEP-HTTP1
),假设也失败了;现在,我们的虚拟 IP 不会定向到任何后端!因此,概率是基于剩余可选择的后端数量的。如果要插入第三个后端,则该规则的概率为 33%。
netns_leah
和 netns_dustin
网络命名空间中的 python HTTP 服务器。这样我们算是通过 iptables 来进行负载均衡了!文章来源:K8sMeetup社区
译者:Sarah
原文链接:http://mtw.so/5QwkHd
- END -
推荐阅读
不用Docker也能构建容器的4种方法
Kubernetes 证书默认1年过期时间修改
60道常见的 Kubernetes 面试题总结
Kubernetes 集群灾备环境部署
Kubernetes Ingress-Nginx实现蓝绿、灰度发布
订阅,一起成长
K8s生态圈
点在看,K8s一年不出问题👇