Amazon EKS 上的网络负载均衡 - Amazon EKS

Amazon EKS 上的网络负载均衡

网络流量在 OSI 模型的 L4 上实现负载均衡。若要对 L7 上的应用程序流量进行负载均衡,请部署 Kubernetes ingress,它会预置 AWS 应用程序负载均衡器。有关更多信息,请参阅Amazon EKS 上的应用程序负载均衡。要了解更多有关两种负载均衡类型之间差异的信息,请参阅 AWS 网站上的 Elastic Load Balancing 功能

创建类型为 LoadBalancer 的 Kubernetes Service 时,AWS 云提供程序负载均衡器控制器默认创建 AWS 经典负载均衡器,但也可以创建 AWS 网络负载均衡器。此控制器将来仅接收关键错误修复。有关如何使用 AWS 云提供程序负载均衡器的更多信息,请参阅 Kubernetes 文档中的 AWS 云提供程序负载均衡器控制器。本主题中未涵盖其使用。

对于部署到 1.19 版或更高版本集群的新服务,建议您使用 2.4.2 版本或更高版本的 安装 AWS Load Balancer Controller 附加组件,而不是AWS云提供程序负载均衡器控制器。如果您的集群早于 1.19 版本,则我们建议使用 2.3.1 版本的控制器。AWS Load Balancer Controller 创建 AWS 网络负载均衡器,但不创建 AWS 经典负载均衡器。本主题的其余部分介绍如何使用 AWS 负载均衡器控制器。

AWS 网络负载均衡器可以对部署到 Amazon EC2 IP 和实例目标或 AWS Fargate IP 目标的 pods 的网络流量进行负载均衡。有关更多信息,请参阅 GitHub 上的 AWS负载均衡器控制器

先决条件

必须满足以下要求,才能使用 AWS Load Balancer Controller 对网络流量进行负载均衡。

  • 拥有现有集群。如果没有现有集群,请参阅 开始使用 Amazon EKS。如果您需要更新现有集群的版本,请参阅 更新 Amazon EKS 集群 Kubernetes 版本

  • 在集群上部署 AWS Load Balancer Controller。有关更多信息,请参阅安装 AWS Load Balancer Controller 附加组件。对于 1.19 或更高版本的集群,我们建议使用 2.4.2 或更高版本。如果您的集群早于 1.19 版本,则我们建议使用 2.3.1 版本。

  • 至少有一个子网。如果在一个可用区中发现多个标记子网,则该控制器会按子网 ID 的字典顺序选择第一个子网。子网必须具有至少 8 个可用 IP 地址。

  • 如果使用 2.1.1 或更早版本的 AWS Load Balancer Controller,则必须按如下方式标记子网。如果使用版本 2.1.2 或更高版本,则此标签是可选的。如果您在同一 VPC 中运行多个集群,或者 VPC 中有多个 AWS 服务共享子网,并且希望对每个集群中预置负载均衡器的位置时效性更多控制,则可能需要标记子网。如果您明确指定子网 ID 作为服务对象上的注释,则 Kubernetes 和 AWS Load Balancer Controller 会直接使用这些子网来创建负载均衡器。如果您选择使用此方法来预置负载均衡器,则不需要子网标记,您可以跳过以下私有和公有子网标记要求。将 cluster-name 替换为您的集群名称。

    • 密钥kubernetes.io/cluster/cluster-name

    • sharedowned

  • 除非您明确指定子网 ID 作为服务或入口对象上的注释,否则您的公有子网和私有子网必须满足以下要求。如果通过明确指定子网 ID 作为服务或入口对象上的注释来预置负载均衡器,则 Kubernetes 和 AWS Load Balancer Controller 会直接使用这些子网来创建负载均衡器,并且不需要以下标签。

    • 私有子网:必须采用以下格式标记。这样,Kubernetes 和 AWS 负载均衡器控制器就会知道子网可用于内部负载均衡器。如果您在 2020 年 3 月 26 日之后使用 eksctl 或 Amazon EKS AWS AWS CloudFormation 模板创建 VPC,则在创建子网时会对子网进行适当标记。有关 Amazon EKS AWS AWS CloudFormation VPC 模板的更多信息,请参阅 为 Amazon EKS 集群创建 VPC

      • 密钥kubernetes.io/role/internal-elb

      • 1

    • 公有子网:必须采用以下格式标记。这样,Kubernetes 就会知道仅将这些子网用于外部负载均衡器,而不是在每个可用区中选择公有子网(按子网 ID 的词典式顺序选择)。如果您在 2020 年 3 月 26 日之后使用 eksctl 或 Amazon EKS AWS CloudFormation 模板创建 VPC,则在创建子网时会对子网进行适当标记。有关 Amazon EKS AWS CloudFormation VPC 模板的更多信息,请参阅 为 Amazon EKS 集群创建 VPC

      • 密钥kubernetes.io/role/elb

      • 1

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

