浮动 IP 地址最佳做法

本解决方案介绍使用浮动 IP 地址将应用从本地网络环境迁移到 Compute Engine 的替代方案。浮动 IP 地址也称为“共享”或“虚拟”IP 地址,常常用于使本地网络环境具备高可用性。使用浮动 IP 地址,您可以在多台配置相同的物理服务器或虚拟服务器之间传递 IP 地址,从而实现生产软件的故障转移或升级。但是,您无法在 Compute Engine 环境中直接实现浮动 IP 地址。

本地环境中的浮动 IP 地址

浮动 IP 地址常常用于本地环境。以下列表仅列出了浮动 IP 地址的几种使用场景:

  • 高可用性物理设备(例如一组防火墙或负载平衡器)通常使用浮动 IP 地址进行故障转移。
  • 需要具备高可用性的服务器通常使用浮动 IP 地址,例如主要/辅助关系型数据库,如使用 Always On 可用性组的 Microsoft SQL Server。
  • 实现负载平衡器或反向代理的 Linux 环境(例如 IPVSHAProxyNGINX)使用浮动 IP 地址。为检测节点故障并在实例间移动浮动 IP 地址,这些环境使用守护程序,如 heartbeatpacemakerkeepalived
  • 搭配使用 Windows Server 故障转移集群的 Windows 服务,浮动 IP 地址可实现高可用性。

有几种方法可以在本地环境中实现浮动 IP 地址。在所有情况下,共享 IP 地址的服务器还必须通过检测信号机制共享彼此的状态。该机制使服务器能够相互通知其运行状况;它还使辅助服务器能够在链接服务器发生故障后接管浮动 IP 地址。此方案通常使用虚拟路由器冗余协议 (VRRP) 实现,但您也可以使用其他类似的机制。

启动 IP 地址故障转移后,接管浮动 IP 地址的服务器会将地址添加到其网络接口。服务器通过发送免费地址解析协议 (ARP) 帧宣布使用第 2 层接管其他设备。 作为替代方法,IP 地址有时通过诸如开放最短路径优先 (OSPF) 的路由协议向上游第 3 层路由器进行通告。

下图展示了本地环境中的典型设置。

典型的本地环境

您使用与本地负载平衡解决方案稍有不同的设置,例如具有直接服务器响应的 Windows 网络负载平衡或 Linux 负载平衡,例如,IP 虚拟服务器 (IPVS)。 在这些情况下,该服务还发送免费 ARP 帧,但使用另一台服务器的 MAC 地址作为免费 ARP 源,其实质是仿冒 ARP 帧并接管另一台服务器的源地址。这种设置超出了本解决方案的范围。因为几乎在所有情况下,迁移到负载平衡都是首选的迁移路径。

将浮动 IP 地址迁移到 Compute Engine 的挑战

Compute Engine 在 Virtual Private Cloud (VPC) 网络中使用虚拟化网络栈,因此无法立即使用典型的实现机制。例如,VPC 网络根据配置的路由拓扑处理 ARP 请求,并忽略免费 ARP 帧。此外,您无法使用诸如 OSPF 或边界网关协议 (BGP) 等标准路由协议直接修改 VPC 网络路由表。

您可以借助覆盖网络创建配置,以使用 ARP 请求启用完整的第 2 层通信和 IP 地址接管。但是,设置覆盖网络很复杂,这使得管理 Compute Engine 网络资源变得困难。该方法也超出了本解决方案的范围。相反,本解决方案提供了在原生 Compute Engine 网络环境中实现故障转移场景的替代方法。

本解决方案介绍了将大多数概述的使用场景迁移到 Compute Engine 的方法。

对于更具体的使用场景,请参阅以下分步指南:

迁移的示例使用场景

本解决方案概述了从本地浮动 IP 地址迁移到 Compute Engine 的四种不同迁移方案。

本使用场景涉及迁移两台内部 HAProxy 服务器,这些服务器将流量路由到不同的后端,具体取决于复杂的第 7 层标头匹配和替换。由于涉及复杂的规则,这组服务器不能替换为内部 TCP/UDP 负载平衡HTTP 负载平衡。下图展示了此使用场景的概览。

