gslb

package module
v0.20.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 15, 2026 License: MIT Imports: 40 Imported by: 0

README ¶

Go Report Go lint Go tests Go coverage Lines of code Integration tests

release

CoreDNS-GSLB

What is CoreDNS-GSLB?

CoreDNS-GSLB is a plugin that provides Global Server Load Balancing functionality in CoreDNS. It intelligently routes your traffic to healthy backends based on geographic location, priority, or load balancing algorithms.

What it does:

  • Health monitoring of your backends with HTTP(S), TCP, ICMP, MySQL, gRPC, or custom Lua checks
  • Reusable healthcheck profiles: Define health check templates globally (in the Corefile) or per zone, and reference them by name in your backends
  • Geographic routing using MaxMind GeoIP databases or custom location mapping
  • Load balancing with failover, round-robin, random, weighted or GeoIP-based selection
  • Adaptive monitoring that reduces healthcheck frequency for idle records
  • Live configuration reload without restarting CoreDNS
  • Bulk backends management via API: Instantly enable or disable multiple backends by location or IP prefix
  • No external database: Records are defined using a YAML file.

Unlike many existing solutions, this plugin is designed for non-Kubernetes infrastructures — including virtual machines, bare metal servers, and hybrid environments.

  • Non-Kubernetes focused: Designed for VMs, bare metal, and hybrid environments
  • Multiple health check types: From simple TCP to complex Lua scripting
  • Real client IP detection: EDNS Client Subnet support for accurate GeoIP routing
  • Resource efficient: Adaptive healthchecks reduce load on unused backends
  • Production ready: Prometheus metrics and comprehensive observability

🚀 Quick Start

  1. Create docker-compose.yml:

Prepare folder

mkdir coredns

Expected folder structure

coredns-gslb/
├── docker-compose.yml
└── coredns/
    ├── Corefile
    ├── db.gslb.example.com
    └── db.gslb.example.com.yml

Create the docker-compose.yml, update binding ports according to your system

services:
  coredns-gslb:
    image: dmachard/coredns_gslb:latest
    ports:
      - "53:53/udp"
      - "53:53/tcp"
      - "9153:9153"  # Metrics
    volumes:
      - ./coredns:/coredns
    command: ["-conf", "/coredns/Corefile"]
    restart: unless-stopped
  1. Create coredns/Corefile:

Create the Corefile

.:53 {
    file /coredns/db.gslb.example.com gslb.example.com
    template IN HTTPS { rcode NOERROR }
    gslb {
        zone  gslb.example.com. /coredns/db.gslb.example.com.yml
    }
    prometheus
}
  1. Create coredns/db.gslb.example.com:
$ORIGIN gslb.example.com.
@       3600    IN      SOA     ns1.example.com. admin.example.com. (
                                2024010101 7200 3600 1209600 3600 )
        3600    IN      NS      ns1.gslb.example.com.
        3600    IN      NS      ns2.gslb.example.com.
  1. Create coredns/gslb_config.yml:
healthcheck_profiles:
  https_default:
    type: http
    params:
      enable_tls: true
      port: 443
      uri: "/"
      expected_code: 200
      timeout: 5s

records:
  webapp.gslb.example.com.:
    mode: "failover"
    record_ttl: 30
    scrape_interval: 10s
    backends:
    - address: "172.16.0.10"
      priority: 1
      healthchecks: [ https_default ]
    - address: "172.16.0.11"
      priority: 2
      healthchecks: [ https_default ]
  1. Run and test:
docker-compose up -d
dig @localhost webapp.gslb.example.com
dig @localhost TXT webapp.gslb.example.com  # Debug info

📚 Documentations

Topic Description
Selection Modes Failover, round-robin, random, GeoIP routing, weighted
Health Checks HTTP(S), TCP, ICMP, MySQL, gRPC, Lua scripting
GeoIP Setup MaxMind databases and custom location mapping
Configuration Complete parameter reference
High Availability Production deployment patterns
API Reference REST API endpoints and OpenAPI schema
CLI Guide Command-line tool for operations
Observability Prometheus metrics
Benchmarking Performance
Troubleshooting Troubleshooting and debugging

👥 Contributions

Contributions are welcome! Please read the Developer Guide for local setup and testing instructions.

  • DNS-tester - DNS testing toolkit
  • DNS-collector - Grab your DNS logs, detect anomalies, and finally understand what's happening on your network.

Documentation ¶

Index ¶

Constants ¶

View Source
const ICMPType = "icmp"

Variables ¶

View Source
var GlobalHealthcheckProfiles map[string]*HealthCheck

Global map for global healthcheck profiles loaded from Corefile

