ハイブリッドノード用にタイプ LoadBalancer の Service を設定する - Amazon EKS

このページの改善にご協力ください

このユーザーガイドに貢献するには、すべてのページの右側のペインにある「GitHub でこのページを編集する」リンクを選択してください。

ハイブリッドノード用にタイプ LoadBalancer の Service を設定する

このトピックでは、Amazon EKS Hybrid Nodes で動作するアプリケーションに対してレイヤー 4 (L4) ロードバランシングを設定する方法について説明します。タイプ LoadBalancer の Kubernetes Service は、クラスターの外部に Kubernetes アプリケーションを公開するために使用されます。タイプ LoadBalancer の Service は、ワークロードのトラフィックを処理するために、クラウド環境やオンプレミス環境の物理的なロードバランサーインフラストラクチャと共によく使用されます。このロードバランサーインフラストラクチャは通常、環境固有のコントローラーでプロビジョニングされます。

AWS は、EKS Hybrid Nodes で実行されているタイプ LoadBalancer の Service 用に AWS Network Load Balancer (NLB) と Cilium をサポートしています。NLB を使用するか、Cilium を使用するかは、アプリケーショントラフィックのソースに基づきます。AWS では、アプリケーショントラフィックの発信元が AWS リージョンである場合には AWS NLB と AWS Load Balancer Controller を使用することを推奨しています。AWS では、アプリケーショントラフィックの発信元がローカルのオンプレミス環境またはエッジ環境である場合には Cilium に組み込みのロードバランシング機能を使用することを推奨しています。この機能は、お使いの環境にロードバランサーインフラストラクチャを搭載しているかどうかにかかわらず使用できます。

レイヤー 7 (L7) アプリケーショントラフィックのロードバランシングについては、「ハイブリッドノード用に Kubernetes Ingress を設定する」を参照してください。EKS によるロードバランシングの全般的な情報については、「Best Practices for Load Balancing」を参照してください。

AWS Network Load Balancer

ハイブリッドノード上で実行されているワークロードのターゲットタイプが ip の場合、AWS Load Balancer および NLB を使用できます。ターゲットタイプ ip を使用している場合、NLB はトラフィックをポッドに直接転送して、Service レイヤーネットワークパスをバイパスします。NLB がハイブリッドノードのポッド IP ターゲットに到達するためには、オンプレミスネットワークでオンプレミスポッド CIDR をルーティング可能である必要があります。また、AWS Load Balancer Controller はウェブフックを使用し、EKS コントロールプレーンからの直接通信が必要です。詳細については、「ハイブリッドノード用のウェブフックを設定する」を参照してください。

前提条件

手順

  1. ユーザーに代わって AWS API を呼び出すことを許可する、AWS Load Balancer Controller 用の IAM ポリシーをダウンロードします。

    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 チャートリポジトリを追加します。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 Controller Helm チャートバージョン (AWS_LBC_HELM_VERSION) の各値を自分の設定値に置き換えます。Helm チャートの最新バージョンを確認するには、helm search repo eks/aws-load-balancer-controller --versions を実行します。ハイブリッドノードと AWS クラウド内のノードの両方を使用して混合モードクラスターを実行している場合は、「AWS ロードバランサーコントローラー」の手順に従ってクラウドノード上で AWS Load Balancer Controller を実行できます。

    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 Controller が正常にインストールされたことを確認します。

    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 の Service を定義します。

    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. Service 用に NLB をプロビジョニングするには、数分かかる場合があります。NLB がプロビジョニングされると、NLB デプロイの DNS 名に対応するアドレスが Service に割り当てられます。

    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 のアドレスを使用して Service にアクセスします。

    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 Hybrid Nodes で実行されているワークロードのクラスター内ロードバランサーとして使用できます。お使いの環境にロードバランサーインフラストラクチャがない場合に便利です。Cilium のロードバランシング機能は、kube-proxy 置換、Load Balancer IP Address Management (IPAM)、BGP コントロールプレーンなどの Cilium 機能を組み合わせて構築されています。これらの機能が担当する作業は以下のとおりです。

  • Cilium kube-proxy 置換: バックエンドポッドへの Service トラフィックのルーティングを処理します。

  • Cilium Load Balancer IPAM: タイプ LoadBalancer の Service に割り当てることができる IP アドレスを管理します。

  • Cilium BGP コントロールプレーン: Load Balancer IPAM が割り当てた IP アドレスをオンプレミスネットワークにアドバタイズします。

