设置网络负载平衡

本指南介绍如何创建基本网络负载平衡配置。该示例假定您在 Compute Engine 实例上有多个 Web 服务器,您希望在这些实例之间平衡流量。此场景设置了一个第 4 层负载平衡配置,以在运行状况良好的实例之间分配 HTTP 流量。基本 HTTP 运行状况检查已配置,确保仅将流量发送给运行状况良好的实例。

虽然此示例是对 HTTP 流量进行负载平衡,但您可以使用网络负载平衡对 UDP、TCP 和 SSL 流量进行负载平衡。在开始之前,请先阅读网络负载平衡概览,了解有关网络负载平衡的概念信息。

准备工作

安装 gcloud 命令行工具。如需全面了解此工具,请参阅 gcloud 工具指南。您可以在 gcloud compute 命令组中找到与负载平衡相关的命令。

您还可以使用 --help 标志获取有关任何 gcloud 命令的详细帮助:

gcloud compute http-health-checks create --help

如果您之前未运行过 gcloud 命令行工具,请先运行 gcloud init 进行身份验证。

此外,您还必须为负载平衡器创建一个静态外部 IP 地址。如果您使用的是 Compute Engine 提供的映像,则系统会自动配置虚拟机 (VM) 实例处理此 IP 地址。如果您使用任何其他映像,则必须将此地址配置为 eth0 上的别名或者每个实例上的环回地址。

本指南假定您熟悉 bash

配置 Compute Engine 虚拟机实例

对于此负载平衡场景,您将创建三个 Compute Engine 虚拟机实例并在实例上安装 Apache。您将添加一条允许 HTTP 流量访问这些实例的防火墙规则。

作为网络负载平衡器的后端虚拟机参与的实例必须运行相应的 Linux 客机环境Windows 客机环境或提供同等功能的其他进程。

设置后端实例

控制台

  1. 转到 Google Cloud Console 中的“虚拟机实例”页面。
    转到“虚拟机实例”页面
  2. 点击创建实例
  3. 名称设置为 www1
  4. 地区设置为 us-central1
  5. 区域设置为 us-central1-b
  6. 启动磁盘下,默认操作系统映像 Debian GNU/Linux 9 (stretch) 已选定。
  7. 点击管理、安全、磁盘、网络、单独租用以显示高级设置。
    1. 管理标签页上,将以下脚本插入到启动脚本字段:
      #! /bin/bash
      sudo apt-get update
      sudo apt-get install apache2 -y
      sudo service apache2 restart
      echo '<!doctype html><html><body><h1>www1</h1></body></html>' | tee /var/www/html/index.html
      
    2. 网络下,使用 network-lb-tag 填充标记字段。
    3. 其余字段保留默认值。
    4. 点击创建
  8. 使用相同的设置创建实例 www2,但要在自动化启动脚本字段中插入以下脚本。
    #! /bin/bash
    sudo apt-get update
    sudo apt-get install apache2 -y
    sudo service apache2 restart
    echo '<!doctype html><html><body><h1>www2</h1></body></html>' | tee /var/www/html/index.html
    
  9. 使用相同的设置创建实例 www3,但要在自动化启动脚本字段中插入以下脚本。
    #! /bin/bash
    sudo apt-get update
    sudo apt-get install apache2 -y
    sudo service apache2 restart
    echo '<!doctype html><html><body><h1>www3</h1></body></html>' | tee /var/www/html/index.html
    

gcloud

以下命令都在本地系统上运行,并且采用 bash 命令提示符。

