为混合节点配置 LoadBalancer 类型服务 - Amazon EKS
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

帮助改进此页面

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

为混合节点配置 LoadBalancer 类型服务

本主题介绍了如何为在 Amazon EKS 混合节点上运行的应用程序配置第 4 层(L4)负载均衡。LoadBalancer 类型的 Kubernetes 服务用于向集群外部公开 Kubernetes 应用程序。LoadBalancer 类型服务通常与云或本地环境中的物理负载均衡器基础设施结合使用,以处理工作负载的流量。这种负载均衡器基础设施通常通过特定于环境的控制器进行预置。

对于在 EKS 混合节点上运行的 LoadBalancer 类型服务,Amazon 支持使用 Amazon 网络负载均衡器(NLB)和 Cilium。使用 NLB 还是 Cilium 取决于应用程序流量的来源。如果应用程序流量来自某个 Amazon 区域,Amazon 建议使用 Amazon NLB 和 Amazon 负载均衡器控制器。如果应用程序流量来自本地或边缘环境,Amazon 建议使用 Cilium 的内置负载均衡功能,无论是否在环境中使用负载均衡器基础设施,均可使用该功能。

有关第 7 层(L7)应用程序流量负载均衡的信息,请参阅为混合节点配置 Kubernetes 入口。有关使用 EKS 实现负载均衡的一般信息,请参阅 Best Practices for Load Balancing

Amazon 网络负载均衡器

您可以将 Amazon 负载均衡器控制器和目标类型为 ip 的 NLB 用于在混合节点上运行的工作负载。使用目标类型 ip 时,NLB 会绕过服务层网络路径,直接将流量转发到容器组(pod)。为了让 NLB 到达混合节点上的容器组(pod)IP 目标,本地容器组(pod)CIDR 必须可在本地网络中路由。此外,Amazon 负载均衡器控制器使用 Webhook,需要来自 EKS 控制面板的直接通信。有关更多信息,请参阅 为混合节点配置 Webhook

先决条件

过程

  1. 下载Amazon负载均衡器控制器的 IAM 策略,该策略允许负载均衡器代表您调用 Amazon API。

    curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/refs/heads/main/docs/install/iam_policy.json
  2. 使用上一步中下载的策略创建一个 IAM 策略。

    aws iam create-policy \ --policy-name AWSLoadBalancerControllerIAMPolicy \ --policy-document file://iam_policy.json
  3. 将集群名称 (CLUSTER_NAME)、Amazon 区域 (AWS_REGION) 和 Amazon 账户 ID (AWS_ACCOUNT_ID) 的值替换为您的设置,然后运行以下命令。

    eksctl create iamserviceaccount \ --cluster=CLUSTER_NAME \ --namespace=kube-system \ --name=aws-load-balancer-controller \ --attach-policy-arn=arn:aws:iam::AWS_ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy \ --override-existing-serviceaccounts \ --region AWS_REGION \ --approve
  4. 添加 eks-charts Helm 图表存储库。Amazon 会在 GitHub 上维护此存储库。

    helm repo add eks https://aws.github.io/eks-charts
  5. 更新本地 Helm 存储库,确保拥有最新的图表。

    helm repo update eks
  6. 安装Amazon负载均衡器控制器。将集群名称 (CLUSTER_NAME)、Amazon 区域 (AWS_REGION)、VPC ID (VPC_ID) 和 Amazon 负载均衡器控制器 Helm 图表版本 (AWS_LBC_HELM_VERSION) 的值替换为您的设置。您可以通过运行 helm search repo eks/aws-load-balancer-controller --versions 找到最新版本的 Helm 图表。如果您运行的混合模式集群同时包含混合节点和 Amazon 云中的节点,则可以按照Amazon Load Balancer Controller 中的说明,在云端节点上运行 Amazon 负载均衡器控制器。

    helm install aws-load-balancer-controller eks/aws-load-balancer-controller \ -n kube-system \ --version AWS_LBC_HELM_VERSION \ --set clusterName=CLUSTER_NAME \ --set region=AWS_REGION \ --set vpcId=VPC_ID \ --set serviceAccount.create=false \ --set serviceAccount.name=aws-load-balancer-controller
  7. 验证 Amazon 负载均衡器控制器是否成功安装。

    kubectl get -n kube-system deployment aws-load-balancer-controller
    NAME READY UP-TO-DATE AVAILABLE AGE aws-load-balancer-controller 2/2 2 2 84s
  8. 在名为 tcp-sample-app.yaml 的文件中定义示例应用程序。以下示例使用带有 TCP 端口的简单 NGINX 部署。

    apiVersion: apps/v1 kind: Deployment metadata: name: tcp-sample-app namespace: default 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
  9. 将部署应用于集群。

    kubectl apply -f tcp-sample-app.yaml
  10. 在名为 tcp-sample-service.yaml 的文件中为部署定义 LoadBalancer 类型服务。

    apiVersion: v1 kind: Service metadata: name: tcp-sample-service namespace: default 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
  11. 将服务配置应用于集群。

    kubectl apply -f tcp-sample-service.yaml
  12. 为服务预置 NLB 可能需要几分钟时间。预置 NLB 后,将为服务分配一个与 NLB 部署的 DNS 名称相对应的地址。

    kubectl get svc tcp-sample-service
    NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE tcp-sample-service LoadBalancer 172.16.115.212 k8s-default-tcpsampl-xxxxxxxxxx-xxxxxxxxxxxxxxxx.elb.<region>.amazonaws.com 80:30396/TCP 8s
  13. 使用 NLB 的地址访问服务。

    curl k8s-default-tcpsampl-xxxxxxxxxx-xxxxxxxxxxxxxxxx.elb.<region>.amazonaws.com

    输出示例如下。

    <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> [...]
  14. 清理您创建的 资源。

    kubectl delete -f tcp-sample-service.yaml kubectl delete -f tcp-sample-app.yaml

