하이브리드 노드에 대한 LoadBalancer 유형의 Service 구성 - Amazon EKS

이 페이지 개선에 도움 주기

이 사용자 가이드에 기여하려면 모든 페이지의 오른쪽 창에 있는 GitHub에서 이 페이지 편집 링크를 선택합니다.

하이브리드 노드에 대한 LoadBalancer 유형의 Service 구성

이 주제에서는 Amazon EKS Hybrid Nodes에서 실행되는 애플리케이션에 대해 계층 4(L4) 로드 밸런싱을 구성하는 방법을 설명합니다. LoadBalancer 유형의 Kubernetes Service는 클러스터 외부에 Kubernetes 애플리케이션을 노출하는 데 사용됩니다. LoadBalancer 유형의 Service는 일반적으로 클라우드 또는 온프레미스 환경의 물리적 로드 밸런서 인프라에서 사용되어 워크로드의 트래픽을 처리합니다. 이 로드 밸런서 인프라는 일반적으로 환경별 컨트롤러로 프로비저닝됩니다.

AWS는 EKS Hybrid Nodes에서 실행되는 LoadBalancer 유형의 Service에 대해 AWS Network Load Balancer(NLB) 및 Cilium을 지원합니다. NLB 또는 Cilium 중 무엇을 사용할지는 애플리케이션 트래픽의 소스를 기반으로 합니다. 애플리케이션 트래픽이 AWS 리전에서 발생하는 경우 AWS는 AWS NLB 및 AWS Load Balancer Controller 사용을 권장합니다. 애플리케이션 트래픽이 로컬 온프레미스 또는 엣지 환경에서 발생하는 경우 AWS는 환경에서 로드 밸런서 인프라 유무와 무관하게 사용할 수 있는 Cilium의 내장 로드 밸런싱 기능을 사용할 것을 권장합니다.

계층 7(L7) 애플리케이션 트래픽 로드 밸런싱은 하이브리드 노드에 대한 Kubernetes Ingress 구성 섹션을 참조하세요. EKS를 사용한 로드 밸런싱에 대한 일반적인 정보는 로드 밸런싱 운영 모범 사례 섹션을 참조하세요.

AWS Network Load Balancer

하이브리드 노드에서 실행되는 워크로드의 대상 유형 ip에서 AWS Load Balancer Controller 및 NLB를 사용할 수 있습니다. 대상 유형 ip를 사용하는 경우 NLB는 Service 계층 네트워크 경로를 우회하여 트래픽을 포드로 직접 전달합니다. NLB가 하이브리드 노드의 포드 IP 대상에 도달하려면 온프레미스 포드 CIDR이 온프레미스 네트워크에서 라우팅 가능해야 합니다. 추가로 AWS Load Balancer Controller는 웹후크를 사용하며 EKS 컨트롤 플레인과의 직접 통신이 필요합니다. 자세한 내용은 하이브리드 노드용 웹후크 구성 섹션을 참조하세요.

사전 조건

