Your first DNS charm deployment¶
Introduction¶
Imagine that you just acquired the lovely domain flying-saucer.local and that you want to host your own authoritative DNS server.
In a traditional setup, you would need to learn how to install and configure a DNS server like BIND on Ubuntu and then get through the hassle of understanding how to create a high availability setup. But with our DNS charm, this is going to be easy and you’ll be able to do it in no time.
In this short tutorial we will deploy an authoritative DNS charm locally on your machine and create a test zone for you to query. It will take us about 20 minutes.
If you’re new to the charming world, don’t worry: we’ll explain every step.
What you’ll need¶
A local system, e.g., a laptop, with AMD64 or ARM64 architecture which has sufficient resources to launch a virtual machine with 4 CPUs, 4 GB RAM, and a 50 GB disk.
Familiarity with Linux.
What you’ll do¶
Deploy the bind charm.
Deploy the dns-integrator charm and relate it to bind.
Edit your zone and query it.
Scale up your charm to make it highly available.
Set things up¶
We recommend starting from a clean Ubuntu installation. If you don’t have one available, you can create one using Multipass.
Is Multipass already installed and active? Check by running:
snap services multipass
If you see the multipass service but it isn’t “active”, run:
sudo snap start multipass
If you get an error saying snap "multipass" not found, install it with:
sudo snap install multipass
See the Multipass installation instructions and switch to Windows in the dropdown menu.
See the Multipass installation instructions and switch to macOS in the dropdown menu.
Once Multipass is ready, create the VM with the following command:
multipass launch --cpus 4 --memory 4G --disk 50G --name dns-dev 24.04
Finally, once the VM is up, open a shell into it:
multipass shell dns-dev
Note
Unless stated otherwise, we will work entirely within the VM from now on.
Use Concierge to set up Juju:
sudo snap install --classic concierge
sudo concierge prepare -p machine
This installs Concierge and uses it to install and configure Juju with a local LXD cloud.
For this tutorial, Juju must be bootstrapped to a LXD controller. Concierge should complete this step for you. You can verify by running:
juju controllers
You should see output similar to:
Controller Model User Access Cloud/Region Models Nodes HA Version
concierge-lxd* testing admin superuser localhost/localhost 2 1 none 3.6.20
Delete the default testing model that Juju creates. We will create a new model for this tutorial in the next step.
juju destroy-model testing
Set up a tutorial model¶
To manage resources effectively and to separate this tutorial’s workload from your usual work, create a new model using the following command.
juju add-model dns-tutorial
Deploy bind¶
Now that we have everything we need, let’s deploy our DNS server!
juju deploy bind --channel=latest/edge
Running juju status should show you the following after waiting a bit for things to settle:
ubuntu@dns-dev:~$ juju status
App Version Status Scale Charm Channel Rev Exposed Message
bind active 1 bind latest/edge 80 no active
Unit Workload Agent Machine Public address Ports Message
bind/0* active idle 0 10.124.97.210 53/tcp 53/udp active
Our bind DNS server is now deployed and running. You can see it’s listening on ports 53/tcp and 53/udp, which are the standard DNS ports. We can check the health of our DNS server using the built-in status record:
ubuntu@dns-dev:~$ dig @<IP> status.service.test TXT +short
"ok"
Note
Replace <IP> with the public address of your bind unit, as shown in juju status. In my case, it would be 10.124.97.210.
Deploy dns-integrator¶
We now have a fully functioning DNS server but we still need a way to specify the records that we want to serve. That’s what the dns-integrator charm is for. Let’s deploy it:
juju deploy dns-integrator --channel=latest/edge
After waiting a bit, juju status should show:
ubuntu@dns-dev:~$ juju status
App Version Status Scale Charm Channel Rev Exposed Message
bind active 1 bind latest/edge 80 no active
dns-integrator blocked 1 dns-integrator latest/edge 2 no Waiting for some configuration
Unit Workload Agent Machine Public address Ports Message
bind/0* active idle 0 10.124.97.210 53/tcp 53/udp active
dns-integrator/0* blocked idle 1 10.124.97.236 Waiting for some configuration
The dns-integrator charm is waiting for some configuration.
Let’s create a DNS record for our flying-saucer.local domain. We’ll add a simple TXT record:
juju config dns-integrator requests="message flying-saucer.local 600 IN TXT Hello"
Let’s check the status again:
ubuntu@dns-dev:~$ juju status
App Version Status Scale Charm Channel Rev Exposed Message
bind active 1 bind latest/edge 80 no active
dns-integrator blocked 1 dns-integrator latest/edge 2 no Waiting for integration
Unit Workload Agent Machine Public address Ports Message
bind/0* active idle 0 10.124.97.210 53/tcp 53/udp active
dns-integrator/0* blocked idle 1 10.124.97.236 Waiting for integration
The dns-integrator is still in a blocked state because it needs to be related to a DNS server.
juju integrate bind dns-integrator
And now, everything should be active:
ubuntu@dns-dev:~$ juju status
App Version Status Scale Charm Channel Rev Exposed Message
bind active 1 bind latest/edge 80 no active
dns-integrator active 1 dns-integrator latest/edge 2 no
Unit Workload Agent Machine Public address Ports Message
bind/0* active executing 0 10.124.97.210 53/tcp 53/udp active
dns-integrator/0* active executing 1 10.124.97.236
Now let’s query the TXT record we just created for our flying-saucer.local domain:
ubuntu@dns-dev:~$ dig @<IP> message.flying-saucer.local TXT +short
"Hello"
Note
Replace <IP> with the public address of your bind unit, as shown in juju status. In my case, it would be 10.124.97.210.
Our DNS server is up and serving records. You’ve just deployed a fully functional authoritative DNS server using Juju charms!
Scale up¶
Bind can be scaled up to prevent outages and divide incoming requests among multiple units. To do that, you just need to run:
juju add-unit -n 2 bind
After letting things settle down a bit, we can now see:
ubuntu@dns-dev:~$ juju status
App Version Status Scale Charm Channel Rev Exposed Message
bind active 3 bind latest/edge 80 no active
dns-integrator active 1 dns-integrator latest/edge 2 no
Unit Workload Agent Machine Public address Ports Message
bind/0* active idle 0 10.124.97.210 53/tcp 53/udp active
bind/1 active idle 2 10.124.97.65 53/tcp 53/udp
bind/2 active idle 3 10.124.97.201 53/tcp 53/udp
dns-integrator/0* active idle 1 10.124.97.236
Now bind has three units! We can query each one with dig to get the same results.
Note that only one unit is marked as “active” at a time. This unit will act as a hidden primary and you should not expose it publicly, leaving the task of responding to client queries to the other units instead.
Conclusion¶
You’ve reached the end of this tutorial. You have now:
deployed a functioning DNS server
instructed it to serve a list of records
scaled it up using a hidden primary architecture
Next steps¶
To enhance your current setup, follow Deploy a secondary DNS server and resolver to deploy a secondary DNS server and let a resolver handle the actual client queries.
Tear things down¶
If you’d like to quickly tear things down, start by exiting the Multipass VM:
exit
And then you can proceed with its deletion:
multipass delete dns-dev
multipass purge