Amazon EKS의 네트워크 로드 밸런싱 - Amazon EKS

이 페이지 개선에 도움 주기

이 사용자 설명서에 기여하고 싶으신가요? 이 페이지 하단으로 스크롤하여 GitHub에서 이 페이지 편집을 선택하세요. 여러분의 기여는 모두를 위한 더 나은 사용자 설명서를 만드는 데 도움이 됩니다.

Amazon EKS의 네트워크 로드 밸런싱

네트워크 트래픽은 OSI 모델의 L4에서 로드 밸런싱됩니다. L7에서 애플리케이션 트래픽을 로드 밸런싱하려면 Kubernetes ingress를 배포합니다. 이는 AWS Application Load Balancer를 프로비저닝합니다. 자세한 내용은 Amazon EKS 애플리케이션 로드 밸런싱 단원을 참조하십시오. 두 가지 로드 밸런싱 간의 차이점을 자세히 알아보려면 AWS 웹 사이트에서 Elastic 로드 밸런싱 기능 부분을 참조하세요.

Kubernetes 유형의 Service LoadBalancer를 생성하면 AWS 클라우드 공급자 로드 밸런서 컨트롤러가 기본적으로 AWS Classic 로드 밸런서를 생성하지만 AWS Network Load Balancer도 생성할 수 있습니다. 이 컨트롤러는 향후 중요한 버그 수정만 수신하고 있습니다. AWS 클라우드 공급자 로드 밸런서 사용에 대한 자세한 내용은 Kubernetes 설명서의 AWS 클라우드 공급자 로드 밸런서 컨트롤러를 참조하세요. 이 주제에서는 이에 대해 다루지 않습니다.

AWS 클라우드 공급자 로드 밸런서 컨트롤러 대신 AWS Load Balancer Controller의 버전 2.7.2 이상을 사용하는 것이 좋습니다. AWS Load Balancer Controller는 AWS Network Load Balancer를 생성하지만 AWS Classic 로드 밸런서는 생성하지 않습니다. 이 주제의 나머지 부분은 AWS 로드 밸런서 컨트롤러 사용에 대한 것입니다.

AWS Network Load Balancer는 Amazon EC2 AWS Fargate IP 및 인스턴스 대상 또는 Pods IP 대상에 배포된 네트워크 트래픽을 로드 밸런싱할 수 있습니다. 자세한 내용은 GitHub의 AWS 로드 밸런서 컨트롤러를 참조하세요.

필수 조건

