1. 路由的区别
当把 eth0 网卡 v4 IP 地址删除的时候,v4 的路由应该是不存在的,但是,当把 eth0 网卡 v6 IP 地址删除的时候,v6 的路由依然是存在的。
2. 默认路由以及网卡地址获取的区别
v4 默认路由以及地址获取可以简单通过一个 dhclient -4 eth0 实现,但是这一点,在 v6 场景,完全做不到。
在 v6 场景,网关和地址需要基于两个步骤。
ipv6 场景,在虚拟机启动的时候,会基于 mac 生成一个 fe80 开头的 link-local 的地址,该地址应该只能在同一个物理交换机内部使用,它的网关是 fe80:::1。
link-local 地址和 ipv4 的 loopback 地址不一样,loopback 只能在 node 上使用,而 link-local 地址的域是指该机器所连接到的交换机。link-local 可以看做一个专用的私网地址。
ipv6 场景中,虚拟机一旦创建就有一个私网地址。
那么提出一个问题,虚拟机的网关如何拿到? 虚拟机的公网地址如何获取?
按照 dhcp v4 的使用场景,一个 dhclient -4 eth0 实现,
但是在 v6 场景中,完全没有做到这么简单。
第一: ipv6场景,如何拿到默认路由的网关,网关是什么?
网关是 fe80:::1。 服务器需要通过交换机 RA(router advertisement)报文才能拿到网关。 在 SDN 场景,如果该报文被安全组限制丢了,那么该报文就拿不到,虚拟机就拿不到网关。
第二:该报文是谁处理的?
一开始我认为这个起码应该是操作系统处理吧,毕竟涉及包的解析,感觉和协议栈很有关系。
但是,实际测试发现,这个包的处理竟然是由是由 NetworkManager 来实现的:
我们做了一个实验,如果关闭 NetworkManager 服务。即使虚拟机收到 RA 报文,那么该网关也无法被处理,即最终在 ip route -6 查看,看不到路由。
如果没有 NetworkManager 服务,不单没有默认 via fe80:::1 的路由。即使手动执行 dhclient -6 eth0,也拿不到公网 IPv6 地址。
存疑:
一开始,我们定位问题的时候,认为是交换机没有开启 ipv6 RA 报文,但是当时基于 dhclient -6 eth0 是可以成功拿到 ipv6 公网地址的。
后续,也确实证明,交换机确实没有开 ipv6 RA,开启之后,只要重启一下 NetworkManager ,可以确保 ipv6 公网地址和 link-local 的默认路由确实是都具备的。
小结: dhclient -6 eth0 能拿到 ipv6 公网地址 和 NetworkManager 能拿到网关是互相独立的,但是 NetworkManager 会确认能拿到网关之后,才会调用 dhclient -6 eth0 ,这种先后逻辑的设计,才导致地址没有拿到。
另一种可能的解决方式:
交换机根本不用开 ipv6 RA, 虚拟机内部用 cloud init 配 link-local 路由,然后只用 NetworkManager 调 dhclient -6 eth0 能拿到 ipv6 公网地址即可。
其他
虚拟机网卡配置文件都是基于dhcp的,cloud-init 是通过 NetworkManager 的 dhcp 功能来获取ip地址以及路由的。
总结:
ipv6 相比于 ipv4, ipv6 dhcp 服务把网关和 ip 地址获取分开的功能分开的实现,感觉功能没那么内聚了。
在 cloudinit 阶段就会配置好 fe80 link-local 地址
仅能成功拿到 v4 地址
cloud-init 是基于 NetworkManager 服务调用 dhcp client 的
dhcp 相关的配置目录
nm 查看 网卡
这个虚拟机所在的子网和网关信息
虚拟机正常拿到 ip 之后的信息
虚拟机正常后的路由信息
ip addr flush 之后,地址不存在, v6 路由确实还在
对比 kubeovn pod v6 路由使用方式
对比其他环境 vlan underlay pod v6 ip 以及路由
node02-netshoot:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
15089: eth0@if15090: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether be:71:89:90:3d:df brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.251.175.38/27 brd 10.251.175.63 scope global eth0
valid_lft forever preferred_lft forever
inet6 2409:8c20:1833:2000::afb:af39/123 scope global
valid_lft forever preferred_lft forever
inet6 fe80::bc71:89ff:fe90:3ddf/64 scope link
valid_lft forever preferred_lft forever
node02-netshoot:~#
node02-netshoot:~# ip -6 route
2409:8c20:1833:2000::afb:af20/123 dev eth0 proto kernel metric 256 pref medium
fe80::/64 dev eth0 proto kernel metric 256 pref medium
default via 2409:8c20:1833:2000::afb:af3e dev eth0 metric 1024 pref medium
default via fe80::1 dev eth0 proto ra metric 1024 expires 1703sec hoplimit 64 pref medium
node02-netshoot:~#
可以看到 默认路由 default via 有两条,而 fe80::1 那条路由看起来路由检测显示超时很久了,是无法使用的。
我目前认为 pod 的路由是最佳实践,和 ipv4 的使用方式是一致的。
而虚拟机的 v6 路由,是没有用真实的 v6 网关作为默认路由的下一跳的。