迁移使用场景

HAProxy 服务器使用本地 keepalived 软件通过单独的交叉连接检查可用性,并在两台服务器之间传递浮动 IP 地址。

对于此使用场景,下文中介绍的所有四种方案均为浮动 IP 地址的有效本地替换方法。对于其他可能更复杂的使用场景,相关的可用方案可能较少。在介绍完这些方案后,本解决方案根据特定使用场景提供了首选方案指南。

下一部分将介绍如何将此使用场景迁移到 Compute Engine。

使用 Compute Engine 实现

本部分概述了将本地场景迁移到 Compute Engine 的几种方法。为了降低复杂性,所有请求使用最小后端配置转发到单个 NGINX 后端组,而不是使用先前描述的基于标头的匹配。

对于所有示例,流量都是从 HAProxy 路由到布置在自动扩缩实例组中的一组 Compute Engine 后端。这些后端是通过内部 TCP/UDP 负载平衡器来访问的。对于示例配置,这些后端提供 NGINX 默认配置。

若要实现示例使用场景,请使用专用项目进行测试。

配置后端

在本部分中,您将配置由 HAProxy 节点访问的 NGINX 后端。最佳做法是,您可以在专用于此部署的 VPC 中创建这些后端,而不是在默认网络中。

如需设置后端,请按照下列步骤操作:

  1. 设置默认区域,例如:

    gcloud config set compute/zone us-central1-f
    
  2. 设置网络进行测试并设置防火墙规则以允许内部流量,然后使用 ssh 命令与网络通信:

    gcloud compute networks create ip-failover
    
    gcloud compute firewall-rules create failover-internal \
        --network ip-failover --allow all --source-ranges 10.128.0.0/11
    
    gcloud compute firewall-rules create failover-ssh \
        --network ip-failover --allow tcp:22 --source-ranges 0.0.0.0/0
    
  3. 为 NGINX 后端创建实例模板:

    gcloud compute instance-templates create www \
        --machine-type n1-standard-1 --network ip-failover \
        --metadata startup-script="apt-get -y install nginx"
    
  4. 基于模板创建自动扩缩区域代管实例组:

    gcloud compute instance-groups managed create www \
        --template www --size 1 --zone us-central1-f
    
    gcloud compute instance-groups managed set-autoscaling www \
        --max-num-replicas 10 --min-num-replicas 1 \
        --target-cpu-utilization 0.8 --zone us-central1-f
    
  5. 将具有固定 IP 地址 (10.128.2.2) 的内部 TCP/UDP 负载平衡器连接到此实例组:

    gcloud compute health-checks create http simple-check
    
    gcloud compute backend-services create www-lb \
        --load-balancing-scheme internal \
        --region us-central1 \
        --health-checks simple-check \
        --protocol tcp
    
    gcloud compute backend-services add-backend www-lb\
        --instance-group www \
        --instance-group-zone us-central1-f \
        --region us-central1
    
    gcloud compute forwarding-rules create www-rule \
        --load-balancing-scheme internal \
        --ports 80 \
        --network ip-failover \
        --region us-central1 \
        --address 10.128.2.2 \
        --backend-service www-lb
    
  6. 创建一个用于测试的实例,使用 ssh 命令连接到该实例,并检查是否可以访问内部 TCP/UDP 负载平衡 IP 地址:

    gcloud compute instances create testing \
        --machine-type n1-standard-1 --zone us-central1-f \
        --network ip-failover --scopes compute-ro
    
    gcloud compute ssh testing --zone us-central1-f
    
    username@testing:~$ curl 10.128.2.2
    <!DOCTYPE html> [...]
    username@testing:~$ exit

本示例配置使用 n1-standard-1 实例,并且每个实例的网络吞吐量限制为每秒 2 GB。对于实际部署,您可以根据需要调整实例大小。

此外,应使用外部 IP 地址创建实例,这样它们就可以使用启动脚本下载必要的软件包。在生产设置中,您将创建自定义映像并创建没有外部 IP 地址的实例。

方案 1:使用内部 TCP/UDP 负载平衡

