top of page
작성자 사진LoxiLB

LoxiLB : 고가용성(HA)을 사용한 Anycast 서비스 로드 밸런싱


LoxiLB를 오픈소스 프로젝트로 공개한 이후 다양한 요구사항들과 아이디어를 공유할 수 있었습니다. 그 요구사항들 중 HA 로드밸런싱과 L3DSR 지원에 관한 내용도 있었습니다.

이 포스트에서는 LoxiLB를 Hyperscale 로드 밸런서로 배포하여 L3DSR 모드에서 고가용성 Anycast 서비스를 지원하는 방법을 설명하겠습니다.

시작하기 전에 Anycast 서비스와 DSR에 대한 기본적인 내용에 대해 알아보겠습니다.


Anycast란?

Anycast는 여러 개의 서버가 한 개의 동일한 IP주소를 갖는 네트워크 주소 지정 및 라우팅 방법입니다. Anycast는 일반적으로 동일한 서비스를 최단 거리에 있는 서버와 통신하여 더 빠르고 효율적인 전송, 고가용성을 제공합니다. 따라서 서버의 부하를 줄이거나 로드 밸런싱 시키는 데 용이합니다. 모든 인스턴스는 서비스를 제공할 준비가 되었으므로 한 인스턴스가 중단되어도 클라이언트 요청에 영향을 주지 않습니다.


DSR이란?

서비스를 향해 가는 패킷은 로드 밸런서를 거치지만, 서비스의 응답 패킷은 로드 밸런서를 거치지 않고 보내는 방법입니다. Low Latency가 요구되는 애플리케이션이나 보안 또는 인증을 위해서 클라이언트의 IP 주소 가시성이 필요한 애플리케이션, 로드밸런서의 대역폭 유지가 중요한 애플리케이션을 운영할 때 유용한 모드입니다.


DSR 의 두 가지 모드:

  1. L2DSR (Layer-2 DSR) Mode: 엔드포인트가 같은 네트워크에 있고 직접적으로 도달 가능한 경우입니다. 대상 MAC만 엔드포인트 서버 MAC으로 변경되고 나머지는 동일하게 유지되므로 이 모드를 MAC 변환 모드라고도 합니다.

  2. L3DSR (Layer-3 DSR) Mode: 엔드포인트가 같은 네트워크에 없고 몇 개의 홉(hop)이 떨어져 있는 경우입니다. 이 모드에서는 엔드포인트까지 IP-over-IP 터널이 생성됩니다. 패킷은 IP 헤더로 캡슐화 되어 엔드포인트로 라우팅됩니다.

둘 다 들어오는 경로에서는 로드밸런서를 통해서 들어오고 돌아가는 경로에서는 패킷이 로드 밸런서를 통과하지 않고 클라이언트에게 직접 전달됩니다. 이 포스트에서는 L3DSR 모드에 대해 더 자세히 말씀 드리겠습니다.


LoxiLB의 역할

다양한 네트워크 서비스에 대한 요구가 증가함에 따라 하이퍼스케일 컴퓨팅과 고가용성(HA)이 가장 중요한 요구사항이 되었습니다. 하이퍼스케일 컴퓨팅이나 고가용성을 위해서는 여러 인스턴스를 실행하기 때문입니다. 네트워크 설계에 따라 여러 인스턴스는 Active-Active 모드 또는 Active-Standby 모드로 실행될 수 있습니다.

LoxiLB는 스테이트풀 로드밸런서이며 고가용성 기능을 구현해서 클러스터 간 커넥션을 유지합니다. 고가용성의 구현 방법에 대해서 간략하게 설명을 하면, 커넥션을 추적/유지함과 동시에 커넥션 정보를 클러스터 내 모든 로드밸런서 인스턴스와 동기화함으로서 로드밸런서가 고가용성 기능을 갖추게 됩니다(자세한 내용은 여기).


