Creating a DNS Service on the Cloud
Date: Jan 28, 2013
IBM Senior Software Engineer Alexander Amies and IBM Software Engineer Pan Xia Zou discuss how to configure and use a DNS server for management of virtual machines on the cloud. This is described in the context of a cloud-based virtual local area network and scripting to automate network configuration of virtual machines. One of the architects of the IBM SmartCloud Enterprise platform, Alex is a co-author of Developing and Hosting Applications on the Cloud.
The domain name system (DNS) is a fundamental building block of the World Wide Web, and DNS can be a powerful tool in public and private cloud computing. You can use DNS to solve many practical problems associated with the dynamic nature of cloud server provisioning. In particular, DNS can make virtual machine images, migration, and workloads portable.
This article presents an overview of the reasons and challenges for hostname management of virtual machines on the cloud. We describe client setup on Windows and Linux systems, and server setup and maintenance with the BIND DNS server on Linux. Finally, we outline how to automate and externalize DNS and network configuration of Linux virtual machines with image-customization scripts.
The procedures in this article were tested with IBM SmartCloud Enterprise (SCE). The principles we discuss apply to other Infrastructure as a Service (IaaS) clouds as well. However, no warranty is given that the tools and techniques described here will work. The opinions presented are those of the authors and not IBM.
Introduction
The DNS system was introduced in the 1980s to provide a human-friendly system of connecting to and managing servers and interacting with network servers. The World Wide Web is a prime example of one place where DNS is crucial, and it would be hard to imagine the Web without hostnames in URLs. In cloud systems, servers are dynamically provisioned and change frequently. However, since the management of the DNS system falls between cloud provider and cloud consumer, it's a thorny and often overlooked area. That's the motivation for writing this article, which explains the concepts and steps for common requirements on the Web.
Why use DNS instead of using IP addresses? DNS names are easier to remember and more meaningful than IP addresses. Consider using them in bookmarks, configuration files, email to other people, and so on. You'll easily be able to remember the purpose of the virtual machine with a meaningful hostname, but have difficulty using an IP address. When giving addresses to other people, you'll be free to switch the hostname to another machine, but you'll have difficulty switching IP addresses.
One assumption often made about cloud systems is that it's simple to capture images of virtual machine instances and reinstantiate those images later. Unfortunately, hostname is a critical parameter in many configuration files, and it usually becomes "frozen" in the images. For example, hostnames are embedded in X.509 (SSL) certificates and application-server configuration files. In some cases, this fact prevents system services from operating. If you have no control over the hostname assigned to your server, it might require considerable configuration effort to set things right. With the techniques described in this article, however, you'll be able to assign the hostname of your choice to a virtual machine, completely avoiding the problem.
Overview of DNS and Networking
Hostnames are traditionally assigned by end users, who inform an administrator of the virtual machine's desired IP address and primary hostname (such as vhost1234). The administrator creates a record in the DNS system so the fully qualified domain name can be used (such as vhost.sceexample.com). In addition, an alias is created (such as fred-db2-singapore.sceexample.com).
The article makes special reference to virtual local area networks (VLANs). Having a VLAN is just like having your own private data center on the cloud. After you provision a virtual machine to a VLAN, it won't be visible to the Internet. Making the changes to the virtual machine instances in this document will enable networking and DNS within your VLAN. However, for most cloud providers, DNS typically won't be configured when provisioning virtual machines on a VLAN, because it's difficult for a cloud provider to manage hostnames for private IP addresses. On the public Internet, IP addresses are unique, but private IP addresses only need to be unique within the private network to which they belong. A more precise definition is beyond the scope of this article, but you can roughly understand that the private network domain is visible to you, including your corporate network, as well as any VPN connections that you might have to different VLANs on the cloud. So it makes more sense to use your own DNS server when working with virtual machines on a VLAN. Figure 1 shows a simple DNS topology with VLANs on the cloud.
Figure 1 Simple DNS topology with VLANs.
The same arguments for the DNS server also apply to the network gateway. In a VLAN you'll also be responsible for managing your own network gateway, which will typically be a virtual machine with IP addresses on both the Internet and the VLAN. That virtual machine might be configured to route all traffic originating in the VLAN to the Internet, allowing only restricted traffic into the VLAN.
The Firewall image in IBM SmartCloud Enterprise is a good choice for the gateway because it includes preconfigured firewall software and is security-hardened in a way that's appropriate for an Internet-facing server. In the examples in this article, the network gateway hosts the DNS servers. Figure 2 shows the network topology for the example in this article.
Figure 2 Network topology for the examples in this article.
Although in Figure 1 we showed the user communicating directly with a Linux virtual machine in a VLAN, this is actually a simplification. As Figure 2 shows, the network topology forces all traffic to and from the Linux virtual machine on the VLAN to be routed through the firewall, which has one IP address on the Internet (shown as the public IP) and one on the VLAN (shown as the private IP). Outbound traffic to the Internet with a connection originating on the Linux virtual machine (VM) in the VLAN must use the private IP address of the firewall as a gateway.
In IBM SmartCloud Enterprise, all IP addresses are statically assigned. With the dynamic nature of the self-service user interface (that is, the web portal), which can allocate IP addresses rapidly and automatically, you get the convenience of a DHCP system without concern for the IP address changing. Not all clouds operate this way. Some clouds use DHCP to assign IP addresses to virtual machines. In that kind of network environment, some steps described in this article would need to be modified.
Client Setup
In these steps, we'll configure Linux and Windows machines to act as DNS clients. We start with client setup because it's the most common task. Provisioning virtual machines to a VLAN offers several challenges, including configuring the network gateway and the DNS servers you want to use. It's difficult for the cloud provider to know the gateway and DNS settings for your VLAN, so that you typically need to do this part yourself. First we'll explain the steps for configuring network and hostname settings for a Linux virtual machine on a VLAN. The client in this example was provisioned from the base Red Hat Enterprise Linux (RHEL) version 6.2 virtual machine image in the SCE image library.
If your goal is to configure a DNS server, these steps are also good to try out manually if your goal is to automate them. You may want to revisit this section after performing the steps in the later section "DNS Server Setup."
Prerequisites
The steps in this section assume the following:
- You already have a DNS server and know its IP address. (Ask your administrative contact, if necessary.)
- You have a virtual machine and an SSH key to connect to it.
If you're the administrative contact and you haven't set up your own DNS server yet, you can begin with the cloud provider's public DNS server. You can determine whether this will work by provisioning a virtual machine to the Internet and checking the DNS system that it's configured to use.
Conventions
Several conventions are used in the following sections related to commands:
> The right angle bracket (>) represents a command-line prompt on a local workstation.
$ The dollar sign ($) represents a command-line prompt on a Linux VM, executed by a regular user (idcuser).
# The number sign (#) represents a command-line prompt on a Linux VM, executed by the root user.
The text after the command is the output from the command. We include it only when there's something particular to note in the output. In cases where the command is vi, the text following the command is the contents of a file for editing.
Step 1: Configure the Gateway
In this step, you'll configure your Linux virtual machine to point at the proper network gateway. Set the gateway to the private IP of the gateway server for the VLAN and restart the network service. As root, edit the files shown in Listing 1.
Listing 1Configuring the gateway on the RHEL 6 virtual machine on a VLAN.
# vi /etc/sysconfig/network-scripts/route-eth0 . . . default table route_eth0 via <gateway> dev eth0 # vi /etc/sysconfig/network-scripts/ifcfg-eth0 . . . GATEWAY=<gateway> # /sbin/service network restart
Replace the <gateway> values in Listing 1 with the values for your own environment.
Test that you can reach a public server, such as a Yahoo! server, by using curl:
$ curl 106.10.170.118
You should see the HTML page returned from curl.
Step 2: Configure DNS Resolution
Client network settings are configured in the resolv.conf file in Linux. Edit the /etc/resolv.conf file as shown in Listing 2; add a line using the IP address of your own DNS server, and substituting the names of your own domain and DNS server IP.
Listing 2Configuring a DNS client.
# vi /etc/resolv.conf domain sceexample.com nameserver <dns_server_ip>
Test the settings by using the nslookup or dig command on the VM with the BIND server using a well-known website, such as Yahoo! (http://www.yahoo.com). Basic use of the nslookup command is as follows:
$ nslookup http://www.yahoo.com Name: ds-sg-fp3.wg1.b.yahoo.com Address: 106.10.170.118 . . .
The result of this nslookup command shows that the IP address 106.10.170.118 of the Yahoo! server was found.
Step 3: Add Compatible Entries for the Local Server
The hostname settings for the virtual machine itself are contained in the /etc/hosts file. Edit the /etc/hosts file to add a line as shown :
# vi /etc/hosts . . . 10.128.105.47 vm-10-128-105-47 vm-10-128-105-47.scexample.com 10.128.105.47 myserver myserver.scexample.com
Substitute the hostname of your own virtual machine and your own domain name.
Using nslookup as shown below, test that you can look up the address of your own server, including the newly configured domain and some other servers that are on the same VLAN:
# nslookup vm-10-128-105-47 . . . Name: vm-10-128-105-47.sceexample.com Address: 10.128.105.47 # nslookup vm-10-128-105-48 . . . Name: vm-10-128-105-48.sceexample.com Address: 10.128.105.48
This completes the configuration of the Linux machine as a DNS client.
Configuring a Windows Client
It can be convenient to set up your Windows client workstation to use the same DNS server as your cloud-based virtual machines. The configuration for Windows Server is similar. You can configure these settings to use the nameserver with the dialog in Figure 3.
Figure 3 Windows DNS configuration.
DNS Server Setup
BIND is an open source DNS server software package. It's the most popular DNS server on the Internet and can be installed easily on Linux systems via the package management system. After that, some configuration is necessary to enable the server to listen for incoming requests and to act as an authoritative server for your domain. Several executable files are packaged with BIND; the main file that concerns us is the named DNS service. We'll also briefly describe the dig command for doing DNS lookup and the rndc management utility.
Prerequisites
To follow the instructions in this section, you'll need the following things:
- SCE user account. Sign up if you don't have an account, or you can probably perform similar steps on another cloud.
- SSH key pair. The public key should be stored on the SCE server and the private key saved on your local workstation. If you created the SSH key through the SSH portal and saved the downloaded file, you have these.
- SCE command-line toolkit. If you prefer to use the cloud web portal, you won't need this. The command-line instructions in this article are for Windows, but similar commands are available for Linux.
- VLANs at each data center. All SCE accounts come with a VLAN at each data center, but you don't generally need a VLAN to run a DNS server. If you don't want to use a VLAN, you'll have to adapt some of the following steps to suit your own network configuration.
Step 1: Provision the Server and Install BIND
In this step, we provision a virtual machine for the DNS server. We also install and start the BIND named service.
Provision an instance of the IBM Firewall image with two IP addresses. The VPN server or firewall for the VPN is a good choice. It should be a hardened image like the IBM firewall in the image catalog. You can use either the SCE web user interface or API to create the virtual machine instance.
Reserve an IP address on the VLAN with the command in Listing 3. Execute the command on your local workstation.
Listing 3Allocating an IP address with the SCE command-line tool.
> ic-allocate-address.cmd -u <user_id> -g <password_file>-w <passphrase> -x <vlan_id> -L 141 -O 20027868 Executing action: AllocateAddress ... The request has been submitted successfully. ID: 344533 InstanceId: State: NEW Executing AllocateAddress finished
In the command in Listing 3, substitute your own username for <user_id>, password file for <password_file>, and password phrase for <passphrase>.
The -x parameter lists the VLAN ID (<vlan_id>); this is specific to your customer account. Use ic-describe-vlans to find it.
The -L parameter is the data center ID; 141 is the ID for the Singapore data center. If you don't want to use Singapore, use the ic-describe-locations command to find the ID for another data center.
The -O parameter is the offering ID; 20027868 is the ID for an IP address on a private VLAN in Singapore. Use the ic-describe-address-offerings command to find an alternative offering ID if you don't want to use the Singapore data center.
This command will give an address ID in the response output, as shown in Listing 3. The IP address will take a short period of time to be allocated. Use the ic-describe-addresses command to check the status of the request, and wait for the state to be FREE, indicating that the address is available to be associated with a virtual machine instance.
The command in Listing 4 shows how to create the virtual machine with the SCE command line.
Listing 4Creating a DNS server with the SCE command-line tool.
> ic-create-instance.cmd -u <user_id> -g <password_file> -w<passphrase> -k 20036705 -n DNS_Server -t "COP32.1/2048/60"
-L 141 -m "{secondary.ip.0:<address_id>}" . . . ID: 325599 . . . Status: NEW
The -k parameter is the specific image ID for the IBM Firewall image in the Singapore data center. Search the image catalog or use the ic-describe-images command to find an alternative image.
The -n parameter is the name that you give the server. You can use any name you want here, but enclose it in double quotes (" ") if the name includes spaces or special characters.
The -t parameter is the server size—in this case, a single-CPU, 32-bit machine with 2048MB of memory and 60GB of disk space. If you want a different size, use the ic-describe-image command to find the supported server sizes.
The -L parameter is the data center, as described for Listing 3. The -m is the ID for the secondary address (<address_id>), which was obtained in the output of the ic-allocate-address command in Listing 3. The Internet-facing primary address will be assigned automatically.
The instance will take a short time to be provisioned. The instance ID is shown in the output of the ic-create-instance command, in this case 325599. Note this ID and use it in the ic-describe-instance command to check the status of the request, waiting for it to become ACTIVE:
> ic-describe-instance.cmd -u <user_id> -g <password_file> -w <passphrase> -l 325599 . . . IP: 170.225.160.40 . . . Status: ACTIVE . . .
At this point you can use your default SSH key to connect to the instance via the primary IP address, which is also the Internet-facing address. That IP address is also shown in the output from the ic-describe-instance command we just discussed.
The secondary IP address faces the VLAN. Initially, the network interface associated with the secondary IP is not active. The network interface for the secondary IP is typically eth1; you can check the status with the ifconfig -a command. SSH to the server and execute the ifup command shown in Listing 5 to activate the secondary network address.
Listing 5Activating the network interface for the secondary IP address
$ sudo /sbin/ifconfig -a eth1 Link encap:Ethernet HWaddr DE:AD:BE:6A:71:45 BROADCAST MULTICAST MTU:1500 Metric:1 . . . $ sudo /sbin/ifup eth1 $ sudo /sbin/ifconfig -a eth1 Link encap:Ethernet HWaddr DE:AD:BE:6A:71:45 inet addr:10.128.105.40 Bcast:10.128.105.255 Mask:255.255.255.0 inet6 addr: fe80::dcad:beff:fe6a:7145/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 . . .
Notice that the status of the network interface changes to UP in the output of the ifconfig command and the Internet address is displayed.
Follow the instructions in the Firewall image guide, located in the SCE image catalog, to enable routing from the Internet to virtual machines in the VLAN. If you didn't use the Firewall image, configure iptables to route between the Internet and the VLAN.
SSH to the server and install BIND from the yum repository with the following commands:
$ sudo yum install bind
Set the service to be on by default, and start it with these commands:
$ sudo chkconfig named on $ sudo service named start
After the BIND server has started, verify installation against your local interface to make sure that the firewall is open on each end.
You can check that BIND is running properly by using the dig command:
$ dig @127.0.0.1 http://www.yahoo.com . . . ;; ANSWER SECTION: http://www.yahoo.com. 300 IN CNAME fd-fp3.wg1.b.yahoo.com. fd-fp3.wg1.b.yahoo.com. 300 IN CNAME ds-fp3.wg1.b.yahoo.com. ds-fp3.wg1.b.yahoo.com. 60 IN CNAME ds-sg-fp3-lfb.wg1.b.yahoo.com. ds-sg-fp3-lfb.wg1.b.yahoo.com. 300 IN CNAME ds-sg-fp3.wg1.b.yahoo.com. ds-sg-fp3.wg1.b.yahoo.com. 60 IN A 106.10.170.118 . . .
The dig command is packaged with BIND and also installed by default on the Firewall image in the SCE image catalog. It's a Linux DNS client utility similar to nslookup, but it provides more useful information in the command output. The @ parameter specifies the DNS server to use. If it's not provided, the DNS server in resolv.conf will be used.
The output of the command shows a CNAME record that defines the domain name http://www.yahoo.com as an alias, and several other aliases are defined, which finally point at the address (A) record linking to the IP address 106.10.170.118. We'll look at how to define the CNAME and A records for our own domain shortly.
On RHEL systems, BIND is configured by default to respond only to requests from the local system. We need to perform additional configuration to enable it to respond to external requests.
Step 2: Configure the DNS Server to Accept External Requests
In this step we configure BIND to accept requests from any incoming client. Open the main configuration file /etc/named.conf and edit the lines related to the listener and query restrictions, as shown in Listing 6.
Listing 6Configuring BIND to accept outside requests for DNS queries.
# vi /etc/named.conf
listen-on port 53 { any; };
. . .
allow-query { any; };
After saving the changes to named.conf, restart the named server:
# service named restart
At this point the BIND server is listening for outside requests, but the firewall is blocking those requests from being delivered.
Step 3: Configure the Firewall
In this step we configure the firewall and check the DNS service. Open port 53 in the firewall for both UDP and TCP with the commands in Listing 7.
Listing 7Configuring iptablesto accept outside requests connections on port 53.
# vi /etc/sysconfig/iptables # Add lines allowing any port if accessed from the local machine. . . . -A INPUT -p udp -m udp --dport 53 -j ACCEPT -A INPUT -p tcp -m tcp --dport 53 -j ACCEPT . . . # /sbin/service iptables restart
After restarting the firewall, verify installation against all network interfaces to make sure that the firewall is open on each one:
$ dig @<private_ip> http://www.yahoo.com $ dig @<public_ip> http://www.yahoo.com
The <private_ip> and <public_ip> parameters are the IP addresses of the two network interfaces with which you provisioned the server in the earlier section "Step 1: Provision the Server and Install BIND." If you only want to accept requests from within your VLAN, you should add a further restriction to the firewall rules above, based on source address range.
Step 4: Set Up the Zone for the New Domain in the DNS System
In this step, we configure BIND to be the primary domain server for our new domain. A zone entry is used to specify a DNS domain. We'll make our server the primary name server for the domain sceexample.com. You should substitute your own domain for all occurrences of sceexample.com in the listings here. We'll add a zone statement for this purpose and include a zone file that will contain the individual resource records for the domain. Edit the main configuration file /etc/named.conf to add the section in Listing 8.
Listing 8Zone entry in named configuration file.
zone "sceexample.com" {
type master;
file "sceexample.com";
};
Now we've defined the zone, but we don't have any DNS records for that zone.
Step 5: Add DNS Records
In this step we add DNS records for the zone. Create the zone file /var/named/sceexample.com for the domain, and add text as shown in Listing 9. It includes Time to Live ($TTL), root name ($ORIGIN), start of Authority (SOA) entries, and some Address (A) resource records. Use your own hostname <client> and IP address <linux_client_ip>. We also name this as a web server with a www prefix to the hostname, as an example of an alias.
Listing 9DNS zone file.
$TTL 1h $ORIGIN sceexample.com. @ 1D IN SOA ns hostmaster ( 2006100201 ; se = serial number 1h ; ref = refresh 15m ; ret = update retry 3w ; ex = expiry 3h ; min = minimum ) IN NS ns.sceexample.com. ns IN A <nameserver_ip> <client> IN A <linux_client_ip> www IN CNAME <client> :wq!
Substitute your own hostname for <client> and IP addresses for <nameserver_ip> and <linux_client_ip>. This should be another virtual machine instance on your VLAN. If you don't have one, leave out the two lines with <client>. The value for <client> is the primary hostname, such as vhost0915.sceexample.com. This is specified in an Address (A) record. The alias www is just an example, appropriate for a web server. It's what's known as a CNAME or alias record that defines an additional name by which you can refer to the machine . After saving the file, restart the server:
# /sbin/service named restart
Now that we've created the zone and entries for it, we can test it.
Step 6: Test Looking Up a Domain Name
In this step we use dig to test the definition of the domain in the BIND configuration files. Use the dig command on the machine with the BIND server:
# dig @127.0.0.1 http://www.sceexample.com . . . ;; ANSWER SECTION: http://www.sceexample.com. 3600 IN CNAME vm-10-128-105-48.sceexample.com. vm-10-128-105-48.sceexample.com. 3600 IN A 10.128.105.48 . . .
The result of the command shows the alias (CNAME record) for the xx server referring to the primary hostname and the Address (A) record pointing to the IP address (<linux_client_ip> in Listing 9).
If you don't want to register your domain with a public domain registration provider or don't need a secondary server, then you can skip Steps 7–8 in the next two sections and jump directly to the later section "Managing the BIND Server." However, public domain registration providers require a minimum of two DNS servers when registering a self-managed domain. See how to define a secondary server in the next section.
Step 7: Set Up a Secondary Server
In this step we set up a secondary DNS server on another virtual machine instance, similar to the primary. Change the secondary BIND server file to be the same as the primary except for the lines in Listing 10.
Listing 10Testing the domain definition with dig.
# vi /etc/named.conf
. . .
zone "sceexample.com" {
type slave;
file "sceexample.com";
masters { <primary_ip>; };
};
This code defines the BIND server to be a slave for the domain. All the resource records will be copied from the primary server. Restart the server with the following command:
$ sudo /sbin/service named start
At this point we have a working DNS system, but it's not known to anyone other than us. We can perform a special client setup to refer to it, or we can make it publicly discoverable on the World Wide Web with the step in the next section.
Step 8: Register the Domain
This section explains how to register the DNS system that we have set up to be authoritative for our domain. You can do it by registering the domain with a public DNS registration service, such as GoDaddy.com. You'll need to set the nameservers for the domain to be the DNS servers that you set up earlier. You must configure at least two DNS servers if you're setting these as the DNS servers using a public service.
If you're using GoDaddy.com, first add the two DNS servers as hosts using their hostnames, such as vhostxxx. The domain will be appended. (It will take some time to process.) Then set the DNS servers for the domain.
Managing the BIND Server
The way that we've set up the DNS servers makes them visible on the Internet, so security is a prime concern. You should check the BIND server regularly and keep it up to date with the latest software available in the yum repository. This process is explained in the following sections.
Maintaining BIND
This section explains the basics of checking the status of the named service and updating BIND. To check the status, use the following command:
$ sudo /sbin/service named status rndc: connect failed: 127.0.0.1#953: connection refused named is stopped
The output of the command shows that the named server is stopped.
To check the BIND version installed, use the yum command:
$ sudo yum info bind Installed Packages Name : bind Version : 9.8.2 Release : 0.10.rc1.el6_3.5 Repo : installed . . .
To upgrade BIND, use the yum upgrade command:
$ sudo yum upgrade bind
Using the rndc Command-Line Tool
The rndc utility is a management client that communicates over a TCP connection to manage the BIND server. You can use rndc to add DNS entries without restarting the named server. It's authenticated with a cryptographic key; the default key is stored in /etc/rndc.key. The default port is 953. The configuration settings are stored at /etc/rndc.conf.
Make sure that the firewall is open on port 953. Using the command line on the BIND server, use rndc as shown in Listing 11 to check status, reload configuration files, or reload a zone.
Listing 11Managing BIND with the rndc command.
$ sudo rndc status . . . $ sudo rndc reload server reload successful $ sudo rndc reload sceexample.com zone reload up-to-date
Maintaining the Firewall
This section explains the basics of firewall settings for DNS beyond what we discussed in the earlier section "Step 3: Configure the Firewall." Running BIND on the Internet can be a potential security risk if the software isn't kept up to date with security patches and proper settings. To reduce security risks, you can limit traffic to within your VLAN, by using a CIDR IP address range in the iptables rules, as shown in Listing 12.
Listing 12Restricting access to the DNS system with the firewall.
# vi /etc/sysconfig/iptables -A INPUT -p udp -m udp -s 10.128.120.0/24 --dport 53 -j ACCEPT -A INPUT -p tcp -m tcp -s 10.128.120.0/24 --dport 53 -j ACCEPT -A INPUT -p tcp -m tcp -s 127.0.0.1 --dport 953 -j ACCEPT
The -s (source) flag takes a CIDR range 10.128.120.0/24, indicating that only the packets originating in the 10.128.120.x VLAN will be accepted. (Substitute your own VLAN address range in place of the one given here.) The management port is configured to allow only connections from the local machine. Restart the firewall with the iptables restart command.
Automation of Client Configuration
IBM SmartCloud Enterprise and some other cloud providers give a framework for injecting data and scripts into virtual machines at provisioning time. We'll use the SCE framework here for automation of the DNS and other network configurations, explaining the features as we use them. If your cloud doesn't support dynamic injection of scripts and data during provisioning, another way to automate the configuration is to create a virtual machine instance, copying the automation files manually, and then save it as a base image.
Externalization of the virtual machine network customization from the image binary is a critical step. It allows you adapt to a changed network environment without creating a new image binary, and it enables you to inject different network configurations into an image binary that already exists. The image binary is opaque to us unless we provision an instance of it, so externalizing critical settings is an important advantage.
However you customize the image, a Python script will be used to make file changes and a configuration file will be created to store the network settings. We'll use Python to automate the steps that we've described above in the client configuration. Python is part of the Linux Standard Base and is an excellent choice for image-customization scripts. The version of Python shipped in RHEL 6.2 and most Linux systems is Python 2.6.6. There are some differences between this version and Python 3, but the scripts shown here are mostly compatible with Python 3 (with the exception of the ConfigParser class). Listing 13 shows the Python configuration script.
Listing 13Python script for automated network and DNS client configuration. Python keywords are in bold.
import ConfigParser
import re
import shutil
def update_file(filename, patterns, replacements):
''' Update file with lines matching given patterns '''
backup = filename + '.bak'
shutil.copyfile(filename, backup)
f = open(backup, 'r')
text = ""
for line in f:
if (len(line.strip()) == 0) or (line[0] == '#'):
text += line
else:
matched = False
for i in range(len(patterns)):
if re.match(patterns[i], line):
text += replacements[i] + '\n'
matched = True
if not matched:
text += line
f.close()
f = open(filename, 'w')
f.write(text)
f.close()
def configure():
''' Make configuration changes '''
print("Make configuration changes")
config = ConfigParser.ConfigParser()
config.read('/etc/cloud/dns.conf')
replacement = 'GATEWAY={0}'.format(config.get('Network','gateway'))
update_file('/etc/sysconfig/network-scripts/ifcfg-eth0', ['GATEWAY'], [replacement])
replacement = 'default table route_eth0 via {0} dev eth0'.format(config.get('Network','gateway'))
update_file('/etc/sysconfig/network-scripts/route-eth0', ['default'], [replacement])
patterns = ['domain', 'nameserver']
replacements = ['domain {0}'.format(config.get('Network','domain')),
'nameserver {0}'.format(config.get('Network','nameserver'))]
update_file('/etc/resolv.conf', patterns, replacements)
if __name__ == '__main__':
configure()
The entry point to this program from the command line is the if __name__ statement, which calls the configure() function. You can copy this script into any editor and save it. I developed it on my Windows workstation with the Eclipse PyDev plug-in and then tested it on a Linux machine that was already running before inserting it into the virtual machine instance-provisioning process.
The Python script will read the network settings in dns.conf and inject the values stored there into the virtual machine files for setting the gateway and DNS server. The dns.conf file is shown in Listing 14.
Listing 14Configuration file dns.conf.
# Network configuration file [Network] gateway: <gateway_ip> domain: sceexample.com nameserver: <dns_server_ip>
Replace the values of <gateway_ip>, sceexample.com, and <dns_server_ip> with appropriate values for your own environment.
To add this script and configuration file to a virtual machine image, we make a clone of an image in the public image catalog and add the scripts as image metadata. This step is essential because we need ownership of the image to change the metadata. In the SCE web portal, navigate to the Control Panel > Images tab and click the Add Image button, as shown in Figure 4.
Figure 4 Cloning an image in IBM SmartCloud Enterprise.
The next screen allows you to choose an image to clone. In this example, we'll use Red Hat Enterprise Linux 6 (64-bit) in the Singapore data center. After adding the image clone, the image will appear under My Assets in the My Dashboard of the cloud Asset Catalog, as shown in Figure 5.
Figure 5 The cloned image appears under My Assets.
Clicking the name of the image in My Assets will lead you to the metadata for the image, as shown in Figure 6. Make a note of the image ID, which we'll use later when creating an instance of the image with the command-line tool.
Figure 6 Cloned image metadata.
Navigate to the activation_scripts folder (see Figure 7) and download the files it contains. Place these files in a directory called activation_scripts on your local workstation, adding dns_client_config.py and dns.conf to it.
Figure 7 Image metadata contents.
Edit the cloud-startup script to call our Python script dns_client_config.py, as shown in Listing 15.
Listing 15Modification of the startup script cloud-startup3.txt.
start) . . . if [ -e /etc/cloud/dns_client_config.py ] ; then echo " [cloud-startup] Performing network configuration ..." /usr/bin/python /etc/cloud/dns_client_config.py fi ;; stop)
Edit scripts.txt to define the location where dns_client_config.py and dns.conf will be copied during instance-provisioning time, as shown in Listing 16.
Listing 16Modification of scripts.txt.
cloud-startup3.txt=/etc/init.d/cloud-startup3.sh activate.txt=/etc/cloud/activate.sh dns.conf=/etc/cloud/dns.conf dns_client_config.py=/etc/cloud/dns_client_config.py
After making the changes to scripts.txt, zip the activation_scripts directory. Click the pencil icon in the upper-right corner of the Asset Catalog tab (marked in Figure 7) to edit the asset metadata. Upload activation_scripts to the image catalog and save to update the image asset. The Contents should look like those in Figure 8.
Figure 8 Updated image metadata.
To test our automation script, we provision an instance with the SCE command-line tool and check the network settings. Execute the ic-create-instance command:
>ic-create-instance.cmd -u <user_id> -g <password_file> -w <passphrase> -k 20069951 -n "RHEL Clone Instance" -t "COP64.2/4096/60" -L 141 -x <vlan_id> . . . ID: 326329 Name: RHEL Clone Instance . . .
In the command above, the -k parameter is the image ID of the image that you've customized, -n is the cloud display name of the virtual machine, -t is the server size, -L is the data center (Singapore), and -x is the VLAN ID. After the instance has become active, log in with SSH and check the resolv.conf and other network configuration files to make sure that your script injected the settings as expected. Use the nslookup command to exercise the DNS server as shown below:
$ dig http://www.yahoo.com . . . ;; ANSWER SECTION: http://www.yahoo.com. 300 IN CNAME fd-fp3.wg1.b.yahoo.com. fd-fp3.wg1.b.yahoo.com. 300 IN CNAME ds-fp3.wg1.b.yahoo.com. ds-fp3.wg1.b.yahoo.com. 60 IN CNAME ds-any-fp3-lfb.wa1.b.yahoo.com. ds-any-fp3-lfb.wa1.b.yahoo.com. 300 IN CNAME ds-any-fp3-real.wa1.b.yahoo.com. ds-any-fp3-real.wa1.b.yahoo.com. 60 IN A 72.30.38.140
If the dig command can find the IP address of the Yahoo! server, you've successfully automated the network configuration of a Linux client on a private VLAN.
Next Steps
Consider the steps below when applying the principles in this article to your own system.
- We haven't automated all the hostname entries in the /etc/hosts file. You might want to allow the user to choose a hostname or alias when requesting a new provisioning machine in the web portal. IBM SmartCloud Enterprise allows you to define additional parameters using the image metadata file parameters.xml. The parameter values supplied by the user requesting the instance are copied to the directory /etc/cloud in the running instance. You can use these values to change the settings in /etc/hosts.
- BIND can also store DNS records in a relational database. If you're managing a domain with many virtual machines, this may be a good option, enabling your domain to scale more easily and allowing you to add new DNS entries without editing files.
- Automate registration of new domains and subdomains, as well as addition of resource records. You could implement the Apache LibCloud DNS interface as a DNS service provider, to give it a consistent interface shared by other cloud-based DNS providers.
- Separate the management of public and private IP addresses. Ideally, public and private IP addresses should belong to different domains, and mappings of private IP addresses shouldn't be visible in a public network. You can make this change with additional settings in the BIND named.conf file. It's also possible for BIND to give different responses to a name query, based on the network zone from which the query comes. For example, if the query comes from the Internet, return a public IP address; if the query comes from a private network, return the private address.
Resources
- IBM SmartCloud Enterprise command-line tool reference (user login required)
- Internet Systems Consortium BIND Documentation
- Red Hat Enterprise Linux 6 Deployment Guide
Copyright and Trademarks
©IBM Corporation 2012.
IBM, the IBM logo, ibm.com, Cognos, DB2, Informix, Lotus, Rational, SmartCloud, System x, Tivoli and WebSphere are trademarks or registered trademarks of International Business Machines Corporation in the United States, other countries, or both. If these and other IBM trademarked terms are marked on their first occurrence in this information with the appropriate symbol (® or ™), these symbols indicate U.S. registered or common law trademarks owned by IBM at the time this information was published. Such trademarks may also be registered or common law trademarks in other countries. A current list of IBM trademarks is available on the web at "Copyright and trademark information" at http://www.ibm.com/legal/copytrade.shtml.
Linux is a registered trademark of Linus Torvalds in the United States, other countries, or both.
Microsoft and Windows are trademarks of Microsoft Corporation in the United States, other countries, or both.
Other company, product, and service names may be trademarks or service marks of others.
References in this publication to IBM products or services do not imply that IBM intends to make them available in all countries in which IBM operates.