如需查看操作系统映像名称、特性和状态,请使用 gcloud compute images list 命令。

  1. 在给定的区域中创建三个新的虚拟机,并为所有虚拟机分配相同标记。此示例将区域设置为 us-central1-b。通过设置 tags 字段,您可以一次性同时引用所有这些实例,例如使用防火墙规则。这些命令也会在每个实例上安装 Apache,还会为每个实例提供唯一的主页。

    gcloud compute instances create www1 \
      --image-family debian-9 \
      --image-project debian-cloud \
      --zone us-central1-b \
      --tags network-lb-tag \
      --metadata startup-script="#! /bin/bash
        sudo apt-get update
        sudo apt-get install apache2 -y
        sudo service apache2 restart
        echo '<!doctype html><html><body><h1>www1</h1></body></html>' | tee /var/www/html/index.html"
    gcloud compute instances create www2 \
      --image-family debian-9 \
      --image-project debian-cloud \
      --zone us-central1-b \
      --tags network-lb-tag \
      --metadata startup-script="#! /bin/bash
        sudo apt-get update
        sudo apt-get install apache2 -y
        sudo service apache2 restart
        echo '<!doctype html><html><body><h1>www2</h1></body></html>' | tee /var/www/html/index.html"
    gcloud compute instances create www3 \
      --image-family debian-9 \
      --image-project debian-cloud \
      --zone us-central1-b \
      --tags network-lb-tag \
      --metadata startup-script="#! /bin/bash
        sudo apt-get update
        sudo apt-get install apache2 -y
        sudo service apache2 restart
        echo '<!doctype html><html><body><h1>www3</h1></body></html>' | tee /var/www/html/index.html"

API

使用 instances.insert 方法在区域 us-central1-b 中创建实例 www1

POST https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/us-central1-b/instances

{
  "canIpForward": false,
  "deletionProtection": false,
  "disks": [
    {
      "type": "PERSISTENT",
      "boot": true,
      "mode": "READ_WRITE",
      "autoDelete": true,
      "deviceName": "www1",
      "initializeParams": {
        "sourceImage": "projects/eip-images/global/images/debian-9-drawfork-v20181101",
        "diskType": "projects/[PROJECT_ID]/zones/us-central1-b/diskTypes/pd-standard",
        "diskSizeGb": "10"
      }
    }
  ],
  "machineType": "projects/[PROJECT_ID]/zones/us-central1-b/machineTypes/e2-standard-2",
  "metadata": {
    "items": [
      {
        "key": "startup-script",
        "value": "sudo apt-get update\nsudo apt-get install apache2 -y\nsudo a2ensite default-ssl\nsudo a2enmod ssl\nsudo service apache2 restart\necho '<!doctype html><html><body><h1>www1</h1></body></html>' | tee /var/www/html/index.html"
      }
    ]
  },
  "name": "www1",
  "networkInterfaces": [
    {
      "network": "projects/[PROJECT_ID]/global/networks/default",
      "subnetwork": "projects/[PROJECT_ID]/regions/us-central1/subnetworks/default"
    }
  ],
  "tags": {
    "items": [
      "network-lb-tag"
    ]
  }
}

使用相同的设置创建实例 www2www3,但需要替换 deviceNamevaluename 字段中的 www1

创建一条防火墙规则以允许外部流量进入这些虚拟机实例

控制台

  1. 转到 Google Cloud Console 中的“防火墙”页面。
    转到“防火墙”页面
  2. 点击创建防火墙规则
  3. 输入 www-firewall-network-lb 作为名称
  4. 选择要应用防火墙规则的网络默认)。
  5. 目标下,选择指定的目标标记
  6. 目标标记字段中,输入 network-lb-tag
  7. 来源 IP 地址范围设置为 0.0.0.0/0(允许来自任何来源的流量)。
  8. 指定的协议和端口下,点击 TCP 旁边的复选框,然后输入 80
  9. 点击创建。新的防火墙规则可能需要一段时间才能在控制台中显示,或者您可能需要点击刷新才能看见规则。

gcloud

gcloud compute firewall-rules create www-firewall-network-lb \
    --target-tags network-lb-tag --allow tcp:80

API

使用 firewalls.insert 方法创建允许子网内所有流量通过的防火墙规则

POST https://compute.googleapis.com/compute/projects/[PROJECT_ID]/global/firewalls

