為混合節點設定 LoadBalancer 類型的服務 - Amazon EKS

協助改進此頁面

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

為混合節點設定 LoadBalancer 類型的服務

本主題會說明如何為在 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。如需使用 EKS 進行負載平衡的一般資訊,請參閱負載平衡的最佳實務

AWS Network Load Balancer

對於在混合節點上執行的工作負載,您可以搭配目標類型 ip 使用 AWS Load Balancer 控制器和 NLB。使用目標類型 ip 時,NLB 可繞過服務層網路路徑,將流量直接轉送至 Pod。若要讓 NLB 達到混合節點上的 Pod IP 目標,您的內部部署 Pod CIDR 必須在內部部署網路上可路由。此外,AWS Load Balancer 控制器使用 Webhook 並且需要從 EKS 控制平面直接通訊。如需詳細資訊,請參閱 設定混合節點的 Webhook

先決條件

程序

  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
  2. 使用上一個步驟中下載的政策,建立 IAM 政策。

    aws iam create-policy \ --policy-name AWSLoadBalancerControllerIAMPolicy \ --policy-document file://iam_policy.json
  3. 使用您的設定取代下列值:叢集名稱 (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
  4. 新增 eks-charts Helm Chart 儲存庫。AWS 會在 GitHub 上維護此儲存庫。

    helm repo add eks https://aws.github.io/eks-charts
  5. 更新您的本機 Helm 儲存庫,以確保您擁有最近的圖表。

    helm repo update eks
  6. 安裝 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 控制器 中的指示,在雲端節點上執行 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
  7. 驗證 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
  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 取代、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 處理。

先決條件

  • 在啟用或未啟用 kube-proxy 取代的情況下,遵循 設定混合節點的 CNI 中的指示安裝 Cilium。Cilium 的 kube-proxy 取代需要執行至少與 v4.19.57、v5.1.16 或 v5.2.0 相近的 Linux 核心作業系統。除了 Red Hat Enterprise Linux (RHEL) 8.x 外,所有支援與混合節點搭配使用的最新版作業系統皆符合此條件。

  • 遵循 設定混合節點的 Cilium BGP 中的指示啟用 Cilium BGP 控制平面。如果您不想使用 BGP,則必須使用替代方法,以讓內部部署 Pod CIDR 在內部部署網路上可路由,如需詳細資訊,請參閱 可路由的遠端 Pod CIDR

  • 已在命令列環境中安裝 Helm,請參閱安裝 Helm 說明

程序

  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 位址管理

    • 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. 使用 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
  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 類型服務。

    • 您可以從負載平衡器 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 功能公告 (目前為 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
  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. 使用指派的 load balancerIP 位址存取服務。

    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