AWS Load Balancer Controller를 사용하여 네트워크 트래픽을 로드 밸런싱하려면 먼저 다음 요구 사항을 충족해야 합니다.

  • 기존 클러스터를 보유해야 합니다. 기존 클러스터가 없는 경우 Amazon EKS 시작하기 부분을 참조하세요. 기존 클러스터의 버전을 업데이트해야 하는 경우에는 Amazon EKS 클러스터 Kubernetes 버전 업데이트 부분을 참조하세요.

  • 클러스터에 배포된 AWS Load Balancer Controller가 있습니다. 자세한 내용은 AWS Load Balancer Controller란 무엇인가요? 단원을 참조하십시오. 버전 2.7.2 이상을 사용하는 것이 좋습니다.

  • 하나 이상의 서브넷. 가용 영역에서 태그가 지정된 서브넷이 여러 개 있는 경우 컨트롤러는 서브넷 ID가 사전 순으로 가장 먼저 표시되는 서브넷을 선택합니다. 또한 서브넷에는 최소 8개의 사용 가능한 IP 주소가 있어야 합니다.

  • AWS Load Balancer Controller 버전 2.1.1 이하를 사용하는 경우 서브넷에 다음과 같이 태깅되어야 합니다. 버전 2.1.2 이상을 사용하는 경우 이 태그는 선택 사항입니다. 동일한 VPC에서 여러 클러스터를 실행 중이거나 AWS 서비스가 VPC에서 서브넷을 공유하는 경우 로드 밸런서가 클러스터별로 프로비저닝되는 위치를 보다 효과적으로 제어하려면 서브넷에 태깅할 수 있습니다. 서브넷 ID를 서비스 객체에 대한 주석으로 명시적으로 지정하면 Kubernetes 및 AWS Load Balancer Controller는 이러한 서브넷을 직접 사용하여 로드 밸런서를 생성합니다. 로드 밸런서를 프로비저닝하는 데 이 방법을 사용하도록 선택한 경우에는 서브넷 태깅이 필요하지 않으며 다음과 같은 프라이빗 및 퍼블릭 서브넷 태깅 요구 사항을 건너뛸 수 있습니다. my-cluster을 클러스터 이름으로 교체합니다.

    • - kubernetes.io/cluster/my-cluster

    • - shared 또는 owned

  • 서비스 또는 수신 객체에 대한 주석으로 서브넷 ID를 명시적으로 지정하지 않는 한 퍼블릭 및 프라이빗 서브넷은 다음 요구 사항을 충족해야 합니다. 서브넷 ID를 서비스 또는 수신 객체에 대한 주석으로 명시적으로 지정하여 로드 밸런서를 프로비저닝하면 Kubernetes 및 AWS Load Balancer Controller는 이러한 서브넷을 직접 사용하여 로드 밸런서를 생성하며 다음 태그가 필요하지 않습니다.

    • 프라이빗 서브넷(Private subnets) - 다음 형식으로 태그를 지정해야 합니다. 이렇게 하면 Kubernetes 및 AWS 로드 밸런서 컨트롤러가 서브넷을 내부 로드 밸런서에 사용할 수 있음을 알 수 있습니다. 2020년 3월 26일 이후에 eksctl 또는 Amazon EKS AWS AWS CloudFormation 템플릿을 사용하여 VPC 생성하는 경우 서브넷은 생성될 때 적절하게 태깅됩니다. Amazon EKS AWS AWS CloudFormation VPC 템플릿에 대한 자세한 내용은 Amazon EKS 클러스터에 대해 VPC 생성를 참조하세요.

      • - kubernetes.io/role/internal-elb

      • - 1

    • 퍼블릭 서브넷(Public subnets) - 다음 형식으로 태그를 지정해야 합니다. 이렇게 하면 Kubernetes가 각 가용 영역에서 퍼블릭 서브넷을 선택하는 대신 외부 로드 밸런서에 대해 이러한 서브넷만 사용하는 것을 알 수 있습니다(서브넷 ID를 기준으로 사전순으로). 2020년 3월 26일 이후에 eksctl 또는 Amazon EKS AWS CloudFormation 템플릿을 사용하여 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 사용 설명서에서 대상 유형을 참조하세요.

  • 로드 밸런서가 생성될 때 또는 그 이후에 로드 밸런서에 태그를 추가하려면 서비스 사양에 다음 주석을 추가합니다. 자세한 내용을 알아보려면 AWS Load Balancer Controller 설명서의 AWS 리소스 태그를 참조하세요.

    service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags
  • 다음 주석을 추가하여 Network Load Balancer에 Elastic IP 주소를 할당할 수 있습니다. 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는 클라이언트 트래픽에 대한 노드의 보안 그룹에 인바운드 규칙 하나를 추가하고, 생성하는 각 Network Load Balancer의 상태 확인을 위해 VPC에 각 로드 밸런서 서브넷에 대한 규칙 하나를 추가합니다. LoadBalancer 유형의 서비스 배포는 Amazon EKS가 보안 그룹에 허용된 최대 규칙 수에 대한 할당량을 초과하는 규칙을 생성하려고 하면 실패할 수 있습니다. 자세한 내용은 Amazon VPC 사용 설명서의 Amazon VPC 할당량에 있는 보안 그룹을 참조하세요. 보안 그룹에 대한 최대 규칙 수를 초과할 가능성을 최소화하려면 다음 옵션을 고려합니다.

    • 보안 그룹 할당량당 규칙 증가를 요청합니다. 자세한 내용은 Service Quotas 사용 설명서에서 할당량 증가 요청을 참조하세요.

    • 인스턴스 대상이 아닌 IP 대상을 사용합니다. IP 대상을 사용하면 동일한 대상 포트에 대해 규칙을 공유할 수 있습니다. 로드 밸런서 서브넷은 주석을 사용하여 수동으로 지정할 수 있습니다. 자세한 내용은 GitHub에서 주석을 참조하세요.

    • LoadBalancer 유형의 서비스 대신 수신을 사용하여 서비스에 트래픽을 전송할 수 있습니다. AWS Application Load Balancer에는 Network Load Balancer보다 적은 수의 규칙이 필요합니다. 여러 수신 간에 ALB를 공유할 수 있습니다. 자세한 내용은 Amazon EKS 애플리케이션 로드 밸런싱 단원을 참조하십시오. 여러 서비스에서 Network Load Balancer를 공유할 수 없습니다.

    • 클러스터를 여러 계정에 배포합니다.

  • Pods가 Amazon EKS 클러스터의 Windows에서 실행되는 경우 로드 밸런서가 있는 단일 서비스는 최대 1,024개의 백엔드 Pods를 지원할 수 있습니다. 각 Pod에는 고유한 IP 주소가 있습니다.

  • AWS Load Balancer Controller를 사용하여 새 Network Load Balancer만 생성하는 것이 좋습니다. AWS 클라우드 공급자 로드 밸런서 컨트롤러로 생성된 기존 Network Load Balancer를 교체하려고 하면 여러 Network Load Balancer가 발생하여 애플리케이션 가동 중지를 유발할 수 있습니다.