{
  "name": "www-firewall-network-lb",
  "direction": "INGRESS",
  "priority": 1000,
  "targetTags": [
    "network-lb-tag"
  ],
  "allowed": [
    {
      "IPProtocol": "tcp",
      "ports": [
        "80"
      ]
    }
  ],
  "sourceRanges": [
    "0.0.0.0/0"
  ]
}

获取实例的外部 IP 地址并验证它们正在运行

控制台

  1. 转到 Google Cloud Console 中的“虚拟机实例”页面。
    转到“虚拟机实例”页面
  2. 外部 IP 列中查看您的实例的地址。
  3. 在实例名称左侧查找绿色对勾标记,以验证您的实例是否正在运行。如果您没有看到绿色对勾标记,请参阅实例的“常规问题排查”页面

gcloud

  1. 列出您的实例,从 EXTERNAL_IP 列中获取其 IP 地址。

    gcloud compute instances list
    
  2. 验证各个实例是否正在运行。

    在命令行中,使用每个实例的外部 IP 地址运行 curl,确认所有实例都能响应。

    curl http://[IP_ADDRESS]
    

API

使用 instances.get 方法获取有关实例 www1 的信息

确保 status 字段显示 RUNNING,然后在 natIP 字段中查找外部 IP 地址。

GET https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/us-central1-b/instances/www1

{
 "kind": "compute#instance",
 "id": "6734015273571474749",
 "creationTimestamp": "2018-11-09T11:45:23.487-08:00",
 "name": "www1",
 "description": "",
 "tags": {
  "items": [
   "network-lb-tag"
  ],
  "fingerprint": "9GVlO4gPawg="
 },
 "machineType": "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/us-central1-b/machineTypes/e2-standard-2",
 "status": "RUNNING",
 "zone": "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/us-central1-b",
 "canIpForward": false,
 "networkInterfaces": [
  {
   "kind": "compute#networkInterface",
   "network": "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/global/networks/default",
   "subnetwork": "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/regions/us-central1/subnetworks/default",
   "networkIP": "10.128.0.2",
   "name": "nic0",
   "accessConfigs": [
    {
     "kind": "compute#accessConfig",
     "type": "ONE_TO_ONE_NAT",
     "name": "External NAT",
     "natIP": "35.192.37.233",
     "networkTier": "PREMIUM"
    }
   ],
   "fingerprint": "lxD5f5ua_sw="
  }
 ],
 "disks": [
  {
   "kind": "compute#attachedDisk",
   "type": "PERSISTENT",
   "mode": "READ_WRITE",
   "source": "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/us-central1-b/disks/www1",
   "deviceName": "www1",
   "index": 0,
   "boot": true,
   "autoDelete": true,
   "licenses": [
    "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/licenses/debian-9-stretch"
   ],
   "interface": "SCSI",
   "guestOsFeatures": [
    {
     "type": "VIRTIO_SCSI_MULTIQUEUE"
    }
   ]
  }
 ],
 "metadata": {
  "kind": "compute#metadata",
  "fingerprint": "IyHRmHoJx6E=",
  "items": [
   {
    "key": "startup-script",
    "value": "#! /bin/bash\n sudo apt-get update\n sudo apt-get install apache2 -y\n sudo service apache2 restart\n echo '\u003c!doctype html\u003e\u003chtml\u003e\u003cbody\u003e\u003ch1\u003ewww1\u003c/h1\u003e\u003c/body\u003e\u003c/html\u003e' | tee /var/www/html/index.html"
   }
  ]
 },
 "serviceAccounts": [
  {
   "email": "674259759219-compute@developer.gserviceaccount.com",
   "scopes": [
    "https://www.googleapis.com/auth/devstorage.read_only",
    "https://www.googleapis.com/auth/logging.write",
    "https://www.googleapis.com/auth/monitoring.write",
    "https://www.googleapis.com/auth/servicecontrol",
    "https://www.googleapis.com/auth/service.management.readonly",
    "https://www.googleapis.com/auth/trace.append"
   ]
  }
 ],
 "selfLink": "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/us-central1-b/instances/www1",
 "scheduling": {
  "onHostMaintenance": "MIGRATE",
  "automaticRestart": true,
  "preemptible": false
 },
 "cpuPlatform": "Intel Haswell",
 "labelFingerprint": "42WmSpB8rSM=",
 "startRestricted": false,
 "deletionProtection": false
}

