我正在运行 Debian Buster 的 Google Compute Engine 中启动一个 VM,并使用两个网络接口对其进行配置。
第一个使用临时 IP 配置,并分配给通过 DHCP 配置的公共可路由网络。我想保持原样。
第二个接口使用静态 IP 配置,并分配给专用网络。我想阻止 GCE 使用 DHCP 来配置这个接口,而是使用 systemd-networkd 自己来配置它,以便轻松添加一些自定义路由。
虽然 systemd-networkd 配置确实成功,但问题是当机器重新启动时,GCE 的 DHCP 设置在 systemd-networkd 设置之后运行,并覆盖了我的自定义配置。
到目前为止,我已经尝试了很多方法来解决这个问题,包括:
- 禁用 /etc/network/interfaces 中 /var/run/interfaces.d 的条目
- 添加自定义 systemd 服务以在 GCE 的网络服务之后运行
到目前为止唯一有效的是一个可怕的脚本黑客在启动后等待 30 秒,然后再次启动 systemd-networkd 以覆盖 GCE 配置。
我可以在操作系统级别进行一些更清晰的配置更改,或者在网络/服务器设置期间进行配置设置,以防止 GCE 自动配置第二个网络接口?
编辑#1:
这是我更喜欢使用的 systemd-networkd 配置示例:
[Match]
Name=ens5
[Network]
Address=10.1.3.30/32
LinkLocalAddressing=no
[Route]
Destination=10.1.3.1/32
Scope=link
[Route]
Gateway=10.1.3.1
Destination=10.1.3.0/24
GatewayOnlink=yes
[Route]
Gateway=10.1.3.1
Destination=10.1.1.0/24
GatewayOnlink=yes
[Route]
Gateway=10.1.3.1
Destination=10.1.2.0/24
GatewayOnlink=yes
[Route]
Gateway=10.1.3.1
Destination=10.10.0.0/24
GatewayOnlink=yes
使用此配置,我可以在接口上设置其他路由到其他子网。请注意,这些其他子网可能在也可能不在 GCP 上。
上述配置有效,即使我必须将 10.1.3.30 静态 IP 地址声明为我的 GCE 服务器设置的一部分。问题只是我不能让 GCE 停止对接口进行自己的配置,这会覆盖上面的配置。在 Azure 上,我可以简单地注释掉对in的source
引用。/var/run/network/interfaces.d
/etc/network/interfaces
至于为什么我更喜欢这种设置,这是一种通过服务器配置管理软件设置内部网络的优雅方法——我只需将上述配置放入/etc/systemd/network/
并发出systemctl enable systemd-networkd && systemctl restart systemd-networkd
,它会处理配置接口并将配置设置为也在启动时发生。
更新#1:
我已经在 GCP 的问题跟踪器中提交了https://issuetracker.google.com/issues/153513472,希望他们能解决。当他们这样做时,我会相应地更新问题。
更新#2:
经过一轮付费 GCP 支持后,他们向我指出了另一个持续存在的问题:https ://issuetracker.google.com/issues/167371074
支持代理还建议其他用户只需放置 cron 脚本以定期重新启动网络。
我已经根据我的特定网络需求调整了这个建议,并使用了以下 crontab 条目:
* * * * * /usr/bin/test -z "$(/sbin/ip route | /bin/grep "10.1.1.0/24")" && /bin/systemctl restart systemd-networkd
其中 '10.1.1.0/24' 是一个子网,我知道在我的路由配置中不应丢失。
更新#3:
最后,一个干净而令人满意的答案!谷歌工程师告诉我,google-guest-agent.service
作为他们在 Debian 系统上的来宾环境的一部分运行的它有一个网络守护进程,当它重新配置任何接口时,它会dhclient
直接调用。看起来dhclient
这种方式会消除现有的路线。鉴于此,一个简单的解决方法是通过在/etc/dhcp/dhclient-exit-hooks.d/
.
就我而言,我在以下位置添加了以下脚本/etc/dhcp/dhclient-exit-hooks.d/systemd-networkd
:
case $reason in
BOUND|RENEW|REBIND|REBOOT)
systemctl restart systemd-networkd.service
;;
esac
这似乎解决了问题,包括重新启动。