您可以将这两台 HAProxy 服务器布置在内部 TCP/UDP 负载平衡后面的代管实例组中,并使用内部 TCP/UDP 负载平衡 IP 地址作为虚拟 IP 地址,从而在 Compute Engine 中实现本地场景,如下图所示。

方案 1:内部 TCP/UDP 负载平衡

本地迁移服务默认仅在内部公开。如果您尝试迁移的服务可供外部使用,您可以使用 HTTP(S) 负载平衡TCP 代理SSL 代理网络负载平衡以类似的方式实现此场景。

您还可以使用仅限于 Beta 版的以下方案:

与本地设置的差异

内部 TCP/UDP 负载平衡 IP 地址的作用类似于本地环境中的浮动 IP 地址,但存在一些显著差异:

  • 流量分配

    最显著的区别在于流量在两个节点之间共享,而在原始设置中,流量一次只到达一个节点。在根据请求本身的内容路由流量的场景中,这种方法效果很好,但如果存在不经常同步的计算机状态(例如,主要/辅助数据库),则该方法不起作用。

  • 故障转移时间

    在本地环境中搭配使用 keepalived 和免费 ARP 可在几秒钟内完成 IP 地址故障转移。在 Compute Engine 环境中,平均恢复时间则取决于故障模式。如果虚拟机实例或虚拟机实例服务失败,则平均故障转移时间流量取决于运行状况检查参数,例如 Check IntervalUnhealthy Threshold。将这些参数设置为其默认值后,故障转移通常需要 15-20 秒,但可以通过调整这些参数来减少所需时间。在 Compute Engine 中,区域内或区域间的故障转移所需的时间相同。

  • 运行状况检查

    当在本地使用时,除了等待活动信号之外,keepalived 还可以通过不同方式检查主机的运行状况,例如监控 HAProxy 进程的可用性。在 Compute Engine 中,必须使用 HTTP/HTTPS/TCP 或 SSL 端口从主机外部访问运行状况检查。如果必须检查主机细节,则需要在实例上安装一个简单服务以公开这些细节,或选择其他方案。

  • 端口

    在本地设置中,浮动 IP 地址接受所有流量。对于内部 TCP/UDP 负载平衡器,您必须在内部转发规则中选择以下端口规范之一:

    • 按编号指定 1-5 个端口
    • 指定 ALL 以转发所有端口上的流量

实现方案 1

若要实现此解决方案,请完成以下步骤:

  1. 为转发请求的 HAProxy 服务器创建实例模板:

    gcloud compute instance-templates create haproxy \
        --machine-type n1-standard-1 --network ip-failover \
        --metadata "startup-script=
    sudo apt-get install -y haproxy
    cat << EOF >> /etc/haproxy/haproxy.cfg
    frontend www
        bind :80
        option http-server-close
        default_backend web-backend
    backend web-backend
        server web-1 10.128.2.2:80 check
    EOF
    service haproxy restart"
    
  2. 根据静态大小为 2 的实例模板创建区域实例组。使用先前创建的运行状况检查将自动修复政策附加到实例:

    gcloud compute instance-groups managed create haproxy \
        --template haproxy --size 2 --zone us-central1-f
    
    gcloud compute instance-groups managed update \
        haproxy --health-check simple-check --zone us-central1-f
    
  3. 使用运行状况检查将内部 TCP/UDP 负载平衡器连接到 HAProxy 服务器:

    gcloud compute backend-services create haproxy-lb \
        --load-balancing-scheme internal \
        --region us-central1 \
        --health-checks simple-check \
        --protocol tcp
    gcloud compute backend-services add-backend haproxy-lb\
        --instance-group haproxy \
        --instance-group-zone us-central1-f \
        --region us-central1
    
    gcloud compute forwarding-rules create haproxy-rule \
        --load-balancing-scheme internal \
        --ports 80 \
        --network ip-failover \
        --region us-central1 \
        --address 10.128.1.1 \
        --backend-service haproxy-lb
    
  4. 测试您能否通过内部 TCP/UDP 负载平衡访问 HAProxy:

    gcloud compute ssh testing --zone us-central1-f
    
    username@testing:~$ curl 10.128.1.1
    <!DOCTYPE html> [...]
    username@testing:~$ exit

