

 **帮助改进此页面** 

要帮助改进本用户指南，请选择位于每个页面右侧窗格中的**在 GitHub 上编辑此页面**链接。

# 使用网络负载均衡器路由 TCP 和 UDP 流量
<a name="network-load-balancing"></a>

**注意**  
 **新增：**Amazon EKS 自动模式可自动执行负载均衡例行任务。有关更多信息，请参阅：  
 [将示例负载均衡器工作负载部署到 EKS 自动模式](auto-elb-example.md) 
 [使用服务注释配置网络负载均衡器](auto-configure-nlb.md) 

网络流量在 OSI 模型的 `L4` 上实现负载均衡。若要对 `L7` 上的应用程序流量进行负载均衡，请部署 Kubernetes `ingress`，它会预置 AWS 应用程序负载均衡器。有关更多信息，请参阅 [使用应用程序负载均衡器路由应用程序和 HTTP 流量](alb-ingress.md)。要了解更多有关两种负载均衡类型之间差异的信息，请参阅 AWS 网站上的 [Elastic Load Balancing 功能](https://aws.amazon.com/elasticloadbalancing/features/)。

创建类型为 `LoadBalancer` 的 Kubernetes `Service` 时，AWS 云提供程序负载均衡器控制器默认创建 AWS [经典负载均衡器 ](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/introduction.html)，但也可以创建 AWS [Network Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/introduction.html)。此控制器将来仅接收关键错误修复。有关如何使用 AWS 云提供程序负载均衡器的更多信息，请参阅 Kubernetes 文档中的 [AWS 云提供程序负载均衡器控制器](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer)。本主题中未涵盖其使用。

我们建议您使用版本 `2.7.2` 或更高版本的 [AWS Load Balancer Controller](aws-load-balancer-controller.md)，而不是AWS 云提供程序负载均衡器控制器。AWS 负载均衡器控制器创建 AWS 网络负载均衡器，但不创建 AWS 经典负载均衡器。本主题的其余部分介绍如何使用 AWS 负载均衡器控制器。

AWS 网络负载均衡器可以对部署到 Amazon EC2 IP 和实例[目标](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-target-groups.html#target-type)、AWS Fargate IP 目标或 Amazon EKS 混合节点功能即 IP 目标的容器组（pod）的网络流量进行负载均衡。有关更多信息，请参阅 GitHub 上的 [AWS Load Balancer Controller](https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/guide/targetgroupbinding/targetgroupbinding/#targettype)。

## 先决条件
<a name="_prerequisites"></a>

必须满足以下要求，才能使用 AWS 负载均衡器控制器对网络流量进行负载均衡。
+ 拥有现有集群。如果您没有现有集群，请参阅[开始使用 Amazon EKS](getting-started.md)。如果您需要更新现有集群的版本，请参阅 [将现有集群更新到新的 Kubernetes 版本](update-cluster.md)。
+ 在集群上部署 AWS Load Balancer Controller。有关更多信息，请参阅 [使用 AWS 负载均衡器控制器路由互联网流量](aws-load-balancer-controller.md)。建议升级到版本 `2.7.2` 或更高版本。
+ 至少有一个子网。如果在一个可用区中发现多个标记子网，则该控制器会按子网 ID 的字典顺序选择第一个子网。子网必须具有至少 8 个可用 IP 地址。
+ 如果使用 `2.1.1` 或更低版本的 AWS 负载均衡器控制器，则必须按如下方式标记子网。如果使用版本 `2.1.2` 或更高版本，则此标签是可选的。如果您在同一 VPC 中运行多个集群，或者 VPC 中有多个 AWS 服务共享子网，并且希望对每个集群中预置负载均衡器的位置时效性更多控制，则可能需要标记子网。如果您明确指定子网 ID 作为服务对象上的注释，则 Kubernetes 和 AWS 负载均衡器控制器会直接使用这些子网来创建负载均衡器。如果您选择使用此方法来预置负载均衡器，则不需要子网标记，您可以跳过以下私有和公有子网标记要求。将 *my-cluster* 替换为您的集群名称。
  +  **密钥** – `kubernetes.io/cluster/<my-cluster>` 
  +  **值** – `shared` 或 `owned` 
+ 除非您明确指定子网 ID 作为服务或入口对象上的注释，否则您的公有子网和私有子网必须满足以下要求。如果通过明确指定子网 ID 作为服务或入口对象上的注释来预置负载均衡器，则 Kubernetes 和 AWS 负载均衡器控制器会直接使用这些子网来创建负载均衡器，并且不需要以下标记。
  +  **私有子网**：必须采用以下格式标记。这样 Kubernetes 和 AWS 负载均衡器控制器就会知道子网可用于内部负载均衡器。如果您在 2020 年 3 月 26 日之后使用 `eksctl` 或 Amazon EKS AWS AWS CloudFormation 模板创建 VPC，则在创建子网时会对子网进行适当标记。有关 Amazon EKS AWS AWS CloudFormation VPC 模板的更多信息，请参阅[为您的 Amazon EKS 集群创建 Amazon VPC](creating-a-vpc.md)。
    +  **密钥** – `kubernetes.io/role/internal-elb` 
    +  **值** – `1` 
  +  **公有子网**：必须采用以下格式标记。这样， Kubernetes 就会知道仅将这些子网用于外部负载均衡器，而不是在每个可用区中选择公有子网（按子网 ID 的字典表顺序选择）。如果您在 2020 年 3 月 26 日之后使用 `eksctl` 或 Amazon EKS AWS CloudFormation 模板创建 VPC，则在创建子网时会对子网进行适当标记。有关 Amazon EKS AWS CloudFormation VPC 模板的更多信息，请参阅[为您的 Amazon EKS 集群创建 Amazon VPC](creating-a-vpc.md)。
    +  **密钥** – `kubernetes.io/role/elb` 
    +  **值** – `1` 

  如果未显式添加子网角色标记，则 Kubernetes 服务控制器将检查集群 VPC 子网的路由表，确定子网是私有子网还是公有子网。我们建议您不要依赖此行为，而是明确地添加私有或公有角色标记。AWS 负载均衡器控制器不会检查路由表，并且需要存在私有和公有标记才能成功地自动发现。

## 注意事项
<a name="_considerations"></a>
+ 负载均衡器的配置由添加到服务清单中的注释控制。使用 AWS 负载均衡器控制器和使用 AWS 云提供程序负载均衡器控制器的服务注释不同。部署服务前，请务必检查 AWS 负载均衡器控制器的[注释](https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/guide/service/annotations/)。
+ 使用[适用于 Kubernetes 的 Amazon VPC CNI 插件](managing-vpc-cni.md)时，AWS 负载均衡器控制器可以对 Amazon EC2 IP 或实例目标和 Fargate IP 目标进行负载均衡。使用[备选的兼容 CNI 插件](alternate-cni-plugins.md)时，控制器只能对实例目标进行负载均衡，除非您要对 Amazon EKS 混合节点功能执行负载均衡。对于混合节点，控制器可以对 IP 目标进行负载均衡。有关 Network Load Balancer 目标类型的更多信息，请参阅 Network Load Balancer 用户指南中的[目标类型](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-target-groups.html#target-type)
+ 如果要在创建负载均衡器时或之后将标记添加到负载均衡器，请在服务规范中添加以下注释。有关更多信息，请参阅 AWS Load Balancer Controller 文档中的 [AWS 资源标签](https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/guide/service/annotations/#aws-resource-tags)。

  ```
  service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags
  ```
+ 您可以通过添加以下注释，从而将[弹性 IP 地址](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html)分配到 Network Load Balancer。将示例值替换为弹性 IP 地址的 `Allocation IDs`。`Allocation IDs` 的数量必须与用于负载均衡器的子网数量相匹配。有关更多信息，请参阅 [AWS Load Balancer Controller](https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/guide/service/annotations/#eip-allocations) 文档。

  ```
  service.beta.kubernetes.io/aws-load-balancer-eip-allocations: eipalloc-xxxxxxxxxxxxxxxxx,eipalloc-yyyyyyyyyyyyyyyyy
  ```
+ 对于您创建的每个网络负载均衡器，Amazon EKS 会向节点的安全组添加一个用于客户端流量的入站规则，并为 VPC 中的每个负载均衡器子网添加一个用于运行状况检查的规则。如果 Amazon EKS 尝试创建的规则超过安全组允许的最大规则数配额，则部署 `LoadBalancer` 类型的服务可能会失败。有关更多信息，请参阅 Amazon VPC 用户指南的 Amazon VPC 配额中的[安全组](https://docs.aws.amazon.com/vpc/latest/userguide/amazon-vpc-limits.html#vpc-limits-security-groups)。请考虑以下选项，以最大限度地减少超过安全组最大规则数的可能性：
  + 请求增加每个安全组配额的规则数。有关更多信息，请参阅 Service Quotas 用户指南中的[请求增加配额](https://docs.aws.amazon.com/servicequotas/latest/userguide/request-quota-increase.html)。
  + 使用 IP 目标，而不是实例目标。对于 IP 目标，可以为相同目标端口共享规则。可以使用注释手动指定负载均衡器子网。有关更多信息，请参阅 GitHub 上的[注释](https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/guide/service/annotations/)。
  + 使用入口（而不是 `LoadBalancer` 类型的服务）将流量发送到您的服务。AWS Application Load Balancer 需要的规则数比 Network Load Balancer 少。您可以跨多个入口共享 ALB。有关更多信息，请参阅 [使用应用程序负载均衡器路由应用程序和 HTTP 流量](alb-ingress.md)。您无法跨多个服务共享网络负载均衡器。
  + 将您的集群部署到多个账户。
+ 如果您的容器组（pod）在 Windows 上运行，则在 Amazon EKS 集群中，采用负载均衡器的单个服务最多可支持 1024 个后端容器组（pod）。每个 Pod 都有自己的唯一 IP 地址。
+ 我们建议您仅使用 AWS 负载均衡器控制器创建新的 Network Load Balancer。尝试替换使用 AWS 云提供程序负载均衡器控制器创建的现有 Network Load Balancer，将产生多个可能导致应用程序停机的 Network Load Balancer。

## 创建网络负载均衡器
<a name="network-load-balancer"></a>

您可以使用 IP 或实例目标创建网络负载均衡器。

### 创建网络负载均衡器 – IP 目标
<a name="_create_network_load_balancerip_targets"></a>
+ 您可以将 IP 目标与部署到 Amazon EC2 节点、Fargate 或 Amazon EKS 混合节点功能的容器组（pod）结合使用。您的 Kubernetes 服务必须创建为类型 `LoadBalancer`。有关更多信息，请参阅 Kubernetes 文档中的[类型 LoadBalancer](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer)。

  要创建使用 IP 目标的负载均衡器，请将以下注释添加到服务清单中并部署您的服务。`aws-load-balancer-type` 的 `external` 值是导致 AWS 负载均衡器控制器而不是 AWS 云提供程序负载均衡器控制器创建 Network Load Balancer 的原因。您可以查看带有注释的[示例服务清单](#network-load-balancing-service-sample-manifest)。

  ```
  service.beta.kubernetes.io/aws-load-balancer-type: "external"
  service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
  ```
**注意**  
如果要对 `IPv6` 容器组（pod）进行负载均衡，请添加以下注释。您只能通过 `IPv6` 对 IP 目标进行负载均衡，无法对实例目标进行负载均衡。如果没有此注释，则通过 `IPv4` 进行负载均衡。

  ```
  service.beta.kubernetes.io/aws-load-balancer-ip-address-type: dualstack
  ```

  默认情况下，Network Load Balancer 使用 `internal` `aws-load-balancer-scheme` 创建。您可以在集群 VPC 的任意子网中启动网络负载均衡器，包括在创建集群时未指定的子网。

  Kubernetes 会检查子网的路由表来确定它们是公有还是私有。公有子网有使用互联网网关直接连接到 Internet 的路由，但私有子网没有。

  如果要在公有子网中创建 Network Load Balancer 以将负载均衡到 Amazon EC2 节点（Fargate 只能是私有的），请指定具有以下注释的 `internet-facing`：

  ```
  service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
  ```
**注意**  
仍支持 `service.beta.kubernetes.io/aws-load-balancer-type: "nlb-ip"` 注释的向后兼容性。但是，我们建议您将以前的注释用于新负载均衡器，而不是 `service.beta.kubernetes.io/aws-load-balancer-type: "nlb-ip"`。
**重要**  
创建服务后，请勿编辑注释。如果需要对其进行修改，请删除相应服务对象，然后使用此注释的所需值重新创建它。

### 创建网络负载均衡器 – 实例目标
<a name="_create_network_load_balancerinstance_targets"></a>
+ AWS 云提供程序负载均衡器控制器仅使用实例目标创建 Network Load Balancer。`2.2.0` 版和更高版本的 AWS 负载均衡器控制器也使用实例目标创建网络负载均衡器。我们建议使用该控制器而不是 AWS 云提供程序负载均衡器控制器来创建新的 Network Load Balancer。您可以将网络负载均衡器实例目标与部署到 Amazon EC2 节点（而不是部署到 Fargate）的容器组（pod）结合使用。要在部署到 Fargate 的不同 Pod 之间对网络流量进行负载均衡，必须使用 IP 目标。

  要将 Network Load Balancer 部署到私有子网，您的服务规范须具有以下注释。您可以查看带有注释的[示例服务清单](#network-load-balancing-service-sample-manifest)。`aws-load-balancer-type` 的 `external` 值是导致 AWS 负载均衡器控制器而不是 AWS 云提供程序负载均衡器控制器创建 Network Load Balancer 的原因。

  ```
  service.beta.kubernetes.io/aws-load-balancer-type: "external"
  service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "instance"
  ```

  默认情况下，Network Load Balancer 使用 `internal` `aws-load-balancer-scheme` 创建。对于内部 Network Load Balancer，Amazon EKS 集群必须配置为使用 VPC 中的至少一个私有子网。Kubernetes 会检查子网的路由表来确定它们是公有还是私有。公有子网有使用互联网网关直接连接到 Internet 的路由，但私有子网没有。

  如果要在公有子网中创建 Network Load Balancer 以将负载均衡到 Amazon EC2 节点，请指定具有以下注释的 `internet-facing`：

  ```
  service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
  ```
**重要**  
创建服务后，请勿编辑注释。如果需要对其进行修改，请删除相应服务对象，然后使用此注释的所需值重新创建它。

## （可选）部署示例应用程序
<a name="load-balancer-sample-application"></a>
+ 集群 VPC 中至少有一个公有或私有子网。
+ 在集群上部署 AWS Load Balancer Controller。有关更多信息，请参阅 [使用 AWS 负载均衡器控制器路由互联网流量](aws-load-balancer-controller.md)。建议升级到版本 `2.7.2` 或更高版本。

  1. 如果部署到 Fargate，请确保您的 VPC 中有一个可用的私有子网，然后创建 Fargate 配置文件。如果您不部署到 Fargate，请跳过此步骤。您可以通过运行以下命令来创建配置文件，也可以在 [AWS 管理控制台](fargate-profile.md#create-fargate-profile) 中，使用该命令中 `name` 和 `namespace` 的相同值创建配置文件。将 example values 替换为您自己的值。

     ```
     eksctl create fargateprofile \
         --cluster my-cluster \
         --region region-code \
         --name nlb-sample-app \
         --namespace nlb-sample-app
     ```

  1. 部署示例应用程序。

     1. 为应用程序创建命名空间。

        ```
        kubectl create namespace nlb-sample-app
        ```

     1. 将以下内容保存到计算机上名为 `sample-deployment.yaml` 文件的文件中。

        ```
        apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: nlb-sample-app
          namespace: nlb-sample-app
        spec:
          replicas: 3
          selector:
            matchLabels:
              app: nginx
          template:
            metadata:
              labels:
                app: nginx
            spec:
              containers:
                - name: nginx
                  image: public.ecr.aws/nginx/nginx:1.23
                  ports:
                    - name: tcp
                      containerPort: 80
        ```

     1. 将清单应用于集群。

        ```
        kubectl apply -f sample-deployment.yaml
        ```

  1. 创建具有面向互联网的网络负载均衡器的服务，以便将负载均衡到 IP 目标。

     1.  将以下内容保存到计算机上名为 `sample-service.yaml` 文件的文件中。如果部署到 Fargate 节点，请删除 `service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing` 行。

        ```
        apiVersion: v1
        kind: Service
        metadata:
          name: nlb-sample-service
          namespace: nlb-sample-app
          annotations:
            service.beta.kubernetes.io/aws-load-balancer-type: external
            service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
            service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
        spec:
          ports:
            - port: 80
              targetPort: 80
              protocol: TCP
          type: LoadBalancer
          selector:
            app: nginx
        ```

     1. 将清单应用于集群。

        ```
        kubectl apply -f sample-service.yaml
        ```

  1.  确认是否已部署相应服务。

     ```
     kubectl get svc nlb-sample-service -n nlb-sample-app
     ```

     示例输出如下。

     ```
     NAME            TYPE           CLUSTER-IP         EXTERNAL-IP                                                                    PORT(S)        AGE
     sample-service  LoadBalancer   10.100.240.137   k8s-nlbsampl-nlbsampl-xxxxxxxxxx-xxxxxxxxxxxxxxxx.elb.region-code.amazonaws.com  80:32400/TCP   16h
     ```
**注意**  
*10.100.240.137* 和 *xxxxxxxxxx*-*xxxxxxxxxxxxxxxx* 的值与示例输出不同（它们将是您的负载均衡器独有的），并且 *us-west-2* 根据集群所在的 AWS 区域而不同。

  1. 打开 [Amazon EC2 AWS 管理控制台](https://console.aws.amazon.com/ec2)。在左侧导航窗格中，选择 **Target Groups**（目标组）（位于 **Load Balancing**（负载均衡）下）。在**名称**列中，选择目标组的名称，其中**负载均衡器**列的值与上一步输出的 `EXTERNAL-IP` 列中的一部分名称相匹配。例如，如果您的输出与之前的输出相同，则应选择名为 `k8s-default-samplese-xxxxxxxxxx ` 的目标组。**Target type**（目标类型）为 `IP`，因为在示例服务清单中指定。

  1. 选择 **Target group（目标组）**，然后选择 **Targets（目标）**选项卡。在 **Registered targets（已注册目标）**中，您应该可看到上一步中部署的三个副本的三个 IP 地址。在所有目标的状态均为 **healthy（正常）**之前，请耐心等待，然后再继续。可能需要几分钟时间所有目标的状态才能达到 `healthy`。在更改为 `healthy` 状态之前，目标可能是 `unhealthy` 状态。

  1. 将流量发送到服务，将 *xxxxxxxxxx-xxxxxxxxxxxxxxxx* 和 *us-west-2* 替换为在[上一步](#nlb-sample-app-verify-deployment)输出中为 `EXTERNAL-IP` 返回的值。如果您已部署到私有子网，则需要从 VPC 中的设备（例如堡垒主机）查看页面。有关更多信息，请参阅 [AWS 上的 Linux 堡垒主机](https://aws.amazon.com/quickstart/architecture/linux-bastion/)。

     ```
     curl k8s-default-samplese-xxxxxxxxxx-xxxxxxxxxxxxxxxx.elb.region-code.amazonaws.com
     ```

     示例输出如下。

     ```
     <!DOCTYPE html>
     <html>
     <head>
     <title>Welcome to nginx!</title>
     [...]
     ```

  1. 完成示例部署、服务和命名空间后，将其移除。

     ```
     kubectl delete namespace nlb-sample-app
     ```