Cilium 集群内负载均衡

Cilium 可用作在 EKS 混合节点上运行的工作负载的集群内负载均衡器,这对于没有负载均衡器基础设施的环境非常有用。Cilium 的负载均衡功能基于多种 Cilium 功能构建而成,包括 kube-proxy 替换、负载均衡器 IP 地址管理(IPAM)和 BGP 控制面板。这些功能的职责详述如下:

  • Cilium kube-proxy 替换:负责将服务流量路由到后端容器组(pod)。

  • Cilium 负载均衡器 IPAM:管理可分配给 LoadBalancer 类型服务的 IP 地址。

  • Cilium BGP 控制面板:向本地网络通告负载均衡器 IPAM 分配的 IP 地址。

如果不使用 Cilium 的 kube-proxy 替换,您仍然可以使用 Cilium 负载均衡器 IPAM 和 BGP 控制面板为 LoadBalancer 类型服务分配和指定 IP 地址。如果不使用 Cilium 的 kube-proxy 替换,则在默认情况下,服务到后端容器组(pod)的负载均衡将由 EKS 中的 kube-proxy 和 iptables 规则处理。

先决条件

  • 无论是否启用 kube-proxy 替换,都已按照为混合节点配置 CNI 中的说明安装 Cilium。Cilium 的 kube-proxy 替换需要运行 Linux 内核至少为 v4.19.57、v5.1.16 或 v5.2.0 的最新操作系统。除 Red Hat Enterprise Linux(RHEL)8.x 外,所有支持用于混合节点的操作系统的最新版本都符合此标准。

  • 按照为混合节点配置 Cilium BGP 中的说明启用 Cilium BGP 控制面板。如果您不想使用 BGP,则必须使用其他方法,使本地容器组(pod)CIDR 可在本地网络中路由,有关更多信息,请参阅可路由的远程容器组(pod)CIDR

  • 在命令行环境中安装 Helm,请参阅安装 Helm 说明

