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」(AWS クラウドプロバイダーロードバランサーコントローラー) を参照してください。使用方法については、このトピックでは説明しません。

クラスターが 1.19 以降にデプロイされた新しいサービスの場合、AWS クラウドプロバイダーのロードバランサーコントローラーの代わりに、バージョン 2.4.0 以降の AWS Load Balancer Controller アドオンのインストール を使用することをお勧めします。クラスターが 1.19 以前の場合は、コントローラーのバージョン 2.3.1 の使用をお勧めします。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 ターゲットにデプロイされたポッドへのネットワークトラフィックの負荷分散を行えます。詳細については、GitHub の AWS Load Balancer Controller を参照してください。

前提条件

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

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

  • クラスターに AWS Load Balancer Controller がデプロイされている。詳細については、「AWS Load Balancer Controller アドオンのインストール」を参照してください。クラスターが 1.19 以降の場合、バージョン 2.4.0 以降をお勧めします。クラスターが 1.19 以前の場合は、バージョン 2.3.1 の使用をお勧めします。

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

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

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

    • shared または owned

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

    • プライベートサブネット — 次の形式でタグ付けする必要があります。これは、Kubernetes と AWS Load Balancer Controller が、サブネットを内部ロードバランサーに使用できることを認識できるようするためです。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

    • パブリックサブネット — 次の形式でタグ付けする必要があります。これは、各アベイラビリティーゾーンでパブリックサブネットを選択するのではなく (サブネット ID の辞書順)、Kubernetes がそれらのサブネットのみを外部ロードバランサーに使用することを認識できるようにするためです。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 EKS VPC CNI プラグインを使用する場合、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 つのインバウンドルールを追加し、作成した各 Network Load Balancer に対するヘルスチェック用に VPC 内の各ロードバランサーサブネットに 1 つずつルールを追加します。Amazon EKS で、セキュリティグループに許可されているルールの最大数に対するクォータを超えるルールを作成しようとした場合、タイプ LoadBalancer のサービスのデプロイが失敗することがあります。詳細については、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 を共有することはできません。

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

  • ポッドが Amazon EKS クラスター内の Windows で実行されている場合、ロードバランサーを使用する 1 つのサービスで最大 64 個のバックエンドポッドをサポートできます。各ポッドには固有の IP アドレスがあります。これは、Amazon EC2 ノード上の Windows OS での制約事項です。

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

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

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

IP targets

NLB IP ターゲットは、Amazon EC2 ノードまたは Fargate にデプロイされたポッドで使用できます。Kubernetes サービスはタイプ LoadBalancer として作成する必要があります。詳細については、Kubernetes ドキュメントの「Garbage Collecting 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 ポッドへの負荷分散を行う場合は、次のアノテーションを追加します。IPv6 を使用して負荷分散を行えるのは、IP ターゲットにのみです。インスタンスターゲットには行えません。このアノテーションなしでは、負荷分散には IPv4 が使用されます。

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

デフォルトでは、Network Load Balancer は internal aws-load-balancer-scheme を使用して作成されます。internal Network Load Balancer の場合、Amazon EKS クラスターは、VPC 内で少なくとも 1 つのプライベートサブネットを使用するように設定されている必要があります。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 ノードにデプロイされたポッドで使用できますが、Fargate にデプロイされたポッドでは使用できません。Fargate にデプロイされたポッド間でネットワークトラフィックを負荷分散するには、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.4.0 以降をお勧めします。

サンプルアプリケーションをデプロイするには

  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.21 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.us-west-2.amazonaws.com 80:32400/TCP 16h
    注記

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

    curl k8s-default-samplese-xxxxxxxxxx-xxxxxxxxxxxxxxxx.elb.us-west-2.amazonaws.com

    出力は次のとおりです。

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

    kubectl delete namespace nlb-sample-app