alxrt / powergslb

PowerGSLB - PowerDNS Remote GSLB Backend

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

PowerGSLB - PowerDNS Remote GSLB Backend

PowerGSLB is a simple DNS based Global Server Load Balancing (GSLB) solution.

Table of Contents

Main features

  • Quick installation and setup
  • Written in Python 2.7
  • Built as PowerDNS Authoritative Server Remote Backend
  • Web based administration interface using w2ui
  • HTTPS support for the web server
  • DNS GSLB configuration stored in a MySQL / MariaDB database
  • Master-Slave DNS GSLB using native MySQL / MariaDB replication
  • Multi-Master DNS GSLB using native MySQL / MariaDB Galera Cluster
  • Check status and data stored in local Redis instance Redis
  • Modular architecture
  • Multithreaded architecture
  • Systemd status and watchdog support
  • Extendable health checks:
    • ICMP ping
    • TCP connect
    • HTTP(s) request
    • Arbitrary command execution
  • Fallback if all the checks failed
  • Weighted (priority) records
  • Per record client IP / subnet persistence
  • DNS GSLB views support
  • All-in-one Docker image

Database diagram

Class diagram

Web based administration interface

Status grid

Stats on status

Advanced search

Add new record

More images

Installation on CentOS 7

Setup PowerGSLB and PowerDNS

yum -y install epel-release
yum -y update
yum -y install python2-pip

pip install pyping

VERSION=1.7.1
yum -y --setopt=tsflags= install \
    "https://github.com/AlekseyChudov/powergslb/releases/download/$VERSION/powergslb-$VERSION-1.el7.noarch.rpm" \
    "https://github.com/AlekseyChudov/powergslb/releases/download/$VERSION/powergslb-admin-$VERSION-1.el7.noarch.rpm" \
    "https://github.com/AlekseyChudov/powergslb/releases/download/$VERSION/powergslb-pdns-$VERSION-1.el7.noarch.rpm"

sed -i 's/^password = .*/password = your-database-password-here/g' /etc/powergslb/powergslb.conf

cp /etc/pdns/pdns.conf /etc/pdns/pdns.conf~
cp "/usr/share/doc/powergslb-pdns-$VERSION/pdns/pdns.conf" /etc/pdns/pdns.conf

Setup MariaDB

yum -y install mariadb-server

sed -i '/\[mysqld\]/a bind-address=127.0.0.1\ncharacter_set_server=utf8' /etc/my.cnf.d/server.cnf

systemctl enable mariadb.service
systemctl start mariadb.service
systemctl status mariadb.service

mysql_secure_installation

VERSION=1.7.1
mysql -p << EOF
CREATE DATABASE powergslb;
GRANT ALL ON powergslb.* TO powergslb@localhost IDENTIFIED BY 'your-database-password-here';
USE powergslb;
source /usr/share/doc/powergslb-$VERSION/database/scheme.sql
source /usr/share/doc/powergslb-$VERSION/database/data.sql
EOF

Start services

systemctl enable powergslb.service pdns.service
systemctl start powergslb.service pdns.service
systemctl status powergslb.service pdns.service

Test PowerGSLB

yum -y install bind-utils

dig @127.0.0.1 example.com SOA
dig @127.0.0.1 example.com A
dig @127.0.0.1 example.com AAAA
dig @127.0.0.1 example.com ANY

Web based administration interface

Open URL https://SERVER/admin/.

  • Default username: admin
  • Default password: admin

Health checks

Health checks are configured in the "Monitors" sidebar section in JSON format.

Supported check types:

type description
exec arbitrary command execution
icmp ICMP ping
http HTTP request
tcp TCP connect

Mandatory parameters

General parameters for all checks:

parameter description
type check type
interval interval between checks
timeout check timeout
fall number of failed checks to disable record
rise number of successful checks to enable record

Exec parameters

parameter description
type exec
args command to execute and arguments

Example:

{"type": "exec", "args": ["/etc/powergslb/powergslb-check", "%(content)s"], "interval": 3, "timeout": 1, "fall": 3, "rise": 5}

ICMP parameters

parameter description
type icmp
ip endpoint IP address

Example:

{"type": "icmp", "ip": "%(content)s", "interval": 3, "timeout": 1, "fall": 3, "rise": 5}

HTTP parameters

parameter description
type http
url endpoint URL

Example:

{"type": "http", "url": "http://%(content)s/status", "interval": 3, "timeout": 1, "fall": 3, "rise": 5}

