Amazon EKS でのネットワーク負荷分散 - Amazon EKS

Amazon EKS でのネットワーク負荷分散

ネットワークトラフィックは、OSI モデルの L4 で負荷分散されます。L7 でアプリケーショントラフィックの負荷を分散するには、Kubernetes ingress をデプロイし、これによって AWS Application Load Balancer をプロビジョニングします。詳細については、「Amazon EKS でのアプリケーション負荷分散」を参照してください。2 種類の負荷分散の違いについては、AWS ウェブサイトの「Elastic Load Balancing の特徴」を参照してください。

タイプ LoadBalancer の Kubernetes Service を作成する際、デフォルトでは AWS クラウドプロバイダーロードバランサーコントローラーにより AWS Classic Load Balancer が作成されますが、AWS Network Load Balancer も作成できます。このコントローラーは、将来の重大なバグ修正のみを受けています。AWS クラウドプロバイダーのロードバランサーの使用に関する情報は、「Kubernetes ドキュメント」の「AWS cloud provider load balancer controller」( クラウドプロバイダーのロードバランサーコントローラー) を参照してください。使用方法については、このトピックでは説明しません。

2.7.1 クラウドプロバイダーロードバランサーコントローラーの代わりに、AWS Load Balancer Controller のバージョン AWS 以降を使用することをお勧めします。AWS Load Balancer Controller では、AWS Network Load Balancer は作成できますが、AWS Classic Load Balancer は作成できません。このトピックの残りの部分では、AWS Load Balancer Controller の使用について説明します。

AWS Network Load Balancer では、Amazon EC2 IP およびインスタンスターゲットや AWS Fargate IP ターゲットにデプロイされた Pods へのネットワークトラフィックの負荷分散を行うことができます。詳細については、「GitHub」の「AWS Load Balancer Controller」を参照してください。

前提条件

AWS Load Balancer Controller を使用してネットワークトラフィックの負荷分散を行う前に、次の要件を満たす必要があります。

  • 既存のクラスターがある。既存のクラスターがない場合は、「Amazon EKS の使用開始」を参照してください。既存のクラスターのバージョンを更新する必要がある場合は、Amazon EKS クラスターの Kubernetes バージョンの更新 を参照して下さい。

  • クラスターにデプロイ済みの AWS Load Balancer Controller があること。詳細については、「AWS Load Balancer Controller とは」を参照してください。バージョン 2.7.1 以降をお勧めします。

  • 少なくとも 1 つのサブネット。アベイラビリティーゾーンで複数のタグ付きサブネットが見つかった場合、コントローラーは、サブネット ID が辞書式順序で最初に来る最初のサブネットを選択します。サブネットには、利用可能な IP アドレスが最低 8 個必要です。

  • AWS Load Balancer Controller バージョン 2.1.1 以前を使用している場合、サブネットに次のようにタグ付けする必要があります。バージョン 2.1.2 以降を使用している場合、このタグはオプションです。同じ VPC 内で複数のクラスターを実行していたり、VPC 内で複数の AWS のサービスがサブネットを共有していたりして、クラスターごとにロードバランサーがプロビジョニングされる場所をより詳細に制御したい場合は、サブネットにタグを付けることができます。サービスオブジェクトのアノテーションとしてサブネット ID を明示的に指定すると、Kubernetes と AWS Load Balancer Controller は、これらのサブネットを直接使用してロードバランサーを作成します。ロードバランサーのプロビジョニングにこの方法を使用することを選択した場合、サブネットのタグ付けは不要です。次のプライベートサブネットおよびパブリックサブネットのタグ付け要件は省略できます。my-cluster をクラスター名に置き換えます。

    • キーkubernetes.io/cluster/my-cluster

    • shared または owned

  • サービスオブジェクトまたは Ingress オブジェクトのアノテーションとしてサブネット ID を明示的に指定しない場合、パブリックサブネットとプライベートサブネットは次の要件を満たしている必要があります。サービスまたはイングレス オブジェクトのアノテーションとしてサブネット ID を明示的に指定してロードバランサーをプロビジョニングする場合、Kubernetes と AWS Load Balancer Controller はそれらのサブネットを直接使用してロードバランサーを作成するため、次のタグは必要ありません。

    • プライベートサブネット — 次の形式でタグ付けする必要があります。これは、サブネットを内部ロードバランサーに使用できることを、Kubernetes と AWS ロードバランサーコントローラーが認識できるようにするためです。eksctl または Amazon EKS AWS AWS CloudFormation テンプレートを使用して、2020 年 3 月 26 日以降に VPC を作成する場合、サブネットは、作成時に適切にタグ付けされます。Amazon EKS AWS AWS CloudFormation VPC テンプレートの詳細については、「Amazon EKS クラスター VPC の作成」を参照してください。

      • キーkubernetes.io/role/internal-elb

      • 1

    • パブリックサブネット — 次の形式でタグ付けする必要があります。これは、Kubernetes が (サブネットIDの辞書式順序に基づいて) 各アベイラビリティーゾーンでパブリックサブネットを選択する代わりに、外部ロードバランサーにこれらのサブネットのみを使用することを認識できるようにするためです。eksctl または Amazon EKS AWS CloudFormation テンプレートを使用して、2020 年 3 月 26 日以降に VPC を作成する場合、サブネットは、作成時に適切にタグ付けされます。Amazon EKS AWS CloudFormation VPC テンプレートの詳細については、「Amazon EKS クラスター VPC の作成」を参照してください。

      • キーkubernetes.io/role/elb

      • 1

    サブネットロールタグが明示的に追加されていない場合、Kubernetes サービスコントローラーはクラスター VPC サブネットのルートテーブルを調べて、サブネットがプライベートかパブリックかを判断します。この動作に頼らず、プライベートまたはパブリックロールタグを明示的に追加することをお勧めします。AWS Load Balancer Controller は、ルートテーブルを検査しないため、自動検出を正常に実行するには、プライベートタグとパブリックタグが必要です。