在通过控制台删除其中一个 HAProxy 实例或在其中一个实例上停止 HAProxy 进程后,curl 仍会在短暂的故障转移时间后成功实现。

方案 2:使用单个代管实例

根据恢复时间要求,即使在本地使用多台服务器,通过单个虚拟机实例进行迁移也可能是可行的 Compute Engine 方案。原因在于您在几分钟内即能启动一个新的 Compute Engine 实例,而本地故障通常需要数小时甚至数天才能修复。

方案 2:单个代管实例

将方案 2 与方案 1(内部 TCP/UDP 负载平衡)进行比较

与方案 1 相比,方案 2 的优缺点更明显。

优点:

  • 流量分配

    因为只有一个实例,所以所有流量都会流向一个实例,类似于本地主要/辅助场景。

  • 节约费用

    相比两个虚拟机实例,使用单个虚拟机实例可以将费用减半。

  • 简单性

    此解决方案很容易实现,并且开销很小。

缺点:

  • 故障转移时间

    在运行状况检查检测到机器故障后,删除失败的实例并重新创建实例至少需要 1 分钟,但通常需要更长的时间。此过程比从内部 TCP/UDP 负载平衡中移除实例要慢得多。

  • 对区域故障作出反应

    若区域发生故障,则在其中大小为 1 的代管实例组也会失败。如需对区域故障作出反应,请考虑在服务失败时添加 Cloud Monitoring 提醒,并在发生区域故障时在另一个区域中手动创建实例组。

实现方案 2

完成以下步骤以实现方案 2:

  1. 为 HAProxy 虚拟机实例创建具有静态内部 IP 地址的实例模板:

    gcloud compute instance-templates create haproxy-single \
        --machine-type n1-standard-1 --network ip-failover \
        --private-network-ip=10.128.3.3 \
        --metadata "startup-script=
    sudo apt-get install -y haproxy
    cat << EOF >> /etc/haproxy/haproxy.cfg
    frontend www
        bind :80
        option http-server-close
        default_backend web-backend
    backend web-backend
        server web-1 10.128.2.2:80 check
    EOF
    service haproxy restart"
    
  2. 为 HAProxy 虚拟机创建大小为 1 的代管实例组,并附加自动修复政策:

    gcloud compute instance-groups managed create haproxy-single \
        --template haproxy-single --size 1 --zone us-central1-f
    
    gcloud compute instance-groups managed update \
        haproxy-single --health-check simple-check --zone us-central1-f
    
  3. 测试您能否通过内部 TCP/UDP 负载平衡 IP 地址访问 HAProxy:

    gcloud compute ssh testing --zone us-central1-f
    
    username@testing:~$ curl 10.128.3.3
    <!DOCTYPE html> [...]
    username@testing:~$ exit

    如果您使用控制台删除 HAProxy 实例或停止 HAProxy 实例进程,则该实例稍后会自动恢复并使用相同的实例名称和 IP 地址。

方案 3:使用不同优先级的路由进行故障转移

当无法使用内部 TCP/UDP 负载平衡时,可使用具有不同优先级的两个 Compute Engine 路由在两个实例间进行流量故障转移。

在本部分中,您将创建两个虚拟机实例并将它们放入静态大小为 1 的自动修复代管实例组中,从而使系统能够自动修复。

您必须在这两个实例上启用 IP 转发。然后,在创建实例后,通过设置具有不同优先级的两个路由来处理流量,将所有浮动 IP 地址流量转移到这两个实例。

方案 3:不同优先级的路由

将方案 3 与方案 1(内部 TCP/UDP 负载平衡)进行比较

使用方案 3,您可以迁移无法轻松使用内部 TCP/UDP 负载平衡的使用场景。此方案具有以下优点:

  • 流量分配

    流量始终流向具有最低优先级的虚拟机实例。当此虚拟机实例不可用时,流量使用下一个最佳路由。此架构类似于本地环境,即在给定时间内只有一个服务器处于活动状态。

  • 协议

    内部 TCP/UDP 负载平衡仅适用于一组特定的协议或端口,而路由适用于指向具体目标的所有流量。

  • 地区性

    内部 TCP/UDP 负载平衡仅在地区内可用,而路由可以全局创建。