过程

  1. 创建一个名为 cilium-lbip-pool-loadbalancer.yaml 的文件,其中包含 CiliumLoadBalancerIPPool 资源,用于为 LoadBalancer 类型服务配置负载均衡器 IP 地址范围。

    • LB_IP_CIDR 替换为用于负载均衡器 IP 地址的 IP 地址范围。要选择单个 IP 地址,请使用 /32 CIDR。有关更多信息,请参阅 Cilium 文档中的 LoadBalancer IP Address Management

    • 配置 serviceSelector 字段,使其与将在后续步骤中创建的服务名称相匹配。此配置完成后,此池中的 IP 将仅分配给名为 tcp-sample-service 的服务。

      apiVersion: cilium.io/v2alpha1 kind: CiliumLoadBalancerIPPool metadata: name: tcp-service-pool spec: blocks: - cidr: "LB_IP_CIDR" serviceSelector: matchLabels: io.kubernetes.service.name: tcp-sample-service
  2. CiliumLoadBalancerIPPool 资源应用于集群。

    kubectl apply -f cilium-lbip-pool-loadbalancer.yaml
  3. 确认池中至少有一个可用的 IP 地址。

    kubectl get ciliumloadbalancerippools.cilium.io
    NAME DISABLED CONFLICTING IPS AVAILABLE AGE tcp-service-pool false False 1 24m
  4. 创建一个名为 cilium-bgp-advertisement-loadbalancer.yaml 的文件,其中包含 CiliumBGPAdvertisement 资源,用于通告将在下一步中创建的服务的负载均衡器 IP 地址。如果您不使用 Cilium BGP,则可跳过此步骤。用于服务的负载均衡器 IP 地址必须可在本地网络中路由,以便您可以在最后一步中查询服务。

    • advertisementType 字段设置为 Serviceservice.addresses 设置为 LoadBalancerIP,以仅通告 LoadBalancer 类型服务的 LoadBalancerIP

    • 配置 selector 字段,使其与将在后续步骤中创建的服务名称相匹配。此配置完成后,仅会通告名为 tcp-sample-service 的服务的 LoadBalancerIP

      apiVersion: cilium.io/v2alpha1 kind: CiliumBGPAdvertisement metadata: name: bgp-advertisement-tcp-service labels: advertise: bgp spec: advertisements: - advertisementType: "Service" service: addresses: - LoadBalancerIP selector: matchLabels: io.kubernetes.service.name: tcp-sample-service
  5. CiliumBGPAdvertisement 资源应用于集群。如果您不使用 Cilium BGP,则可跳过此步骤。

    kubectl apply -f cilium-bgp-advertisement-loadbalancer.yaml
  6. 在名为 tcp-sample-app.yaml 的文件中定义示例应用程序。以下示例使用带有 TCP 端口的简单 NGINX 部署。

    apiVersion: apps/v1 kind: Deployment metadata: name: tcp-sample-app namespace: default 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
  7. 将部署应用于集群。

    kubectl apply -f tcp-sample-app.yaml
  8. 在名为 tcp-sample-service.yaml 的文件中为部署定义 LoadBalancer 类型服务。

    • 您可以使用服务对象上的 lbipam.cilium.io/ips 注释,从负载均衡器 IP 池请求特定 IP 地址。如果您不想为服务请求特定 IP 地址,可以删除此注释。

    • loadBalancerClass 规范字段为必填字段,用于防止传统 Amazon 云提供商为服务创建经典负载均衡器。在以下示例中,将此字段配置为 io.cilium/bgp-control-plane,以将 Cilium 的 BGP 控制面板用作负载均衡器类。也可将此字段配置为 io.cilium/l2-announcer,以使用 Cilium 的 L2 通告功能(目前处于测试阶段,尚未得到 Amazon 正式支持)。

      apiVersion: v1 kind: Service metadata: name: tcp-sample-service namespace: default annotations: lbipam.cilium.io/ips: "LB_IP_ADDRESS" spec: loadBalancerClass: io.cilium/bgp-control-plane ports: - port: 80 targetPort: 80 protocol: TCP type: LoadBalancer selector: app: nginx
  9. 将服务应用于集群。服务将使用外部 IP 地址创建,您可以使用该地址访问应用程序。

    kubectl apply -f tcp-sample-service.yaml
  10. 确认服务是否已成功创建,是否为其分配了来自上一步创建的 CiliumLoadBalancerIPPool 的 IP。

    kubectl get svc tcp-sample-service
    NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE tcp-sample-service LoadBalancer 172.16.117.76 LB_IP_ADDRESS 80:31129/TCP 14m
  11. 如果您在 kube-proxy 替换模式下使用 Cilium,则可通过运行以下命令来确认 Cilium 是否正在处理服务的负载均衡。在以下输出中,10.86.2.x 地址是服务后端容器组(pod)的容器组(pod)IP 地址。

    kubectl -n kube-system exec ds/cilium -- cilium-dbg service list
    ID Frontend Service Type Backend ... 41 LB_IP_ADDRESS:80/TCP LoadBalancer 1 => 10.86.2.76:80/TCP (active) 2 => 10.86.2.130:80/TCP (active) 3 => 10.86.2.141:80/TCP (active)
  12. 确认 Cilium 正在通过 BGP 向本地网络通告 IP 地址。在以下示例中,有五个混合节点,每个节点都将向本地网络通告 tcp-sample-service 服务的 LB_IP_ADDRESS

    Node VRouter Prefix NextHop Age Attrs mi-026d6a261e355fba7 NODES_ASN LB_IP_ADDRESS/32 0.0.0.0 12m3s [{Origin: i} {Nexthop: 0.0.0.0}] mi-082f73826a163626e NODES_ASN LB_IP_ADDRESS/32 0.0.0.0 12m3s [{Origin: i} {Nexthop: 0.0.0.0}] mi-09183e8a3d755abf6 NODES_ASN LB_IP_ADDRESS/32 0.0.0.0 12m3s [{Origin: i} {Nexthop: 0.0.0.0}] mi-0d78d815980ed202d NODES_ASN LB_IP_ADDRESS/32 0.0.0.0 12m3s [{Origin: i} {Nexthop: 0.0.0.0}] mi-0daa253999fe92daa NODES_ASN LB_IP_ADDRESS/32 0.0.0.0 12m3s [{Origin: i} {Nexthop: 0.0.0.0}]
  13. 使用分配的负载均衡器 IP 地址访问服务。

    curl LB_IP_ADDRESS

    输出示例如下。

    <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> [...]
  14. 清理您创建的 资源。

    kubectl delete -f tcp-sample-service.yaml kubectl delete -f tcp-sample-app.yaml kubectl delete -f cilium-lb-ip-pool.yaml kubectl delete -f cilium-bgp-advertisement.yaml