考慮事項
  • ロードバランサーの設定は、サービス用のマニフェストに追加された注釈により制御されます。AWS Load Balancer Controller を使用する場合のサービスアノテーションは、AWS クラウドプロバイダーのロードバランサーコントローラーを使用する場合のサービスアノテーションとは異なります。サービスをデプロイする前に、必ず AWS Load Balancer Controller のアノテーションを確認してください。

  • Amazon VPC CNI plugin for Kubernetes を使用する場合、AWS Load Balancer Controller は、Amazon EC2 IP またはインスタンスターゲットおよび Fargate IP ターゲットに負荷分散を行います。互換性のある代替 CNI プラグインを使用する場合、コントローラーはインスタンスターゲットにのみ負荷分散できます。Network Load Balancer のターゲットタイプの詳細については、「Network Load Balancer のユーザーガイド」の「Target type」(ターゲットタイプ) を参照してください。

  • ロードバランサーの作成時 (または作成後) にタグを追加する場合は、サービス仕様に次のアノテーションを追加します。詳細については、「AWS Load Balancer Controller ドキュメント」の「AWS リソースタグ」を参照してください。

    service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags
  • Elastic IP アドレスを Network Load Balancer に割り当てるには、次のアノテーションを追加します。example values を Elastic IP アドレスの Allocation IDs に置き換えます。Allocation IDs の数は、ロードバランサーに使用されるサブネットの数に一致する必要があります。詳細については、AWS Load Balancer Controller ドキュメントを参照してください。

    service.beta.kubernetes.io/aws-load-balancer-eip-allocations: eipalloc-xxxxxxxxxxxxxxxxx,eipalloc-yyyyyyyyyyyyyyyyy
  • Amazon EKS は、クライアントトラフィック用のインバウンドルールをノードのセキュリティグループに 1 つ追加し、VPC 内のロードバランサーのサブネットごとに、作成する各 Network Load Balancer のヘルスチェック用のルールを 1 つずつ追加します。タイプ LoadBalancer のサービスの展開は、Amazon EKS が、セキュリティグループに許可されているルールの最大数に対するクォータを超えるルールを作成しようとした場合に失敗することがあります。詳細については、Amazon VPC ユーザーガイドの「セキュリティグループ」を参照してください。セキュリティグループのルールの最大数を超える可能性を最小限に抑えるために、次のオプションを検討します。

    • セキュリティグループクォータあたりのルールの増加をリクエストする。詳細については、Service Quotas ユーザーガイドの「Requesting a quota increase (クォータの引き上げのリクエスト)」を参照してください。

    • インスタンスターゲットではなく IP ターゲットを使用する。IP ターゲットを使用すると、同じターゲットポートでルールを共有できます。ロードバランサーのサブネットは、アノテーションを使用して手動で指定できます。詳細については、「GitHub」の「アノテーション」を参照してください。

    • タイプ LoadBalancer のサービスの代わりにイングレスを使用して、サービスにトラフィックを送信します。AWS Application Load Balancer では、Network Load Balancer よりも必要なルールは少なくなります。複数のイングレス間で ALB を共有できます。詳細については、「Amazon EKS でのアプリケーション負荷分散」を参照してください。複数のサービス間で Network Load Balancer を共有することはできません。

    • クラスターを複数のアカウントにデプロイする。

  • Pods が Amazon EKS クラスター内の Windows で実行されている場合、ロードバランサーを使用する 1 つのサービスで最大 1,024 個のバックエンド Pods をサポートできます。各 Pod には固有の IP アドレスがあります。

  • 新しい Network Load Balancer の作成には、AWS Load Balancer Controller を使用することをお勧めします。AWS クラウドプロバイダーロードバランサーコントローラーで作成された既存の Network Load Balancer を置き換えようとすると、複数の Network Load Balancer でアプリケーションのダウンタイムを引き起こす可能性があります。