View Source
var Version = "dev"

Version of the GSLB plugin, set at build time

Functions ¶

func IncBackendSelected ¶

func IncBackendSelected(name, address string)

func IncConfigReloads ¶

func IncConfigReloads(result string)

func IncHealthcheckFailures ¶

func IncHealthcheckFailures(typ, address, reason string)

func IncHealthcheckTotal ¶

func IncHealthcheckTotal(name, typ, address, result string)

func IncRecordResolutions ¶

func IncRecordResolutions(name, result string)

func NewHTTPSTransport ¶

func NewHTTPSTransport(cc *tls.Config) *http.Transport

NewHTTPSTransport returns an HTTP transport configured using tls.Config

func NewTLSClientConfig ¶

func NewTLSClientConfig(certPath, keyPath, caPath string) (*tls.Config, error)

NewTLSConfig returns a TLS config that includes a certificate and key pair If caPath is empty, system CAs will be used If certPath or keyPath are empty, client certificate will not be loaded

func ObserveHealthcheck ¶

func ObserveHealthcheck(name, typeStr, address string, start time.Time, result bool)

func ObserveHealthcheckDuration ¶

func ObserveHealthcheckDuration(typ, address string, duration float64)

func ObserveRecordResolutionDuration ¶

func ObserveRecordResolutionDuration(name, result string, duration float64)

func RegisterMetrics ¶

func RegisterMetrics()

func SetActiveBackends ¶

func SetActiveBackends(name string, value float64)

func SetBackendHealthStatus ¶

func SetBackendHealthStatus(name, address string, value float64)

func SetBackendHealthcheckStatus ¶

func SetBackendHealthcheckStatus(name, address, typeStr string, value float64)

func SetBackendsTotal ¶

func SetBackendsTotal(value float64)

func SetHealthchecksTotal ¶

func SetHealthchecksTotal(value float64)

func SetRecordHealthStatus ¶

func SetRecordHealthStatus(name string, value float64)

func SetRecordsTotal ¶

func SetRecordsTotal(value float64)

func SetVersionInfo ¶

func SetVersionInfo(version string)

func SetZonesTotal ¶

func SetZonesTotal(value float64)

func WithClientInfo ¶

func WithClientInfo(ctx context.Context, ip net.IP, prefix uint8) context.Context

Types ¶

type Backend ¶

type Backend struct {
	Fqdn            string               // Fully qualified domain name
	Description     string               // Description of the backend
	Address         string               // IP address or hostname
	Priority        int                  // Priority for load balancing
	Weight          int                  // Weight for weighted load balancing
	Enable          bool                 // Enable or disable the backend
	Tags            []string             // List of tags for filtering or grouping
	HealthChecks    []GenericHealthCheck `yaml:"healthchecks"` // Health check configurations
	Timeout         string               // Timeout for requests
	Alive           bool                 // Indicates if the backend is alive
	Continent       string               // Continent code for GeoIP (e.g. EU)
	Country         string               // Country code for GeoIP
	Subdivision     string               // Subdivision/state code for GeoIP (e.g. CA, NY)
	City            string               // City name for GeoIP
	ASN             string               // ASN for GeoIP
	Location        string               // location
	Longitude       float64              // Longitude for distance-based GeoIP routing
	Latitude        float64              // Latitude for distance-based GeoIP routing
	LongitudeRad    float64              // Precomputed longitude in radians for distance calculations
	LatitudeRad     float64              // Precomputed latitude in radians for distance calculations
	HasCoordinates  bool                 // Indicates whether both coordinates were explicitly configured
	LastHealthcheck time.Time            // Last time a healthcheck was launched
	// contains filtered or unexported fields
}

Backend represents an individual backend with health check settings.

func (*Backend) GetASN ¶

func (b *Backend) GetASN() string

func (*Backend) GetAddress ¶

func (b *Backend) GetAddress() string

func (*Backend) GetCity ¶

func (b *Backend) GetCity() string

func (*Backend) GetContinent ¶

func (b *Backend) GetContinent() string

func (*Backend) GetCountry ¶

func (b *Backend) GetCountry() string

func (*Backend) GetDescription ¶

func (b *Backend) GetDescription() string

func (*Backend) GetFqdn ¶

func (b *Backend) GetFqdn() string

func (*Backend) GetHealthChecks ¶

func (b *Backend) GetHealthChecks() []GenericHealthCheck

func (*Backend) GetLatitude ¶

func (b *Backend) GetLatitude() float64

func (*Backend) GetLatitudeRad ¶

func (b *Backend) GetLatitudeRad() float64

func (*Backend) GetLocation ¶

func (b *Backend) GetLocation() string

