GCP:在 Debian VM 上为 nic1 保留基于源的路由

GCP: Persist source-based route for nic1 on a Debian VM

初始情况:我创建了一个带有 2 个网卡的计算引擎 VM,每个网卡都属于不同的 VPC 网络。 GCP 只为属于第一个 VPC 的 nic0 设置默认路由。对于任何其他 nic,必须手动设置路由以使分配的 VPC 中的流量按预期工作。在这里完美描述(也很好用):

https://cloud.google.com/vpc/docs/create-use-multiple-interfaces#configuring_policy_routing

现在的问题是:

如何使这个额外的路由 table 在 Debian 机器上持久化,例如在重启后存活下来?

以下已经尝试过但没有成功:

四处寻找这个问题,似乎根本原因是系统启动时网卡的设置是由 Google 网络守护进程完成的,完成后它是未定义的。一个成功的解决方法是在启动脚本中等待几秒钟,但这显然不是一个好的和防弹的解决方案。也是一个比启动脚本更易于维护的解决方案。

有更好的建议吗?

看起来网络接口卡的路由配置可以通过您所描述的 ip 命令(或类似命令)来执行。但是,正如您所描述的,这些都是暂时的,并且在机器重新启动时会丢失。我 Google 搜索了如何使这些永久化并发现了以下文章:

Configure Static Routes In Debian or Red Hat Enterprise Linux

我建议深入阅读这篇文章。总之,在 Debian 上,似乎有一个名为 /etc/network/interfaces 的文件,可以编辑它来定义所需的路由表和其他配置。具体来说,似乎有一个名为 post-up 的配置标志允许定义路由条目。

在对此进行更多研究之后,我认为我有一个可行的解决方案,该解决方案具有足够的可维护性和可扩展性。

这是结果和解决方案:

  1. Compute Engine 显然在 为每个 nic 飞行(在我的例子中 ens4ens5)。 “传统”配置文件没有像往常一样使用。

    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 的标准程序。

  2. 相反,我在 /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.

  3. 为了防止 Google 网络守护进程覆盖我们的路由设置,在 /etc/default/instance_configs.cfg 的网络部分将 setup 更改为 false

    [NetworkInterfaces]
    dhclient_script = /sbin/google-dhclient-script
    dhcp_command = 
    ip_forwarding = true
    setup = false
    

有必要对 if-up 脚本进行一些进一步的改进,以使该解决方案更加通用并适用于自动缩放等(例如,通过元数据检索动态 IP 地址)。但总的来说,这个解决方案是有效的。

编辑

更新了第 2 步中提供的 if-up 脚本,以通过 curl 使用元数据检索来动态获取 Compute Engine 实例的 IP 和网关。详情请参考metadata docs.

解决方案现在可以很好地创建用于自动缩放的机器映像图像和实例模板。

如果您需要有关如何使用 >1 NIC 创建 Compute Engine 实例模板的提示,请参阅 my GIST for that