ネットワークロードバランサーを作成する

IP またはインスタンスのターゲットを含むネットワークロードバランサーを作成できます。

IP targets

IP ターゲットは、Amazon EC2 ノードまたは Fargate にデプロイされた Pods で使用できます。Kubernetes サービスはタイプ LoadBalancer として作成する必要があります。詳細については、「Kubernetes ドキュメント」の「Type Load Balancers」を参照してください。

IP ターゲットを使用するロードバランサーを作成するには、次のアノテーションをサービスマニフェストに追加し、サービスをデプロイします。aws-load-balancer-typeexternal 値により、AWS クラウドプロバイダーのロードバランサーコントローラーではなく、AWS Load Balancer Controller によって Network Load Balancer が作成されます。アノテーション付きのサンプルサービスマニフェストを表示できます。

service.beta.kubernetes.io/aws-load-balancer-type: "external" service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
注記

IPv6 Pods への負荷分散を行う場合は、次のアノテーションを追加します。IPv6 を使用して負荷分散を行えるのは、IP ターゲットにのみです。インスタンスターゲットには行えません。このアノテーションを使用しない場合、負荷分散には IPv4 が使用されます。

service.beta.kubernetes.io/aws-load-balancer-ip-address-type: dualstack

デフォルトでは、Network Load Balancer は internal aws-load-balancer-scheme を使用して作成されます。Network Load Balancer は、クラスターの VPC 内にある任意のサブネットで起動できます。これには、クラスターの作成時に指定されていないサブネットも含まれます。

Kubernetes は、サブネットのルートテーブルを調べて、サブネットがパブリックかプライベートかどうかを特定します。パブリックサブネットには、インターネットゲートウェイを使ったインターネットへの直接の経路がありますが、プライベートサブネットにはありません。

パブリックサブネットに Network Load Balancer を作成して Amazon EC2 ノードへの負荷分散を行う場合 (Fargate はプライベートのみ可能)、次のアノテーションを付けて internet-facing を指定します。

service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
注記

service.beta.kubernetes.io/aws-load-balancer-type: "nlb-ip" アノテーションは、下位互換性のために引き続きサポートされています。ただし、新しいロードバランサーには、service.beta.kubernetes.io/aws-load-balancer-type: "nlb-ip" の代わりに以前のアノテーションを使用することをお勧めします。

重要

サービスの作成後は、このアノテーションを編集しないでください。変更する必要がある場合は、サービスオブジェクトを削除し、このアノテーションを希望する値にして再度作成します。

Instance targets

AWS クラウドプロバイダーロードバランサーコントローラーでは、インスタンスターゲットのみを使用して Network Load Balancer を作成します。バージョン 2.2.0 以降の AWS Load Balancer Controller でも同様に、インスタンスターゲットを使用して Network Load Balancer を作成します。新しい Network Load Balancer の作成には、AWS クラウドプロバイダーロードバランサーコントローラーではなく、こちらを使用することをお勧めします。Network Load Balancer のインスタンスターゲットは、Amazon EC2 ノードにデプロイされた Pods で使用できますが、Fargate にデプロイされたポッドでは使用できません。Fargate にデプロイされた Pods 間でネットワークトラフィックを負荷分散するには、IP ターゲットを使用する必要があります。

Network Load Balancer をプライベートサブネットにデプロイするには、サービスの仕様に次のアノテーションが必要です。アノテーション付きのサンプルサービスマニフェストを表示できます。aws-load-balancer-typeexternal 値により、AWS クラウドプロバイダーロードバランサーコントローラーではなく、AWS Load Balancer Controller によって Network Load Balancer が作成されます。

service.beta.kubernetes.io/aws-load-balancer-type: "external" service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "instance"

デフォルトでは、Network Load Balancer は internal aws-load-balancer-scheme を使用して作成されます。内部 Network Load Balancer の場合、Amazon EKS クラスターは、VPC 内で少なくとも 1 つのプライベートサブネットを使用するように設定されている必要があります。Kubernetesはルートテーブルを調べサブネットがパブリックかプライベートかを特定します。パブリックサブネットには、インターネットゲートウェイを使ったインターネットへの直接の経路がありますが、プライベートサブネットにはありません。

