

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

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

# ハイブリッドノード用にタイプ LoadBalancer の Service を設定する
<a name="hybrid-nodes-load-balancing"></a>

このトピックでは、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 を設定する](hybrid-nodes-ingress.md)」を参照してください。EKS によるロードバランシングの全般的な情報については、「[Best Practices for Load Balancing](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 はトラフィックをポッドに直接転送して、Service レイヤーネットワークパスをバイパスします。NLB がハイブリッドノードのポッド IP ターゲットに到達するためには、オンプレミスネットワークでオンプレミスポッド CIDR をルーティング可能である必要があります。また、AWS Load Balancer Controller はウェブフックを使用し、EKS コントロールプレーンからの直接通信が必要です。詳細については、「[ハイブリッドノード用のウェブフックを設定する](hybrid-nodes-webhooks.md)」を参照してください。
+ サブネット設定要件については「[Network Load Balancer を使用して TCP および UDP トラフィックをルーティングする](network-load-balancing.md)」を参照し、AWS Network Load Balancer と AWS Load Balancer Controller の詳細については「[Helm による AWS Load Balancer Controller のインストール](lbc-helm.md)」と「[Best Practices for Load Balancing](https://docs.aws.amazon.com/eks/latest/best-practices/load-balancing.html)」を参照してください。
+ AWS Network Load Balancer でタイプ `LoadBalancer` の Service に適用できる設定については、「[AWS Load Balancer Controller NLB configurations](https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/guide/service/nlb/)」を参照してください。

### 前提条件
<a name="_prerequisites"></a>
+ 「[ハイブリッドノードの CNI を設定する](hybrid-nodes-cni.md)」の手順に従って Cilium がインストールされていること。
+ 「[ハイブリッドノード向けに Cilium BGP を設定する](hybrid-nodes-cilium-bgp.md)」の手順に従って Cilium BGP コントロールプレーンを有効にしていること。BGP を使用しない場合は、別の方法を使用して、オンプレミスネットワークでオンプレミスポッド CIDR をルーティング可能にする必要があります。詳細については、「[ルーティング可能なリモートポッド CIDR](hybrid-nodes-concepts-kubernetes.md#hybrid-nodes-concepts-k8s-pod-cidrs)」を参照してください。
+ コマンドライン環境に Helm がインストールされていること。「[Setup Helm instructions](helm.md)」を参照してください。
+ コマンドライン環境に eksctl がインストールされていること。「[Setup eksctl instructions](install-kubectl.md#eksctl-install-update)」を参照してください。

### 手順
<a name="_procedure"></a>

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

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 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 ロードバランサーコントローラー](hybrid-nodes-webhooks.md#hybrid-nodes-mixed-lbc)」の手順に従ってクラウドノード上で 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
   ```

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

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

1. サービス設定をクラスターに適用します。

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

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

1. NLB のアドレスを使用して Service にアクセスします。

   ```
   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 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 ルールによって処理されます。

### 前提条件
<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 を使用しない場合は、別の方法を使用して、オンプレミスネットワークでオンプレミスポッド CIDR をルーティング可能にする必要があります。詳細については、「[ルーティング可能なリモートポッド CIDR](hybrid-nodes-concepts-kubernetes.md#hybrid-nodes-concepts-k8s-pod-cidrs)」を参照してください。
+ コマンドライン環境に Helm がインストールされていること。「[Setup Helm instructions](helm.md)」を参照してください。

### 手順
<a name="_procedure_2"></a>

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](https://docs.cilium.io/en/stable/network/lb-ipam/)」を参照してください。
   + `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
     ```

1. `CiliumLoadBalancerIPPool` リソースをクラスターに適用します。

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

1. プール内に使用可能な IP アドレスが少なくとも 1 つあることを確認します。

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

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

1. `CiliumBGPAdvertisement` リソースを使用して、次のステップで作成する Service 用にロードバランサー IP アドレスをアドバタイズするファイルを `cilium-bgp-advertisement-loadbalancer.yaml` という名前で作成します。Cilium BGP を使用していない場合は、このステップをスキップできます。Service に使用するロードバランサー IP アドレスは、最終ステップでサービスをクエリできるように、オンプレミスネットワークでルーティング可能である必要があります。
   + `LoadBalancerIP` をタイプ `LoadBalancer` の Service 用にのみアドバタイズするように、`advertisementType` フィールドは `Service` に設定され、`service.addresses` は `LoadBalancerIP` に設定されます。
   + `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
     ```

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 の 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 機能](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. サービスをクラスターに適用します。Service は、アプリケーションへのアクセスに使用できる外部 IP アドレスと共に作成されます。

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

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

1. 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)
   ```

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

1. 割り当てられたロードバランサー IP アドレスを使用して Service にアクセスします。

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