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

Amazon EKS 上的网络负载均衡

当您创建 LoadBalancer 类型的 Kubernetes Service 时,会预置 AWS Network Load Balancer (NLB) 以实现网络流量负载均衡。有关 NLB 的更多信息,请参阅什么是 Network Load Balancer?。有关 Kubernetes 服务的更多信息,请参阅 Kubernetes 文档中的服务。NLB 可以与部署到 Amazon EC2 节点或 AWS Fargate IP 目标的 Pod 一起使用。您可以将AWS负载均衡器部署到公有子网或私有子网。

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

在 Amazon EKS 中,您可以将网络流量负载均衡到 NLB(实例IP 目标)。有关 NLB 目标的更多信息,请参阅网络负载均衡器用户指南中的目标类型。有关更多信息,请参阅 GitHub 上的AWS负载均衡器控制器

重要

使用 2.2.0 版本的AWS负载均衡器控制器,会弃用 Kubernetes 树内服务负载均衡器控制器,仅会接收关键错误修复。为 LoadBalancer 类型的服务预置新的网络负载均衡器时,建议使用AWS负载均衡器控制器。本主题中的信息假定您使用的是AWS负载均衡器控制器,而不是 Kubernetes 树内控制器。

Prerequisites

在对应用程序的网络流量进行负载均衡之前,您必须符合以下要求。

  • 至少有一个子网。如果在一个可用区中发现多个标记子网,则该控制器会按子网 ID 的字母表顺序选择第一个子网。

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

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

    • sharedowned

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

    • 私有子网 – 必须按如下方式标记,以便 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负载均衡器控制器不会检查路由表,并且需要存在私有和公有标记才能成功地自动发现。

Considerations

  • 您只能将 NLB IP 目标与 Amazon EKS VPC CNI 插件一起使用。您可以将 NLB 实例目标与 Amazon EKS VPC CNI 插件或备选的兼容 CNI 插件一起使用。

  • 控制器会预置 NLB,但不会预置 Classic Load Balancer。

  • 负载均衡器的配置由添加到服务清单中的注释控制。如果要在创建负载均衡器时或之后将标记添加到负载均衡器,请在服务规范中添加以下注释。有关更多信息,请参阅 Kubernetes 文档中的其他 ELB 注释

    service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags
  • 您可以通过添加以下注释,从而将弹性 IP 地址分配到网络负载均衡器。将 example-values 替换为您的弹性 IP 地址的分配 ID。分配 ID 的数量必须与用于负载均衡器的子网数量相匹配。

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

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

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

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

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

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

  • 我们建议您仅使用AWS负载均衡器控制器创建新的 NLB。尝试替换使用 Kubernetes 树内负载均衡器控制器所创建的现有 NLB 可能会产生多个可导致应用程序停机的 NLB。

创建网络负载均衡器

您可以使用 IP 或实例目标创建网络负载均衡器。选择带有要负载均衡到的目标类型的名称的选项卡。

IP targets

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

要创建使用 IP 目标的负载均衡器,请将以下注释添加到服务清单中并部署您的服务。您可以查看带有注释的示例服务清单

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

预设情况下,NLB 创建为内部 NLB。对于内部 NLB,Amazon EKS 集群必须配置为至少使用 VPC 中的一个私有子网。Kubernetes 会检查子网的路由表来确定它们是公有还是私有。公有子网有使用互联网网关直接连接到 Internet 的路由,但私有子网没有。

如果要创建面向 Internet 的 NLB,请添加以下注释:

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

过去,Kubernetes 树内控制器使用实例目标创建了 NLB。2.2.0 版或更高版本的AWS负载均衡器控制器使用实例目标创建 NLB。我们建议使用它(而不是 Kubernetes 树内控制器)来创建新的 NLB。您可以将 NLB 实例目标与部署到 Amazon EC2 节点(而不是部署到 Fargate)的 Pod 结合使用。要在部署到 Fargate 的不同 Pod 之间对网络流量进行负载均衡,必须使用 IP 目标。

要将负载均衡器部署到私有子网,您的服务规范必须具有以下注释。您可以查看带有注释的示例服务清单

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

预设情况下,NLB 创建为内部 NLB。对于内部 NLB,Amazon EKS 集群必须配置为至少使用 VPC 中的一个私有子网。Kubernetes 会检查子网的路由表来确定它们是公有还是私有。公有子网有使用互联网网关直接连接到 Internet 的路由,但私有子网没有。

如果要创建面向 Internet 的 NLB,请添加以下注释:

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

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

部署示例应用程序

部署示例应用程序

  1. 部署示例应用程序。

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

      apiVersion: apps/v1 kind: Deployment metadata: name: 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.19.6 ports: - name: http containerPort: 80
    2. 将清单应用于集群。

      kubectl apply -f sample-deployment.yaml
  2. 创建具有内部 NLB 的服务,以便将负载均衡到 IP 目标。

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

      apiVersion: v1 kind: Service metadata: name: sample-service 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
  3. 确认是否已部署相应服务。

    kubectl get svc sample-service

    输出

    NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE sample-service LoadBalancer 10.100.240.137 k8s-default-samplese-xxxxxxxxxx-xxxxxxxxxxxxxxxx.elb.us-west-2.amazonaws.com 80:32400/TCP 16h
  4. 打开 Amazon EC2 AWS Management Console。在左侧面板中选择 Target Groups(目标组)(位于 Load Balancing(负载均衡)下)。在 Name(名称)列中,选择目标组的名称,其中 Load balancer(负载均衡器)列中的值与上一步中输出的 EXTERNAL-IP 列中的名称相匹配。例如,如果您的输出与上面的输出相同,则您需要选择名为 r k8s-default-samplese-xxxxxxxxxx 的目标组。Target type(目标类型)IP,原因是其是在示例服务部署清单中指定的。

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

  6. 将流量发送到服务,将 xxxxxxxxxx-xxxxxxxxxxxxxxxx 替换为在上一步中返回的 EXTERNAL-IP 的值,并将 us-west-2 替换为您的集群所在的区域。

    curl k8s-default-samplese-xxxxxxxxxx-xxxxxxxxxxxxxxxx.elb.us-west-2.amazonaws.com

    输出

    <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ...
  7. 完成示例部署和服务后,请将其删除。

    kubectl delete service sample-service kubectl delete deployment sample-app