절차

  1. 사용자 대신 AWS API를 직접 호출할 수 있는 AWS 로드 밸런서 컨트롤러의 IAM 정책을 다운로드합니다.

    curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/refs/heads/main/docs/install/iam_policy.json
  2. 이전 단계에서 다운로드한 정책을 사용하여 IAM 정책을 만듭니다.

    aws iam create-policy \ --policy-name AWSLoadBalancerControllerIAMPolicy \ --policy-document file://iam_policy.json
  3. 클러스터 이름(CLUSTER_NAME), AWS 리전(AWS_REGION) 및 AWS 계정 ID(AWS_ACCOUNT_ID)의 값을 사용자 설정에 맞춰 바꾸고 다음 명령을 실행합니다.

    eksctl create iamserviceaccount \ --cluster=CLUSTER_NAME \ --namespace=kube-system \ --name=aws-load-balancer-controller \ --attach-policy-arn=arn:aws:iam::AWS_ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy \ --override-existing-serviceaccounts \ --region AWS_REGION \ --approve
  4. eks-charts Helm 차트 리포지토리를 추가합니다. AWS에서는 이 리포지토리를 GitHub에 유지합니다.

    helm repo add eks https://aws.github.io/eks-charts
  5. 최신 차트가 적용되도록 로컬 Helm 리포지토리를 업데이트합니다.

    helm repo update eks
  6. AWS 로드 밸런서 컨트롤러를 설치합니다. 클러스터 이름(CLUSTER_NAME), AWS 리전(AWS_REGION), VPC ID(VPC_ID) 및 AWS Load Balancer Controller Helm 차트 버전(AWS_LBC_HELM_VERSION)의 값을 사용자 설정에 맞춰 바꿉니다. helm search repo eks/aws-load-balancer-controller --versions를 실행하여 최신 버전의 Helm 차트를 찾을 수 있습니다. 하이브리드 노드와 AWS 클라우드의 노드가 모두 있는 혼합 모드 클러스터를 실행하는 경우 AWS 로드 밸런서 컨트롤러의 지침에 따라 클라우드 노드에서 AWS Load Balancer Controller를 실행할 수 있습니다.

    helm install aws-load-balancer-controller eks/aws-load-balancer-controller \ -n kube-system \ --version AWS_LBC_HELM_VERSION \ --set clusterName=CLUSTER_NAME \ --set region=AWS_REGION \ --set vpcId=VPC_ID \ --set serviceAccount.create=false \ --set serviceAccount.name=aws-load-balancer-controller
  7. AWS Load Balancer Controller가 성공적으로 설치되었는지 확인합니다.

    kubectl get -n kube-system deployment aws-load-balancer-controller
    NAME READY UP-TO-DATE AVAILABLE AGE aws-load-balancer-controller 2/2 2 2 84s
  8. tcp-sample-app.yaml 파일에서 샘플 애플리케이션을 정의합니다. 아래 예시에서는 TCP 포트와 함께 간단한 NGINX 배포를 사용합니다.

    apiVersion: apps/v1 kind: Deployment metadata: name: tcp-sample-app namespace: default 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
  9. 배포를 클러스터에 적용합니다.

    kubectl apply -f tcp-sample-app.yaml
  10. tcp-sample-service.yaml 파일에서 배포에 대한 LoadBalancer 유형의 Service를 정의합니다.

    apiVersion: v1 kind: Service metadata: name: tcp-sample-service namespace: default 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
  11. 클러스터에 Service 구성을 적용합니다.

    kubectl apply -f tcp-sample-service.yaml
  12. Service에 대한 NLB를 프로비저닝하는 데 몇 분 정도 걸릴 수 있습니다. NLB가 프로비저닝되면 Service에 NLB 배포의 DNS 이름에 해당하는 주소가 할당됩니다.

    kubectl get svc tcp-sample-service
    NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE tcp-sample-service LoadBalancer 172.16.115.212 k8s-default-tcpsampl-xxxxxxxxxx-xxxxxxxxxxxxxxxx.elb.<region>.amazonaws.com 80:30396/TCP 8s
  13. NLB의 주소를 사용하여 Service에 액세스합니다.

    curl k8s-default-tcpsampl-xxxxxxxxxx-xxxxxxxxxxxxxxxx.elb.<region>.amazonaws.com

    출력 예시는 아래와 같습니다.

    <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> [...]
  14. 생성한 리소스를 정리합니다.

    kubectl delete -f tcp-sample-service.yaml kubectl delete -f tcp-sample-app.yaml

Cilium 클러스터 내 로드 밸런싱

Cilium은 EKS Hybrid Nodes에서 실행되는 워크로드의 클러스터 내 로드 밸런서로 사용할 수 있으며, 로드 밸런서 인프라가 없는 환경에 유용할 수 있습니다. Cilium의 로드 밸런싱 기능은 kube-proxy 대체, LoadBalancer IPAM(IP Address Management) 및 BGP Control Plane을 포함한 Cilium 기능의 조합을 기반으로 합니다. 이러한 기능의 책임은 아래에서 자세히 설명합니다.

  • Cilium kube-proxy 대체: 백엔드 포드로 Service 트래픽 라우팅을 처리합니다.

  • Cilium LoadBalancer IPAM: LoadBalancer 유형의 Service에 할당할 수 있는 IP 주소를 관리합니다.

  • Cilium BGP Control Plane: LoadBalancer IPAM이 할당한 IP 주소를 온프레미스 네트워크에 알립니다.

Cilium의 kube-proxy 대체를 사용하지 않는 경우에도 Cilium LoadBalancer IPAM 및 BGP Control Plane을 사용하여 LoadBalancer 유형의 Service에 IP 주소를 할당할 수 있습니다. Cilium의 kube-proxy 대체를 사용하지 않는 경우 백엔드 포드에 대한 Service의 로드 밸런싱은 기본적으로 EKS의 kube-proxy 및 iptables 규칙으로 처리됩니다.

