/dns-raft

DNS cluster using Raft protocol for resource records replication.

Primary LanguageGo

dns-raft

DNS cluster using Raft protocol for resource records replication.

The purpose of this case study is to implement the Raft library from Hashicorp in order to maintain consistent DNS records across multiple machines.

Any write attempt to KV Store is forwarded to the leader.

Design

  ┌───────────┐             ┌───────────┐             ┌───────────┐
  │z01.txt    │             │z00.txt    │             │z02.txt    │
  │           │             │           │             │           │
  │bar.com    │             │foo.com    │             │baz.com    │
  └─────▲─────┘             └─────▲─────┘             └─────▲─────┘
        │                         │                         │      
    read│                     read│                     read│      
        │                         │                         │      
  ┌─────┴─────┐             ┌─────┴─────┐             ┌─────┴─────┐
  │           │  leader     │           │     leader  │           │
  │           │forwarding   │           │   forwarding│           │
  │ node 01   ├─────────────▶ node 00   ◀─────────────┤ node 02   │
  │           │             │           │             │           │
  │ follower  │             │ leader    │             │ follower  │
  │           │  replication│           │replication  │           │
  │           ◀─────────────┤           ├─────────────▶           │
  └───────────┘             └───────────┘             └───────────┘

Build

Compile source code:

$ go build -o bin/dns-raft cmd/main.go

Run

Start three nodes:

$ bin/dns-raft -id id0 -raft.addr ":8300" -dns.addr ":8600" -zone.file "./zones/z00.txt"
$ bin/dns-raft -id id1 -raft.addr ":8301" -dns.addr ":8601" -zone.file "./zones/z01.txt" -raft.join ":8300"
$ bin/dns-raft -id id2 -raft.addr ":8302" -dns.addr ":8602" -zone.file "./zones/z02.txt" -raft.join ":8300"

DNS

Each node reads a zone file at execution, and replicates its records to other nodes.

Resolve addresses from first node:

$ dig @127.0.0.1 -p 8600 foo.com
$ dig @127.0.0.1 -p 8600 bar.com
$ dig @127.0.0.1 -p 8600 baz.com

Resolve addresses from second node:

$ dig @127.0.0.1 -p 8601 foo.com
$ dig @127.0.0.1 -p 8601 bar.com
$ dig @127.0.0.1 -p 8601 baz.com

Resolve addresses from third node:

$ dig @127.0.0.1 -p 8602 foo.com
$ dig @127.0.0.1 -p 8602 bar.com
$ dig @127.0.0.1 -p 8602 baz.com

Add a DNS record to a zone file:

echo 'database                 60 A     1.2.3.7' >> zones/z00.txt

Reload zone file by sending SIGHUP to node:

$ pkill -SIGHUP dns-raft

Resolve new address from any node:

$ dig @127.0.0.1 -p 8602 database.foo.com

Play with KV Store

Ping the first node:

$ echo "kv ping" | nc localhost 8300
PONG

Add a key to one of the nodes:

$ echo "kv set foo bar" | nc localhost 8301
SUCCESS

Get the value from any node:

$ echo "kv get foo" | nc localhost 8300
bar
$ echo "kv get foo" | nc localhost 8301
bar
$ echo "kv get foo" | nc localhost 8302
bar

Remove the key:

$ echo "kv del foo" | nc localhost 8302
SUCCESS
$ echo "kv get foo" | nc localhost 8301
ERROR

Inspirations