Network Load Balancers로 TCP 및 UDP 트래픽 라우팅

Network Load Balancers로 TCP 및 UDP 트래픽 라우팅

참고

새 기능: Amazon EKS Auto Mode는 로드 밸런싱을 위한 일상적인 작업을 자동화합니다. 자세한 내용은 다음을 참조하세요.

  • EKS Auto Mode에 샘플 Load Balancer 워크로드 배포
  • Service Annotations을 사용해 Network Load Balancers 구성

네트워크 트래픽은 OSI 모델의 L4에서 로드 밸런싱됩니다. L7에서 애플리케이션 트래픽을 로드 밸런싱하려면 AWS Application Load Balancer를 프로비저닝하는 Kubernetes ingress를 배포합니다. 자세한 내용은 Application Load Balancers로 애플리케이션 및 HTTP 트래픽 라우팅을 참조하세요. 두 로드 밸런싱 유형의 차이점에 대해 알아보려면 AWS 웹사이트의 Elastic Load Balancing features를 참조하세요.

LoadBalancer 유형의 Kubernetes Service를 만들 때 AWS 클라우드 공급자 로드 밸런서 컨트롤러는 기본적으로 AWS Classic Load Balancer를 만들지만 AWS Network Load Balancer도 만들 수 있습니다. 이 컨트롤러는 앞으로 중요한 버그 수정만 받습니다. AWS 클라우드 공급자 로드 밸런서 컨트롤러 사용에 대한 자세한 내용은 Kubernetes 문서의 AWS cloud provider load balancer controller를 참조하세요. 이 주제에서는 그 사용법을 다루지 않습니다.

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

AWS Network Load Balancer는 Amazon EC2 IP 및 인스턴스 대상에 배포된 Pod, AWS Fargate IP 대상, Amazon EKS Hybrid Nodes를 IP 대상으로 하는 Pod에 네트워크 트래픽을 로드 밸런싱할 수 있습니다. 자세한 내용은 GitHub의 AWS Load Balancer Controller를 참조하세요.

출처: 문서

본문

사전 요구 사항

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

  • 기존 클러스터가 있습니다. 기존 클러스터가 없다면 Amazon EKS 시작하기(Get started with Amazon EKS)를 참조하세요. 기존 클러스터의 버전을 업데이트해야 한다면 기존 클러스터를 새 Kubernetes 버전으로 업데이트를 참조하세요.
  • 클러스터에 AWS Load Balancer Controller가 배포되어 있습니다. 자세한 내용은 AWS Load Balancer Controller로 인터넷 트래픽 라우팅을 참조하세요. 버전 2.7.2 이상을 권장합니다.
  • 서브넷이 하나 이상 있습니다. 가용 영역에 태그된 서브넷이 여러 개 있으면 컨트롤러는 서브넷 ID가 사전순으로 먼저 오는 첫 번째 서브넷을 선택합니다. 서브넷에는 사용 가능한 IP 주소가 최소 8개 있어야 합니다.
  • AWS Load Balancer Controller 버전 2.1.1 이하를 사용한다면 서브넷을 다음과 같이 태그해야 합니다. 버전 2.1.2 이상을 사용한다면 이 태그는 선택 사항입니다. 같은 VPC에서 여러 클러스터를 운영하거나 VPC에서 여러 AWS 서비스가 서브넷을 공유하며 각 클러스터에 로드 밸런서가 프로비저닝되는 위치를 더 제어하고 싶다면 서브넷을 태그하고 싶을 수 있습니다. 서비스 객체의 주석으로 서브넷 ID를 명시적으로 지정하면 Kubernetes와 AWS Load Balancer Controller는 그 서브넷을 직접 사용해 로드 밸런서를 만듭니다. 로드 밸런서 프로비저닝에 이 방법을 사용하려면 서브넷 태깅이 필요하지 않으므로 아래의 프라이빗 및 퍼블릭 서브넷 태깅 요구 사항을 건너뛸 수 있습니다. my-cluster를 클러스터 이름으로 바꿉니다.
    • 키(Key) – kubernetes.io/cluster/
    • 값(Value) – shared 또는 owned
  • 서비스 또는 인그레스 객체의 주석으로 서브넷 ID를 명시적으로 지정하지 않는 한 퍼블릭 및 프라이빗 서브넷은 다음 요구 사항을 충족해야 합니다. 서비스 또는 인그레스 객체의 주석으로 서브넷 ID를 명시적으로 지정해 로드 밸런서를 프로비저닝한다면 Kubernetes와 AWS Load Balancer Controller는 그 서브넷을 직접 사용해 로드 밸런서를 만들므로 다음 태그는 필요하지 않습니다.
    • 프라이빗 서브넷 – 다음 형식으로 태그되어야 합니다. 이는 Kubernetes와 AWS Load Balancer Controller가 내부 로드 밸런서에 서브넷을 사용할 수 있음을 알게 하기 위함입니다. 2020년 3월 26일 이후 eksctl이나 Amazon EKS AWS CloudFormation 템플릿으로 VPC를 만들었다면 서브넷이 만들어질 때 적절히 태그됩니다. Amazon EKS AWS CloudFormation VPC 템플릿에 대한 자세한 내용은 Amazon EKS 클러스터용 Amazon VPC 생성을 참조하세요.
      • 키(Key) – kubernetes.io/role/internal-elb
      • 값(Value) – 1
    • 퍼블릭 서브넷 – 다음 형식으로 태그되어야 합니다. 이는 Kubernetes가 각 가용 영역의 퍼블릭 서브넷을 자동으로 선택하는 대신(서브넷 ID의 사전순 기준) 외부 로드 밸런서에 그 서브넷만 사용하도록 알게 하기 위함입니다. 2020년 3월 26일 이후 eksctl이나 Amazon EKS AWS CloudFormation 템플릿으로 VPC를 만들었다면 서브넷이 만들어질 때 적절히 태그됩니다. Amazon EKS AWS CloudFormation VPC 템플릿에 대한 자세한 내용은 Amazon EKS 클러스터용 Amazon VPC 생성을 참조하세요.
      • 키(Key) – kubernetes.io/role/elb
      • 값(Value) – 1
  • 서브넷 역할 태그가 명시적으로 추가되지 않으면 Kubernetes 서비스 컨트롤러는 클러스터 VPC 서브넷의 라우팅 테이블을 검사해 서브넷이 프라이빗인지 퍼블릭인지 판단합니다. 이 동작에 의존하지 말고 프라이빗 또는 퍼블릭 역할 태그를 명시적으로 추가할 것을 권장합니다. AWS Load Balancer Controller는 라우팅 테이블을 검사하지 않으며 성공적인 자동 검색을 위해 프라이빗 및 퍼블릭 태그가 있어야 합니다.

