Skip to content

deunlee/PyGNS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PyGNS

  ____         ____ _   _ ____
 |  _ \ _   _ / ___| \ | / ___|
 | |_) | | | | |  _|  \| \___ \
 |  __/| |_| | |_| | |\  |___) |
 |_|    \__, |\____|_| \_|____/
        |___/

Python으로 구현한 DNS 기반 GSLB 서버입니다.
DNS-based GSLB server implemented in Python.

GSLB란?

GSLB(Global Server Load Balancing)란 DNS 프로토콜을 응용한 기술로, DNS 응답을 이용해서 서버의 부하를 분산시키는 로드 밸런싱 기법입니다.

하나의 서비스에서 부하 분산을 위해 여러 서버를 사용하는 경우, 단순히 DNS에 A 레코드를 여러 개 등록할 수 있습니다. 하지만 레코드 기반 로드 밸런싱은 클라이언트에서 랜덤으로 선택되므로, 서버의 장애에 빠르게 대응할 수 없고, 단순한 라운드 로빈 기법 밖에 사용할 수 없습니다. GSLB를 이용하면 실시간 Health Check를 통해 서버 상태를 모니터링하고, 장애 서버를 자동으로 제외하며, 다양한 로드 밸런싱 알고리즘으로 트래픽을 분산할 수 있습니다.

이 외에도 다양한 장점이 있습니다:

  • 지리적 트래픽 분산: 클라이언트의 물리적 위치에 가까운 리전 또는 데이터 센터로 지역 기반 트래픽 분배
  • 자동 장애 감지: Health Check를 통한 실시간 서버 상태 모니터링 및 장애 서버 자동 제외 (자동 failover)
  • 무중단 운영: 서버 점검/교체 시 해당 멤버만 비활성화하면 서비스 중단 없이 운영 가능
  • 수평 확장: 서비스 멤버 추가/제거만으로 서버 풀(pool) 확장/축소 가능
  • 로드 밸런싱 알고리즘: Round-Robin, Weighted Round-Robin, First-Available, Priority 등 다양한 알고리즘 지원
  • DNS 계층에서 투명하게 동작: 표준 DNS 프로토콜을 그대로 사용하므로 클라이언트/애플리케이션 변경 불필요
  • Hysteresis 모니터링: Health Check에서 상태 플래핑 방지를 위한 rise/fall 임계값 지원 (일시적 장애에 의한 상태 변경 방지)

PyGNS는 DNS 서버 위에 GSLB 기능이 구현되어 있어, 기존 BIND와 호환되는 Zone 파일을 그대로 사용할 수 있으며, 일부 레코드만 GSLB로 제공할 수 있습니다.

PyGNS Features

  • 모든 네트워크 통신은 비동기로 처리 (asyncio 기반 단일 스레드 비동기 아키텍처)
  • Pool/Member 단위 활성화/비활성화 제어
  • GSLB 도메인과 Zone 파일 간 레코드 충돌 자동 검증
  • SIGTERM/SIGINT 시그널 기반 Graceful Shutdown
  • 설정 검증 모드 지원 - 서버 실행 없이 설정 파일 유효성 검사

DNS Server

  • 주요 레코드 타입 지원 (A, AAAA, CNAME, MX, NS, SOA, TXT 등)
  • UDP 및 TCP Query 모두 지원
  • UDP EDNS0 지원 (RFC 6891) - UDP 페이로드 크기 확장 (기본 1232bytes)
  • TCP Pipelining 지원 (RFC 7766)
  • Negative Caching 지원 (RFC 2308) - NXDOMAIN/NODATA 응답에 SOA 레코드 포함
  • 응답 크기 초과 시 단계적 축소 및 TC Flag 설정 지원
  • BIND 호환 Zone 파일 지원
  • Longest-Matching 방식의 다중 Zone 지원

GSLB Manager

  • 멤버(서버) 선택 알고리즘:
    • round-robin: 멤버를 순차 순환, 카운터 기반 균등 분배
    • weighted-round-robin: 가중치(weight) 비율로 확장한 리스트에서 라운드 로빈
    • first-available: 첫 번째 가용 멤버 사용 (Active-Standby 구성)
    • priority: 우선순위 기반 선택 (동일 우선순위는 라운드 로빈)
    • random: 가용 멤버 중 무작위로 선택
  • Fallback 정책: (모든 멤버 DOWN 시)
    • none: 빈 Answer (NODATA) + SOA 반환 (트래픽 차단)
    • all: 전체 멤버를 TTL=0으로 반환 (캐시 방지 및 복구 시 즉시 전환) (기본값)
  • Health Check:
    • HTTP/HTTPS 기반 서버 상태 확인
    • Hysteresis 상태 전환 - rise/fall 임계값을 통한 anti-flapping
    • Pool 레벨 기본 설정 + Member 레벨 개별 오버라이드
    • TCP 커넥션 풀 사용 및 동시 연결 수 제한
    • 초기 실행 시, 랜덤 지연으로 순간 부하 방지
    • 초기 서버 상태는 가용으로 간주하여 빠른 서비스 시작