func (*Backend) GetLongitude ¶

func (b *Backend) GetLongitude() float64

func (*Backend) GetLongitudeRad ¶

func (b *Backend) GetLongitudeRad() float64

func (*Backend) GetPriority ¶

func (b *Backend) GetPriority() int

func (*Backend) GetSubdivision ¶

func (b *Backend) GetSubdivision() string

func (*Backend) GetTags ¶

func (b *Backend) GetTags() []string

func (*Backend) GetTimeout ¶

func (b *Backend) GetTimeout() string

func (*Backend) GetWeight ¶

func (b *Backend) GetWeight() int

func (*Backend) HasGeoCoordinates ¶

func (b *Backend) HasGeoCoordinates() bool

func (*Backend) IsEnabled ¶

func (b *Backend) IsEnabled() bool

func (*Backend) IsHealthy ¶

func (b *Backend) IsHealthy() bool

func (*Backend) Lock ¶

func (b *Backend) Lock()

func (*Backend) SetFqdn ¶

func (b *Backend) SetFqdn(fqdn string)

func (*Backend) Unlock ¶

func (b *Backend) Unlock()

func (*Backend) UnmarshalYAML ¶

func (b *Backend) UnmarshalYAML(unmarshal func(interface{}) error) error

type BackendInterface ¶

type BackendInterface interface {
	GetFqdn() string
	SetFqdn(fqdn string)
	GetDescription() string
	GetAddress() string
	GetPriority() int
	GetWeight() int
	IsEnabled() bool
	GetTags() []string
	GetHealthChecks() []GenericHealthCheck
	GetTimeout() string
	GetContinent() string
	GetCountry() string
	GetSubdivision() string
	GetCity() string
	GetASN() string
	GetLocation() string
	GetLongitude() float64
	GetLatitude() float64
	GetLongitudeRad() float64
	GetLatitudeRad() float64
	HasGeoCoordinates() bool
	IsHealthy() bool

	Lock()
	Unlock()
	// contains filtered or unexported methods
}

type ClientInfo ¶

type ClientInfo struct {
	IP        net.IP
	PrefixLen uint8
}

func GetClientInfo ¶

func GetClientInfo(ctx context.Context) *ClientInfo

type GRPCHealthCheck ¶

type GRPCHealthCheck struct {
	Host    string
	Port    int
	Service string
	Timeout time.Duration
}

func (*GRPCHealthCheck) Check ¶

func (h *GRPCHealthCheck) Check() error

func (*GRPCHealthCheck) Equals ¶

func (h *GRPCHealthCheck) Equals(other GenericHealthCheck) bool

func (*GRPCHealthCheck) GetType ¶

func (h *GRPCHealthCheck) GetType() string

func (*GRPCHealthCheck) PerformCheck ¶

func (h *GRPCHealthCheck) PerformCheck(backend *Backend, fqdn string, maxRetries int) bool

func (*GRPCHealthCheck) SetDefault ¶

func (h *GRPCHealthCheck) SetDefault()

type GSLB ¶

type GSLB struct {
	Next                plugin.Handler
	Zones               map[string]string             // List of authoritative domains
	Records             map[string]map[string]*Record // zone -> fqdn -> record
	HealthcheckProfiles map[string]*HealthCheck       `yaml:"healthcheck_profiles"`

	Zone                      string   // Zone attendue pour la vérification des records
	LastResolution            sync.Map // key: domain (string), value: time.Time
	RoundRobinIndex           sync.Map
	MaxStaggerStart           string
	BatchSizeStart            int
	ResolutionIdleTimeout     string
	ResolutionIdleMultiplier  int // Multiplier for slow healthcheck interval
	HealthcheckIdleMultiplier int // Multiplier for slow healthcheck interval
	Mutex                     sync.RWMutex
	UseEDNSCSubnet            bool
	LocationMap               map[string]string
	GeoIPCountryDB            *geoip2.Reader // Loaded MaxMind DB (country)
	GeoIPCityDB               *geoip2.Reader // Loaded MaxMind DB (city)
	GeoIPASNDB                *geoip2.Reader // Loaded MaxMind DB (ASN)
	APIEnable                 bool           // Enable/disable API HTTP server
	APICertPath               string         // TLS certificate path for API
	APIKeyPath                string         // TLS key path for API
	APIListenAddr             string         // API listen address (default 0.0.0.0)
	APIListenPort             string         // API listen port (default 8080)
	APIBasicUser              string         // HTTP Basic Auth username (optional)
	APIBasicPass              string         // HTTP Basic Auth password (optional)
	// DisableTXT disables TXT record resolution if set to true
	DisableTXT bool
}