与使用内部 TCP/UDP 负载平衡的方案 1 相比,方案 3 具有一些缺点。

  • 运行状况检查

    使用方案 3 时,两个路由都不会附加运行状况检查。 因此无论底层虚拟机服务的运行状况如何,系统都会使用路由。 这样即使服务运行状况不佳,流量也会定向到实例。 将自动修复政策附加到这些实例时,实例会在特定的运行状况不佳时间段后被终止,但当这些实例重启后,流量甚至会在服务启动前恢复,这可能会导致在运行状况不佳的实例仍在提供流量期间或在重启时出现服务错误。

  • 故障转移时间

    删除或停止虚拟机实例后,路由将自动撤消。但是,由于缺少运行状况检查,只要实例仍然可用,则路由仍会被使用。此外,停止实例也需要时间,因而此方案的故障转移时间远远高于内部 TCP/UDP 负载平衡方法。

  • 浮动 IP 地址选择

    您只能将路由设置为不属于任何子网的 IP 地址。 浮动 IP 地址必须在所有现有子网范围之外进行选择。

  • VPC 网络对等互连

    虚拟机实例只能使用来自其自身 VPC 网络的路由,而不能使用任何对等 VPC 网络的路由。

实现方案 3

在实现过程中,您将使用 10.191.1.1 IP 地址,该地址在 ip-failover 网络的所有活跃子网之外。请完成以下步骤:

  1. 为转发请求的 HAProxy 服务器创建实例模板:

    gcloud compute instance-templates create haproxy-route \
        --machine-type n1-standard-1 --network ip-failover \
        --metadata "startup-script=
    apt-get update
    apt-get install -y haproxy
    cat << EOF >> /etc/haproxy/haproxy.cfg
    frontend www
        bind :80
        option http-server-close
        default_backend web-backend
    backend web-backend
        server web-1 10.128.2.2:80 check
    EOF
    cat << EOF >> /etc/network/interfaces
    auto eth0:0
    iface eth0:0 inet static
        address 10.191.1.1
        netmask 255.255.255.255
    EOF
    service haproxy restart
    service networking restart" --can-ip-forward
    
  2. 为 HAProxy 虚拟机实例创建两个大小为 1 的代管实例组,并为其附加自动修复政策:

    gcloud compute instance-groups managed create haproxy-r1 \
        --template haproxy-route --size 1 --zone us-central1-f
    
    gcloud compute instance-groups managed update \
        haproxy-r1 --health-check simple-check --zone us-central1-f
    
    gcloud compute instance-groups managed create haproxy-r2 \
        --template haproxy-route --size 1 --zone us-central1-b
    
    gcloud compute instance-groups managed update \
        haproxy-r2 --health-check simple-check --zone us-central1-b
    
  3. 在这些虚拟机实例启动后,为其创建主路由和备份路由:

    haproxy1=$(gcloud compute instances list |awk '$1 \
        ~ /^haproxy-r1/ { print $1 }')
        #save the instance name of the first HAproxy instance
    
    haproxy2=$(gcloud compute instances list |awk '$1 \
        ~ /^haproxy-r2/ { print $1 }')
        #save the instance name of the second HAproxy instance
    
    gcloud compute routes create haproxy-route1 \
        --destination-range 10.191.1.1/32 --network ip-failover \
        --priority 500 --next-hop-instance-zone us-central1-f \
        --next-hop-instance $haproxy1
    
    gcloud compute routes create haproxy-route2 \
        --destination-range 10.191.1.1/32 --network ip-failover \
        --priority 600 --next-hop-instance-zone us-central1-b \
        --next-hop-instance $haproxy2
    
  4. 测试是否可以通过路由访问 HAProxy:

    gcloud compute ssh testing --zone us-central1-f
    
    username@testing:~$ curl 10.191.1.1
    <!DOCTYPE html> [...]
    username@testing:~$ exit

    当通过控制台删除主 HAProxy 实例时,应在该实例完全关闭后立即使用辅助实例的路由。

