Following on from Testing Ansible Roles Using Containers, this is one of the series of posts that collectively step the reader through the testing of all the services implemented by Libraries – Ansible using Services – Docker. This post covers the testing of the network in Services – Docker, including the DNS service and how the Dynamic DNS service is spoofed in the test environments within Services – Docker in the absence of Akami integration.
- Posts in this Series
- Network Configuration in Services – Docker
- Readying a Test Environment
- Network Routing
- Internal and External DNS Services
- Dynamic DNS Service without Akami Integration
Posts in this Series
Here is the list of posts either published or soon to be published on the topic of testing services implemented within Services – Docker using the Ansible roles defined in Libraries – Ansible. Links to each of the other posts in this series will become available as they are published
- Network and DNS in “Services – Docker”
- Backup in “Services – Docker”
- WordPress Hosting in “Services – Docker”
- Mail Services in “Services – Docker”
- Calendars in “Services – Docker”
Network Configuration in Services – Docker
The diagram Network Configuration in Services – Docker below depicts the networks implemented in the test environments defined in my Services – Docker repository – see Test Environments in the README for Services – Docker.
The Docker Compose configuration in that repository defines two networks office and internet, which are simulations of our office (internal) network and networks external to our office network, i.e. the wider Internet. This is so that the test environments that Services – Docker creates can emulate the split between our office hosted and externally hosted servers.
A Docker Compose router service in each test environment emulates our own office router and firewall in that it acts as a gateway between the Docker office and internet networks, but it doesn’t implement a firewall since one is not necessary in our test environments to achieve our testing objectives.
Each of the test environments implements multiple hosts on each of the office and internet Docker networks, one of which on each network provides the DNS service for that network.
Readying a Test Environment
We’re going to test the network and DNS services implemented by Services – Docker, either directly or using Libraries – Ansible. Refer to the instructions under Using this Repository in the Services – Docker README for a fuller explanation of how to run the docker-compose commands we show here, including how to switch between the different test environments implemented by Services – Docker.
We must first raise-hosts for the services that we require:
docker-compose run --rm -T raise-hosts backup dns | bash
Of course, that’s the command to use if you’re working in an desktop with the Bash shell available. As the instructions in Using this Repository explain, you can pipe to other shells, for example Window’s PowerShell, provided you use the right syntax to do so.
Note that we have defined the services in scope as backup and dns. It might seem surprising that the backup service is included. We won’t go into the testing of the backup service in this article, it’s included here only in relation to testing of the Dynamic DNS Service without Akami Integration.
We must now execute the Ansible playbook to deploy the backup and dns services to the hosts that we just raised:
docker-compose run --rm playbook services backup dns
Once the playbook has completed successfully, we’re all set for testing.
The first thing we’re going to test is the router service in our Services – Docker test environment. Note that this service is not deployed via Ansible, instead it is defined solely by the Docker Compose configuration within Services – Docker. So, we’re not testing the roles in the Libraries – Ansible repository here.
Our router/firewall in the live environment is also not built using Ansible, it’s an appliance that we bought with its own, web configuration interface. However, since the router service is fundamental to everything that follows, we should confirm it’s working as expected here before going further.
To test that the router service is working as expected, two Docker Compose based commands are provided by Services – Docker; traceroute-internal and traceroute-external. These both provide the traceroute command but the first connects to the office (internal) Docker network and the second to the internet (external) Docker network.
When using these commands we must target hosts that are raised with our chosen services scope of backup and dns. These have different IP addresses between the now/to-be test environments and the distributed test environment.
If we run this command:
docker-compose run --rm traceroute-internal 10.0.1.101
It produces output something like this:traceroute to 10.0.1.101 (10.0.1.101), 30 hops max, 60 byte packets 1 services_router_1.services_office (10.0.0.254) 0.083 ms 0.012 ms 0.009 ms 2 10.0.1.101 (10.0.1.101) 0.037 ms 0.016 ms 0.014 ms
This confirms that our router service routes from the office Docker network to the internet Docker network as expected.
If we run this command:
docker-compose run --rm traceroute-external 10.0.0.103
It produces output something like this:traceroute to 10.0.0.103 (10.0.0.103), 30 hops max, 60 byte packets 1 services_router_1.services_internet (10.0.1.254) 0.084 ms 0.012 ms 0.009 ms 2 10.0.0.103 (10.0.0.103) 0.031 ms 0.016 ms 0.013 ms
This confirms the reverse, i.e. that our router service routes from the internet Docker network to the office Docker network as expected.
If testing the router service in the distributed test environment, use IP address 10.0.1.102 again with the traceroute-internal command but you can use 10.0.0.101, 10.0.0.102, 10.0.0.104 and 10.0.0.105 with the traceroute-external command and all should be successful.
Internal and External DNS Services
The Network Configuration in Services Docker includes two DNS servers, one on the Docker internet (external) network and one on the Docker office (internal) network.
The external DNS server in our test environments is an emulation of a third-party DNS service in the live environment. We do not deploy an external DNS service in live but we do configure DNS records for our own domain and for the domains of our customers, which are then of course available as lookups in any third-party DNS service. The external DNS server in our test environments exists solely to emulate this for the dummy customer.com and home.com domains that we test with.
The internal DNS server in our test environments mirrors the office DNS server that we maintain in live using Ansible and since we use the dns and dns_client roles in Libraries – Ansible for that purpose, we use those to deploy both the internal and external DNS services in Services – Docker.
docker-compose run --rm dig SERVER LOOKUP
SERVER is one of external or internal to indicate which of the two DNS servers the lookup request is sent to. LOOKUP is the DNS record to be queried. Both these arguments are mandatory. Again, the specific tests to perform and expected results differ between the now/to-be and distributed test environments.
The table DNS Lookup Tests and Results (now/to-be) below shows the expected results for a series of DNS queries made of both the internal and external DNS servers in either the now or to-be test environments.
|Lookup||Result (internal)||Result (external)|
|hub or hub.home.com||answer = 10.0.0.103 1||no answer 2|
|dns‑external or dns‑external.home.com||answer = 10.0.1.101 3||answer = 10.0.1.101 4|
|bbc.co.uk||answer 3||answer 5|
|bacula‑dir or bacula‑dir.home.com||answer = 10.0.0.103 6||no answer 7|
|bacula‑sd or bacula‑sd.home.com||answer = 10.0.0.103 6||answer = 10.0.1.254 8|
The notes below pertain to the results in the table above.
- 1 The internal DNS server provides lookups for hosts on the Docker office network.
- 2 Hosts on the Docker office network are not known to any external DNS service.
- 3 The internal DNS server uses the external DNS server for upstream DNS lookups.
- 4 The external DNS server provides lookups for hosts on the Docker internet network.
- 5 The external DNS server uses Google’s public DNS servers for upstream DNS lookups.
- 6 The internal DNS server also provides lookups by name for services on the Docker office network.
- 7 Just as for hosts on the Docker office network, services on the Docker office network are not known to any external DNS service.
- 8 See Dynamic DNS Service without Akami Integration below.
The table DNS Lookup Tests and Results (distributed) below shows the expected results for a series of DNS queries made of both the internal and external DNS servers in the distributed test environment. The same notes apply as in the table DNS Lookup Tests and Results (now/to-be) above, the only difference here being that services are distributed across hosts on a one-to-one basis.
|Lookup||Result (internal)||Result (external)|
|backup‑director or backup‑director.home.com||answer = 10.0.0.101||no answer|
|backup‑storage or backup‑storage.home.com||answer = 10.0.0.102||no answer|
|database‑internal or database‑internal.home.com||answer = 10.0.0.104||no answer|
|dns‑internal or dns‑internal.home.com||answer = 10.0.0.105||no answer|
|mail‑internal or mail‑internal.home.com||answer = 10.0.0.108||no answer|
|dns‑external or dns‑external.home.com||answer = 10.0.1.102||answer = 10.0.1.102|
|bacula‑dir or bacula‑dir.home.com||answer = 10.0.0.101||no answer|
|bacula‑sd or bacula‑sd.home.com||answer = 10.0.0.102||answer = 10.0.1.254|
Dynamic DNS Service without Akami Integration
In our live environment we expose some services that are hosted on our office networks externally. These are:
- Non-production websites that are shared with our customers for concept or testing purposes and, being non-production, are not subject to production requirements for availability or performance.
- The storage daemon for our installation of Bacula, which we use for our backup service. We backup hosts that are both internal and external to our office network. Those hosts that are external to our office network must be able to connect to the Bacula storage daemon running on our office network to send it the data to be backed up.
The externally facing IP address of our office network is dynamically assigned by our ISP. Thus, we dynamically maintain the DNS records for these services using API integration with the Akami domain management service, Akami being our preferred cloud computing services provider.
It’s possible to enable and test this integration within our Services – Docker repository, however, this integration is disabled by default. We will publish a future post on this subject. Without this integration enabled, Services – Docker mimics this capability in the following way:
- The router Docker Compose service implements port mapping just as the firewall/router for our office network does. This maps the ports for HTTP, HTTPS and the Bacula storage daemon service from the externally facing service of the router service to the relevant hosts on the office Docker network.
- When you run playbooks for the backup and web services then the relevant lookups are configured in the external DNS server, which is mimicking what our API integration with the Akami domain management service does for our dynamically assigned API address.
The Ansible that implements the second of the two steps above is specific to the playbooks within Services – Docker and the my-roles wrapper that it puts around the roles in Libraries – Ansible – see also Docker Container Workarounds in Testing Ansible Roles Using Containers. It this way it does not pollute Libraries – Ansible with container considerations.