사전 조건

  • kube-proxy 대체 활성화 여부와 무관하게 하이브리드 노드에 대한 CNI 구성의 지침에 따라 Cilium이 설치되어 있습니다. Cilium의 kube-proxy 대체 기능을 사용하려면 최소한 v4.19.57, v5.1.16 또는 v5.2.0과 같은 최신 Linux 커널을 사용하여 운영 체제를 실행해야 합니다. 하이브리드 노드에서의 사용이 지원되는 모든 최신 버전의 운영 체제는 Red Hat Enterprise Linux(RHEL) 8.x를 제외하고 이 기준을 충족합니다.

  • 하이브리드 노드에 대한 Cilium BGP 구성의 지침에 따라 Cilium BGP 컨트롤 플레인이 활성화되어 있습니다. BGP를 사용하지 않으려면 다른 방법을 사용하여 온프레미스 포드 CIDR이 온프레미스 네트워크에서 라우팅할 수 있도록 해야 합니다. 자세한 내용은 라우팅 가능한 원격 포드 CIDR 섹션을 참조하세요.

  • 명령줄 환경에 Helm이 설치되어 있습니다. Helm 설정 지침을 참조하세요.

절차

  1. LoadBalancer 유형의 Service에 대한 로드 밸런서 IP 주소 범위를 구성하는 CiliumLoadBalancerIPPool 리소스를 포함하여 cilium-lbip-pool-loadbalancer.yaml 파일을 생성합니다.

    • LB_IP_CIDR을 로드 밸런서 IP 주소에 사용할 IP 주소 범위로 바꿉니다. 단일 IP 주소를 선택하려면 /32 CIDR을 사용합니다. 자세한 내용은 Cilium 설명서의 LoadBalancer IP Address Management 섹션을 참조하세요.

    • serviceSelector 필드는 후속 단계에서 생성할 Service의 이름과 일치하도록 구성됩니다. 이 구성을 사용하면 이 풀의 IP는 이름이 tcp-sample-service인 Service에만 할당됩니다.

      apiVersion: cilium.io/v2alpha1 kind: CiliumLoadBalancerIPPool metadata: name: tcp-service-pool spec: blocks: - cidr: "LB_IP_CIDR" serviceSelector: matchLabels: io.kubernetes.service.name: tcp-sample-service
  2. 클러스터에 CiliumLoadBalancerIPPool 리소스를 적용합니다.

    kubectl apply -f cilium-lbip-pool-loadbalancer.yaml
  3. 풀에 사용 가능한 IP 주소가 하나 이상 있는지 확인합니다.

    kubectl get ciliumloadbalancerippools.cilium.io
    NAME DISABLED CONFLICTING IPS AVAILABLE AGE tcp-service-pool false False 1 24m
  4. CiliumBGPAdvertisement 리소스가 포함된 cilium-bgp-advertisement-loadbalancer.yaml 파일을 생성하여 다음 단계에서 생성할 Service의 로드 밸런서 IP 주소를 알립니다. Cilium BGP를 사용하지 않는 경우 이 단계를 건너뛸 수 있습니다. Service에 사용되는 로드 밸런서 IP 주소는 마지막 단계에서 서비스를 쿼리할 수 있도록 온프레미스 네트워크에서 라우팅 가능해야 합니다.

    • advertisementType 필드는 Service로 설정되고 service.addressesLoadBalancer 유형의 Service에 대한 LoadBalancerIP만 알리도록 LoadBalancerIP로 설정됩니다.

    • selector 필드는 후속 단계에서 생성할 Service의 이름과 일치하도록 구성됩니다. 이 구성을 사용하면 이름이 tcp-sample-service인 Service의 LoadBalancerIP만 알립니다.

      apiVersion: cilium.io/v2alpha1 kind: CiliumBGPAdvertisement metadata: name: bgp-advertisement-tcp-service labels: advertise: bgp spec: advertisements: - advertisementType: "Service" service: addresses: - LoadBalancerIP selector: matchLabels: io.kubernetes.service.name: tcp-sample-service
  5. 클러스터에 CiliumBGPAdvertisement 리소스를 적용합니다. Cilium BGP를 사용하지 않는 경우 이 단계를 건너뛸 수 있습니다.

    kubectl apply -f cilium-bgp-advertisement-loadbalancer.yaml
  6. tcp-sample-app.yaml 파일에서 샘플 애플리케이션을 정의합니다. 아래 예시에서는 TCP 포트와 함께 간단한 NGINX 배포를 사용합니다.

    apiVersion: apps/v1 kind: Deployment metadata: name: tcp-sample-app namespace: default 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
  7. 배포를 클러스터에 적용합니다.

    kubectl apply -f tcp-sample-app.yaml
  8. tcp-sample-service.yaml 파일에서 배포에 대한 LoadBalancer 유형의 Service를 정의합니다.

    • Service 객체의 lbipam.cilium.io/ips 주석을 사용하여 로드 밸런서 IP 풀에서 특정 IP 주소를 요청할 수 있습니다. Service에 대한 특정 IP 주소를 요청하지 않으려면 이 주석을 제거할 수 있습니다.

    • loadBalancerClass 사양 필드는 레거시 AWS 클라우드 공급자가 Service에 대한 Classic Load Balancer를 생성하지 못하도록 하는 경우 필요합니다. 아래 예시에서는 Cilium의 BGP 컨트롤 플레인을 로드 밸런서 클래스로 사용하도록 io.cilium/bgp-control-plane가 구성됩니다. 또는 Cilium의 L2 Announcements 기능(현재 베타 버전이며, AWS에서 공식적으로 지원되지 않음)을 사용하도록 io.cilium/l2-announcer에 이 필드를 구성할 수 있습니다.

      apiVersion: v1 kind: Service metadata: name: tcp-sample-service namespace: default annotations: lbipam.cilium.io/ips: "LB_IP_ADDRESS" spec: loadBalancerClass: io.cilium/bgp-control-plane ports: - port: 80 targetPort: 80 protocol: TCP type: LoadBalancer selector: app: nginx
  9. Service를 클러스터에 적용합니다. Service는 애플리케이션에 액세스하는 데 사용할 수 있는 외부 IP 주소로 생성됩니다.

    kubectl apply -f tcp-sample-service.yaml
  10. Service가 성공적으로 생성되었고 이전 단계에서 생성된 CiliumLoadBalancerIPPool에서 IP가 할당되었는지 확인합니다.

    kubectl get svc tcp-sample-service
    NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE tcp-sample-service LoadBalancer 172.16.117.76 LB_IP_ADDRESS 80:31129/TCP 14m
  11. kube-proxy 대체 모드에서 Cilium을 사용하는 경우 다음 명령을 실행하여 Cilium이 Service에 대한 로드 밸런싱을 처리하고 있는지 확인할 수 있습니다. 아래 출력에서 10.86.2.x 주소는 Service에 대한 백엔드 포드의 포드 IP 주소입니다.

    kubectl -n kube-system exec ds/cilium -- cilium-dbg service list
    ID Frontend Service Type Backend ... 41 LB_IP_ADDRESS:80/TCP LoadBalancer 1 => 10.86.2.76:80/TCP (active) 2 => 10.86.2.130:80/TCP (active) 3 => 10.86.2.141:80/TCP (active)
  12. Cilium이 BGP를 통해 온프레미스 네트워크에 IP 주소를 알리는지 확인합니다. 아래 예시에는 5개의 하이브리드 노드가 있고, 각 노드는 tcp-sample-service Service에 대한 LB_IP_ADDRESS를 온프레미스 네트워크에 알립니다.

    Node VRouter Prefix NextHop Age Attrs mi-026d6a261e355fba7 NODES_ASN LB_IP_ADDRESS/32 0.0.0.0 12m3s [{Origin: i} {Nexthop: 0.0.0.0}] mi-082f73826a163626e NODES_ASN LB_IP_ADDRESS/32 0.0.0.0 12m3s [{Origin: i} {Nexthop: 0.0.0.0}] mi-09183e8a3d755abf6 NODES_ASN LB_IP_ADDRESS/32 0.0.0.0 12m3s [{Origin: i} {Nexthop: 0.0.0.0}] mi-0d78d815980ed202d NODES_ASN LB_IP_ADDRESS/32 0.0.0.0 12m3s [{Origin: i} {Nexthop: 0.0.0.0}] mi-0daa253999fe92daa NODES_ASN LB_IP_ADDRESS/32 0.0.0.0 12m3s [{Origin: i} {Nexthop: 0.0.0.0}]
  13. 할당된 로드 밸런서 IP 주소를 사용하여 Service에 액세스합니다.

    curl LB_IP_ADDRESS

    출력 예시는 아래와 같습니다.

    <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> [...]
  14. 생성한 리소스를 정리합니다.

    kubectl delete -f tcp-sample-service.yaml kubectl delete -f tcp-sample-app.yaml kubectl delete -f cilium-lb-ip-pool.yaml kubectl delete -f cilium-bgp-advertisement.yaml