ipv6 与 ipv4 在 dhcp 场景的区别

1,188 阅读5分钟

1. 路由的区别

当把 eth0 网卡 v4 IP 地址删除的时候,v4 的路由应该是不存在的,但是,当把 eth0 网卡 v6 IP 地址删除的时候,v6 的路由依然是存在的。

image.png

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地址以及路由的。

image.png

总结:

ipv6 相比于 ipv4, ipv6 dhcp 服务把网关和 ip 地址获取分开的功能分开的实现,感觉功能没那么内聚了。

在 cloudinit 阶段就会配置好 fe80 link-local 地址

image.png

仅能成功拿到 v4 地址

image.png

cloud-init 是基于 NetworkManager 服务调用 dhcp client 的

image.png

dhcp 相关的配置目录

image.png

nm 查看 网卡

image.png

这个虚拟机所在的子网和网关信息

image.png

虚拟机正常拿到 ip 之后的信息

image.png

虚拟机正常后的路由信息

image.png

image.png

ip addr flush 之后,地址不存在, v6 路由确实还在

image.png

对比 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 网关作为默认路由的下一跳的。