パブリックサブネットに Network Load Balancer を作成して Amazon EC2 ノードへの負荷分散を行う場合、次のアノテーションを付けて internet-facing を指定します。

service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
重要

サービスの作成後は、このアノテーションを編集しないでください。変更する必要がある場合は、サービスオブジェクトを削除し、このアノテーションを希望する値にして再度作成します。

(オプション) サンプルアプリケーションをデプロイする

前提条件
  • クラスター VPC に少なくとも 1 つのパブリックサブネットまたはプライベートサブネットが存在する。

  • クラスターにデプロイ済みの AWS Load Balancer Controller があること。詳細については、「AWS Load Balancer Controller とは」を参照してください。バージョン 2.7.1 以降をお勧めします。

サンプルアプリケーションをデプロイするには
  1. Fargate にデプロイする場合は、VPC 内に利用可能なプライベートサブネットがあることを確認し、Fargate プロファイルを作成します。Fargate にデプロイしない場合は、このステップを省略してください。次のコマンドを実行するか、コマンドにある AWS Management Console と name に同じ値を使用して、namespace でプロファイルを作成できます。example values を自分の値に置き換えます。

    eksctl create fargateprofile \ --cluster my-cluster \ --region region-code \ --name nlb-sample-app \ --namespace nlb-sample-app
  2. サンプルアプリケーションをデプロイします。

    1. アプリケーションの名前空間を作成します。

      kubectl create namespace nlb-sample-app
    2. 次の内容をコンピュータ上の sample-deployment.yaml という名前のファイルに保存します。

      apiVersion: apps/v1 kind: Deployment metadata: name: nlb-sample-app namespace: nlb-sample-app 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
    3. マニフェストをクラスターに適用します。

      kubectl apply -f sample-deployment.yaml
  3. IP ターゲットに負荷分散を行うインターネット向け Network Load Balancer を使用して、サービスを作成します。

    1. 次の内容をコンピュータ上の sample-service.yaml という名前のファイルに保存します。Fargate ノードにデプロイする場合は、service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing 行を削除します。

      apiVersion: v1 kind: Service metadata: name: nlb-sample-service namespace: nlb-sample-app 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
    2. マニフェストをクラスターに適用します。

      kubectl apply -f sample-service.yaml
  4. サービスがデプロイされたことを確認します。

    kubectl get svc nlb-sample-service -n nlb-sample-app

    出力例は次のとおりです。

    NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE sample-service LoadBalancer 10.100.240.137 k8s-nlbsampl-nlbsampl-xxxxxxxxxx-xxxxxxxxxxxxxxxx.elb.region-code.amazonaws.com 80:32400/TCP 16h
    注記

    10.100.240.137xxxxxxxxxx - xxxxxxxxxxxxxxxx の値は出力例とは異なります (ロードバランサーに固有のものになります)。[us-west-2] は、クラスターがどの AWS リージョン にあるかによって異なる場合があります。

  5. Amazon EC2 AWS Management Console を開きます。左側のナビゲーションペインで、([Load Balancing] (ロードバランシング) の下の) [Target Groups] (ターゲットグループ) を選択します。[名前] 列で、前のステップの出力である EXTERNAL-IP 列に入っている名前の一部と [Load balancer] 列の値が一致するターゲットグループの名前を選択します 。例えば、出力が以前の出力と同じ場合は、k8s-default-samplese-xxxxxxxxxx という名前のターゲットグループを選択します。[Target type] (ターゲットタイプ) は IP です。これは、サービスのサンプルマニフェストで指定されているためです。

  6. [ターゲットグループ] を選択し、[ターゲット] タブを選択します。[登録済みターゲット] の下に、前のステップでデプロイされた 3 つのレプリカの 3 つの IP アドレスが表示されます。すべてのターゲットのステータスが [正常] になってから次に進みます。すべてのターゲットが healthy になるまで数分かかることがあります。ターゲットは、healthy 状態に変更される前の unhealthy 状態である可能性があります。

  7. xxxxxxxxxx-xxxxxxxxxxxxxxxx および us-west-2 を EXTERNAL-IP の前のステップの出力で返された値に置き換え、サービスにトラフィックを送信します。プライベートサブネットにデプロイした場合は、踏み台ホストなどの VPC 内のデバイスからページを表示する必要があります。詳細については、「AWS の Linux 踏み台ホスト」を参照してください。

    curl k8s-default-samplese-xxxxxxxxxx-xxxxxxxxxxxxxxxx.elb.region-code.amazonaws.com

    出力例は次のとおりです。

    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    [...]
  8. サンプルのデプロイ、サービス、および名前空間の使用が終了したら、それらを削除します。

    kubectl delete namespace nlb-sample-app