Getting Started

  • Python 3.11+ 버전이 설치되어 있어야 합니다.
  • Linux에서는 53번 포트를 열기 위해 root 권한이 필요합니다.
  • Windows에서 시스템 서비스(Dnscache)가 0.0.0.0:53를 사용중인 경우 127.0.0.1로 테스트할 수 있습니다.
  • 아래 스크립트를 이용하면, Python 가상 환경 및 패키지 설치를 자동으로 진행합니다.
    • Windows: gns.bat (or gns.bat -b 127.0.0.1)
    • Linux: sudo ./gns.sh
    • macOS: ./gns.sh

Command-Line Options

Option Description Default
-b, --bind 서버 IP 0.0.0.0
-p, --port 서버 포트 53
-z, --zone-dir Zone 파일 디렉터리 ./config/zone
-g, --gslb-dir GSLB 설정 디렉터리 ./config/gslb
-l, --log-level 로그 레벨 (DEBUG, INFO, WARNING, ERROR) INFO
--edns-max-payload UDP EDNS0 최대 페이로드 1232
--hc-initial-delay Health Check 초기 랜덤 지연 최대값 (초) 3
--hc-conn-limit Health Check 최대 동시 연결 수 128
-c, --check-configs 설정 검증 후 종료 -

GSLB Configuration Example

domain: gslb.test.com           # GSLB 도메인 (FQDN, trailing dot은 생략 가능)
ttl: 10                         # DNS 응답 TTL (초, 기본값: 10)
algorithm: round-robin          # 로드 밸런싱 알고리즘
fallback: all                   # 모든 멤버 DOWN 시, Fallback 정책 (기본값: all)

health_check:                   # Pool 레벨 헬스체크 설정
  protocol: http                # http | https
  port: 80                      # 포트 (기본값: 80)
  url_path: /health_check.html  # URL (기본값: /)
  interval: 10                  # 헬스체크 주기 (초, 기본값: 10)
  timeout: 5                    # 응답 타임아웃 (초, 기본값: 5)
  expected_status: [200, 204]   # 정상 판정 HTTP 상태 코드 (기본값: [200, 204])
  rise: 2                       # UP 상태 전환에 필요한 연속 성공 횟수 (기본값: 2)
  fall: 3                       # DOWN 상태 전환에 필요한 연속 실패 횟수 (기본값: 3)

members:
  - address: 127.0.0.10         # 서버 IP 주소 (필수)
    # weight: 10                # 가중치 (weighted-round-robin용, 기본값: 10)
    # priority: 5               # 우선순위 (priority용, 낮을수록 높은 우선순위, 기본값: 5)
    # enabled: true             # 활성화 여부 (기본값: true)
    comment: "Server 1"         # 멤버 설명 (선택)
    # health_check:             # 멤버별 헬스체크 오버라이드
    #   port: 8080
    #   url_path: /status

  - address: 127.0.0.20
    comment: "Server 2"

  - address: 127.0.0.30
    comment: "Server 3"

Example Output

A Record

$ dig @localhost ns1.test.com
...
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;ns1.test.com.                  IN      A

;; ANSWER SECTION:
ns1.test.com.           3600    IN      A       10.20.30.40

GSLB Round-Robin

$ dig @localhost gslb.test.com +short
10.10.10.10

$ dig @localhost gslb.test.com +short
20.20.20.20

$ dig @localhost gslb.test.com +short
30.30.30.30

GSLB Distribution (100 Queries)

$ for i in $(seq 1 100); do dig @localhost gslb.test.com +short; done | sort | uniq -c
  33 10.10.10.10
  33 20.20.20.20
  34 30.30.30.30

Acceptance Test

전체 테스트 케이스와 결과는 test_result.txt 파일을 참고하세요.

$ ./test.sh

[*] Starting PyGNS server on 127.0.0.1:53...
[+] PyGNS server started! (PID: 11504)
...
[*] Total: 120 / Pass: 120 / Fail: 0
[PASS] RESULT: ALL TESTS PASSED

TODO

  • GSLB에 AAAA 레코드 지원 추가
  • GeoIP 및 ECS (Client Subnet) 구현
  • 설정 파일 Hot Reload 구현
  • TCP/ICMP에 대한 Health Check 구현
  • Zone 전송 및 위임 구현

License

  • MIT License

About

GSLB (Global Server Load Balancing) Server based on DNS

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors