初始情况:我创建了一个具有 2 个网卡的计算引擎虚拟机,每个网卡都属于不同的 VPC 网络。 GCP 只为属于第一个 VPC 的 nic0 设置默认路由。对于任何其他网卡,必须手动设置路由才能使分配的 VPC 中的流量按预期工作。这里完美描述(也很好用):
https://cloud.google.com/vpc/docs/create-use-multiple-interfaces#configuring_policy_routing
现在的问题是:
如何使这个额外的路由表在 Debian 机器上持久存在,例如重启后仍能生存?
以下已经尝试过但没有成功:
ip route
和 ip rule
命令放入虚拟机的启动脚本中搜索问题的根源似乎是系统启动时网卡的设置是由 Google 网络守护进程完成的,完成后它是未定义的。成功的解决方法是在启动脚本中等待几秒钟,但这显然不是一个很好且万无一失的解决方案。另外,比启动脚本更易于维护的解决方案将是首选。
还有更好的建议吗?
在对此进行了更多研究之后,我认为我有一个可行的解决方案,该解决方案具有足够的可维护性和可扩展性。
以下是结果和解决方案:
Compute Engine 显然会在 为每个 nic 飞行(就我而言
ens4
和 ens5
)。 “传统”配置文件没有像平常一样使用。
test@vm-1:~$ cat /etc/network/interfaces
# Include files from /etc/network/interfaces.d:
source-directory /etc/network/interfaces.d
# Cloud images dynamically generate config fragments for newly
# attached interfaces. See /etc/udev/rules.d/75-cloud-ifupdown.rules
# and /etc/network/cloud-ifupdown-helper. Dynamically generated
# configuration fragments are stored in /run:
source-directory /run/network/interfaces.d
test@vm-1:~$ ls -la /etc/network/interfaces.d/
total 0
test@vm-1:~$ ls -la /run/network/interfaces.d/
total 8
drwxr-xr-x 2 root root 80 Dec 13 20:52 .
drwxr-xr-x 3 root root 160 Dec 13 20:52 ..
-rw-r--r-- 1 root root 51 Dec 13 20:52 ens4
-rw-r--r-- 1 root root 51 Dec 13 20:52 ens5
原始文件
/etc/network/interfaces
仅用于转发到/run/network/interfaces.d
下生成的文件。您可以轻松检查它们是否是在每次实例启动时新生成的。
在此放置任何附加配置可能不是最佳解决方案,因为它会干扰 GCP 的标准程序。
相反,我在
/etc/network/if-up.d/
下的新脚本中添加了额外所需的路由配置。像这样:
test@vm-1:~$ cat /etc/network/if-up.d/ens5routing
#!/bin/sh
if [ "$IFACE" = ens5 ]; then
IP=$(curl -s http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/1/ip -H "Metadata-Flavor: Google")
GW=$(curl -s http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/1/gateway -H "Metadata-Flavor: Google")
ifconfig ens5 $IP netmask 255.255.255.255 broadcast $IP mtu 1430
ip route add $GW src $IP dev ens5 table rt1
ip route add default via $GW dev ens5 table rt1
ip rule add from $IP/32 table rt1
ip rule add to $IP/32 table rt1
echo "Routing table for ens5 set up using IP $IP and GW $GW"
fi
请注意,脚本必须是可执行的,并且不应具有任何扩展名,如
.sh
。此外,每个即将出现的网络接口都会调用此目录中的脚本,因此请确保仅针对所需的网卡执行它。出现的界面将变量 IFACE
传递给脚本。有关如何构建此类脚本的更多详细信息,请参阅 https://manpages.debian.org/testing/ifupdown/interfaces.5.en.html。
为了防止 Google 网络守护程序覆盖我们的路由设置,请将
setup
的网络部分中的 false
更改为 /etc/default/instance_configs.cfg
:
[NetworkInterfaces]
dhclient_script = /sbin/google-dhclient-script
dhcp_command =
ip_forwarding = true
setup = false
需要对 if-up 脚本进行一些进一步改进,以使该解决方案更加通用并适用于自动缩放等(例如,通过元数据进行动态 IP 地址检索)。但总的来说,这个解决方案是有效的。
编辑
更新了步骤 2 中提供的 if-up 脚本,以通过
curl
使用元数据检索来动态获取 Compute Engine 实例的 IP 和网关。有关详细信息,请参阅元数据文档。
解决方案现在可以很好地创建机器映像图像和实例模板以进行自动缩放。
如果您需要有关如何创建具有 >1 个 NIC 的 Compute Engine 实例模板的提示,请参阅我的 GIST 。
看起来网络接口卡的路由配置可以通过 ip 命令(或类似命令)来执行,正如您所描述的那样。但是,正如您所描述的,这些都是暂时的,并且在计算机重新启动时会丢失。我在谷歌上搜索了如何使这些永久化,并发现了以下文章:
在 Debian 或 Red Hat Enterprise Linux 中配置静态路由
我建议深入阅读这篇文章。总之,在 Debian 上,似乎有一个名为
/etc/network/interfaces
的文件,可以编辑它来定义您所需的路由表和其他配置。具体来说,看起来有一些名为 post-up
的配置标志允许定义路由条目。
@塞巴斯蒂安,
谢谢你。你的解决方案对我有用。 在我意识到我需要在 Debian 上进行基于策略的路由之前,我花了几个小时试图找出为什么我的 VPC 防火墙规则在第二个网络接口上不起作用。
尽管如此,在我尝试的 4 台机器中,只有 1 台可以工作。 后来,我开始意识到,当我执行
ifdown ens5
和 ifup ens5
时,我看到了如下错误:
Error: argument "rt1" is wrong: "table" value is invalid
Error: argument "rt1" is wrong: "table" value is invalid
Error: argument "rt1" is wrong: invalid table ID
Error: argument "rt1" is wrong: invalid table ID
我继续更新了
/etc/iproute2/rt_tables
来自:
#
# reserved values
#
255 local
254 main
253 default
0 unspec
#
# local
#
1 inr.ruhep
至:
#
# reserved values
#
255 local
254 main
253 default
0 unspec
#
# local
#
#1 inr.ruhep
1 rt1
此后,我可以很好地使用辅助外部 IP 和我的所有虚拟机。 ...
我一直在尝试实现 Sebastian 为 Rocky linux 共享的等效解决方案,但由于“网络脚本”已被弃用以及 GCP 在 GCE 上摄取的额外网络定制,我放弃了。 对我来说,一个等效且快速的解决方案是将 ip 路由命令放入 VM 实例元数据启动脚本中。