TCP parameters

parameter description
type tcp
ip endpoint IP address
port endpoint port number

Example:

{"type": "tcp", "ip": "%(content)s", "port": 80, "interval": 3, "timeout": 1, "fall": 3, "rise": 5}

Building PowerGSLB RPM packages

You should always create RPM packages in a clean environment and preferably on a separate machine!

Please read How to create an RPM package.

yum -y update
yum -y install @Development\ Tools

VERSION=1.7.1
curl "https://codeload.github.com/AlekseyChudov/powergslb/tar.gz/$VERSION" -o "powergslb-$VERSION.tar.gz"
rpmbuild -tb --define "version $VERSION" "powergslb-$VERSION.tar.gz"

Upon successful completion you will have three packages

~/rpmbuild/RPMS/noarch/powergslb-$VERSION-1.el7.noarch.rpm
~/rpmbuild/RPMS/noarch/powergslb-admin-$VERSION-1.el7.noarch.rpm
~/rpmbuild/RPMS/noarch/powergslb-pdns-$VERSION-1.el7.noarch.rpm

Using PowerGSLB Docker image

For quick setup, you can pull all-in-one Docker image from docker.io.

VERSION=1.7.1

docker pull docker.io/alekseychudov/powergslb:"$VERSION"

docker run -it --name powergslb --hostname powergslb docker.io/alekseychudov/powergslb:"$VERSION"

docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' powergslb

docker exec -it powergslb bash

docker stop powergslb

For systemd to run in Docker container the following SELinux boolean should be enabled.

semanage boolean --modify --on container_manage_cgroup

Building PowerGSLB Docker image

To create an all-in-one Docker image.

VERSION=1.7.1

docker build -f docker/Dockerfile --build-arg VERSION="$VERSION" \
    --force-rm --no-cache -t powergslb:"$VERSION" https://github.com/AlekseyChudov/powergslb.git

Install using VirtualEnv

> virtualenv powergslb
> cd powergslb
> source bin/activate
> git clone https://github.com/AlekseyChudov/powergslb.git
> cd powergslb
> pip install -r requirements.txt
> sudo ln -s $(pwd)/powergslb/powergslb.service /etc/systemd/system/powergslb.service
> python setup.py install ; sudo service powergslb restart

Nginx as reverse proxy

Example:

upstream powergslb {
  server localhost:8080;
}

server {
        listen 80;
        server_name powergslb.local;

        return 301 https://$host$request_uri;
}

server {
    server_name powergslb.local;

    # SSL configuration
    #
    listen 443 ssl;
    listen [::]:443 ssl;
    #
    # Note: You should disable gzip for SSL traffic.
    # See: https://bugs.debian.org/773332
    #
    # Read up on ssl_ciphers to ensure a secure configuration.
    # See: https://bugs.debian.org/765782
    #
    # Self signed certs generated by the ssl-cert package
    # Don't use them in a production server!
    #
    #include snippets/snakeoil.conf;
    ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
    ssl_certificate_key     /etc/ssl/private/ssl-cert-snakeoil.key;

    location / {
        proxy_pass              http://powergslb;
        proxy_set_header        Host $host;
        proxy_set_header        Referer "";
        proxy_set_header        X-Remotebackend-Real-Remote $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_http_version      1.1;
    }

    error_log /var/log/nginx/powergslb_error.log;
    access_log /var/log/nginx/powergslb_access.logd;
}

Checks

Checks are implemented in src/powergslb/monitor/.

Supported types are :

  • icmp
  • tcp
  • http
  • https
  • command execution

Common mandatory parameters

type: the type of check interval: timeout: fall: rise:

ICMP (type: icmp)

Specific Arguments:

  • ip: the endpoint IP

Example:

{"type": "icmp", "ip": "%(content)s", "interval": 3, "timeout": 1, "fall": 3, "rise": 5}

TCP

Specific Arguments:

  • ip: the endpoint IP
  • port: the endpoint port

Example:

{"type": "tcp", "ip": "%(content)s", "port": 9200, "interval": 3, "timeout": 1, "fall": 3, "rise": 5}

HTTP

Specific Arguments:

  • url: the url to check

Optionnal Arguments:

  • headers: add specififc request headers (default to empty dictionnary {})
  • store: if True store returned value in timeserie database (default to False)

Example:

