DNS Operations
dr-provision provides a simple DNS query server. Most records are supported and can be returned by the server.
Endpoint Startup Configuration¶
Whether the DNS server is enabled and what ports it will listen on are controlled by the following startup options:
--disable-dnsto disable basic DNS functionality.--dns-portto change the DNS port from the default of 53 to something else. This is both TCP and UDP.
If none of these options are present, then we default to DNS being enabled on the standard port. The DNS server listens on all interfaces, and that behaviour cannot be modified at the present time.
Warning
Some services will conflict with DNS. Common sevices that must be disabled when running DRP DNS server
- dnsmasq
- bind
Runtime Configuration¶
By default, (without any Zones or Reservations defined) the DNS server will respond with negative matches.
Zones¶
A Zone defines a set of information that can be returned to DNS queries.
This includes dynamic records built from templatized rendering strings from Machine objects.
Reservations¶
A Reservation defines a one-to-one mapping between a specific network interface to be configured and the IP addressing information that should be applied to that interface.
If the reservation and its optional subnet contain an address, hostname, and a domainname, an A and PTR record will be created with in a zone that matches the Origin for the system.
Common Use Cases¶
This section provides real-world examples for typical DNS configurations.
Use Case 1: Basic Machine DNS¶
Map all machines to a domain with automatic DNS records.
Scenario: You want all machines managed by DRP to automatically get DNS entries like machine1.lab.local, machine2.lab.local.
Setup:
# Create zone for your domain
drpcli zones create - <<EOF
Name: lab-local
Origin: "lab.local."
Priority: 100
Records:
- Name: "eval:{{.Machine.Name}}"
Type: A
Value:
- "{{.Machine.Address}}"
TTL: 300
EOF
# Create forwarding zone for everything else
drpcli zones create - <<EOF
Name: root
Origin: "."
Priority: 10000
Forwarders:
- 8.8.8.8
- 8.8.4.4
EOF
Result: Any machine with an FQDN name matching the zone origin will automatically get an A record. For example, a machine named node1.lab.local with address 192.168.1.10 will resolve to 192.168.1.10.
Dynamic DNS Record Patterns
Using Machine.Name: eval:{{.Machine.Name}} only works if the machine's Name field already contains the full FQDN matching the zone origin.
- If Name =
minio1and dns-domain =storage.local→ nothing renders (Name doesn't match zone origin) - If Name =
minio1.storage.localand dns-domain =storage.local→ renders (Name matches zone origin) - In both cases, the
dns-domainparameter is not used - it depends entirely on what's in the Name field
Using ShortName + ParamExpand (Recommended): Build the FQDN dynamically from ShortName and parameter:
Records:
- Name: "eval:{{.Machine.ShortName}}.{{.ParamExpand \"dns-domain\"}}"
Type: A
Value:
- "{{.Machine.Address}}"
dns-domain parameter value, so machines with short names like minio1 will correctly resolve as minio1.storage.local.
Advanced: Conditional DNS Records: Only create records for machines with a specific dns-domain:
Records:
- Name: "eval:{{if eq (.ParamExpand \"dns-domain\") \"storage.local\"}}{{.Machine.ShortName}}.{{.ParamExpand \"dns-domain\"}}{{else}}do-not-match.this.domain.{{end}}"
Type: A
Value:
- "{{.Machine.Address}}"
dns-domain: "storage.local". Others get a non-matching domain to avoid polluting the zone.
Testing:
# View live DNS records
drpcli zones view lab-local
# Test resolution
nslookup node1.lab.local <drp-ip>
Use Case 2: Service Cluster DNS (MinIO Example)¶
Create DNS records for a distributed service cluster with multiple nodes.
Scenario: You have a MinIO S3 cluster with 4 nodes that need consistent DNS naming: minio1.storage.local, minio2.storage.local, etc.
Setup:
Create a profile for MinIO nodes:
# Create MinIO cluster profile with DNS domain
drpcli profiles create - <<EOF
Name: minio-cluster
Params:
dns-domain: "storage.local"
EOF
Create the storage zone:
drpcli zones create - <<EOF
Name: storage-local
Origin: "storage.local."
Priority: 100
Records:
- Name: "eval:{{.Machine.ShortName}}.{{.ParamExpand \"dns-domain\"}}"
Type: A
Value:
- "{{.Machine.Address}}"
TTL: 300
- Name: "minio"
Type: A
Value:
- "eval:{{.Machine.Address}}"
TTL: 300
EOF
Apply profile to machines:
# Apply MinIO cluster profile with dns-domain parameter
drpcli machines update minio1 '{"Profiles": ["minio-cluster"]}'
drpcli machines update minio2 '{"Profiles": ["minio-cluster"]}'
drpcli machines update minio3 '{"Profiles": ["minio-cluster"]}'
drpcli machines update minio4 '{"Profiles": ["minio-cluster"]}'
Result: Each MinIO node gets its own DNS entry, and all nodes also respond to the shared minio.storage.local name for load balancing.
Testing:
# Test individual nodes
nslookup minio1.storage.local <drp-ip>
nslookup minio2.storage.local <drp-ip>
# Test shared name (returns all IPs)
nslookup minio.storage.local <drp-ip>
Use Case 3: Split DNS with External Forwarding¶
Handle internal zones while forwarding external queries.
Scenario: You want DRP to handle DNS for your lab environment (lab.internal) but forward all other queries to your corporate DNS servers.
Setup:
# Internal lab zone
drpcli zones create - <<EOF
Name: lab-internal
Origin: "lab.internal."
Priority: 50
Continue: false
Records:
- Name: "eval:{{.Machine.Name}}"
Type: A
Value:
- "{{.Machine.Address}}"
TTL: 300
- Name: "drp"
Type: A
Value:
- "192.168.10.10"
TTL: 3600
EOF
# Corporate domain forwarding
drpcli zones create - <<EOF
Name: corporate
Origin: "corp.example.com."
Priority: 500
Continue: true
Forwarders:
- 10.0.0.53
EOF
# Catch-all forwarding for internet
drpcli zones create - <<EOF
Name: root
Origin: "."
Priority: 10000
Forwarders:
- 8.8.8.8
- 1.1.1.1
EOF
Result: Queries for *.lab.internal are answered by DRP, *.corp.example.com queries are forwarded to 10.0.0.53, and all other queries go to public DNS.
Use Case 4: Static Service Records¶
Create static DNS entries for services and infrastructure.
Scenario: You need static DNS records for services like load balancers, storage arrays, and infrastructure.
Setup:
drpcli zones create - <<EOF
Name: services
Origin: "services.local."
Priority: 100
Records:
- Name: "lb"
Type: A
Value:
- "192.168.1.100"
TTL: 3600
- Name: "storage"
Type: A
Value:
- "192.168.1.200"
TTL: 3600
- Name: "api"
Type: CNAME
Value:
- "lb.services.local."
TTL: 3600
- Name: "www"
Type: CNAME
Value:
- "lb.services.local."
TTL: 3600
EOF
Result: Static DNS entries for services that don't change frequently.
Use Case 5: Multi-Zone Setup with Templates¶
Create zones from templates in a content bundle.
Scenario: You want to package DNS configuration in a content bundle for repeatable deployments.
Setup:
Create zone files in your content bundle:
content/zones/internal.yaml:
Name: "internal"
Origin: "internal.local."
Priority: 100
Records:
- Name: "eval:{{.Machine.Name}}"
Type: A
Value:
- "{{.Machine.Address}}"
TTL: 300
content/zones/forwarding.yaml:
Template String Quoting
When creating multiple zones in a bundle, double-quote template strings to avoid import issues:
Import:
Example Configuration¶
The following Zone will act as a forwarding name server for all queries that aren't matched by other zones. This is a common final zone in the configuration.
The following Zone will service the example.com domain (as declared in the Origin field). It will also be authoritative
and can be used in delegation.
Continue: false
Name: example.com
Origin: example.com.
Priority: 0
Records:
- Name: .
TTL: 86400
Type: SOA
Value:
- dns1.example.com.
- hostmaster.example.com.
- "762016905"
- "21600"
- "3600"
- "604800"
- "86400"
- Name: .
TTL: 86400
Type: NS
Value:
- dns1.example.com.
- Name: .
TTL: 86400
Type: NS
Value:
- dns2.example.com.
- Name: .
TTL: 86400
Type: MX
Value:
- "10"
- mail.example.com.
- Name: .
TTL: 86400
Type: MX
Value:
- "20"
- mail2.example.com.
- Name: dns1
TTL: 86400
Type: A
Value:
- 10.0.1.1
- Name: dns2
TTL: 86400
Type: A
Value:
- 10.0.1.2
- Name: server1
TTL: 86400
Type: A
Value:
- 10.0.1.5
- Name: server2
TTL: 86400
Type: A
Value:
- 10.0.1.6
- Name: ftp
TTL: 86400
Type: A
Value:
- 10.0.1.3
- Name: ftp
TTL: 86400
Type: A
Value:
- 10.0.1.4
- Name: mail
TTL: 86400
Type: CNAME
Value:
- server1.example.com.
- Name: mail2
TTL: 86400
Type: CNAME
Value:
- server2.example.com.
- Name: www
TTL: 86400
Type: CNAME
Value:
- server1.example.com.
TTL: 3600
Import Configuration¶
The drpcli command can also be used to import RFC-compliant zone files. For example, existing BIND or other server
files can be imported as zones into the DRP server. This is a create operation. If you wish to make changes to the zone
through the file, you will need to destroy the DRP zone and reimport the file.
The Name of the Zone will be based upon the $Origin part of the file.
Example file
$ORIGIN example.com.
$TTL 86400
@ IN SOA dns1.example.com. hostmaster.example.com. (
2001062501 ; serial
21600 ; refresh after 6 hours
3600 ; retry after 1 hour
604800 ; expire after 1 week
86400 ) ; minimum TTL of 1 day
IN NS dns1.example.com.
IN NS dns2.example.com.
IN MX 10 mail.example.com.
IN MX 20 mail2.example.com.
dns1 IN A 10.0.1.1
dns2 IN A 10.0.1.2
server1 IN A 10.0.1.5
server2 IN A 10.0.1.6
ftp IN A 10.0.1.3
IN A 10.0.1.4
mail IN CNAME server1
mail2 IN CNAME server2
www IN CNAME server1
CLI Operations¶
The drpcli can be used to create, update, and delete zones. Additionally, there are helpers to add and remove records.
CRUD Operations¶
Using the yaml files above, a zone can be created by:
or updated by:
or destroyed by:
or viewed by:
or view the live records (including dynamic records and reservation records) by:
The output looks like:
Data:
.:
MX:
- Data:
- "10"
- mail.example.com.
TTL: 86400
Uuid: zones:example.com
- Data:
- "20"
- mail2.example.com.
TTL: 86400
Uuid: zones:example.com
NS:
- Data:
- dns1.example.com.
TTL: 86400
Uuid: zones:example.com
- Data:
- dns2.example.com.
TTL: 86400
Uuid: zones:example.com
SOA:
- Data:
- dns1.example.com.
- hostmaster.example.com.
- "762259547"
- "21600"
- "3600"
- "604800"
- "86400"
TTL: 86400
Uuid: zones:example.com
1.1.1.1:
PTR:
- Data:
- New Record.example.com.
TTL: 3600
Uuid: zones:example.com
3.3.3.3:
PTR:
- Data:
- fred.example.com.
TTL: 300
Uuid: machines:34553cb1-7425-465a-a3a9-fb67458506bf
4.4.4.4:
PTR:
- Data:
- jane.example.com.
TTL: 3600
Uuid: reservations:04040404
10.0.1.1:
PTR:
- Data:
- dns1.example.com.
TTL: 86400
Uuid: zones:example.com
10.0.1.2:
PTR:
- Data:
- dns2.example.com.
TTL: 86400
Uuid: zones:example.com
10.0.1.3:
PTR:
- Data:
- ftp.example.com.
TTL: 86400
Uuid: zones:example.com
10.0.1.4:
PTR:
- Data:
- ftp.example.com.
TTL: 86400
Uuid: zones:example.com
10.0.1.5:
PTR:
- Data:
- server1.example.com.
TTL: 86400
Uuid: zones:example.com
10.0.1.6:
PTR:
- Data:
- server2.example.com.
TTL: 86400
Uuid: zones:example.com
New Record:
A:
- Data:
- 1.1.1.1
TTL: 3600
Uuid: zones:example.com
dns1:
A:
- Data:
- 10.0.1.1
TTL: 86400
Uuid: zones:example.com
dns2:
A:
- Data:
- 10.0.1.2
TTL: 86400
Uuid: zones:example.com
fred:
A:
- Data:
- 3.3.3.3
TTL: 300
Uuid: machines:34553cb1-7425-465a-a3a9-fb67458506bf
ftp:
A:
- Data:
- 10.0.1.3
TTL: 86400
Uuid: zones:example.com
- Data:
- 10.0.1.4
TTL: 86400
Uuid: zones:example.com
jane:
A:
- Data:
- 4.4.4.4
TTL: 3600
Uuid: reservations:04040404
mail:
CNAME:
- Data:
- server1.example.com.
TTL: 86400
Uuid: zones:example.com
mail2:
CNAME:
- Data:
- server2.example.com.
TTL: 86400
Uuid: zones:example.com
server1:
A:
- Data:
- 10.0.1.5
TTL: 86400
Uuid: zones:example.com
server2:
A:
- Data:
- 10.0.1.6
TTL: 86400
Uuid: zones:example.com
www:
CNAME:
- Data:
- server1.example.com.
TTL: 86400
Uuid: zones:example.com
The returned object a map with a single key, Data. The object in the Data key is another map whose keys are the
values that are to be looked up. The . key is the same as the Origin of the zone. Special IP address entries are
used as short-hand for the PTR zones for reverse lookups.
Under each lookup zey is a map of record types (e.g. A or AAAA). The object in that section is a list of values for a
single record. DNS can return multiple values for a single lookup. This list provides all return values for that name
and type pair. The Data field is a list of strings that will be converted into the record type when being sent to the
requester. Additionally, a TTL field defines the actual type for that specific value. The Uuid field defines where
that record comes from. The value is read as <type>:<id>. Static records have the value, zones:<zone name>. Machine
records have the value, machines:<uuid> and the Reservation records have the value, reservations:<ip address in hex>
Records¶
Once a zone is added, records can be added by:
# Adds an A/PTR record for greg.example.com to 3.3.3.3
drpcli zones records add example.com A greg 3.3.3.3
Additionally, the ttl for the record can be provided by adding the --ttl flag.
# Adds an A/PTR record for greg.example.com to 3.3.3.3
drpcli zones records add example.com A greg 3.3.3.3 --ttl 3600
Or adding a dynamic record for machines that have Name fields that fall in the example.com domain.
# Adds an A/PTR record for all the Machines that match *.example.com in the Name field
drpcli zones records add example.com A "eval:{{.Machine.Name}}" "{{.Machine.Address}}"
This record is special and will generate a live entry for each machine that has a name that ends in example.com using
the Machine's Address field.
Records can be removed by:
# Adds an A/PTR record for greg.example.com to 3.3.3.3
drpcli zones records remove example.com A greg 3.3.3.3
You can also get the formats and fields of the allowed record types by:
This will produce something like this:
A:
Key: 1
Max: 1
Min: 1
Records:
- Name: A
Subtype: a
Type: net.IP
AAAA:
Key: 28
Max: 1
Min: 1
Records:
- Name: AAAA
Subtype: aaaa
Type: net.IP
AFSDB:
Key: 18
Max: 2
Min: 2
Records:
- Name: Subtype
Subtype: ""
Type: uint16
- Name: Hostname
Subtype: domain-name
Type: string
...
The map is string record type (e.g. A) and the object defines the format.
The object has the fields:
- Key - the 16-bit integer type of the record
- Max - the maximum number of fields for this record (-1 means unlimited)
- Min - the minimum number of fields for this record (-1 means no minimum)
- Records - A list of the required fields for this record.
- Name - the name of the field
- Type - the type of the field
- Subtype - helper to clarify additional properties of the type. (e.g. domain-name for a string type)