介绍
DMIT(以及不少通过 cloud-init 开机、用 RA 下发 IPv6 网关的商家)的 IPv6 有个典型的坑:默认 auto 模式本身一直正常,但只要把它改成手动静态——地址写死、网关(fe80:: 开头的 link-local 地址)也写死——就会”一开始能用、过段时间失效”:IPv6 不通了,重新把网关填一遍又恢复,长期这么用每次都要手动救。
这篇教程讲清静态网关方案为什么会失效,并给出长期使用最稳的推荐配置(三件套):IPv6 地址静态固定、默认路由交给 RA 自动维护——即”静态的地址 + 活的网关”。文末附完整的取消步骤,可随时恢复 DMIT 出厂默认。两套流程互为逆操作、无残留,适用于 DMIT 全部机器,其他同类架构的商家也通用(系统以 Debian / Ubuntu 的 ifupdown 配置为例)。

为什么静态 IPv6 会过段时间失效
1. 写死的网关不会自动维护,也没有自愈机制
DMIT 的 IPv6 网关是 fe80:: 开头的 link-local 地址,由上游路由器通过 RA(Router Advertisement,路由器通告)持续通告、自动刷新:auto 模式下内核跟着 RA 走,网关换了、路由状态变了都能自动跟随(默认路由带 expires,周期性从 RA 续期)。把地址和网关都写成静态之后,网关就靠配置里那一行撑着——上游路由器维护、迁移导致 link-local 变化时它不会跟随;路由、邻居表状态出问题时也没有任何自动恢复机制。典型表现就是“过段时间 IPv6 不通,重新填一遍网关又好了”——重填配置相当于把网络状态整体重置了一次。
2. cloud-init 会在重启时重写配置
DMIT 的 /etc/network/interfaces.d/50-cloud-init 由 cloud-init 生成,文件头明确写着:修改在实例重启后不会保留。也就是手动修改活不过下一次重启——cloud-init 会按数据源重新生成这个文件(面板的 IPv6 设置决定写回 auto 还是静态格式),把你的修改全部覆盖。
推荐配置:静态地址 + RA 管网关(三件套)
这个组合同时解决几件事:地址静态固定(出口 IP 固定)、默认路由由 RA 维护(网关变更、状态变化自动跟随,不再需要手动重填)、即使开着转发也接受 RA(转发环境不会破坏上面的机制)。
开始前先记下你的 IPv4 网关,后面配置要用:
ip -4 route show | grep default
记下 default via 后面的地址,下文用 <你的IPv4网关> 代替。
步骤 1:禁用 cloud-init 网络接管
echo 'network: {config: disabled}' > /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg
这一步让配置能”活过”重启,否则每次重启 cloud-init 都会把修改覆盖掉。
步骤 2:写入 sysctl 配置
cat > /etc/sysctl.d/99-ipv6-ra.conf <<'EOF'
net.ipv6.conf.eth0.accept_ra = 2
net.ipv6.conf.eth0.autoconf = 0
net.ipv6.conf.eth0.accept_ra_defrtr = 1
EOF
sysctl --system
三个参数各堵一个坑:
| 参数 | 值 | 作用 |
|---|---|---|
accept_ra |
2 |
即使开了转发也接受 RA(开了转发的机器上,默认值 1 会让内核忽略 RA,网关就失去自动维护) |
autoconf |
0 |
不用 SLAAC 自动生成地址(地址由你静态配置),避免多出地址导致出口 IP 漂移 |
accept_ra_defrtr |
1 |
允许从 RA 学习默认路由 |
步骤 3:写入网络配置
编辑 /etc/network/interfaces.d/50-cloud-init,替换为(地址、网关照抄你机器实际值;IPv6 网关不写):
auto lo
iface lo inet loopback
dns-nameservers 1.1.1.1 1.0.0.1
auto eth0
iface eth0 inet static
address <你的IPv4地址>/32
gateway <你的IPv4网关>
iface eth0 inet6 static
address <你的IPv6地址>/64
改动要点:
- IPv4 部分保持原样;
- 出厂文件里生效的是
iface eth0 inet6 auto(静态段是注释示例):改成 static 生效、auto 注释掉(或删掉); - static 段只保留
address,不写gateway行——默认路由交给 RA 自动装上并续期,网关变了也会自动跟着切换; - 文件头的 cloud-init 注释可以一并删掉(cloud-init 已禁用,用不上了)。
步骤 4:重启
reboot
步骤 5:验证
# sysctl 是否生效(期望 accept_ra = 2,autoconf = 0)
sysctl net.ipv6.conf.eth0.accept_ra net.ipv6.conf.eth0.autoconf
# 地址是否只有静态配的那一个 + link-local(没有多余地址)
ip -6 addr show eth0
# 默认路由是否由 RA 学来、带续期时间
ip -6 route show
# 期望类似:default via fe80::xxxx dev eth0 proto ra metric 1024 expires 1786sec pref medium
# 连通性测试
ping6 -c 3 2606:4700:4700::1111
看到默认路由带 proto ra 和 expires 就算配好了。expires 的秒数会随 RA 周期自动刷新(几十秒到几分钟都正常),说明这条路由是”活”的:上游只要还在发 RA 就永不过期,网关换地址了也会自动切换,不需要手动干预。
注意:ping6 不通不一定是配置问题。如果上面三条检查全部符合预期,那大概率是商家上游的问题,直接开工单即可,配置本身不用再折腾。
极简方案:只删网关行
如果不想动 sysctl 和 cloud-init,也可以只在现有配置里把 IPv6 的 gateway 行删掉(地址保持静态)。这个方案逻辑上成立,但有两个前提:
- 机器没开 IPv6 转发——
sysctl net.ipv6.conf.eth0.forwarding为 0 时,默认accept_ra=1也能正常工作;开了转发的话 RA 直接被忽略,默认路由装不上; - 能接受修改活不过重启——没禁用 cloud-init 的话,重启后配置被重写回出厂格式,网关行又回来了。
另外默认 autoconf=1,如果商家哪天把 RA 的 A 标志打开,机器会多出一个 SLAAC 地址(和静态地址并存),出口 IP 会变得不确定。
结论:临时测试够用;长期使用(特别是开了转发的机器)建议直接上三件套,每个文件都在堵一个真实的坑。
取消配置:完整恢复 DMIT 出厂默认
想回到 DMIT 原厂状态,把三件套全部撤销:
步骤 1:删除创建的两个文件
rm -f /etc/sysctl.d/99-ipv6-ra.conf
rm -f /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg
步骤 2:恢复 interfaces 文件为出厂格式
# This file is generated from information provided by the datasource. Changes
# to it will not persist across an instance reboot. To disable cloud-init's
# network configuration capabilities, write a file
# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:
# network: {config: disabled}
auto lo
iface lo inet loopback
dns-nameservers 1.1.1.1 1.0.0.1
auto eth0
iface eth0 inet static
address <你的IPv4地址>/32
gateway <你的IPv4网关>
# control-alias eth0
iface eth0 inet6 auto
#iface eth0 inet6 static
#address <你的IPv6地址>/64
#gateway <当前 RA 通告的 link-local 网关>
替换要点:IPv4 地址和网关照抄你机器的实际值;IPv6 部分按出厂默认——iface eth0 inet6 auto 生效,静态示例段(address / gateway)保持注释状态。
步骤 3:清理测试期间手动添加的临时地址(可选)
如果测试时用 ip -6 addr add 临时加过地址,可以顺手删掉(不删也行,重启后会自动消失):
ip -6 addr del <临时地址>/64 dev eth0 2>/dev/null
步骤 4:重启并验证
reboot
重启后 cloud-init 恢复接管,会按数据源重新生成配置:
cat /etc/network/interfaces.d/50-cloud-init
# 看 cloud-init 重新生成了什么内容
sysctl net.ipv6.conf.eth0.accept_ra net.ipv6.conf.eth0.autoconf
# 期望恢复内核默认:1 和 1
ip -6 addr show eth0
ip -6 route show
ping6 -c 3 2606:4700:4700::1111
如果 cloud-init 重新写入的 IPv6 地址和面板显示的不一致,那这个差异本身就是问题线索,截图存证去找商家开工单。
出问题时的排查命令
IPv6 又出问题时,先跑这几条抓现场:
ip -6 addr show eth0 # 地址还在不在
ip -6 route show # default 路由还在不在
ip -6 neigh show dev eth0 # 网关邻居状态:REACHABLE 还是 FAILED
sysctl net.ipv6.conf.all.forwarding net.ipv6.conf.eth0.accept_ra
对照判断:
- 地址、路由都在,但邻居是 FAILED → 上游网关变了或没响应,正是”写死网关”的硬伤,三件套能根治;
- default 路由没了 → RA 没被处理(检查 forwarding 与 accept_ra 的值);
- 重启后配置被改回去了 → cloud-init 重写(禁用文件没建或没生效)。
总结
auto模式本身正常,失效发生在”地址和网关都写死”之后:写死的网关不会自动维护、没有自愈机制(过段时间不通,重填一遍才恢复),cloud-init 还会在重启时重写配置;- 长期使用直接上三件套:禁用 cloud-init +
accept_ra=2 / autoconf=0(sysctl)+ 静态地址不写网关(interfaces),一次配好,网关变更自动跟随; - 要回出厂状态:删两个文件 + 恢复 interfaces 出厂格式 + 重启,两套流程互为逆操作、无残留;
- 判断配置对不对,看
ip -6 route show里有没有proto ra的默认路由,而不是 ping 通不通。




