
vc5 v0.3.4
Linux용 XDP/eBPF를 사용하는 수평 확장 가능한 Direct Server Return 레이어 4 로드 밸런서
VC5
이 README는 최근 변경 사항을 반영하기 위해 업데이트 중입니다. 일부 정보는 현재 코드베이스를 반영하지 않을 수 있습니다. 이번 코드 반복은 아직 실전 준비가 되지 않았습니다. 프로덕션에는 v0.2 릴리스를 사용하세요.
Linux용 XDP/eBPF를 사용하는 수평 확장 가능한 Direct Server Return (DSR) 계층 4 로드 밸런서(L4LB)입니다.
이것이 유용하다고 생각하거나 질문/제안이 있으시면 [email protected]로 연락하거나 GitHub 이슈를 등록해 주세요.
이제 IPv6 및 계층 3(터널링)에서의 분산을 지원합니다! XVS 라이브러리도 이러한 기능을 포함하도록 업데이트되었으며, 네트워크 네임스페이스에서 상태 확인을 실행할 필요가 없어져 코드가 상당히 간결해졌습니다. 이제 모든 백엔드가 로드 밸런서와 VLAN을 공유해야 하는 요구 사항이 사라집니다.
현재 코드 제한으로 인해 서비스별로 터널링을 활성화하는 것은 지원되지 않습니다.
-tunnel 옵션을 사용하면 단일 방식(IP-in-IP, GRE, FOU 또는 GUE)을 사용하여
계층 3 터널링을 전역적으로 활성화할 수 있습니다. 향후에는 서비스 수준에서
터널링을 구성할 수 있도록 코드가 업데이트될 예정입니다.
계층 2 로드 밸런싱은 계속 지원됩니다. 이 프로젝트를 시작한 주된 이유는 Facebook의 Katran 로드 밸런서가 계층 2를 지원하지 않았기 때문입니다.
샘플 IPv6/L3 구성 파일이 포함되어 있습니다. 더 나은 문서는 추후 제공됩니다.
소개
VC5는 레거시 하드웨어 장비를 대체하도록 설계된 네트워크 로드 밸런서입니다.
가상 IP 주소(VIP)를 가진 서비스를 백엔드("실제") 서버 세트에 분산할 수 있습니다.
실제 서버는 서비스 자체를 실행하거나 다른 계층의 서버에 대한 프록시 역할(예: 애플리케이션
계층 결정이 필요할 때 HAProxy가 계층 7 HTTP 라우터/SSL 오프로드 역할 수행)을 할 수
있습니다. 유일한 요구 사항은 VIP가 각 실제 서버의 루프백 장치에 구성되어야 한다는
것입니다(예: ip addr add 192.168.101.1/32 dev lo).
서비스와 실제 서버는 상태 확인 정의와 함께 구성 파일에 지정됩니다. 백엔드 서버가 검사를 통과하고 서비스를 제공할 수 있을 만큼 충분히 사용 가능해지면 가상 IP 주소가 BGP를 통해 라우터에 알려집니다.
이제 계층 2와 계층 3 모두에서 트래픽 분산이 지원됩니다. 계층 2 분산은 실제 서버가 로드 밸런서와 VLAN을 공유해야 합니다. 분산할 패킷을 수신하면 로드 밸런서는 패킷의 이더넷 하드웨어 주소를 업데이트하여 대상 MAC 주소로 실제 서버의 MAC 주소를, 소스 MAC 주소로 자신의 MAC 주소를 사용하고, 적절한 인터페이스를 통해 패킷을 전달하며, 패킷이 VLAN 태그된 경우 802.1Q VLAN ID를 업데이트합니다.
계층 3 분산은 패킷을 실제 서버 IP로 주소 지정된 터널링 프로토콜로 캡슐화하고 라우터를 통해 전달해야 합니다(서버와 로드 밸런서가 VLAN을 공유하지 않는 경우). 캡슐화되었을 때 패킷이 네트워크 최대 전송 크기를 초과하면 적절한 MTU를 조언하는 ICMP 메시지가 소스로 전송됩니다. 백엔드 서버는 패킷을 역캡슐화하기만 하면 됩니다. 로드 밸런서와의 양방향 터널링은 필요하지 않습니다.
대부분의 인터넷 트래픽이 비대칭적이기 때문에 10Gbit/s 네트워크 인터페이스를 갖춘 서버 한 대는 100Gbit/s 이상의 송신 대역폭을 가진 HTTP 서비스를 지원할 수 있습니다. 소규모 서비스의 경우 적당한 가상 머신 한두 대로도 수 기가비트/s의 송신 트래픽을 발생시키는 서비스를 처리할 수 있습니다.
한 인스턴스로 충분하지 않은 경우 라우터의 ECMP 기능을 사용하여 서버를 더 추가하여 용량을 수평으로 확장하고(그리고 중복성을 제공)할 수 있습니다. 802.3ad 본딩 인터페이스와 802.1Q VLAN 트렁킹이 지원됩니다(examples/ 디렉토리 참조).
커널 모듈이나 복잡한 설정이 필요하지 않지만, 최상의 성능을 위해서는 XDP 네이티브 모드 드라이버(예: mlx4, mlx5, i40e, ixgbe, ixgbevf, nfp, bnxt, thunder, dpaa2, qede)를 사용하는 네트워크 카드가 권장됩니다. 전체 목록은 XDP 프로젝트의 드라이버 지원 페이지에서 확인할 수 있습니다.
목표/현황
- ✅ 단일 바이너리로 간편한 배포
- ✅ Maglev 해싱 알고리즘을 사용한 안정적인 백엔드 선택
- ✅ 경로 상태 삽입이 자동으로 처리됨; ExaBGP와 같은 다른 소프트웨어를 실행할 필요 없음
- ✅ 최소한의 개입; 밸런서에서 iptables 규칙을 수정할 필요 없음
- ✅ L3 분산의 경우 VIP를 루프백 장치/터널 종단에 추가하는 것 외에는 백엔드 서버를 수정할 필요 없음
- ✅ 상태 확인은 백엔드 서버의 실제 주소가 아닌 VIP에 대해 실행됨
- ✅ HTTP/HTTPS, 반개방 SYN 프로브 및 UDP/TCP DNS 상태 확인이 내장됨
- ✅ eBPF/XDP를 사용한 커널 내 패킷 스위칭; 네이티브 모드 드라이버는 sk_buff 할당을 피함
- ✅ 다중 VLAN 지원
- ✅ 저대역폭/개발 애플리케이션을 위한 다중 NIC 지원
- ✅ 고가용성/고대역폭을 지원하는 태그/본딩 네트워크 장치
- ✅ 웹 콘솔, Elasticsearch 로깅(개발 중) 및 Prometheus 메트릭을 통한 관찰 가능성
- ✅ IPv6 지원 및 IPv4와 IPv6 백엔드를 모든 유형의 VIP와 혼합 가능
- ✅ IP-in-IP, GRE, FOU 및 GUE를 지원하는 계층 3 트래픽 분산
빠른 시작
최상의 결과를 얻으려면 irqbalance를 비활성화/제거해야 합니다.
밸런서에 전달할 기본 IP를 선택해야 합니다. 이 IP는 BGP 라우터 ID로 사용됩니다.
단일 태그 없는 이더넷 인터페이스를 사용하는 서버의 간단한 예:
apt-get install git make libelf-dev golang-1.20 libyaml-perl libjson-perl ethtool(또는 배포판에 해당하는 것)ln -s /usr/lib/go-1.20/bin/go /usr/local/bin/go(Go 바이너리가 PATH에 있는지 확인)git clone https://github.com/davidcoles/vc5.gitcd vc5/cmdcp config.sample.yaml config.yaml(요구 사항에 맞게 config.yaml 편집)make(libbpf 라이브러리를 내려받고 바이너리와 JSON 구성 파일 빌드)./vc5 10.1.10.100 config.json eth0(서버 IP 주소와 이더넷 인터페이스를 사용하도록 수정)- 기본적으로 로드 밸런서 서버의 포트 80에서 웹 콘솔이 제공됨
- 백엔드 서버의 루프백 장치에 VIP 추가(예:
ip addr add 192.168.101.1/32 dev lo) - BGP(구성 파일 참조) 또는 정적 라우팅을 통해 VIP에 대한 트래픽이 로드 밸런서로 전송되도록 네트워크/클라이언트 구성
최신 Github 릴리스(x86-64용으로 컴파일됨)의 바이너리를 사용하는 것이 거의 확실히 더 쉽습니다. 이 바이너리는 프로덕션에서 테스트되었으므로 신뢰할 수 있습니다. 태그된 릴리스의 config.pl 스크립트를 사용하여 구성이 이 버전과 호환되는지 확인하십시오(물론 원하는 대로 JSON 구성을 직접 빌드할 수도 있습니다).
YAML 구성 파일을 업데이트하고 JSON을 재생성한 후(make config.json) SIGINT(Ctrl-C) 또는
SIGUSR2를 프로세스에 보내 새 구성을 다시 로드할 수 있습니다. SIGQUIT(Ctrl-) 또는 SIGTERM은
프로세스가 BGP 연결을 정상적으로 종료하고 종료되도록 합니다.
두 개의 인터페이스(내 테스트 서버에서는 Intel X520 10Gbps)로 구성된 LACP 본딩 이더넷 장치와 네이티브 XDP 드라이버 모드 및 태그된 VLAN을 사용하는 더 복잡한 예:
config.yaml vlans 항목:
vlans:
10: 10.1.10.0/24
20: 10.1.20.0/24
30: 10.1.30.0/24
명령줄:
./vc5 -n 10.1.10.100 config.json enp130s0f0 enp130s0f1
바이너리는 구성 파일의 VLAN 접두사에 포함된 IP 주소를 가진 장치를 찾아 VLAN 인터페이스를 감지합니다. 별도의 태그되지 않은 물리적 인터페이스를 사용하는 경우 추가 구성 없이도 투명하게 작동해야 합니다. 명령줄에 모든 인터페이스를 나열하기만 하면 eBPF 코드가 각 인터페이스에 로드됩니다.
연결 상태는 코어별로 추적되므로(BPF_MAP_TYPE_LRU_PERCPU_HASH), LACP 토폴로지가 변경될 때 스위치가 다른 인터페이스를 선택하는 경우 RSS(Receive Side Scaling)가 흐름에 대한 패킷을 동일한 CPU 코어로 일관되게 라우팅하도록 해야 합니다. irqbalance를 비활성화하고, 각 인터페이스의 채널 설정이 동일한지 확인하고(ethtool -l/-L), RSS 흐름 해시 인디렉션이 일치하는지 확인하십시오 (ethtool -x/-X).
설정은 백엔드 서버 세트에 대한 장기 실행 연결(예: iperf를 -t 옵션과 함께 사용)을 시작한 후
구성 파일에서 IP 주소 뒤에 별표를 사용하여 선택한 백엔드를 비활성화하고,
로드 밸런서에서 흐름을 수신하는 인터페이스를 확인한 후(예: watch -d 'cat /proc/interrupts | grep enp130s0f'를
사용하여 빠르게 증가하는 IRQ 카운터 찾기) LACP에서 이 인터페이스를 제외함으로써(ifenslave -d bond0 enp130s0f0)
테스트할 수 있습니다. 흐름이 다른 네트워크 인터페이스로 이동하지만 여전히 동일한 코어에 도달하는 것을 볼 수 있습니다.
여러 서브넷의 백엔드를 사용할 때 최상의 성능을 얻으려면 모든 VLAN이 단일 트렁크 인터페이스(물리적 인터페이스가
여러 개인 경우 LACP 본딩)에 태그되어 있고 구성 파일의 vlans 섹션에 서브넷/VLAN ID 매핑이 지정되어 있는지
확인하십시오.
이것이 불가능한 경우(예: vSphere에서 트렁크 인터페이스를 만드는 것이 간단하지 않음), 각 서브넷을 서로 다른 태그 없는 인터페이스에 할당할 수 있습니다:
./vc5 10.1.10.100 config.json eth0 eth1 eth2
배경/추가 정보
사용 중인 개념에 대한 좋은 요약은 Patrick Shuff의 "Building a Billion User Load Balancer" 강연과 Nitika Shirokov의 Katran 강연에서 논의됩니다.
기본 웹 콘솔과 Prometheus 메트릭 서버가 포함되어 있습니다: 
로깅을 위한 실험적인 elasticsearch 지원(시스템 로그를 스크래핑할 필요 없이 클러스터에 직접 기록)이
이제 포함되었습니다. 백엔드 서버에 대한 모든 프로브가 기록되므로, 다운된 서버가 있으면 정확히 어떤 오류가
반환되었는지와 다른 여러 조건을 확인할 수 있습니다. 이것은 많은 개선과 로그 매개변수의 더 합리적인 명명 등이
필요합니다(통찰력이 있으면 연락 주세요). 하지만 시스템에서 무슨 일이 일어나고 있는지에 대한 좋은 통찰력을
얻을 수 있을 것입니다. 제가 매우 서투르게 처음 만든 Kibana 대시보드 예시: 
성능
주로 Icecast 백엔드 서버를 사용하여 클라이언트가 낮은 비트레이트와 높은 비트레이트의 스트림(48kbps ~ 192kbps)을 혼합하여 가져오는 방식으로 테스트되었습니다.
XDP 제네릭 드라이버를 사용하는 VMWare 게스트(4코어, 8GB)는 로드 밸런서를 통해 100K 동시 클라이언트, 380Mbps/700Kpps의 트래픽을 지원하고, 백엔드에서 클라이언트로 직접 8Gbps의 트래픽을 처리할 수 있는 것으로 보입니다.
단일(비가상화) Intel Xeon Gold 6314U CPU(2.30GHz, 32 물리적 코어, 하이퍼스레딩 활성화로 64 논리적 코어)와 Intel 10G 4P X710-T4L-t 이더넷 카드를 사용하여, 700K 스트림을 2Gbps/3.8Mpps 수신 트래픽 및 46.5Gbps 송신 트래픽으로 실행할 수 있었습니다. 서버는 90% 이상 유휴 상태였습니다. 불행히도 더 많은 클라이언트/서버를 생성할 리소스가 없었습니다.
동작
세 가지 동작 모드가 있습니다: 단순 모드, VLAN 모드, 다중 NIC 모드입니다. 단순 모드에서는 모든 호스트가 로드 밸런서의 기본 주소와 동일한 서브넷에 있어야 합니다. VLAN 모드(YAML/JSON 구성 파일의 "vlans" 섹션 아래에 항목을 선언하여 활성화)에서는 서버 항목이 VLAN/CIDR 서브넷 항목과 일치해야 합니다. VLAN 태그 인터페이스는 OS에서 생성되어야 하며 서브넷 내에 IP 주소가 할당되어야 합니다. 다중 NIC 모드에서는 서브넷에 VLAN과 동일한 방식으로 ID가 부여되지만, VLAN ID를 변경하고 XDP_TX를 사용하는 대신 bpf_redirect()를 사용하여 적절하게 구성된 인터페이스를 통해 트래픽을 보냅니다.
VLAN 모드에서는 로드 밸런서로 들어오는 모든 트래픽이 태그된 VLAN에 있어야 합니다(802.1Q 푸시 또는 팝은 아직 수행되지 않습니다).