고려 사항

  • 로드 밸런서의 구성은 서비스 매니페스트에 추가되는 주석으로 제어됩니다. Service 주석은 AWS Load Balancer Controller를 사용할 때와 AWS 클라우드 공급자 로드 밸런서 컨트롤러를 사용할 때 다릅니다. 서비스를 배포하기 전에 AWS Load Balancer Controller의 주석을 검토하세요.
  • Amazon VPC CNI 플러그인 for Kubernetes를 사용할 때 AWS Load Balancer Controller는 Amazon EC2 IP 또는 인스턴스 대상과 Fargate IP 대상으로 로드 밸런싱할 수 있습니다. 대체 호환 CNI 플러그인을 사용할 때 컨트롤러는 Amazon EKS Hybrid Nodes로 로드 밸런싱하지 않는 한 인스턴스 대상으로만 로드 밸런싱할 수 있습니다. 하이브리드 노드의 경우 컨트롤러는 IP 대상으로 로드 밸런싱할 수 있습니다. Network Load Balancer 대상 유형에 대한 자세한 내용은 Network Load Balancers User Guide의 대상 유형(Target type)을 참조하세요.
  • 로드 밸런서가 만들어질 때나 만든 뒤에 로드 밸런서에 태그를 추가하려면 서비스 사양에 다음 주석을 추가합니다. 자세한 내용은 AWS Load Balancer Controller 문서의 AWS Resource Tags를 참조하세요.
    service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags
    
  • Network Load Balancer에 탄력적 IP 주소를 할당하려면 다음 주석을 추가합니다. 예시 값을 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 User Guide의 Amazon VPC 할당량의 보안 그룹(Security groups)을 참조하세요. 보안 그룹의 최대 규칙 수 초과 가능성을 최소화하려면 다음 옵션을 고려하세요.
    • 보안 그룹당 규칙 할당량 증가를 요청합니다. 자세한 내용은 Service Quotas User Guide의 할당량 증가 요청(Requesting a quota increase)을 참조하세요.
    • 인스턴스 대상 대신 IP 대상을 사용합니다. IP 대상으로 같은 대상 포트의 규칙을 공유할 수 있습니다. 주석으로 로드 밸런서 서브넷을 직접 지정할 수 있습니다. 자세한 내용은 GitHub의 Annotations를 참조하세요.
    • 서비스에 트래픽을 보내려면 LoadBalancer 유형의 서비스 대신 ingress를 사용합니다. AWS Application Load Balancer는 Network Load Balancer보다 규칙이 적게 필요합니다. 여러 ingress에서 ALB를 공유할 수 있습니다. 자세한 내용은 Application Load Balancers로 애플리케이션 및 HTTP 트래픽 라우팅을 참조하세요. Network Load Balancer는 여러 서비스에서 공유할 수 없습니다.
    • 클러스터를 여러 계정에 배포합니다.
  • Pod가 Amazon EKS 클러스터에서 Windows에서 실행된다면 로드 밸런서가 있는 단일 서비스가 최대 1024개의 백엔드 Pod를 지원할 수 있습니다. 각 Pod에는 고유한 IP 주소가 있습니다.
  • 새 Network Load Balancer는 AWS Load Balancer Controller로만 만들 것을 권장합니다. AWS 클라우드 공급자 로드 밸런서 컨트롤러로 만든 기존 Network Load Balancer를 교체하려 하면 여러 Network Load Balancer가 생겨 애플리케이션 다운타임을 초래할 수 있습니다.

