Architecture¶
Code Base¶
There are two top level component of RestKnot. First is resknot-api
which
exposes the REST API to be consumed by the client. The app is built on top of
Flask. If you want to familiarize yourself with the codebase, the best way to start
is the controllers (api/app/controllers
). domain.py
acts as
an entry point after user registration (user.py
). It serves the creation of
new zone and default records.
The second component is the agent
. It receives a JSON message from the
broker, parses it then sends a command to the Knot server via
libknot.py
. It’s a simple app and the main entry point is agent/dnsagent/start.py
.
The Ecosystem¶
This part describes how resknot-api
talks to resknot-agent
and other
applications. You can also see the Basic Deployment Architecture to learn the basic form of RESTKnot
deployment.
To learn how each application talks with each other, let’s start with a request
from the client
. Such as asking for new zone creation. The request is a REST API call
that is exposed by restknot-api
. While interacting with client
, it also
talks with database
to store and retrieves new zones, user, etc. Then the
restknot-api
send a JSON message to message broker
.
In turn, The broker
pushes the message to all resknot-agent
(including the slaves). The agent
parses the message and send a command to
Knot DNS server
using libknot.py
For creating a new zone. resknot-api
will send 4 messages. The first message
contains data to create zone config, it will be consumed by both master
and
slave
agent.
first message
{
"agent": {
"agent_type": [
"master",
"slave"
]
},
"knot": [
{
"cmd": "conf-begin",
"zone": "example.com"
},
{
"cmd": "conf-set",
"section": "zone",
"item": "domain",
"data": "example.com"
},
{
"cmd": "conf-commit",
"zone": "example.com"
}
]
}
The second message contains data to create default records (SOA, NS,
CNAME). It’s only consumed by master
.
second message
{
"agent": {
"agent_type": [
"master"
]
},
"knot": [
{
"cmd": "zone-begin",
"zone": "example.com"
},
{
"cmd": "zone-set",
"zone": null,
"owner": "@",
"rtype": "SOA",
"ttl": "3600",
"data": "one.dns.id. hostmaster.dns.id. 20 ..."
},
{
"cmd": "zone-set",
"zone": null,
"owner": "@",
"rtype": "NS",
"ttl": "3600",
"data": "one.dns.id."
},
{
"//": "some messages omitted for brevity"
},
{
"cmd": "zone-commit",
"zone": "example.com"
}
]
}
The third message contains data to set additional config such serial-policy
,
notify
, and ACL
. The third and fourth message contains similar data,
only it’s refined toward master
agent or slave
agent. This is why we
have to set RESTKNOT_AGENT_TYPE
correctly. Otherwise, the zone can not be
created.
third message
[
{
"item": "notify",
"data": "slave1",
"cmd": "conf-set",
"section": "zone",
"zone": "example.com"
},
{
"item": "notify",
"data": "slave2",
"cmd": "conf-set",
"section": "zone",
"zone": "example.com"
},
{
"item": "acl",
"data": "slave1",
"cmd": "conf-set",
"section": "zone",
"zone": "example.com"
},
{
"item": "acl",
"data": "slave2",
"cmd": "conf-set",
"section": "zone",
"zone": "example.com"
}
]
The fourth message contains similar data as the third, but it’s only geared
toward slave
. Such notify
keyword being changed to master
. These
keyword differences also represented in knot.conf
and
config.yml
. To learn more, take a look at knot.conf.master
and
knot.conf.slave
in /deploy/examples/
.
fourth message
{
"item":"master",
"data":"master1",
"cmd":"conf-set",
"section":"zone",
"zone":"example.com"
}
If we look closely at the figure above. Message broker pushing the message to all
agent
(represented by a straight line). In zone creation example, all the zone
config data is sent to all agent
. This is due to the fact that knot DNS
slaves
can’t create zone config automatically, so the agent
there for it.
After the config is created in the slaves
. It starts talking with master
via
AXFR
to receive zone’s records and updates (represented by dotted line). But
before any zone’s config is created, The slave
can’t do anything.
If config creation is done automatically in the slaves
via AXFR
maybe we
can get rid of the agent
in the slaves
entirely.