func (*GSLB) GetMaxStaggerStart ¶

func (g *GSLB) GetMaxStaggerStart() time.Duration

func (*GSLB) GetResolutionIdleTimeout ¶

func (g *GSLB) GetResolutionIdleTimeout() time.Duration

func (*GSLB) Name ¶

func (g *GSLB) Name() string

func (*GSLB) RegisterAPIHandlers ¶

func (g *GSLB) RegisterAPIHandlers(mux *http.ServeMux)

RegisterAPIHandlers registers all API endpoints to the provided mux.

func (*GSLB) ServeAPI ¶

func (g *GSLB) ServeAPI()

func (*GSLB) ServeDNS ¶

func (g *GSLB) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error)

func (*GSLB) UnmarshalYAML ¶

func (g *GSLB) UnmarshalYAML(unmarshal func(interface{}) error) error

UnmarshalYAML implements custom YAML unmarshaling to handle healthcheck_profiles

type GenericHealthCheck ¶

type GenericHealthCheck interface {
	// PerformCheck executes the health check for a backend.
	PerformCheck(backend *Backend, fdqn string, maxRetries int) bool

	// GetType returns the type of the health check (e.g., "http/80").
	GetType() string

	// Equals compares the current health check with another instance for equality.
	Equals(other GenericHealthCheck) bool
}

GenericHealthCheck defines a common interface for health checks

type HTTPHealthCheck ¶

type HTTPHealthCheck struct {
	Port          int               `yaml:"port" default:"443"`
	EnableTLS     bool              `yaml:"enable_tls" default:"true"`
	Cert          string            `yaml:"cert_path" default:""`
	Key           string            `yaml:"key_path" default:""`
	CA            string            `yaml:"ca_path" default:""`
	URI           string            `yaml:"uri" default:"/"`
	Method        string            `yaml:"method" default:"GET"`
	Host          string            `yaml:"host" default:"localhost"`
	Headers       map[string]string `yaml:"headers"`
	Timeout       string            `yaml:"timeout" default:"5s"`
	ExpectedCode  int               `yaml:"expected_code" default:"200"`
	ExpectedBody  string            `yaml:"expected_body" default:""`
	SkipTLSVerify bool              `yaml:"skip_tls_verify" default:"false"`
}

HTTPHealthCheck represents HTTP-specific health check settings.

func (*HTTPHealthCheck) Equals ¶

func (h *HTTPHealthCheck) Equals(other GenericHealthCheck) bool

Equals compares two HTTPHealthCheck objects for equality.

func (*HTTPHealthCheck) GetType ¶

func (h *HTTPHealthCheck) GetType() string

func (*HTTPHealthCheck) PerformCheck ¶

func (h *HTTPHealthCheck) PerformCheck(backend *Backend, fqdn string, maxRetries int) bool

PerformCheck implements the HealthCheck interface for HTTP health checks

func (*HTTPHealthCheck) SetDefault ¶

func (h *HTTPHealthCheck) SetDefault()

type HealthCheck ¶

type HealthCheck struct {
	Type   string                 `yaml:"type"`
	Params map[string]interface{} `yaml:"params"`
}

func ResolveHealthcheckProfile ¶

func ResolveHealthcheckProfile(profileName string, localProfiles map[string]*HealthCheck) (*HealthCheck, error)

ResolveProfile resolves a healthcheck profile to a concrete HealthCheck

func (*HealthCheck) ToSpecificHealthCheck ¶

func (hc *HealthCheck) ToSpecificHealthCheck() (GenericHealthCheck, error)

type ICMPHealthCheck ¶

type ICMPHealthCheck struct {
	Count   int    `yaml:"count" default:"3"`    // Number of ICMP packets to send
	Timeout string `yaml:"timeout" default:"5s"` // Maximum duration for pings
}

ICMPHealthCheck represents the configuration for an ICMP health check.

func (*ICMPHealthCheck) Equals ¶

func (h *ICMPHealthCheck) Equals(other GenericHealthCheck) bool

Equals compares two ICMPHealthCheck objects for equality.

func (*ICMPHealthCheck) GetType ¶

func (h *ICMPHealthCheck) GetType() string

GetType returns the type of the health check as a string.

func (*ICMPHealthCheck) PerformCheck ¶

func (h *ICMPHealthCheck) PerformCheck(backend *Backend, fqdn string, maxRetries int) bool

PerformCheck executes the ICMP health check for a backend.

func (*ICMPHealthCheck) SetDefault ¶

func (h *ICMPHealthCheck) SetDefault()

SetDefault applies default values to ICMPHealthCheck fields.

type LuaHealthCheck ¶

