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转发策略

posted @ 2024-04-28 15:43  vx_guanchaoguo0  阅读(91)  评论(0编辑  收藏  举报