Network Load Balancer 생성

IP 또는 인스턴스 대상을 사용하여 Network Load Balancer를 생성할 수 있습니다.

IP targets

Amazon EC2 노드 또는 Fargate에 배포된 Pods와 함께 IP 대상을 사용할 수 있습니다. Kubernetes 서비스는 LoadBalancer 유형으로 생성되어야 합니다. 자세한 내용은 Kubernetes 설명서에서 LoadBalancer 유형을 참조하세요.

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으로 생성됩니다. 클러스터를 생성했을 때 지정되지 않았던 서브넷을 포함하여 클러스터 VPC의 모든 서브넷에서 Network Load Balancer를 시작할 수 있습니다.

Kubernetes는 서브넷의 라우팅 테이블을 검사하여 퍼블릭인지 또는 프라이빗인지 판단합니다. 퍼블릭 서브넷에는 인터넷 게이트웨이를 사용해 인터넷으로 직접 연결되는 경로가 있지만 프라이빗 서브넷은 그렇지 않습니다.

Amazon EC2 노드로 로드 밸런싱하기 위해 퍼블릭 서브넷에 Network Load Balancer를 생성하려는 경우(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를 생성합니다. AWS 로드 밸런서 컨트롤러의 버전 2.2.0 이상도 인스턴스 대상을 사용하여 Network Load Balancer를 생성합니다. AWS 클라우드 공급자 로드 밸런서 컨트롤러보다 이를 사용하여 새 Network Load Balancer를 생성하는 것이 좋습니다. Amazon EC2 노드에 배포된 Pods와 함께 Network Load Balancer 인스턴스 대상을 사용할 수 있지만 Fargate에는 사용할 수 없습니다. Fargate에 배포된 Pods에서 네트워크 트래픽을 로드 밸런싱하려면 IP 대상을 사용해야 합니다.

프라이빗 서브넷에 Network Load Balancer를 배포하려면 서비스 사양에 다음과 같은 주석이 있어야 합니다. 주석이 있는 샘플 서비스 매니페스트를 볼 수 있습니다. aws-load-balancer-typeexternal 값은 AWS 클라우드 공급자 로드 밸런서 컨트롤러가 아닌 AWS 로드 밸런서 컨트롤러가 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에서 하나 이상의 프라이빗 서브넷을 사용하도록 구성되어야 합니다. Kubernetes는 서브넷의 라우팅 테이블을 검사하여 퍼블릭인지 또는 프라이빗인지 판단합니다. 퍼블릭 서브넷에는 인터넷 게이트웨이를 사용해 인터넷으로 직접 연결되는 경로가 있지만 프라이빗 서브넷은 그렇지 않습니다.

Amazon EC2 노드로 로드 밸런싱하기 위해 퍼블릭 서브넷에 Network Load Balancer를 생성하려는 경우 다음 주석과 함께 internet-facing을 지정합니다.

service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
중요

서비스를 생성한 후에는 주석을 편집하지 마세요. 수정해야 하는 경우 서비스 객체를 삭제하고 이 주석에 대해 원하는 값으로 다시 작성하세요.

(선택 사항) 샘플 애플리케이션을 배포합니다.

필수 조건
  • 클러스터 VPC의 퍼블릭 또는 프라이빗 서브넷 하나 이상 보유해야 합니다.

  • 클러스터에 배포된 AWS Load Balancer Controller가 있습니다. 자세한 내용은 AWS Load Balancer Controller란 무엇인가요? 단원을 참조하십시오. 버전 2.7.2 이상을 사용하는 것이 좋습니다.

샘플 애플리케이션 배포
  1. Fargate에 배포하는 경우 VPC에 사용 가능한 프라이빗 서브넷이 있는지 확인하고 Fargate 프로파일을 생성합니다. Fargate에 배포하지 않는 경우 이 단계를 건너뜁니다. 다음 명령을 실행하여 프로필을 생성하거나, AWS Management Console에서 명령의 namenamespace에 동일한 값을 사용하여 프로필을 생성할 수 있습니다. 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의 값은 예제 출력과 다르며(로드 밸런서마다 고유함) 클러스터가 있는 AWS 리전에 따라 us-west-2이 다를 수 있습니다.

  5. Amazon EC2 AWS Management Console을 엽니다. 왼쪽 탐색 창의 로드 밸런싱(Load Balancing) 아래에서 대상 그룹(Target Groups)을 선택합니다. 이름(Name) 열에서 로드 밸런서(Load balancer) 열의 값이 이전 단계에서 출력의 EXTERNAL-IP 열에 있는 이름의 일부와 일치하는 대상 그룹의 이름을 선택합니다. 예를 들어 출력이 이전 출력과 동일한 경우 k8s-default-samplese-xxxxxxxxxx라는 대상 그룹을 선택합니다. 샘플 서비스 매니페스트에 지정되었기 때문에 대상 유형(Target type)IP입니다.

  6. 대상 그룹(Target group)을 선택한 다음 대상(Targets) 탭을 선택합니다. 등록된 대상(Registered targets)에서 이전 단계에서 배포한 3개 복제본의 IP 주소 3개가 표시되어야 합니다. 계속하기 전에 모든 대상의 상태가 정상이 될 때까지 기다립니다. 모든 대상이 healthy가 될 때까지 몇 분 정도 걸릴 수 있습니다. 대상은 healthy 상태로 변경하기 전에 unhealthy 상태일 수 있습니다.

  7. xxxxxxxxxx-xxxxxxxxxxxxxxxx와 us-west-2를 EXTERNAL-IP에 대한 이전 단계의 출력에서 반환된 값으로 바꿔 서비스로 트래픽을 전송합니다. 프라이빗 서브넷에 배포한 경우 Bastion Host와 같은 VPC 내의 디바이스에서 페이지를 확인해야 합니다. 자세한 내용은 AWS 기반 Linux Bastion Host를 참조하세요.

    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