Chapter 1. Overview of DNSaaS
Red Hat OpenStack Platform includes a Technology Preview of DNS-as-a-Service (DNSaaS), also known as Designate. DNSaaS includes a REST API for domain and record management, is multi-tenanted, and integrates with OpenStack Identity Service (keystone) for authentication. DNSaaS includes a framework for integration with Compute (nova) and OpenStack Networking (neutron) notifications, allowing auto-generated DNS records. In addition, DNSaaS includes integration support for Bind9.
DNS-as-a-Service (DNSaaS), also known as Designate, is available in this release as a Technology Preview, and therefore is not fully supported by Red Hat. If you are interested in running DNSaaS in your production environment, please file a support ticket and mention the bug tracker BZ#1374002
, so we can gauge the interest for this tool. For more information about Technology Preview features, see https://access.redhat.com/support/offerings/techpreview.
1.1. Topics covered in this chapter
- Manual DNSaaS installation steps, as DNSaaS is not currently included in Director deployment.
- Managing and configuring DNSaaS from the command line interface.
- Integration with Bind9, including API usage and auto-creation of instance records.
1.1.1. DNSaaS prerequisites
- A fully functioning non-HA OpenStack environment.
1.1.2. DNSaaS services
A deployment of DNSaaS includes the following components:
designate-api | Provides an OpenStack-native REST API. |
designate-central | Handles requests and coordinates storage in the mysql database. |
designate-mdns | A small MiniDNS server used only to communicate with other DNS servers over standard DNS protocol. |
designate-pool-manager | Manages the states of the DNS servers that DNSaaS manages. Ensures the backend DNS servers are in sync with DNSaaS. |
designate-sink | An optional service that is used to listen to nova and neutron notification events to trigger automatic record creation/deletion. |
designate-agent | Used for DNS servers that cannot accept zone transfers (AXFR). Not needed for BIND backends. |
1.1.3. DNSaaS integration with Compute and OpenStack Networking
DNSaaS record management begins when the designate-sink
service sends a message to designate-central
, which then triggers the workflow described below:
-
designate-sink
receives an instance boot/delete event from Compute, or a floating IP add/remove event from OpenStack Networking. These events are sent using the OpenStack message bus. -
designate-sink
constructs the FQDN of the host from the VM name and the configured domain ID (see below). -
designate-sink
tellsdesignate-central
to add/delete the record with the given name and IP address. -
designate-central
adds/deletes the record in the DNSaaS database (shared betweendesignate-central
anddesignate-mdns
). -
designate-central
tellsdesignate-pool-manager
to send aDNS NOTIFY
to the backend DNS server (BIND9) for this domain. -
The backend DNS servers receive the
DNS NOTIFY
and send anAXFR
(zone transfer) request todesignate-mdns
. -
designate-mdns
reads the changes from the database and sends them to the backend DNS servers in theAXFR
response.
1.2. Manual DNSaaS installation
Your server must be registered to receive the OpenStack packages. For more information, see https://access.redhat.com/documentation/en-us/red_hat_openstack_platform/10/html-single/director_installation_and_usage/#sect-Registering_your_System
Install the DNSaaS and BIND packages on the controller node. NOTE: You can also an external BIND service; you will need change the variables below accordingly.
yum install openstack-designate-api openstack-designate-central openstack-designate-sink openstack-designate-pool-manager openstack-designate-mdns openstack-designate-common python-designate python-designateclient openstack-designate-agent openstack-utils bind bind-utils
Configure DNS. It is important to define a specific boolean, otherwise you will get AVCs / Access denied in Designate when creating new zones:
setsebool named_write_master_zones 1
Configure ISC BIND to listen in all IP addresses:
sed -i -e "s/listen-on port.*/listen-on port 53 { any; };/" /etc/named.conf
Configure
rndc
to bind in all IP addresses, accepts onlyrndc-key
key:sed -i '/^options.*/i include "/etc/rndc.key"; controls { inet * allow { any; } keys { "rndc-key"; }; };' /etc/named.conf
Allow queries for local DNS server from all IP addresses:
sed -i '/allow-query.*/d' /etc/named.conf
Configure DNS server to permit new zone creation via
rndc
:sed -i '/^options.*/a allow-new-zones yes; allow-query { any; };' /etc/named.conf
Create
rndc
initial configuration:rndc-confgen -a
Permit group
named
to write in/var/named
:chmod g+w /var/named
Fix
rndc
key permissions:chgrp named /etc/rndc.key chmod g+r /etc/rndc.key
And finally, start the DNS service:
systemctl enable named systemctl start named
-
Source your
openstackrc
file, as the following steps interact with OpenStack services. To ease the deployment process, this guide relies on a number of variables; you will need to populate the values accordingly:
CONTROLLER_IP_ADDRESS=192.168.2.1 ZONE_NAME=testzone.example.com INTERNAL_NET_NAME=net_internal INSTANCES_PROJECT_NAME=myinstancesproject SERVICES_PROJECT_NAME=service DESIGNATE_PASSWORD=SecureDesignatePassword EXTERNAL_DNS_SERVER_IP=$CONTROLLER_IP_ADDRESS EXTERNAL_DNS_SERVER_FQDN=`hostname` DESIGNATE_VIP_IP=$CONTROLLER_IP_ADDRESS RABBIT_SERVER_IP=$CONTROLLER_IP_ADDRESS REDIS_SERVER_IP=$CONTROLLER_IP_ADDRESS MYSQL_SERVER_IP=$CONTROLLER_IP_ADDRESS KEYSTONE_SERVER_IP=$CONTROLLER_IP_ADDRESS DESIGNATE_SERVER_1=$CONTROLLER_IP_ADDRESS
The following variables will also populate the required IDs that will be used during the install process.
SERVICES_TENANT_ID=`openstack project show $SERVICES_PROJECT_NAME -f value -c id` INSTANCES_TENANT_ID=`openstack project show $INSTANCES_PROJECT_NAME -f value -c id` DEFAULT_NAMESERVER_ID=$(uuidgen) DEFAULT_TARGET_ID=$(uuidgen) INTERNAL_NET_ID=`openstack network show $INTERNAL_NET_NAME -f value -c id`
Create the backend database:
mysql -u root << EOF CREATE DATABASE designate; GRANT ALL ON designate.* TO 'designate'@'%' IDENTIFIED BY '$DESIGNATE_PASSWORD'; GRANT ALL ON designate.* TO 'designate'@'localhost' IDENTIFIED BY '$DESIGNATE_PASSWORD'; CREATE DATABASE designate_pool_manager; GRANT ALL ON designate_pool_manager.* TO 'designate'@'%' IDENTIFIED BY '$DESIGNATE_PASSWORD'; GRANT ALL ON designate_pool_manager.* TO 'designate'@'localhost' IDENTIFIED BY '$DESIGNATE_PASSWORD'; FLUSH PRIVILEGES; quit EOF
Create the DNSaaS service account in keystone:
openstack user create designate --password $DESIGNATE_PASSWORD --email designate@localhost
Add the DNSaaS account to the
service
project:openstack role add --project $SERVICES_PROJECT_NAME --user designate admin
Create the DNSaaS service:
openstack service create dns --name designate --description "Designate DNS Service"
Create the DNSaaS endpoint:
openstack endpoint create --region RegionOne --publicurl http://$DESIGNATE_VIP_IP:9001 --internalurl http://$DESIGNATE_VIP_IP:9001 --adminurl http://$DESIGNATE_VIP_IP:9001 designate
Add the keystone token settings to the DNSaaS configuration:
crudini --set /etc/designate/designate.conf keystone_authtoken auth_uri http://$KEYSTONE_SERVER_IP:5000/v2.0 crudini --set /etc/designate/designate.conf keystone_authtoken identity_uri http://$KEYSTONE_SERVER_IP:35357/ crudini --set /etc/designate/designate.conf keystone_authtoken admin_tenant_name $SERVICES_PROJECT_NAME crudini --set /etc/designate/designate.conf keystone_authtoken project_name $SERVICES_PROJECT_NAME crudini --set /etc/designate/designate.conf keystone_authtoken admin_user designate crudini --set /etc/designate/designate.conf keystone_authtoken admin_password $DESIGNATE_PASSWORD
Configure the API extensions for DNSaaS:
crudini --set /etc/designate/designate.conf service:api enabled_extensions_v1 "diagnostics, quotas, reports, sync, touch" crudini --set /etc/designate/designate.conf service:api enabled_extensions_v2 "quotas, reports"
Configure DNSaaS to integrate with the
Instances
project:crudini --set /etc/designate/designate.conf service:central managed_resource_tenant_id $INSTANCES_TENANT_ID
Add the connection to the backend database:
crudini --set /etc/designate/designate.conf storage:sqlalchemy connection mysql+pymysql://designate:$DESIGNATE_PASSWORD@$MYSQL_SERVER_IP/designate crudini --set /etc/designate/designate.conf pool_manager_cache:sqlalchemy connection mysql+pymysql://designate:$DESIGNATE_PASSWORD@$MYSQL_SERVER_IP/designate_pool_manager
And the Messaging endpoint:
crudini --set /etc/designate/designate.conf oslo_messaging_rabbit rabbit_hosts $RABBIT_SERVER_IP:5672
Populate and prepare the Designate MySQL database:
su -s /bin/sh -c "designate-manage database sync" designate su -s /bin/sh -c "designate-manage pool-manager-cache sync" designate
Enable and start only the
central
andapi
designate services:systemctl enable designate-central designate-api systemctl start designate-central designate-api
Create the following file in
/etc/designate/pools.yaml
. Remember that you need to change the variablesEXTERNAL_DNS_SERVER_FQDN
,EXTERNAL_DNS_SERVER_IP
andDESIGNATE_SERVER_1
. There are provisions for additional DNS servers, if needed:- name: default description: Default BIND9 Pool attributes: external: true ns_records: - hostname: $EXTERNAL_DNS_SERVER_FQDN. priority: 1 # - hostname: $EXTERNAL_DNS_SERVER_FQDN_2. # priority: 1 nameservers: - host: $EXTERNAL_DNS_SERVER_IP port: 53 # - host: $EXTERNAL_DNS_SERVER_IP_2 # port: 53 targets: - type: bind9 description: BIND9 Server 1 masters: - host: $DESIGNATE_SERVER_1 port: 5354 # - host: $DESIGNATE_SERVER_2 # port: 5354 # - host: $DESIGNATE_SERVER_3 # port: 5354 options: host: $EXTERNAL_DNS_SERVER_IP port: 53 rndc_host: $EXTERNAL_DNS_SERVER_IP rndc_port: 953 rndc_key_file: /etc/designate/rndc.key # - type: bind9 # description: BIND9 Server 2 # masters: # - host: $DESIGNATE_SERVER_1 # port: 5354 ## - host: $DESIGNATE_SERVER_2 ## port: 5354 ## - host: $DESIGNATE_SERVER_3 ## port: 5354 # options: # host: $EXTERNAL_DNS_SERVER_IP_2 # port: 53 # rndc_host: $EXTERNAL_DNS_SERVER_IP_2 # rndc_port: 953 # rndc_key_file: /etc/designate/rndc.key
Copy the
rndc
keyfile to/etc/designate
:cp -f /etc/rndc.key /etc/designate/rndc.key
Ensure
designate
owns it:chown designate:designate /etc/designate/rndc.key
Load the above YAML file into the DNSaaS runtime configuration:
su -s /bin/sh -c "designate-manage pool update" designate
Start the remaining DNSaaS services:
systemctl enable designate-pool-manager designate-mdns designate-sink systemctl start designate-pool-manager designate-mdns designate-sink
Create a DNS zone and export the
ZONE_ID
variable after its creation:ZONE_ID=`openstack zone create --email admin@$ZONE_NAME $ZONE_NAME. -f value -c id`
Add the UUID of the new zone to the nova and neutron handlers:
crudini --set /etc/designate/designate.conf handler:nova_fixed domain_id $ZONE_ID crudini --set /etc/designate/designate.conf handler:neutron_floatingip domain_id $ZONE_ID
Restart the DNSaaS services:
systemctl restart designate-api designate-central designate-mdns designate-pool-manager designate-sink
The DNSaaS portion is now fully configured. Next, you will configure neutron integration. Add
dns
to the list of ML2 drivers. For example:crudini --set /etc/neutron/plugins/ml2/ml2_conf.ini ml2 extension_drivers port_security,dns
If you want your DNS agent (
dnsmasq
) to query DNSaaS (it does not by default):crudini --set /etc/neutron/dhcp_agent.ini DEFAULT dnsmasq_dns_servers $EXTERNAL_DNS_SERVER_IP
Enable DNSaaS integration for neutron:
crudini --set /etc/neutron/neutron.conf designate url http://$DESIGNATE_VIP_IP:9001/v2 crudini --set /etc/neutron/neutron.conf designate admin_auth_url http://$DESIGNATE_VIP_IP:35357/v2.0 crudini --set /etc/neutron/neutron.conf designate admin_username designate crudini --set /etc/neutron/neutron.conf designate admin_password $DESIGNATE_PASSWORD crudini --set /etc/neutron/neutron.conf designate admin_tenant_name $SERVICES_PROJECT_NAME crudini --set /etc/neutron/neutron.conf designate allow_reverse_dns_lookup True crudini --set /etc/neutron/neutron.conf designate ipv4_ptr_zone_prefix_size 24 crudini --set /etc/neutron/neutron.conf designate ipv6_ptr_zone_prefix_size 116 crudini --set /etc/neutron/neutron.conf designate insecure true
Restart the neutron and nova services:
openstack-service restart neutron openstack-service restart nova
Configure your neutron network to use DNSaaS:
neutron net-update $INTERNAL_NET_ID --dns_domain $ZONE_NAME.
1.3. Test OpenStack Networking floating IP record creation
Check that the zone is correctly configured and in an
ACTIVE
state:$ openstack zone list +--------------------------------------+-----------------------+---------+------------+--------+--------+ | id | name | type | serial | status | action | +--------------------------------------+-----------------------+---------+------------+--------+--------+ | 1bae1c6e-06e6-4a5d-8b03-483875478b73 | testzone.example.com. | PRIMARY | 1523471795 | ACTIVE | NONE | +--------------------------------------+-----------------------+---------+------------+--------+--------+
Enumerate the existing networks to retrieve the UUIDs. These will be used in the later steps. This example uses the
internal
andexternal
networks:$ openstack network list +--------------------------------------+----------+--------------------------------------+ | ID | Name | Subnets | +--------------------------------------+----------+--------------------------------------+ | 0efce5d7-b2ec-4877-b6bb-de339a76c80b | external | d03cdc41-6962-4d3d-bed1-68b0a5f6b93c | | c020e6a9-f483-48a9-893d-983ae23d248a | internal | b59684af-d4ea-403e-8b14-d3821a46d52f | +--------------------------------------+----------+--------------------------------------+
Create a instance named
testinstance
, using base image namedweb
, flavorm1.small
, attached to networkinternal
, with SSH keypairkeypair-demo
:$ openstack server create --image web --flavor m1.small --nic net-id=c020e6a9-f483-48a9-893d-983ae23d248a --key-name keypair-demo -f value -c id testinstance 14e1d0da-30bd-4adf-927b-8f54932cbe95
Confirm that your instance enters the
ACTIVE
state before proceeding:$ openstack server list +--------------------------------------+--------------+--------+-----------------------+------------+ | ID | Name | Status | Networks | Image Name | +--------------------------------------+--------------+--------+-----------------------+------------+ | 14e1d0da-30bd-4adf-927b-8f54932cbe95 | testinstance | ACTIVE | interna=192.168.10.12 | web | +--------------------------------------+--------------+--------+-----------------------+------------+
Review the DNSaaS records and confirm that the new instance does not yet have a record:
$ openstack recordset list 1bae1c6e-06e6-4a5d-8b03-483875478b73 +--------------------------------------+-----------------------+------+----------------------------------------------------------------------+--------+--------+ | id | name | type | records | status | action | +--------------------------------------+-----------------------+------+----------------------------------------------------------------------+--------+--------+ | 4092f9f2-4fcb-4097-91bc-c4fa3b0965f9 | testzone.example.com. | NS | example10-cont1.testzone.example.com. | ACTIVE | NONE | | c08400a1-2bb1-4f6b-ae90-9f1b3a3dec82 | testzone.example.com. | SOA | example10-cont1.testzone.example.com. admin.testzone.example.com. | | | | | | | 1523471795 3531 600 86400 3600 | ACTIVE | NONE | +--------------------------------------+-----------------------+------+----------------------------------------------------------------------+--------+--------+
Create a floating IP address in the
external
network.---- $ openstack floating ip create -f value -c floating_ip_address 0efce5d7-b2ec-4877-b6bb-de339a76c80b 172.25.250.146
Attach the floating IP to
testinstance
:$ openstack server add floating ip 14e1d0da-30bd-4adf-927b-8f54932cbe95 172.25.250.146
Check DNSaaS records. This example shows an RR entry for
testinstance.testzone.example.com
, in aPENDING
state.$ openstack recordset list 1bae1c6e-06e6-4a5d-8b03-483875478b73 +--------------------------------------+------------------------------------+------+-------------------------------------------------+---------+--------+ | id | name | type | records | status | action | +--------------------------------------+------------------------------------+------+-------------------------------------------------+---------+--------+ | 4092f9f2-4fcb-4097-91bc-c4fa3b0965f9 | testzone.example.com. | NS | example10-cont1.testzone.example.com. | ACTIVE | NONE | | c08400a1-2bb1-4f6b-ae90-9f1b3a3dec82 | testzone.example.com. | SOA | example10-cont1.testzone.example.com. | PENDING | UPDATE | | | | | admin.testzone.example.com. 1523473397 3531 600 | | | | | | | 86400 3600 | | | | 058f6862-cf1b-4da3-9d78-b3a890aff32f | testinstance.testzone.example.com. | A | 172.25.250.146 | PENDING | CREATE | +--------------------------------------+------------------------------------+------+-------------------------------------------------+---------+--------+
After a few seconds wait, you can expect the newly-created entry to change to
ACTIVE
:$ openstack recordset list 1bae1c6e-06e6-4a5d-8b03-483875478b73 +--------------------------------------+------------------------------------+------+-------------------------------------------------+--------+--------+ | id | name | type | records | status | action | +--------------------------------------+------------------------------------+------+-------------------------------------------------+--------+--------+ | 4092f9f2-4fcb-4097-91bc-c4fa3b0965f9 | testzone.example.com. | NS | example10-cont1.testzone.example.com. | ACTIVE | NONE | | c08400a1-2bb1-4f6b-ae90-9f1b3a3dec82 | testzone.example.com. | SOA | example10-cont1.testzone.example.com. | ACTIVE | NONE | | | | | admin.testzone.example.com. 1523473397 3531 600 | | | | | | | 86400 3600 | | | | 058f6862-cf1b-4da3-9d78-b3a890aff32f | testinstance.testzone.example.com. | A | 172.25.250.146 | ACTIVE | NONE | +--------------------------------------+------------------------------------+------+-------------------------------------------------+--------+--------+
Use the DNSaaS Designate API to create a manual record. This example creates
web.testzone.example.com
as an alias totestinstance.testzone.example.com
:$ openstack recordset create --records testinstance.testzone.example.com. --type CNAME 1bae1c6e-06e6-4a5d-8b03-483875478b73 web +-------------+--------------------------------------+ | Field | Value | +-------------+--------------------------------------+ | action | CREATE | | created_at | 2018-04-11T19:05:23.000000 | | description | None | | id | 3f99a737-c1a4-4137-a4a5-26f934e60dfa | | name | web.testzone.example.com. | | project_id | 6b34751621f449499569dfb077f5a7ed | | records | testinstance.testzone.example.com. | | status | PENDING | | ttl | None | | type | CNAME | | updated_at | None | | version | 1 | | zone_id | 1bae1c6e-06e6-4a5d-8b03-483875478b73 | | zone_name | testzone.example.com. | +-------------+--------------------------------------+
Check the DNSaaS configuration. It should now contain a record for
web.testzone.example.com
:[root@example10-cont1 ~(keystone_admin)]# openstack recordset list 1bae1c6e-06e6-4a5d-8b03-483875478b73 +--------------------------------------+------------------------------------+-------+-------------------------------------------------+---------+--------+ | id | name | type | records | status | action | +--------------------------------------+------------------------------------+-------+-------------------------------------------------+---------+--------+ | 4092f9f2-4fcb-4097-91bc-c4fa3b0965f9 | testzone.example.com. | NS | example10-cont1.testzone.example.com. | ACTIVE | NONE | | c08400a1-2bb1-4f6b-ae90-9f1b3a3dec82 | testzone.example.com. | SOA | example10-cont1.testzone.example.com. | PENDING | UPDATE | | | | | admin.testzone.example.com. 1523473523 3531 600 | | | | | | | 86400 3600 | | | | 058f6862-cf1b-4da3-9d78-b3a890aff32f | testinstance.testzone.example.com. | A | 172.25.250.146 | ACTIVE | NONE | | 3f99a737-c1a4-4137-a4a5-26f934e60dfa | web.testzone.example.com. | CNAME | testinstance.testzone.example.com. | PENDING | CREATE | +--------------------------------------+-------------------------------+-------+----------------------------------------------------------------+--------+
Run a DNS test, pointing to
localhost
as the DNS server, as this is where the DNSaaS service actually runs. This example attempts to resolveweb.testzone.example.com
:$ host web.testzone.example.com. localhost Using domain server: Name: localhost Address: ::1#53 Aliases: web.testzone.example.com is an alias for testinstance.testzone.example.com. testinstance.testzone.example.com has address 172.25.250.146
Check the reverse DNS configuration:
$ host 172.25.250.146 localhost Using domain server: Name: localhost Address: ::1#53 Aliases: 146.250.25.172.in-addr.arpa domain name pointer testinstance.testzone.example.com.
For more information, refer to the OpenStack Designate API V2 client documentation.