본문 바로가기
Work/개발 노트

[KANS] 5주차 - LoadBalancer(MetalLB, IPVS)

by ★용호★ 2024. 10. 6.

로드밸런서 타입 개요

  • 쿠버네티스 클러스터 내 Pod로 외부에서 접속하기 위해서는 요청을 수신하기 위한 expose 설정을 해야하는데 방법 중 하나가 LoadBalancer 타입을 지정하는 것
  • 기본적으로 쿠버네티스는 로드밸런서 컴포턴트를 직접적으로 제공하지 않음
    • public cloud를 사용하는 경우에는 CSP에서 제공하는 자체 로드밸런서를 사용
    • 온프레미스에서는 주로 MetalLB를 사용함 (MetalLB는 소프트웨어로 동작함)
  • 일반적으로 다수의 워커 노드로 트래픽을 분산하기 위해서 앞단에 로드밸런서를 두고, 로드밸런서가 수신한 요청을 대상 노드에 전달하면 수신받은 노드는 기존의 ClusterIP 타입의 동작과 동일하게 iptables rule을 통해 대상 Pod로 트래픽을 전달함
    • 이 때는 노드의 포트로 수신한 트래픽을 대상 서비스의 iptables rule로 찾기 위해 iptables chain을 하나 더 거치게됨

 

  • 참고로 AWS의 NLB 또는 ALB를 사용하면 해당 VPC CNI에 의해 로드밸런서에서 대상 Pod로 직접적인 연결이 가능하기 때문에 iptables rule을 거치지 않고 직접 통신하는 구조가 됨

MetalLB란?

  • BareMetalLodbalancer의 약자
  • 온프레미스 환경에서 표준 프로토콜(ARP, BGP)을 사용해 LoadBalancer 유형의 서비스를 구현
    • Layer 2 모드(ARP)와 BGP 모드를 지원함
    • Public Cloud 환경에서는 ARP 사용 시 요청을 차단하기 때문에 BGP 모드를 사용해야함
    • MetalLB로 BGP 모드를 사용하는 것보다는 LoxiLB를 사용하는 것을 권장(기능이 더 많음)
  • DaemonSet으로 Speaker Pod를 생성해서 External IP를 전파함
  • 다수의 노드의 IP 대신 엔드포인트를 제공함으로써 노드 IP가 유출되지 않아 보안성을 향상 시킬 수 있고, 클라이언트 영향 없이 노드가 유연하게 확장/축소 될 수 있도록 함

 

Layer2(ARP) 모드

  • ARP를 통해서 External IP를 전파
    • 참고 : 네트워크 내부에서 통신을 하기 위해 상대방 장비의 MAC 주소를 알아야하는데 이 때 ARP 프로토콜을 통해서 상대방 IP 주소에 해당하는 MAC 주소를 요청하고 응답을 통해 자동으로 알아오게됨
  • speaker pod는 DaemonSet으로 실행되기 때문에 각 노드에 배포가 되는데 이 중 투표를 통해 특정 노드의 speaker pod가 리더 노드로 선정됨. 이 후 클라이언트의 요청은 해당 speaker pod가 속한 노드의 IP로 접속하게 됨. 결국 수신 받은 요청은 iptables rule에 의해 대상 Pod로 트래픽을 전달함
    • 어떤 노드의 speaker Pod를 리더로 선정할지 결정하기 위해 ARP를 사용함. 장애 시에도 다른 speaker pod를 리더로 선정하기 위해 ARP를 사용
    • speaker Pod는 호스트의 네트워크 네임스페이스를 공유해서 사용함
    • 각 노드에 speaker Pod를 배포하는 이유는 서비스 하나만 사용할 것이 아니고, 다수의 서비스를 사용할 때 트래픽의 부담을 분담하기 위함
    • 그럼에도 특정 서비스에 트래픽이 집중 된다면 해당 노드만 부하를 받을 수 있는 Risk가 있음
  • 리더 노드로 트래픽이 집중되는 부분은 ECMP를 사용하여 부하 분산을 할 수는 있지만 리더 노드의 장애 시 ARP를 통해 다시 리더를 선출하고 MetalLB가 동작하게 되기 까지 1분정도 소요될 수 있기 때문에 ARP 모드 보다는 BGP 모드를 사용할 것을 권장
  • ExternalIP로 사용할 IP 범위를 지정 한 후 LoadBalancer 유형으로 Service를 생성해보면 아래와 같이 External-IP를 할당 받은 것을 확인할 수 있음

  • 아래와 같이 서비스의 이벤트 항목을 보면 리더로 선정된 노드의 IP가 기록된 것을 확인할 수 있음

  • 이벤트 기록과 같이 IP가 Assigned되었다고 layer2로 다른 노드들에 announcing 하는 노드가 각각 다른 것을 볼 수 있음
  • 이제 대상 서비스의 External IP로 curl 명령을 실행하여 접속하면 아래와 같이 리더 노드를 통해 정상적으로 응답을 수신하는 것을 확인할 수 있음

 