type LuaHealthCheck struct {
	Script  string        `yaml:"script"`
	Timeout time.Duration `yaml:"timeout"`
}

func (*LuaHealthCheck) Equals ¶

func (l *LuaHealthCheck) Equals(other GenericHealthCheck) bool

func (*LuaHealthCheck) GetType ¶

func (l *LuaHealthCheck) GetType() string

func (*LuaHealthCheck) PerformCheck ¶

func (l *LuaHealthCheck) PerformCheck(backend *Backend, fqdn string, maxRetries int) bool

func (*LuaHealthCheck) SetDefault ¶

func (l *LuaHealthCheck) SetDefault()

type MockHealthCheck ¶

type MockHealthCheck struct{}

Mock a health check that always returns true (successful) For testing purpose

func (*MockHealthCheck) Equals ¶

func (hc *MockHealthCheck) Equals(other GenericHealthCheck) bool

func (*MockHealthCheck) GetType ¶

func (hc *MockHealthCheck) GetType() string

func (*MockHealthCheck) PerformCheck ¶

func (hc *MockHealthCheck) PerformCheck(backend *Backend, fqdn string, maxRetries int) bool

type MySQLHealthCheck ¶

type MySQLHealthCheck struct {
	Host     string `yaml:"host"`
	Port     int    `yaml:"port" default:"3306"`
	User     string `yaml:"user"`
	Password string `yaml:"password"`
	Database string `yaml:"database"`
	Timeout  string `yaml:"timeout" default:"3s"`
	Query    string `yaml:"query" default:"SELECT 1"`
}

MySQLHealthCheck represents MySQL-specific health check settings.

func (*MySQLHealthCheck) Equals ¶

func (h *MySQLHealthCheck) Equals(other GenericHealthCheck) bool

func (*MySQLHealthCheck) GetType ¶

func (h *MySQLHealthCheck) GetType() string

func (*MySQLHealthCheck) PerformCheck ¶

func (h *MySQLHealthCheck) PerformCheck(backend *Backend, fqdn string, maxRetries int) bool

func (*MySQLHealthCheck) SetDefault ¶

func (h *MySQLHealthCheck) SetDefault()

type Pinger ¶

type Pinger interface {
	Run() error
	Statistics() *probing.Statistics
	SetPrivileged(privileged bool)
}

type RealPinger ¶

type RealPinger struct {
	// contains filtered or unexported fields
}

func (*RealPinger) Run ¶

func (r *RealPinger) Run() error

func (*RealPinger) SetPrivileged ¶

func (r *RealPinger) SetPrivileged(privileged bool)

func (*RealPinger) Statistics ¶

func (r *RealPinger) Statistics() *probing.Statistics

type Record ¶

type Record struct {
	Fqdn           string
	Mode           string
	Backends       []BackendInterface
	Owner          string
	Description    string
	RecordTTL      int
	ScrapeInterval string
	ScrapeRetries  int
	ScrapeTimeout  string
	// contains filtered or unexported fields
}

Record represents a GSLB record in the YAML config.

func (*Record) GetScrapeInterval ¶

func (r *Record) GetScrapeInterval() time.Duration

GetScrapeInterval returns the health check interval for HTTPHealthCheck

func (*Record) GetScrapeTimeout ¶

func (r *Record) GetScrapeTimeout() time.Duration

GetScrapeTimeout returns the health check timeout for HTTPHealthCheck

func (*Record) UnmarshalYAML ¶

func (r *Record) UnmarshalYAML(unmarshal func(interface{}) error) error

func (*Record) UpdateRecord ¶

func (r *Record) UpdateRecord()

type TCPHealthCheck ¶

type TCPHealthCheck struct {
	Port    int    `yaml:"port" default:"80"`    // TCP port to connect to
	Timeout string `yaml:"timeout" default:"5s"` // Timeout for the TCP connection
}

TCPHealthCheck represents TCP-specific health check settings.

func (*TCPHealthCheck) Equals ¶

func (h *TCPHealthCheck) Equals(other GenericHealthCheck) bool

Equals compares two TCPHealthCheck objects for equality.

func (*TCPHealthCheck) GetType ¶

func (h *TCPHealthCheck) GetType() string

GetType returns the type of the health check as a string.

func (*TCPHealthCheck) PerformCheck ¶

func (h *TCPHealthCheck) PerformCheck(backend *Backend, fqdn string, maxRetries int) bool

PerformCheck implements the health check logic for TCP connections.

func (*TCPHealthCheck) SetDefault ¶

func (h *TCPHealthCheck) SetDefault()

SetDefault applies default values to TCPHealthCheck fields.

Directories ¶

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL