

 **協助改進此頁面** 

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

若要為本使用者指南貢獻內容，請點選每個頁面右側面板中的**在 GitHub 上編輯此頁面**連結。

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 為混合節點設定 LoadBalancer 類型的服務
<a name="hybrid-nodes-load-balancing"></a>

本主題會說明如何為在 Amazon EKS 混合節點上執行的應用程式設定第 4 層 (L4) 負載平衡。LoadBalancer 類型的 Kubernetes Service 可用於向叢集外部公開 Kubernetes 應用程式。LoadBalancer 類型的服務通常可與雲端或內部部署環境中的實體負載平衡器基礎結構搭配使用，進而提供工作負載的流量。此負載平衡器基礎結構通常使用環境特定的控制器進行佈建。

 AWS 支援針對 EKS 混合節點上執行的 LoadBalancer 類型的服務使用 AWS Network Load Balancer (NLB) 和 Cilium。使用 NLB 還是 Cilium 的決定取決於應用程式流量的來源。如果應用程式流量來自 AWS 區域，則 AWS 會建議使用 AWS NLB 和 AWS Load Balancer 控制器。如果應用程式流量來自本機內部部署或邊緣環境，則 AWS 會建議使用 Cilium 的內建負載平衡功能，而該功能可在您的環境中搭配或不搭配負載平衡器基礎結構使用。

如需第 7 層 (L7) 應用程式流量負載平衡，請參閱 [設定混合節點的 Kubernetes Ingress](hybrid-nodes-ingress.md)。如需使用 EKS 進行負載平衡的一般資訊，請參閱[負載平衡的最佳實務](https://docs.aws.amazon.com/eks/latest/best-practices/load-balancing.html)。

## AWS Network Load Balancer
<a name="hybrid-nodes-service-lb-nlb"></a>

對於在混合節點上執行的工作負載，您可以搭配目標類型 `ip` 使用 [AWS Load Balancer 控制器](aws-load-balancer-controller.md)和 NLB。使用目標類型 `ip` 時，NLB 可繞過服務層網路路徑，將流量直接轉送至 Pod。若要讓 NLB 達到混合節點上的 Pod IP 目標，您的內部部署 Pod CIDR 必須在內部部署網路上可路由。此外，AWS Load Balancer 控制器使用 Webhook 並且需要從 EKS 控制平面直接通訊。如需詳細資訊，請參閱 [設定混合節點的 Webhook](hybrid-nodes-webhooks.md)。
+ 如需有關 AWS Network Load Balancer 和 AWS Load Balancer 控制器的其他資訊，請參閱 [透過 Network Load Balancer 路由 TCP 與 UDP 流量](network-load-balancing.md) 以取得子網路組態需求，並參閱 [搭配 Helm 的 Install AWS Load Balancer 控制器](lbc-helm.md) 和[負載平衡的最佳實務](https://docs.aws.amazon.com/eks/latest/best-practices/load-balancing.html)。
+ 請參閱 [AWS Load Balancer 控制器 NLB 組態](https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/guide/service/nlb/)，了解可套用至具有 AWS Network Load Balancer 的 `LoadBalancer` 類型的服務的組態。

### 先決條件
<a name="_prerequisites"></a>
+ 遵循 [設定混合節點的 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)。

### 程序
<a name="_procedure"></a>

1. 下載適用於 AWS Load Balancer 控制器的 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 Chart 儲存庫。AWS 會在 GitHub 上維護此儲存庫。

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

1. 更新您的本機 Helm 儲存庫，以確保您擁有最近的圖表。

   ```
   helm repo update eks
   ```

1. 安裝 AWS Load Balancer 控制器。使用您的設定取代下列值：叢集名稱 (`CLUSTER_NAME`)、AWS 區域 (`AWS_REGION`)、VPC ID (`VPC_ID`) 和 AWS Load Balancer 控制器 Helm Chart 版本 (`AWS_LBC_HELM_VERSION`)。您可以透過執行 `helm search repo eks/aws-load-balancer-controller --versions` 來尋找最新版本的 Helm Chart。如果您執行具有混合節點和 AWS 雲端中的節點的混合模式叢集，則您可以遵循 [AWS Load Balancer 控制器](hybrid-nodes-webhooks.md#hybrid-nodes-mixed-lbc) 中的指示，在雲端節點上執行 AWS Load Balancer 控制器。

   ```
   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 Load Balancer 控制器是否已成功安裝。

   ```
   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 叢集內負載平衡
<a name="hybrid-nodes-service-lb-cilium"></a>

Cilium 可用作在 EKS 混合節點上執行的工作負載的叢集內負載平衡器，而這對於沒有負載平衡器基礎結構的環境非常有用。Cilium 的負載平衡功能以 Cilium 功能的組合為建置基礎，包括 kube-proxy 取代、Load Balancer IP 位址管理 (IPAM) 和 BGP 控制平面。這些功能的責任詳述如下：
+  **Cilium kube-proxy 取代**：處理將服務流量路由到後端 Pod。
+  **Cilium Load Balancer IPAM**：管理可指派給 `LoadBalancer` 類型的服務的 IP 位址。
+  **Cilium BGP 控制平面**：將 Load Balancer IPAM 配置的 IP 位址公告至內部部署網路。

如果您沒有使用 Cilium 的 kube-proxy 取代，您仍然可以使用 Cilium Load Balancer IPAM 和 BGP 控制平面，以為 LoadBalancer 類型的服務配置和指派 IP 位址。如果您沒有使用 Cilium 的 kube-proxy 取代，則根據預設，EKS 中服務至後端 Pod 的負載平衡將由 kube-proxy 和 iptables 處理。

### 先決條件
<a name="_prerequisites_2"></a>
+ 在啟用或未啟用 kube-proxy 取代的情況下，遵循 [設定混合節點的 CNI](hybrid-nodes-cni.md) 中的指示安裝 Cilium。Cilium 的 kube-proxy 取代需要執行至少與 v4.19.57、v5.1.16 或 v5.2.0 相近的 Linux 核心作業系統。除了 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)。

### 程序
<a name="_procedure_2"></a>

1. 使用 `CiliumLoadBalancerIPPool` 資源建立名為 `cilium-lbip-pool-loadbalancer.yaml` 的檔案，以為 Load Balancer 類型的服務設定 Load Balancer IP 位址範圍。
   + 使用用於 Load Balancer IP 位址的 IP 位址範圍取代 `LB_IP_CIDR`。若要選取單一 IP 位址，請使用 `/32` CIDR。如需詳細資訊，請參閱 Cilium 文件中的 [LoadBalancer IP 位址管理](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. 使用 `CiliumBGPAdvertisement` 資源建立名為 `cilium-bgp-advertisement-loadbalancer.yaml` 的檔案，以公告您將在下一步驟中建立的服務的負載平衡器 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 類型服務。
   + 您可以從負載平衡器 IP 集區請求特定的 IP 位址，並在服務物件上加上 `lbipam.cilium.io/ips` 註釋。如果您不想為服務請求特定的 IP 位址，則可移除此註釋。
   + 需要 `loadBalancerClass` 規格欄位，才能防止舊版 AWS 雲端提供者為服務建立 Classic Load Balancer。在以下範例中，這會設定為 `io.cilium/bgp-control-plane`，以使用 Cilium 的 BGP 控制平面作為負載平衡器類別。或者，此欄位可設定為 `io.cilium/l2-announcer`，以使用 Cilium 的 [L2 功能公告](https://docs.cilium.io/en/latest/network/l2-announcements/) (目前為 beta 版且未受 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. 使用指派的 load balancerIP 位址存取服務。

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