하지만 엔드포인트의 Response가 다시 로드밸런서를 통과할 가능성이 없는 DSR 모드의 경우, 커넥션 추적(Connection track)이 불가능한 시나리오가 있을 수 있습니다. 이 경우 HA를 제공하는 방법은 로드밸런서에서 항상 동일한 엔드포인트로 보내는 특정 커넥션을 만들어서 해결합니다. 즉, 모든 로드밸런서 인스턴스가 커넥션에 대해서 "Application stickiness"를 보장해준다면 커넥션을 동기화하는 작업이 더 이상 필요하지 않게 됩니다. 일반적으로 로드밸런서는 엔드포인트를 선택하기 위해 다양한 기술을 선택 할 수 있는데, 이 경우에는 다중 클러스터 환경에서의 Application stickiness을 유지하기 위해서 "Maglev consistent hashing" 기술을 사용하여 엔드포인트를 선택합니다.





데모를 위한 토폴로지 분석


LoxiLB는 Request의 목적지 IP 주소(VIP)를 커넥션별 일관된 해시를 기반으로 엔드포인트 주소 중 하나와 매핑합니다. 엔드포인트는 로드 밸런서를 거치지 않고 직접 응답을 반환하기 때문에 클라이언트의 IP 주소를 보존해야 합니다. 또한 엔드포인트는 Response에 VIP를 출발지 IP 주소로 사용해야 하기 때문에 DNAT(목적지 IP 주소 변경)을 수행할 수 없습니다.


VIP가 로드 밸런서에 속하므로 로드 밸런서와 엔드포인트 사이의 중간 노드에서는 목적지를 VIP로 가진 Request를 무시해야 합니다. 따라서 로드밸런서 노드와 엔드포인트 사이에 터널링이나 캡슐화가 필요합니다. LoxiLB는 L3DSR모드에서 IP-over-IP 터널링을 지원하여 로드 밸런서와 엔드포인트 간에 터널을 만듭니다. 패킷이 로드 밸런서를 통과할 때(Egress) 클라이언트의 소스 IP와 VIP를 보존하는 캡슐화가 진행되며 IP-over-IP 터널로 패킷이 전송됩니다. 캡슐화된 패킷에는 선택한 엔드포인트의 목적지 IP가 있고 소스 IP는 로드 밸런서의 터널 인터페이스입니다. 중간 노드는 더 이상 VIP를 처리할 필요가 없으며 Request가 선택된 엔드포인트로 전달합니다.


llb1에서의 ep1과 llb1간 IP-over-IP 터널 설정 예시:

#Underlying interface
$ip addr add 31.31.31.253/24 dev ellb1ep1

# Create tunnel interface
$ip link add name ipip11 type ipip local 31.31.31.253 remote 31.31.31.1
$ip link set dev ipip11 up
$ip addr add 45.45.1.254/24 dev ipip11

# Add route for the endpoint
$ip route add 56.56.56.0/24 via 45.45.1.1

NOTE: 엔드포인트 경로는 예시에 나온 것과 같이 Next hop을 사용해서 추가되어야 합니다.

"ip route add <ep> dev <tunnel>"로 설정 하는 경우 제대로 동작하지 않을 수 있습니다.


IP-over-IP 터널 인터페이스는 모든 엔드포인트에서 생성됩니다. 또한 모든 엔드포인트는 루프백 인터페이스에 VIP를 구성해야 합니다. 그렇지 않으면 엔드포인트는 수신된 패킷을 역캡슐화(Decapsulation)한 후 클라이언트의 요청을 거부(Reject)합니다.


ep1에서의 ep1과 llb1간 IP-over-IP 터널 설정 예시:

$ip addr add 31.31.31.1/24 dev eep1llb1
$ip link add name ipip11 type ipip local 31.31.31.1 remote 31.31.31.253
$ip link set dev ipip11 up
$ip addr add 45.45.1.1/24 dev ipip11
$hexec ep1 ip addr add 56.56.56.1/32 dev lo
$hexec ep1 ip addr add 20.20.20.1/32 dev lo
$sysctl -w net.ipv4.conf.all.arp_ignore=3
$sysctl -w net.ipv4.conf.all.arp_announce=2
$sysctl -w net.ipv4.conf.all.rp_filter=2
$sysctl -w net.ipv4.conf.ipip11.rp_filter=0

LoxiLB인스턴스와 엔드포인트간 터널을 만든 뒤에 모든 LoxiLB 인스턴스에 LB rule을 추가합니다:

loxicmd create lb 20.20.20.1 --select=hash --tcp=8080:8080 --endpoints=56.56.56.1:1,57.57.57.1:1,58.58.58.1:1 --mode=dsr --bgp

셋업에 사용된 모든 설정은 여기에서 찾아볼 수 있습니다.


패킷을 dump해서 보면 다음과 같습니다:


Client:


17:02:14.994082 IP 1.1.1.1.57538 > 20.20.20.1.8080: Flags [P.], seq 716235073:716235075, ack 2910196143, win 498, options [nop,nop,TS val 662647407 ecr 4290270063], length 2: HTTP
17:02:14.994293 IP 20.20.20.1.8080 > 1.1.1.1.57538: Flags [.], ack 2, win 490, options [nop,nop,TS val 4292968451 ecr 662647407], length 0
17:02:15.265042 IP 1.1.1.1.57538 > 20.20.20.1.8080: Flags [P.], seq 2:4, ack 1, win 498, options [nop,nop,TS val 662647678 ecr 4292968451], length 2: HTTP
17:02:15.265208 IP 20.20.20.1.8080 > 1.1.1.1.57538: Flags [.], ack 4, win 490, options [nop,nop,TS val 4292968722 ecr 662647678], length 0

LoxiLB:


08:02:15.265117 IP 31.31.31.254 > 31.31.31.1: IP 1.1.1.1.57538 > 20.20.20.1.8080: Flags [P.], seq 2:4, ack 1, win 498, options [nop,nop,TS val 662647678 ecr 4292968451], length 2: HTTP (ipip-proto-4)
08:02:15.521859 IP 31.31.31.254 > 31.31.31.1: IP 1.1.1.1.57538 > 20.20.20.1.8080: Flags [P.], seq 4:6, ack 1, win 498, options [nop,nop,TS val 662647935 ecr 4292968722], length 2: HTTP (ipip-proto-4)

Endpoint:


17:16:28.532316 IP 31.31.31.254 > 31.31.31.1: IP 1.1.1.1.57538 > 20.20.20.1.8080: Flags [P.], seq 2:4, ack 1, win 498, options [nop,nop,TS val 663500945 ecr 4293821805], length 2: HTTP (ipip-proto-4)
17:16:28.532316 IP 31.31.31.254 > 31.31.31.1: IP 1.1.1.1.57538 > 20.20.20.1.8080: Flags [P.], seq 2:4, ack 1, win 498, options [nop,nop,TS val 663500945 ecr 4293821805], length 2: HTTP (ipip-proto-4)
17:16:28.532360 IP 20.20.20.1.8080 > 1.1.1.1.57538: Flags [.], ack 4, win 490, options [nop,nop,TS val 4293821989 ecr 663500945], length 0
17:16:28.532365 IP 20.20.20.1.8080 > 1.1.1.1.57538: Flags [.], ack 4, win 490, options [nop,nop,TS val 4293821989 ecr 663500945], length 0

HA 데모 비디오:



긴 글 읽어주셔서 감사합니다. 더 많은 정보를 원하시면 Github 페이지 방문 부탁드립니다!

조회수 216회댓글 0개

최근 게시물

전체 보기

댓글


GIThub

Learn, Contribute & Share

GETTING STARTED

Get started with deploying LoxiLB in your cluster

Documentation

Check LoxiLB Documentation for more information.

Join the LoxiLB slack channel to chat with the developers community.

bottom of page