

 **帮助改进此页面** 

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

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

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

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

有关第 7 层（L7）应用程序流量负载均衡的信息，请参阅[为混合节点配置 Kubernetes 入口](hybrid-nodes-ingress.md)。有关使用 EKS 实现负载均衡的一般信息，请参阅 [Best Practices for Load Balancing](https://docs.aws.amazon.com/eks/latest/best-practices/load-balancing.html)。

## AWS 网络负载均衡器


您可以将 [AWS 负载均衡器控制器](aws-load-balancer-controller.md)和目标类型为 `ip` 的 NLB 用于在混合节点上运行的工作负载。使用目标类型 `ip` 时，NLB 会绕过服务层网络路径，直接将流量转发到容器组（pod）。为了让 NLB 到达混合节点上的容器组（pod）IP 目标，本地容器组（pod）CIDR 必须可在本地网络中路由。此外，AWS 负载均衡器控制器使用 Webhook，需要来自 EKS 控制面板的直接通信。有关更多信息，请参阅 [为混合节点配置 Webhook](hybrid-nodes-webhooks.md)。
+ 有关子网配置要求，请参阅[使用网络负载均衡器路由 TCP 和 UDP 流量](network-load-balancing.md)；有关 AWS 网络负载均衡器及 AWS 负载均衡器控制器的其他信息，请参阅[使用 Helm 安装 AWS 负载均衡器控制器](lbc-helm.md) 和 [Best Practices for Load Balancing](https://docs.aws.amazon.com/eks/latest/best-practices/load-balancing.html)。
+ 有关可应用于使用 AWS 网络负载均衡器的 `LoadBalancer` 类型服务的配置，请参阅 [AWS Load Balancer Controller NLB configurations](https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/guide/service/nlb/)。

### 先决条件

+ 按照[为混合节点配置 CNI](hybrid-nodes-cni.md)中的说明安装 Cilium。
+ 按照[为混合节点配置 Cilium BGP](hybrid-nodes-cilium-bgp.md) 中的说明启用 Cilium BGP 控制面板。如果您不想使用 BGP，则必须使用其他方法，使本地容器组（pod）CIDR 可在本地网络中路由，有关更多信息，请参阅[可路由的远程容器组（pod）CIDR](hybrid-nodes-concepts-kubernetes.md#hybrid-nodes-concepts-k8s-pod-cidrs)。
+ 在命令行环境中安装 Helm，请参阅[安装 Helm 说明](helm.md)。
+ 在命令行环境中安装 eksctl，请参阅[安装 eksctl 说明](install-kubectl.md#eksctl-install-update)。

### 过程


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

   ```
   curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/refs/heads/main/docs/install/iam_policy.json
   ```

1. 使用上一步中下载的策略创建一个 IAM 策略。

   ```
   aws iam create-policy \
       --policy-name AWSLoadBalancerControllerIAMPolicy \
       --policy-document file://iam_policy.json
   ```

1. 将集群名称 (`CLUSTER_NAME`)、AWS 区域 (`AWS_REGION`) 和 AWS 账户 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
   ```

1. 添加 eks-charts Helm 图表存储库。AWS 会在 GitHub 上维护此存储库。

   ```
   helm repo add eks https://aws.github.io/eks-charts
   ```

1. 更新本地 Helm 存储库，确保拥有最新的图表。

   ```
   helm repo update eks
   ```

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

   ```
   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
   ```

1. 验证 AWS 负载均衡器控制器是否成功安装。

   ```
   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
   ```

1. 在名为 `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
   ```

1. 将部署应用于集群。

   ```
   kubectl apply -f tcp-sample-app.yaml
   ```

1. 在名为 `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
   ```

1. 将服务配置应用于集群。

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

1. 为服务预置 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
   ```

1. 使用 NLB 的地址访问服务。

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

   输出示例如下。

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

1. 清理您创建的 资源。

   ```
   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](hybrid-nodes-cni.md) 中的说明安装 Cilium。Cilium 的 kube-proxy 替换需要运行 Linux 内核至少为 v4.19.57、v5.1.16 或 v5.2.0 的最新操作系统。除 Red Hat Enterprise Linux（RHEL）8.x 外，所有支持用于混合节点的操作系统的最新版本都符合此标准。
+ 按照[为混合节点配置 Cilium BGP](hybrid-nodes-cilium-bgp.md) 中的说明启用 Cilium BGP 控制面板。如果您不想使用 BGP，则必须使用其他方法，使本地容器组（pod）CIDR 可在本地网络中路由，有关更多信息，请参阅[可路由的远程容器组（pod）CIDR](hybrid-nodes-concepts-kubernetes.md#hybrid-nodes-concepts-k8s-pod-cidrs)。
+ 在命令行环境中安装 Helm，请参阅[安装 Helm 说明](helm.md)。

### 过程


1. 创建一个名为 `cilium-lbip-pool-loadbalancer.yaml` 的文件，其中包含 `CiliumLoadBalancerIPPool` 资源，用于为 LoadBalancer 类型服务配置负载均衡器 IP 地址范围。
   + 将 `LB_IP_CIDR` 替换为用于负载均衡器 IP 地址的 IP 地址范围。要选择单个 IP 地址，请使用 `/32` CIDR。有关更多信息，请参阅 Cilium 文档中的 [LoadBalancer IP Address Management](https://docs.cilium.io/en/stable/network/lb-ipam/)。
   + 配置 `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
     ```

1. 将 `CiliumLoadBalancerIPPool` 资源应用于集群。

   ```
   kubectl apply -f cilium-lbip-pool-loadbalancer.yaml
   ```

1. 确认池中至少有一个可用的 IP 地址。

   ```
   kubectl get ciliumloadbalancerippools.cilium.io
   ```

   ```
   NAME               DISABLED   CONFLICTING   IPS AVAILABLE   AGE
   tcp-service-pool   false      False         1               24m
   ```

1. 创建一个名为 `cilium-bgp-advertisement-loadbalancer.yaml` 的文件，其中包含 `CiliumBGPAdvertisement` 资源，用于通告将在下一步中创建的服务的负载均衡器 IP 地址。如果您不使用 Cilium BGP，则可跳过此步骤。用于服务的负载均衡器 IP 地址必须可在本地网络中路由，以便您可以在最后一步中查询服务。
   + 将 `advertisementType` 字段设置为 `Service`，`service.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
     ```

1. 将 `CiliumBGPAdvertisement` 资源应用于集群。如果您不使用 Cilium BGP，则可跳过此步骤。

   ```
   kubectl apply -f cilium-bgp-advertisement-loadbalancer.yaml
   ```

1. 在名为 `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
   ```

1. 将部署应用于集群。

   ```
   kubectl apply -f tcp-sample-app.yaml
   ```

1. 在名为 `tcp-sample-service.yaml` 的文件中为部署定义 LoadBalancer 类型服务。
   + 您可以使用服务对象上的 `lbipam.cilium.io/ips` 注释，从负载均衡器 IP 池请求特定 IP 地址。如果您不想为服务请求特定 IP 地址，可以删除此注释。
   + `loadBalancerClass` 规范字段为必填字段，用于防止传统 AWS 云提供商为服务创建经典负载均衡器。在以下示例中，将此字段配置为 `io.cilium/bgp-control-plane`，以将 Cilium 的 BGP 控制面板用作负载均衡器类。也可将此字段配置为 `io.cilium/l2-announcer`，以使用 Cilium 的 [L2 通告功能](https://docs.cilium.io/en/latest/network/l2-announcements/)（目前处于测试阶段，尚未得到 AWS 正式支持）。

     ```
     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
     ```

1. 将服务应用于集群。服务将使用外部 IP 地址创建，您可以使用该地址访问应用程序。

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

1. 确认服务是否已成功创建，是否为其分配了来自上一步创建的 `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
   ```

1. 如果您在 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)
   ```

1. 确认 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}]
   ```

1. 使用分配的负载均衡器 IP 地址访问服务。

   ```
   curl LB_IP_ADDRESS
   ```

   输出示例如下。

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

1. 清理您创建的 资源。

   ```
   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
   ```