www2www3 重复此 API 调用。

配置负载平衡服务

接下来,设置负载平衡服务。

配置负载平衡服务时,虚拟机实例将接收发往您配置的静态外部 IP 地址的数据包。如果您使用的是 Compute Engine 提供的映像,则系统会自动配置您的实例处理此 IP 地址。如果您使用的是任何其他映像,则必须将此地址配置为 eth0 上的别名或者每个实例上的环回地址

控制台

  1. 转到 Google Cloud Console 中的创建负载平衡器页面。
    转到“创建负载平衡器”页面
  2. TCP 负载平衡下,点击开始配置按钮。

  3. 面向互联网或仅限内部下,选择 From Internet to my VMs

  4. 多区域或单区域下,选择 Single region only

  5. 点击继续按钮。

配置后端

  1. 新建 TCP 负载平衡器屏幕上的名称中,输入新负载平衡器的名称 www-network-lb
  2. 点击后端配置
  3. 您将看到您之前输入的负载平衡器名称,但无法进行修改。
  4. 对于地区,请选择 us-central1
  5. 后端下,点击选择现有实例标签页,然后点击添加实例。输入实例 www1。对实例 www2www3 重复此步骤。
  6. 运行状况检查下,点击创建新的运行状况检查另创建一项运行状况检查

    1. 输入 basic-check 作为运行状况检查的名称
    2. 保留默认设置。
    3. 点击保存并继续按钮。

    后端配置左侧带对勾标记的蓝色圆圈表示设置成功。

配置转发规则

  1. 点击前端配置
  2. 输入 www-rule 作为名称
  3. IP 下,点击下拉菜单并选择创建 IP 地址
    1. 保留静态 IP 地址屏幕上,指定名称 lb-ip-1
    2. 点击保留
  4. 请输入端口 80
  5. 点击完成按钮。

    前端配置左侧带对勾标记的蓝色圆圈表示设置成功。

检查配置

  1. 点击检查并最终确定按钮,检查负载平衡器的所有配置设置。
  2. 如果设置正确,请点击创建。创建负载平衡器需要几分钟的时间。

    在负载平衡屏幕上,在新负载平衡器的“后端”列下,您会看到一个绿色对勾标记,表明新的负载平衡器运行正常。

gcloud

  1. 为负载平衡器创建静态外部 IP 地址

    gcloud compute addresses create network-lb-ip-1 \
        --region us-central1
    
  2. 添加旧版 HTTP 运行状况检查资源

    本示例使用运行状况检查机制的默认设置,但您也可以自行自定义运行状况检查。

    gcloud compute http-health-checks create basic-check
    
  3. 添加目标池

    在虚拟机实例所在的区域中添加目标池。使用上一步为此目标池创建的运行状况检查。目标池需要运行状况检查服务才能正常工作。

    gcloud compute target-pools create www-pool \
        --region us-central1 --http-health-check basic-check
    
  4. 将实例添加到目标池

    gcloud compute target-pools add-instances www-pool \
        --instances www1,www2,www3 \
        --instances-zone us-central1-b
    

    目标池中的实例必须属于同一地区,但可以分布在同一地区内的不同区域中。例如,在一个目标池中,您可以具有区域 us-central1-f 中的实例和区域 us-central1-b 中的实例,因为这些区域位于同一地区 us-central1

  5. 添加转发规则

    添加转发规则,以代表指向目标池的外部 IP 地址和端口范围传送数据。对于 --address 字段,请使用数字 IP 地址或其完全限定名称。

    gcloud compute forwarding-rules create www-rule \
        --region us-central1 \
        --ports 80 \
        --address network-lb-ip-1 \
        --target-pool www-pool
    