Cilium の kube-proxy 置換を使用していない場合でも、Cilium Load Balancer IPAM と BGP コントロールプレーンを使用して、タイプ LoadBalancer の Service 用に IP アドレスを配分して割り当てることができます。Cilium の kube-proxy 置換を使用しない場合、バックエンドポッドへの Service のロードバランシングは、デフォルトでは EKS の 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 を使用しない場合は、別の方法を使用して、オンプレミスネットワークでオンプレミスポッド CIDR をルーティング可能にする必要があります。詳細については、「ルーティング可能なリモートポッド CIDR」を参照してください。

  • コマンドライン環境に Helm がインストールされていること。「Setup Helm instructions」を参照してください。

手順

  1. CiliumLoadBalancerIPPool リソースを使用してタイプ Load Balancer の Service 用に LoadBalancer IP アドレス範囲を設定するファイルを cilium-lbip-pool-loadbalancer.yaml という名前で作成します。

    • LB_IP_CIDR を Load Balancer の IP アドレスに使用する IP アドレス範囲に置き換えます。単一の IP アドレスを選択するには、/32 CIDR を使用します。詳細については、Cilium のドキュメントの「LoadBalancer IP Address Management」を参照してください。

    • serviceSelector フィールドは、後続のステップで作成する Service の名前と一致するように設定されています。この設定の場合、このプールの IP は tcp-sample-service という名前の 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 アドレスが少なくとも 1 つあることを確認します。

    kubectl get ciliumloadbalancerippools.cilium.io
    NAME DISABLED CONFLICTING IPS AVAILABLE AGE tcp-service-pool false False 1 24m
  4. CiliumBGPAdvertisement リソースを使用して、次のステップで作成する Service 用にロードバランサー IP アドレスをアドバタイズするファイルを cilium-bgp-advertisement-loadbalancer.yaml という名前で作成します。Cilium BGP を使用していない場合は、このステップをスキップできます。Service に使用するロードバランサー IP アドレスは、最終ステップでサービスをクエリできるように、オンプレミスネットワークでルーティング可能である必要があります。

    • LoadBalancerIP をタイプ LoadBalancer の Service 用にのみアドバタイズするように、advertisementType フィールドは Service に設定され、service.addressesLoadBalancerIP に設定されます。

    • selector フィールドは、後続のステップで作成する Service の名前と一致するように設定されています。この設定の場合、tcp-sample-service という名前の 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 の Service を定義します。

    • Service オブジェクトの lbipam.cilium.io/ips 注釈を使用して、ロードバランサー IP プールから特定の IP アドレスをリクエストできます。Service 用に特定の IP アドレスをリクエストしない場合は、この注釈を削除してもかまいません。

    • レガシー AWS クラウドプロバイダーが Service の Classic Load Balancer を作成できないようにするには、loadBalancerClass 仕様フィールドが必要です。以下の例では、io.cilium/bgp-control-plane が Cilium の BGP コントロールプレーンをロードバランサークラスとして使用するように、このフィールドを設定しています。また、io.cilium/l2-announcer が Cilium の 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
  9. サービスをクラスターに適用します。Service は、アプリケーションへのアクセスに使用できる外部 IP アドレスと共に作成されます。

    kubectl apply -f tcp-sample-service.yaml
  10. Service が正常に作成されて、前のステップで作成した 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 が Service のロードバランシングを処理していることを確認できます。以下の出力では、10.86.2.x アドレスは Service のバックエンドポッドのポッド 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 アドレスをアドバタイズしていることを確認します。以下の例では、ハイブリッドノードが 5 つあり、それぞれが tcp-sample-service 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 アドレスを使用して Service にアクセスします。

    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