네트워크 로드 밸런서 생성

IP 대상 또는 인스턴스 대상으로 네트워크 로드 밸런서를 만들 수 있습니다.

네트워크 로드 밸런서 생성 — IP 대상

Amazon EC2 노드, Fargate 또는 Amazon EKS Hybrid Nodes에 배포된 Pod에 IP 대상을 사용할 수 있습니다. Kubernetes 서비스는 LoadBalancer 유형으로 만들어야 합니다. 자세한 내용은 Kubernetes 문서의 Type LoadBalancer를 참조하세요.

IP 대상을 사용하는 로드 밸런서를 만들려면 서비스 매니페스트에 다음 주석을 추가하고 서비스를 배포합니다. aws-load-balancer-type의 external 값이 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 Pod로 로드 밸런싱한다면 다음 주석을 추가합니다. 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" 대신 앞선 주석을 사용할 것을 권장합니다.

중요

서비스를 만든 뒤에는 주석을 편집하지 마세요. 수정해야 한다면 서비스 객체를 삭제하고 이 주석의 원하는 값으로 다시 만드세요.

네트워크 로드 밸런서 생성 — 인스턴스 대상

AWS 클라우드 공급자 로드 밸런서 컨트롤러는 인스턴스 대상으로만 Network Load Balancer를 만듭니다. AWS Load Balancer Controller 버전 2.2.0 이상도 인스턴스 대상으로 Network Load Balancer를 만듭니다. 새 Network Load Balancer를 만들 때는 AWS 클라우드 공급자 로드 밸런서 컨트롤러보다 이것을 사용할 것을 권장합니다. Amazon EC2 노드에 배포된 Pod에는 Network Load Balancer 인스턴스 대상을 사용할 수 있지만 Fargate에는 사용할 수 없습니다. Fargate에 배포된 Pod 간 네트워크 트래픽을 로드 밸런싱하려면 IP 대상을 사용해야 합니다.

프라이빗 서브넷에 Network Load Balancer를 배포하려면 서비스 사양에 다음 주석이 있어야 합니다. 주석이 포함된 샘플 서비스 매니페스트를 볼 수 있습니다. aws-load-balancer-type의 external 값이 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에서 프라이빗 서브넷을 하나 이상 사용하도록 구성되어 있어야 합니다. 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 이상을 권장합니다.

Fargate에 배포한다면 VPC에서 사용 가능한 프라이빗 서브넷이 있는지 확인하고 Fargate 프로필을 만듭니다. Fargate에 배포하지 않는다면 이 단계를 건너뜁니다. 다음 명령을 실행하거나 AWS Management Console에서 명령의 name과 namespace와 같은 값을 사용해 프로필을 만들 수 있습니다. 예시 값을 사용자의 값으로 바꿉니다.

eksctl create fargateprofile \
    --cluster my-cluster \
    --region region-code \
    --name nlb-sample-app \
    --namespace nlb-sample-app

샘플 애플리케이션을 배포합니다.

애플리케이션의 네임스페이스를 만듭니다.

kubectl create namespace nlb-sample-app

다음 내용을 컴퓨터의 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

매니페스트를 클러스터에 적용합니다.

kubectl apply -f sample-deployment.yaml

IP 대상을 로드 밸런싱하는 인터넷 연결 Network Load Balancer가 있는 서비스를 만듭니다.

다음 내용을 컴퓨터의 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

매니페스트를 클러스터에 적용합니다.

kubectl apply -f sample-service.yaml

서비스가 배포되었는지 확인합니다.

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.137와 xxxxxxxxxx-xxxxxxxxxxxxxxxx의 값은 예시 출력과 다를 것입니다(로드 밸런서마다 고유) 그리고 us-west-2는 클러스터가 있는 AWS 리전에 따라 다를 수 있습니다.

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

대상 그룹을 선택한 다음 Targets 탭을 선택합니다. 등록된 대상(Registered targets) 아래에서 이전 단계에서 배포한 복제본 3개의 IP 주소 3개가 보여야 합니다. 계속하기 전에 모든 대상의 상태가 healthy가 될 때까지 기다립니다. 모든 대상이 healthy가 되는 데 몇 분이 걸릴 수 있습니다. 대상은 healthy 상태로 바뀌기 전에 unhealthy 상태일 수 있습니다.

xxxxxxxxxx-xxxxxxxxxxxxxxxx와 us-west-2를 이전 단계의 EXTERNAL-IP 출력 값으로 바꿔 서비스에 트래픽을 보냅니다. 프라이빗 서브넷에 배포했다면 베스천 호스트(bastion host) 같은 VPC 안의 기기에서 페이지를 봐야 합니다. 자세한 내용은 AWS의 Linux Bastion Hosts를 참조하세요.

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

예시 출력은 다음과 같습니다.


Welcome to nginx!
[...]

샘플 배포, 서비스, 네임스페이스가 끝나면 제거합니다.

kubectl delete namespace nlb-sample-app

더 알아보기 (Learn more)