方案 4:使用路由 API 调用进行故障转移

与方案 3 一样,方案 4 也使用路由,但存在一些显著差异。 例如,相对于自动修复和重新创建实例,keepalived 或其他脚本使用 API 调用将路由添加到运行状况良好的新实例,或从运行状况不佳的实例中移除路由。 如果您无法使用 Compute Engine 运行状况检查来跟踪应用的运行状况或确定哪个虚拟机是主虚拟机,此方法会非常有用。任何应用逻辑都可以触发路由的动态重编程。

如果需要手动调查应用故障和手动恢复实例,路由 API 调用也是一种实用的故障转移方法。 但是,由于虚拟机需要能够记录所有故障并在其运行状况变得良好时自动替换,因此不要手动调查 Compute Engine 中的故障。

方案 4:使用路由 API 调用进行故障转移

比较方案 4 与使用内部 TCP/UDP 负载平衡的不同之处

与使用内部 TCP/UDP 负载平衡相比,方案 4 具有以下优点:

  • 流量分配

    与方案 2 和 3 一样,流量一次只能流向一个虚拟机实例。

  • 不依赖于 Compute Engine 运行状况检查

    故障转移可以由任何自定义应用逻辑触发。通过方案 4,您可以使用一个脚本来管理 keepalived 对主 HAProxy 和辅助 HAProxy 之间通信故障的响应。当您不能或不希望使用 Compute Engine 运行状况检查时,此方案是唯一有效的方案。

方案 4 也存在以下缺点:

  • 复杂性

    此方案必须通过 Compute Engine API 或 gcloud 调用来自定义构建,以使用 Compute Engine API 撤消路由和设置新路由。以可靠的方式构建这种逻辑通常涉及到复杂的操作。

  • 故障转移时间

    由于通过自定义脚本在 Compute Engine 上撤消路由和创建新路由至少需要两次 Compute Engine API 调用,因此其故障转移比内部负载平衡器稍慢。

  • 浮动 IP 地址选择

    您只能将路由设置为不属于任何子网的 IP 地址。 浮动 IP 地址必须在所有现有子网范围之外进行选择。

  • VPC 网络对等互连

    虚拟机实例只能使用来自其自身 VPC 网络的路由,而不能使用任何对等 VPC 网络的路由。

实现方案 4

此实现会使用 10.190.1.1 IP 地址,该地址在 ip-failover 网络的所有活跃子网之外。此地址的路由将通过 keepalived 自动创建和删除。

首先,使用静态内部 IP 地址创建两个安装了 haproxy 和 keepalived 的 HAProxy 实例。此外,您还必须启用 IP 转发才能终止路由,并且需要访问 Compute Engine API。为了简单起见,在此示例中您将不会使用实例模板和组。

使用以下步骤创建方案 4:

  1. 使用静态 IP 地址 10.128.4.100 创建主实例:

    gcloud compute instances create haproxy-a \
        --machine-type n1-standard-1 --network ip-failover \
        --can-ip-forward --private-network-ip=10.128.4.100 \
        --scopes compute-rw --zone us-central1-f \
        --metadata 'startup-script=
    apt-get update
    apt-get install -y haproxy keepalived
    cat << EOF >> /etc/haproxy/haproxy.cfg
    frontend www
        bind :80
        option http-server-close
        default_backend web-backend
    backend web-backend
        server web-1 10.128.2.2:80 check
    EOF
    cat << EOF >> /etc/network/interfaces
    auto eth0:0
    iface eth0:0 inet static
        address 10.190.1.1
        netmask 255.255.255.255
    EOF
    cat << EOF >> /etc/keepalived/keepalived.conf
    vrrp_script haproxy {
        script "/bin/pidof haproxy"
        interval 2
    }
    
    vrrp_instance floating_ip {
        state MASTER
        interface eth0
        track_script {
            haproxy
        }
        unicast_src_ip 10.128.4.100
        unicast_peer {
            10.128.4.200
        }
        virtual_router_id 50
        priority 100
        authentication {
            auth_type PASS
            auth_pass yourpassword
        }
        notify_master /etc/keepalived/takeover.sh
    }
    EOF
    cat << EOF >> /etc/keepalived/takeover.sh
    #!/bin/bash
    gcloud compute routes delete floating --quiet
    gcloud compute routes create floating \
        --destination-range 10.190.1.1/32 --network ip-failover \
        --priority 500 --next-hop-instance-zone us-central1-f \
        --next-hop-instance haproxy-a --quiet
    EOF
    chmod +x /etc/keepalived/takeover.sh
    service haproxy restart
    service networking restart
    service keepalived start'
    
  2. 使用静态 IP 地址 10.128.4.200 创建辅助实例:

    gcloud compute instances create haproxy-b \
        --machine-type n1-standard-1 --network ip-failover \
        --can-ip-forward --private-network-ip=10.128.4.200 \
        --scopes compute-rw --zone us-central1-c \
        --metadata 'startup-script=
    apt-get update
    apt-get install -y haproxy keepalived
    cat << EOF >> /etc/haproxy/haproxy.cfg
    frontend www
        bind :80
        option http-server-close
        default_backend web-backend
    backend web-backend
        server web-1 10.128.2.2:80 check
    EOF
    cat << EOF >> /etc/network/interfaces
    auto eth0:0
    iface eth0:0 inet static
        address 10.190.1.1
        netmask 255.255.255.255
    EOF
    cat << EOF >> /etc/keepalived/keepalived.conf
    vrrp_script haproxy {
        script "/bin/pidof haproxy"
        interval 2
    }
    
    vrrp_instance floating_ip {
        state BACKUP
        interface eth0
        track_script {
            haproxy
        }
        unicast_src_ip 10.128.4.200
        unicast_peer {
            10.128.4.100
        }
        virtual_router_id 50
        priority 50
        authentication {
            auth_type PASS
            auth_pass yourpassword
        }
        notify_master /etc/keepalived/takeover.sh
    }
    EOF
    cat << EOF >> /etc/keepalived/takeover.sh
    #!/bin/bash
    gcloud compute routes delete floating --quiet
    gcloud compute routes create floating \
        --destination-range 10.190.1.1/32 --network ip-failover \
        --priority 500 --next-hop-instance-zone us-central1-c \
        --next-hop-instance haproxy-b --quiet
    EOF
    chmod +x /etc/keepalived/takeover.sh
    service haproxy restart
    service networking restart
    service keepalived start'
    
  3. 测试是否可以通过路由访问 HAProxy:

    gcloud compute ssh testing --zone us-central1-f
    
    username@testing:~$ curl 10.190.1.1
    <!DOCTYPE html> [...]
    username@testing:~$ exit

    当实例 haproxy-a 上的 HAProxy 被终止或该实例锁定时,VRRP 检测信号将丢失,haproxy-b 实例将调用 takeover.sh 脚本。此脚本将 10.190.1.1 的路由从 haproxy-a 移动到 haproxy-b,且测试仍然有效。

为您的使用场景选择最佳方案

对于涉及使用一组 HAProxy 节点以做出复杂路由决策的示例使用场景,首选的 Compute Engine 实现是“方案 1:内部 TCP/UDP 负载平衡”。这是因为虚拟机实例无状态,并且可以轻松地在“主动-主动”场景中运行。此外,还可以使用 Compute Engine 运行状况检查。对于其他使用场景,方案 1 则可能不是最佳选择。

除了先前列出的每个方案的优缺点之外,您可以利用以下决策树确定实现方案。

决策树

最好使用水平扩缩架构在 Compute Engine 中实现高度可用且可靠的应用,从而最大限度地减少单个节点故障带来的影响。迁移典型的本地场景(例如具有浮动 IP 地址的两台服务器)极具挑战性,因为此场景无法在 Compute Engine 中复制。如前所述,由于虚拟路由基础架构的性质,使用免费 ARP 以几亚秒的速度在不同机器间移动 IP 地址是不现实的。

内部 TCP/UDP 负载平衡使许多使用场景可以简单可靠地转移到 Compute Engine。对于无法使用内部负载平衡器的情况,您可以实现其他几个不需要复杂覆盖路由机制的方案来进行迁移。

后续步骤