{"type": "http", "url": "http://%(content)s/status", "headers": {}, "interval": 3, "timeout": 1, "fall": 3, "rise": 5, "store": False}

Exec

Specific Arguments:

  • args: the command to execute

Optionnal Arguments:

  • store: if True store returned value in timeserie database (default to False)

Example:

{"type": "exec", "args": ["/etc/powergslb/powergslb-check", "%(content)s"], "interval": 3, "timeout": 1, "fall": 3, "rise": 5}

HTTPS

Specific Arguments:

  • url: the url to check

Optionnal Arguments:

  • secure: check certificate '(default to True)
  • headers: add specififc request headers (default to empty dictionnary {})
  • store: if True store returned value in timeserie database (default to False)

Example:

{"type": "https", "url": "https://%(content)s/ping?fmt=json", "secure": False,"headers": {"Host": "test.local", "Accept": "text/html"}, "interval": 3, "timeout": 1, "fall": 3, "rise": 5, "store": False}

LB mode

Priority - p

Records with highest weigth are send, DNS LB is only efficient on A records. On CNAME only first record will always be selected.

Topology - t

Client IP and record content are compared to a topology map in order to extract a region. If both region match, only these records will be selected.

Based on topology map like :

_lb_topology_map = {
  'region1': [ '10.10.0.0/16' ],
  'region2': [ '10.15.0.0/16' ],
  ...
}

If client IP is 10.10.0.1 and possible records are 10.10.0.10 and 10.15.0.10, only 10.10.0.10 will be sent. If 10.10.0.10 is detected as down, 10.15.0.10 will then be send.

Topology Priority - tp

Filter records using topology map and then, apply priority loadbalancing method.

Weighted Round Robin - wrr

One record is sent randomly based on available records respective weight.

Record probability = [record weight] / sum( [record weight] )

Topology Weighted Round Robin - twrr

Mix both topology and weighted round robin (only for A records).

Lowest Timeseries Data - ltd

Use response timeseries data in order to select the record with the lowest check response.

As response measurements are stored on a local Redis Database on each GSLB servers, the lowest data is not always relevant. Typically, timseries data based on response time or network time are biased by the GSLB server position compared to the monitored endpoints.

This kind of information are relevant only if client DNS selection is based on minimal round trip time or if Timseries store information that are independent of the GSLB position (like Load, CPU, bandwith...).

Tests using API

You can set the client IP at the value you want using the http header X-Remotebackend-Real-Remote.

Topology load-balancing:

clients IPs: 10.10.0.1 and 10.15.0.1 t.example.net: 2 A records 10.10.0.10 and 10.15.0.10

Client 10.10.0.1 receives 10.10.0.10:

curl --silent -H 'X-Remotebackend-Real-Remote: 10.10.0.1' -H 'host: powergslb.local' http://127.0.0.1:8080/dns/lookup/t.example.net/ANY | jq .
{
  "result": [
    {
      "content": "10.10.0.10",
      "qtype": "A",
      "qname": "t.example.net",
      "ttl": 10
    }
  ]
}

Client 10.15.0.1 receives 10.15.0.10:

> curl --silent -H 'X-Remotebackend-Real-Remote: 10.15.0.1' -H 'host: powergslb.local' http://127.0.0.1:8080/dns/lookup/t.example.net/ANY | jq .
{
  "result": [
    {
      "content": "10.15.0.10",
      "qtype": "A",
      "qname": "t.example.net",
      "ttl": 10
    }
  ]
}

If checks ara actives, when an IP is failing, the other IP will be delivered to every clients.

Weighted Round Robin

Client IP: 192.168.0.1 wrr.example.net: A records 10.10.0.10 with a weight of 1 and 10.15.0.10 with a weight of 2

> curl --silent -H 'X-Remotebackend-Real-Remote: 192.168.0.1' -H 'host: powergslb.local' http://127.0.0.1:8080/dns/lookup/wrr.example.net/ANY | jq .
{
  "result": [
    {
      "content": "10.15.0.10",
      "qtype": "A",
      "qname": "wrr.example.net",
      "ttl": 10
    }
  ]
}

Client will receive 10.15.0.10 two times more than 10.10.0.10.

About

PowerGSLB - PowerDNS Remote GSLB Backend

License:MIT License


Languages

Language:Python 75.2%Language:JavaScript 20.3%Language:Shell 2.0%Language:CSS 1.9%Language:HTML 0.5%Language:Dockerfile 0.1%