k8s kube-proxy 路由策略 IPVS 为什么iptables 更高效
环境
lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 24.04 LTS
Release: 24.04
Codename: noble
先说原理
- iptables 如果服务过多 或者pod 过多 就要则添加海量的iptabes规则
- iptables 使用的具体算法主要是线性搜索,也可以称为顺序搜索或顺序匹配算法
- 逐条匹配如果海量增加,查找效率大幅度下降
- 但是如果采用 ip_set 作为一个hash表 使用 目标 IP-目标端口-源 IP 可以位置确定唯一一个路由
- 在使用ipvs vip路由到真实的 real ip pod上 效率大幅度提升
开始实验 模拟两个pod 服务
- 添加三个网络命名空间 网桥、pod-x、pod-y
ip link add dev bridge_home type bridge
ip netns add netns_pod_x
ip netns add netns_pod_y
- 配置pod-x、pod-y命名空间DNS
mkdir -p /etc/netns/netns_pod_x && echo "nameserver 114.114.114.114" | tee -a /etc/netns/netns_pod_x/resolv.conf
mkdir -p /etc/netns/netns_pod_y && echo "nameserver 114.114.114.114" | tee -a /etc/netns/netns_pod_y/resolv.conf
- 启用pod-x、pod-y命名空间回环接口
ip netns exec netns_pod_x ip link set dev lo up
ip netns exec netns_pod_y ip link set dev lo up
- 添加网桥到网桥的命名空间
ip address add 10.0.0.1/24 dev bridge_home
- pod-x、pod-y 添加一对虚拟以太网接口
ip link add dev veth_pod_x type veth peer name veth_ns_pod_x
ip link add dev veth_pod_y type veth peer name veth_ns_pod_y
- 虚拟网口对端加入pod-x、pod-y所在命名空间
ip link set dev veth_ns_pod_x netns netns_pod_x
ip link set dev veth_ns_pod_y netns netns_pod_y
- 虚拟以太网接口接入到网桥上
ip link set dev veth_pod_x master bridge_home
ip link set dev veth_pod_y master bridge_home
- 启用pod-x、pod-y虚拟以太网接口
ip link set dev veth_pod_x up
ip link set dev veth_pod_y up
ip netns exec netns_pod_x ip link set dev veth_ns_pod_x up
ip netns exec netns_pod_y ip link set dev veth_ns_pod_y up
- 配置pod-x、pod-y虚拟以太网接口IP
ip netns exec netns_pod_x ip address add 10.0.0.11/24 dev veth_ns_pod_x
ip netns exec netns_pod_y ip address add 10.0.0.21/24 dev veth_ns_pod_y
- 启用网桥
ip link set bridge_home up
- 添加pod-x、pod-y命名空间默认路由
ip netns exec netns_pod_x ip route add default via 10.0.0.1
ip netns exec netns_pod_y ip route add default via 10.0.0.1
- 允许通过 在过滤器表(filter table)中,数据包转发(FORWARD)时可以进出进入桥接设备
iptables --table filter --append FORWARD --in-interface bridge_home --jump ACCEPT
iptables --table filter --append FORWARD --out-interface bridge_home --jump ACCEPT
- 将源地址10.0.0.0/24进行伪装 ,在NAT 表中,添加此规则规则
iptables --table nat --append POSTROUTING --source 10.0.0.0/24 --jump MASQUERADE
- 开启两个终端,前台模式模拟 pod-x、pod-y的服务 服务运行时不要关闭终端
ip netns exec netns_pod_x python3 -m http.server 8080
ip netns exec netns_pod_y python3 -m http.server 8080
测试宿主机 、 pod-x、pod-y命名空间测试 pod-x、pod-y上的模拟服务
curl 10.0.0.11:8080
curl 10.0.0.21:8080
ip netns exec netns_pod_x curl 10.0.0.21:8080
ip netns exec netns_pod_y curl 10.0.0.11:8080
主角登场 ipvs
- install
apt install ipset ipvsadm bridge-utils --yes
- 转发 pod-x上的模拟服务
ipvsadm --add-service --tcp-service 10.100.100.100:8080 --scheduler rr
ipvsadm --add-server --tcp-service 10.100.100.100:8080 --real-server 10.0.0.11:8080 --masquerading
- 测试效果
curl 10.100.100.100:8080
- 模拟 pod-y 内部的受限制的命名空间内访问模拟服务 fail...
ip netns exec netns_pod_y curl 10.100.100.100:8080
pod 内无法访问其他服务 处理办法 一 虚拟网络接口Hairpin模式
- 创建虚拟dummy 接口,它提供路由数据包的功能不提供转发功能
ip link add dev dustin-ipvs0 type dummy
- 配置虚拟静默网口分配IP
ip addr add 10.100.100.100/32 dev dustin-ipvs0
- 允许 iptables 处理通过桥接接口的数据包
modprobe br_netfilter && sysctl --write net.bridge.bridge-nf-call-iptables=1
- 测试 netns_pod_y ok
ip netns exec netns_pod_y curl 10.100.100.100:8080
- 测试 netns_pod_x fail.....
ip netns exec netns_pod_x curl 10.100.100.100:8080
- 失败原因 因为网络 pod_x、 pod_y 、bridge_home 之间是二层转发 相同网段的直接走二层
- ipvs 通过iptables转发时,iptables是三层 、所以开启混杂模式、无论什么数据包都转发、不验证MAC地址
sysctl --write net.ipv4.vs.conntrack=1
ip link set bridge_home promisc on
- 关闭 hairpin
brctl hairpin bridge_home veth_dustin off
- 再次测试后 测试 netns_pod_x ok
ip netns exec netns_pod_x curl 10.100.100.100:8080
pod 内无法访问其他服务 处理办法 二 开启网桥混杂模式
- 每次都使用pod 一个 iptables 规则做对源地址做NAT 显然是不可以接受的
- 同样每次对网口使用hairpin 也是不合适的
- 使用 ipset
ipset create DUSTIN-LOOP-BACK hash:ip,port,ip
- 添加转发到IP_set
iptables --table nat --append POSTROUTING --match set --match-set DUSTIN-LOOP-BACK dst,dst,src --jump MASQUERADE
- 添加 netns_pod_y 规则到ipset
ipset add DUSTIN-LOOP-BACK 10.0.0.11,tcp:8080,10.0.0.11
- 再次 宿主机、pod_x、pod_y ok
curl 10.100.100.100:8080
ip netns exec netns_pod_x curl 10.100.100.100:8080
ip netns exec netns_pod_y curl 10.100.100.100:8080
后续其他pod 只需添加 ipvs 和ipset 即可
- ipvs
ipvsadm --add-server --tcp-service 10.100.100.100:8080 --real-server 10.0.0.21:8080 --masquerading
- ip-set
ipset add DUSTIN-LOOP-BACK 10.0.0.21,tcp:8080,10.0.0.21
查看ipvs转发策略
本文来自博客园,作者:vx_guanchaoguo0,转载请注明原文链接:https://www.cnblogs.com/guanchaoguo/p/18163856