注意事项

  • 负载均衡器的配置由添加到服务清单中的注释控制。使用 AWS Load Balancer Controller 和使用 AWS 云提供程序负载均衡器控制器的服务注释不同。部署服务前,请务必检查 AWS Load Balancer Controller 的注释

  • 使用 Amazon VPC CNI plugin for Kubernetes 时,AWS Load Balancer Controller 可以对 Amazon EC2 IP 或实例目标和 Fargate IP 目标进行负载均衡。使用备选的兼容 CNI 插件时,控制器只能对实例目标进行负载均衡。有关 Network Load Balancer 目标类型的更多信息,请参阅 Network Load Balancer 用户指南中的目标类型

  • 如果要在创建负载均衡器时或之后将标记添加到负载均衡器,请在服务规范中添加以下注释。有关更多信息,请参阅 AWS Load Balancer Controller 文档中的 AWS 资源标签

    service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags
  • 您可以通过添加以下注释,从而将弹性 IP 地址分配到 Network Load Balancer。请将 example-values 替换为弹性 IP 地址的 Allocation IDsAllocation IDs 的数量必须与用于负载均衡器的子网数量相匹配。有关更多信息,请参阅 AWS Load Balancer Controller 文档。

    service.beta.kubernetes.io/aws-load-balancer-eip-allocations: eipalloc-xxxxxxxxxxxxxxxxx,eipalloc-yyyyyyyyyyyyyyyyy
  • Amazon EKS 将一条入站规则添加到节点的安全组用于客户端流量,并添加一条规则用于 VPC 中的每个负载均衡器子网,对您创建的每个 Network Load Balancer 进行运行状况检查。如果 Amazon EKS 尝试创建的规则数超出安全组允许的最大规则数配额,则部署 LoadBalancer 类型的服务可能会失败。有关更多信息,请参阅 Amazon VPC 用户指南的 Amazon VPC 配额中的安全组。请考虑以下选项,以最大限度地减少超过安全组最大规则数的可能性:

    • 请求增加每个安全组配额的规则数。有关更多信息,请参阅 Service Quotas 用户指南中的请求增加配额

    • 使用 IP 目标,而不是实例目标。对于 IP 目标,可以为相同目标端口共享规则。可以使用注释手动指定负载均衡器子网。有关更多信息,请参阅 GitHub 上的注释

    • 使用入口(而不是 LoadBalancer 类型的服务)将流量发送到您的服务。AWS Application Load Balancer 需要的规则数比 Network Load Balancer 少。您可以跨多个入口共享 ALB。有关更多信息,请参阅Amazon EKS 上的应用程序负载均衡。您无法跨多个服务共享 Network Load Balancer。

    • 将您的集群部署到多个账户。

  • 如果您的 pods 在 Amazon EKS 集群中的 Windows 上运行,则采用负载均衡器的单个服务最多可支持 64 个后端 pods。每个 pod 都有自己的唯一 IP 地址。这是对 Amazon EC2 节点上 Windows 操作系统的限制。

  • 我们建议您仅使用 AWS Load Balancer Controller 创建新的网络负载均衡器。尝试替换使用 AWS 云提供程序负载均衡器控制器创建的现有 Network Load Balancer,将产生多个可能导致应用程序停机的 Network Load Balancer。

创建网络负载均衡器

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

IP targets

您可以将 IP 目标与部署到 Amazon EC2 节点或 Fargate 的 pods 结合使用。您的 Kubernetes 服务必须创建为类型 LoadBalancer。有关更多信息,请参阅 Kubernetes 文档中的类型 LoadBalancer

要创建使用 IP 目标的负载均衡器,请将以下注释添加到服务清单中并部署您的服务。aws-load-balancer-typeexternal 值是导致 AWS Load Balancer Controller 而不是 AWS 云提供程序负载均衡器控制器创建网络负载均衡器的原因。您可以查看带有注释的示例服务清单

service.beta.kubernetes.io/aws-load-balancer-type: "external" service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
注意

如果要对 IPv6 pods 进行负载均衡,请添加以下注释。您只能通过 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"

重要

创建服务后,请勿编辑注释。如果需要对其进行修改,请删除相应服务对象,然后使用此注释的所需值重新创建它。

Instance targets

AWS 云提供程序负载均衡器控制器仅使用实例目标创建 Network Load Balancer。2.2.0 版和更高版本的 AWS 负载均衡器控制器也使用实例目标创建网络负载均衡器。我们建议使用该控制器而不是 AWS 云提供程序负载均衡器控制器来创建新的 Network Load Balancer。您可以将网络负载均衡器实例目标与部署到 Amazon EC2 节点(而不是部署到 Fargate)的 pods 结合使用。要在部署到 Fargate 的不同 pods 之间对网络流量进行负载均衡,必须使用 IP 目标。

要将 Network Load Balancer 部署到私有子网,您的服务规范须具有以下注释。您可以查看带有注释的示例服务清单aws-load-balancer-typeexternal 值是导致 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 创建。对于内部网络负载均衡器,Amazon EKS 集群必须配置为使用 VPC 中的至少一个私有子网。Kubernetes 会检查子网的路由表来确定它们是公有还是私有。公有子网有使用互联网网关直接连接到 Internet 的路由,但私有子网没有。

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

service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
重要

创建服务后,请勿编辑注释。如果需要对其进行修改,请删除相应服务对象,然后使用此注释的所需值重新创建它。

(可选)部署示例应用程序

先决条件

部署示例应用程序

  1. 如果部署到 Fargate,请确保您的 VPC 中有一个可用的私有子网,然后创建 Fargate 配置文件。如果您不部署到 Fargate,请跳过此步骤。您可以通过运行以下命令来创建配置文件,也可以在 AWS Management Console 中,使用该命令中 namenamespace 的相同值创建配置文件。将 example values 替换为您自己的值。

    eksctl create fargateprofile \ --cluster my-cluster \ --region region-code \ --name nlb-sample-app \ --namespace nlb-sample-app
  2. 部署示例应用程序。

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

      kubectl create namespace nlb-sample-app
    2. 将以下内容保存到计算机上名为 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.21 ports: - name: tcp containerPort: 80
    3. 将清单应用于集群。

      kubectl apply -f sample-deployment.yaml
  3. 创建具有面向互联网的网络负载均衡器的服务,以便将负载均衡到 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
    2. 将清单应用于集群。

      kubectl apply -f sample-service.yaml
  4. 确认是否已部署相应服务。

    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.137xxxxxxxxxx-xxxxxxxxxxxxxxxx 的值与示例输出不同(这些值将是您的负载均衡器独有的),并且 us-west-2 可能因集群所在的 AWS 区域 而有所不同。

  5. 打开 Amazon EC2 AWS Management Console。在左侧导航窗格中,选择 Target Groups(目标组)(位于 Load Balancing(负载均衡)下)。在 Name(名称)列中,选择目标组的名称,其中 Load balancer(负载均衡器)列的值与上一步输出的 EXTERNAL-IP 列中的一部分名称相匹配。例如,如果您的输出与上面的输出相同,则应需要选择名为 k8s-default-samplese-xxxxxxxxxx 的目标组。Target type(目标类型)为 IP,因为在示例服务清单中指定。

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

  7. 将流量发送到服务,将 xxxxxxxxxx-xxxxxxxxxxxxxxxxus-west-2 替换为在上一步输出中为 EXTERNAL-IP 返回的值。如果您已部署到私有子网,则需要从 VPC 中的设备(例如堡垒主机)查看页面。有关更多信息,请参阅 AWS 上的 Linux 堡垒机主机

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

    输出示例如下。

    <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ...
  8. 完成示例部署、服务和命名空间后,将其移除。

    kubectl delete namespace nlb-sample-app