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

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

タイプ LoadBalancer の Kubernetes Service を作成するとき、ネットワークトラフィックの負荷分散を行う AWS Network Load Balancer (NLB) がプロビジョニングされます。NLB の詳細については、「Network Load Balancer とは」を参照してください。Kubernetes サービスの詳細については、Kubernetes ドキュメントの「Service」を参照してください。NLB は、Amazon EC2 ノードまたは AWS Fargate IP ターゲット にデプロイされたポッドで使用できます。AWS ロードバランサーは、パブリックサブネットまたはプライベートサブネットにデプロイできます。

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

Amazon EKS では、ネットワークトラフィックを NLB (インスタンスまたは IP ターゲット) に負荷分散することができます。NLB ターゲットタイプの詳細については、Network Load Balancer のユーザーガイドの 「ターゲットタイプ」を参照してください。詳細については、GitHub の「AWS Load Balancer Controller」を参照してください。

重要

AWS Load Balancer Controller 2.2.0 のリリースで、Kubernetes インツリーサービスロードバランサーコントローラーは非推奨となり、重要なバグ修正のみを受けています。タイプ LoadBalancer サービス用の新しいネットワークロードバランサーをプロビジョニングする場合、AWS Load Balancer Controller の使用を推奨します。このトピックの情報では、Kubernetes インツリーコントローラーではなく、AWS Load Balancer Controller の使用を前提としています。

Prerequisites

アプリケーションへのネットワークトラフィックの負荷分散を行う前に、次の要件を満たす必要があります。

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

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

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

    • shared または owned

  • Service オブジェクトまたは Ingress オブジェクトのアノテーションとしてサブネット ID を明示的に指定しない限り、パブリックサブネットとプライベートサブネットは次の要件を満たしている必要があります。Service オブジェクトまたは Ingress オブジェクトのアノテーションとしてサブネット 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 は、ルートテーブルを検査しないため、自動検出を正常に実行するには、プライベートタグとパブリックタグが必要です。

Considerations

  • Amazon EKS VPC CNI プラグインを含む NLB IP ターゲットのみ使用できます。NLB インスタンスターゲットを、Amazon EKS VPC CNI プラグインまたは他の互換 CNI プラグインで、使用することができます。

  • コントローラーは NLB をプロビジョニングしますが、Classic Load Balancer はプロビジョニングしません。

  • ロードバランサーの設定は、サービス用のマニフェストに追加された注釈により制御されます。ロードバランサーの作成時 (または作成後) にタグを追加する場合は、サービス仕様に次のアノテーションを追加します。詳細については、Kubernetes ドキュメントの「他のELBアノテーション」を参照してください。

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

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

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

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

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

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

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

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

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

IP またはインスタンスのターゲットを含むネットワークロードバランサーを作成できます。ロードバランスするターゲットタイプの名前が付いているタブを選択します。

IP targets

NLB IP ターゲットは、Amazon EC2 ノードまたは Fargate にデプロイされたポッドで使用できます。Kubernetes サービスはタイプ LoadBalancer として作成する必要があります。詳細については、Kubernetes ドキュメントの「Garbage Collecting Load Balancers (ガベージコレクションを行うロードバランサー」を参照してください。

IP ターゲットを使用するロードバランサーを作成するには、次のアノテーションをサービスマニフェストに追加し、サービスをデプロイします。アノテーション付きのサンプルサービスマニフェストを表示できます。

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

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

インターネット向けの NLB を作成する場合は、次の注釈を追加します。

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

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

ロードバランサーをプライベートサブネットにデプロイするには、サービス仕様に以下のアノテーションが必要です。アノテーション付きのサンプルサービスマニフェストを表示できます。

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

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

インターネット向けの NLB を作成する場合は、次の注釈を追加します。

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

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

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

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

  1. サンプルアプリケーションをデプロイします。

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

      apiVersion: apps/v1 kind: Deployment metadata: name: 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.19.6 ports: - name: http containerPort: 80
    2. マニフェストをクラスターに適用します。

      kubectl apply -f sample-deployment.yaml
  2. IP ターゲットにロードバランシングする内部 NLB を持つサービスを作成します。

    1. 次の内容をコンピュータ上の sample-service.yaml という名前のファイルに保存します。

      apiVersion: v1 kind: Service metadata: name: sample-service 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
  3. サービスがデプロイされたことを確認します。

    kubectl get svc sample-service

    出力は次のとおりです。

    NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE sample-service LoadBalancer 10.100.240.137 k8s-default-samplese-xxxxxxxxxx-xxxxxxxxxxxxxxxx.elb.us-west-2.amazonaws.com 80:32400/TCP 16h
  4. Amazon EC2 AWS Management Console を開きます。左側のパネルで、([ロードバランシング] の下の) [ターゲットグループ] を選択します。[名前] 列で、前のステップの出力である EXTERNAL-IP 列に入っている名前と [Load balancer]列の値が一致するターゲットグループの名前を選択します 。例えば、出力が上記の出力と同じであれば、r k8s-default-samplese-xxxxxxxxxx という名前のターゲットグループを選択することになります。[ターゲットタイプ] は IP です。これは、サンプルサービスデプロイマニフェストで指定されているためです。

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

  6. サービスにトラフィックを送信しますが、その際に xxxxxxxxxx-xxxxxxxxxxxxxxxx を前のステップで EXTERNAL-IP に対して返された値に、また us-west-2 をクラスターのあるリージョンに置き換えます。

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

    出力は次のとおりです。

    <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ...
  7. サンプルのデプロイとサービスが終了したら、それらを削除します。

    kubectl delete service sample-service kubectl delete deployment sample-app