计划顺利应用,隧道也起来了,控制台却称它为基于策略。流量依然不通,而在 Terraform 资源里找基于路由的开关永远找不到,因为根本没有这个字段。在 Classic VPN 中,基于路由的行为不是一个可以选择的模式。它是这样得到的:本地流量选择器为0.0.0.0/0,远端选择器列出你真正想要的网段,并且有一条路由指向该隧道。三件事齐了,标签自然跟上。

误区:隧道模式字段

控制台的标签只反映 API 在选择器里看到的内容。资源里没有任何地方写着基于路由,所以没有可设为真的东西。

找这个字段会花掉问题的第一个小时,而读一遍选择器的值只要最后五分钟。

这里的基于路由是什么意思

Google 把 Classic VPN 的基于路由隧道记录为本地选择器为0.0.0.0/0的基于策略隧道。只有远端网段被点名,本地一侧被当作任意地址。正因如此,你配置里的标记是一个值,而不是一个模式。把两个选择器都写清楚,然后在计划输出里读出来:

local_traffic_selector  = ["0.0.0.0/0"]
remote_traffic_selector = ["10.20.0.0/16"]

那段片段里的对端前缀只是示例;形状才是重点。

路由是独立对象

隧道对象不会安装路由。数据包可以匹配隧道策略,却依然无处可去,因为下一跳由 VPC 路由表决定。路由需要目标网段、网络、作为下一跳的隧道,以及一个能压过任何更宽条目的优先级。忘了这一步,得到的就是一条报告已建立的隧道,和一个永远出不了 VPC 的连通性测试。

resource "google_compute_route" "office" {
  name                = "office-via-vpn"
  dest_range          = "10.20.0.0/16"
  network             = google_compute_network.vpc.name
  next_hop_vpn_tunnel = google_compute_vpn_tunnel.to_office.id
  priority            = 1000
}

把路由和隧道放在同一个模块里创建,这样评审时两者不会走偏。

在对端镜像选择器

远端设备必须按镜像方式配置:它的本地网段就是你的远端选择器,它的远端网段必须覆盖你打算使用的 GCP 子网。任何一侧收窄,即使第 1 阶段成功,第 2 阶段也会失败。控制台里看着正确、却带不动流量的配置,最常见的就是这个形状。

变更评审时,把两侧的选择器并排打印出来。

把静态地址拆成两次应用

在一次应用里同时创建预留地址和引用它的隧道,是已知的抖动来源,因为转发规则必须先看到地址存在。先单独应用地址资源,再加上网关、转发规则和隧道重新应用一次。Terraform 第二次运行时会从状态里读到已有地址并复用。跳过这一步,隧道每次应用都可能拿到新的公网地址,每次都把对端配置弄坏。

现在做两次应用,比每次发版都改对端便宜。

验证协商,而不是标签

应用之后,分别核对三件事:隧道报告已建立,路由存在且下一跳符合预期,对端报告第 1 阶段和第 2 阶段都已起来。

隧道已建立而第 2 阶段掉线,说明两侧对选择器的理解不一致:

  • 一侧列出了另一侧没有列出的子网。
  • 一侧使用的聚合段被另一侧收窄了。
  • 路由存在,但指向了另一条隧道。

Classic VPN 是单条隧道,SLA 低于 HA VPN;HA VPN 使用两个接口、两条隧道,以及资源类型不同的 BGP。把经典示例照搬到 HA 配置里,还指望选择器字段表现一致,是另一个值得避免的错误。隧道字段本身记录在google_compute_vpn_tunnel 参考。

相关文章