API

  1. 为负载平衡器创建静态外部 IP 地址

    POST https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID/regions/us-central1/addresses
    {
      "name": "network-lb-ip-1"
    }
    
  2. 添加旧版 HTTP 运行状况检查

    本示例使用运行状况检查机制的默认设置,但您也可以自行自定义运行状况检查机制。

    POST https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID]/global/httpHealthChecks
    {
      "name": "basic-check"
    }
    
  3. 添加目标池

    在虚拟机实例所在的区域中添加目标池。使用上一步为此目标池创建的运行状况检查。目标池需要运行状况检查服务才能正常工作。

    POST https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID]/regions/us-central1/targetPools
    {
      "name": "www-pool",
      "healthChecks": [
        "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/global/httpHealthChecks/basic-check"
      ]
    }
    
  4. 将实例添加到目标池

    POST https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID]/regions/us-central1/targetPools/www-pool/addInstance
    {
      "instances": [
        {
          "instance": "projects/[PROJECT_ID]/zones/us-central1-b/instances/www1"
        }
      ]
    }
    

    对实例 www2www3 重复此 API 调用。

    目标池中的实例必须属于同一地区,但可以分布在同一地区内的不同区域中。例如,在一个目标池中,您可以具有区域 us-central1-f 中的实例和区域 us-central1-b 中的实例,因为这些区域位于同一地区 us-central1

  5. 添加转发规则

    POST https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID]/regions/us-central1/forwardingRules
    {
      "name": "www-rule",
      "portRange": "80",
      "loadBalancingScheme": "EXTERNAL",
      "target": "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/regions/us-central1/targetPools/www-network-lb"
    }
    

将流量发送到您的实例

在配置了负载平衡服务后,您可以开始将流量发送到转发规则并观察流量分散到不同的实例。

查找转发规则的外部 IP 地址

控制台

  1. 转到 Google Cloud Console 中高级负载平衡页面上的转发规则标签页。
    转到“转发规则”标签页
  2. 找到 www-rule,即负载平衡器使用的转发规则。
  3. www-ruleIP 地址列中,记下列出的外部 IP 地址。

gcloud

输入以下命令,查看负载平衡器使用的 www-rule 转发规则的外部 IP 地址。

gcloud compute forwarding-rules describe www-rule --region us-central1

API

使用 forwardingRules.get 方法查看 www-rule 转发规则的外部 IP 地址

在输出中,查找 IPAddress 字段。

GET https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID]/regions/us-central1/forwardingRules/www-rule
{
  "kind": "compute#forwardingRule",
  "id": "5133886346582800002",
  "creationTimestamp": "2018-11-09T14:21:33.574-08:00",
  "name": "www-rule",
  "description": "",
  "region": "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/regions/us-central1",
  "IPAddress": "35.232.228.9",
  "IPProtocol": "TCP",
  "portRange": "80-80",
  "target": "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/regions/us-central1/targetPools/www-network-lb",
  "selfLink": "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/regions/us-central1/forwardingRules/www-rule",
  "loadBalancingScheme": "EXTERNAL",
  "networkTier": "PREMIUM"
}

后端实例不支持 ICMP

网络负载平衡不会向后端实例递送 ICMP 数据包。如果您发送 ICMP 数据包(例如,使用 pingtraceroute),则响应并非来自负载平衡器的后端实例。

即使您的防火墙规则可禁止负载平衡器后端实例上的 ICMP 流量,Google Cloud 基础架构也可能会发送 ICMP 回复。此行为无法更改。

使用 curl 命令访问外部 IP 地址

来自 curl 命令的响应会在三个实例之间随机交替。如果响应最初不成功,您可能需要等待大约 30 秒才能完全加载配置,并在再次尝试前将实例的状态标记为运行状况良好:

$ while true; do curl -m1 IP_ADDRESS; done

后续步骤