BGP 모드

  • 클러스터 규모가 커지면 ARP를 사용할 경우 브로드캐스트에 대한 패킷량으로 인해 부하가 커질 수 있음
  • BGP는 브로드캐스트하지 않고 BGP 프로토콜을 사용하여 대상 노드로 ExternalIP 전파가 가능하기 때문에 효율적임
    • BGP 모드로 설정하면 회사의 내부 네트워크에 서비스의 External-IP가 등록됨
    • 별도의 등록 없이 해당 IP로 통신할 수 있기 때문에 편리함
  • MetalLB는 규모가 큰 클러스터에 사용은 권장하지 않음
    • Cilium의 경우 자체적으로 MetalLB와 비슷한 소프트웨어 로드밸런서를 제공하고 있음
    • 온프레미스에서 대규모 클러스터를 운영할 경우에는 하드웨어 로드밸런서 장비를 사용할 것을 권장
    • failover의 경우에도 BGP는 1초 이내로 즉시 수행됨
  • BGP 모드에서 Service의 ExternalTrafficPolicy 설정을 Local로 하게 되면 Pod가 존재하는 노드의 IP만 등록되고, SNAT 없이 통신이 가능하기 때문에 클라이언트의 IP를 보존할 수 있음

IPVS

  • iptables이 랜덤 부하분산이었다면, IPVS는 부하분산 알고리즘을 선택해서 사용할 수 있음
  • IPVS를 활성화하면 모든 노드에 kube-ipvs라는 네트워크 인터페이스가 생성됨

 

  • 위 그림에서는 kube-ipvs0 인터페이스에 두개의 IP가 할당되어 있는데 이 IP들이 현재 실행 중인 Service의 ClusterIP

  • ipvsadm 명령을 사용해서 부하분산에 대한 내용을 확인할 수 있음. 아래 그림에서 rr은 기본값인 라운드로빈 방식을 의미하고 설정된 알고리즘으로 그 하위에 있는 IP들로 부하 분산을 수행함

ipvsadm -Ln

  • IPVS도 넷필터를 사용하긴 하지만 기존에 부하 분산을 위해 iptables rule을 사용하는 것과 달리 IPVS 내에서 부하 분산을 관리하기 때문에 iptables rule이 확연히 줄어듦

  • 선택할 수 있는 알고리즘들 중 주요 4가지는 아래와 같음
    • 라운드로빈 : 목적지 Pod로 돌아가면서 순차적으로 전달
    • 최소 연결 : 목적지 Pod의 connection 갯수가 가장 적은 곳을 우선해서 전달
    • 목적지 해싱 : 목적지 IP 주소로 해시값을 계산하여 목적지 Pod에 전달
    • 출발지 해싱 : 출발지 IP 주소로 해시값을 계산하여 목적지 Pod에 전달
  • Service를 생성하면 모든 노드에 kube-proxy에 의해 kube-ipvs0 네트워크 인터페이스에 서비스의 IP가 추가되고, 부하 분산에 대한 설정이 동일하게 적용됨

  • iptables에는 부하분산의 대상이 되는 IP들이 각각 rule로 작성되는 것이 아니라 ipset을 사용해서 규칙이 줄어듦

iptables -t nat -S ❘ grep KUBE-CLUSTER-IP
ipset list KUBE-CLUSTER-IP

  • 트래픽을 전송해보면 거의 균등하게 부하를 분산하고 있는 것을 확인할 수 있음

 

댓글