With a little side of applesauce...

Tuesday, January 30, 2007

Using Fabien Coelho’s Mod_Macro to help scale web farms.

Introduction:

We are currently setting up a load-balanced server farm and have greatly simplified configuration by using Fabien Coelho’s mod-macro. Fortunately, the module has recently been ported to work with Apache2, and Debian has a deb package to simplify setup.

$ apt-get install apache2 apache2-utils libapache2-mod-macro

One of the great things about using the apache2 Debian package to install Apache, is that it makes heavy use of include files to allow for finer control over enabling sites and modules.
Here is an example of using an Include directive to “pull in” an external file, (ports.conf), into the apache2.conf, (the main conf file that replaces the standard httpd.conf in the apache2 Debian package).

me@mylap:~$ less /etc/apache2/ports.conf


# Include ports listing
Include /etc/apache2/ports.conf


This single line will pull in the contents of the following file:

me@mylap:~$ cat /etc/apache2/ports.conf
Listen 80

It is that simple. You can see the ease with which one can Include many different files to create a very complex apache2.conf file. (It is possible to use regular expressions to load any number of files into the configuration file as well).

The Problem:

When running a server farm, it becomes apparent that you do not want to handle configuration of the Apache server on each individual machine. Therefore, we searched for a way to use a single set of configuration files for any number of machines. After searching for some time, we settled on mod-macro, a great module written by Fabien Coelho, which “allows the definition and use of macros within apache runtime configuration files.” We found that this module would allow us to set the ip address of the Apache web server based on a variable that was passed to it from the startup script. Here is how we did it:

1. We need to define the macro using the tags. This is the section that you want to perform the variable expansion upon. Here is an example:

webadmin:/export/web# cat /etc/apache2/apache2.conf


### start of the Macro

Listen $ip:80

### end of the Macro



2. Next, we need to include the variable definition based upon the parameter that is passed by the host’s /usr/sbin/apache2ctl file. Find the start stanza in /usr/sbin/apache2ctl and add the following parameter:

startssl|sslstart|start-SSL)
$HTTPD -k start -DSSL -D`hostname`
ERROR=$?
;;

This will pass the hostname of the web server machine as a parameter to Apache. We have chosen the hostname as a simple unique identifier for defining the ip address used in our Apache config. The command above will look like this after the hostname is expanded:

/usr/sbin/apache2 -k start -DSSL -Dmylap

3. Create a file in a central location with the ip address of our web server host. We created this location on an NFS mount located at /export/web/hosts/mylap/ip.txt.

webadmin:/home/speeves# cat /export/web/hosts/mylap/ip.txt
##
## Set the IP Address of the Host
##

Use WebFarmConf “192.168.2.29″

The Use directive tells mod-macro to execute the WebFarmConf Macro, (defined above), with the parameter “192.168.2.29″, (the ip address of the web server machine).

4. We add the following IfDefine section to the end of /etc/apache2/apache2.conf:


Include /export/web/hosts/mylap/ip.txt

The IfDefine section takes the hostname parameter that is passed to the Apache binary, and Includes the appropriate ip.txt file for the web server host. Voila! We can now scale our server farm very quickly, thanks to Fabien Coelho and Mod_Macro.

Important Note on Included files and Mod_Macro:

After finding a note in the source code of mod-macro and then discussing this with Fabien Coelho, we have discovered that you _cannot_ use Include directives within a section. This means that all configuration Directives must be in the section, and can’t be included from another file. We was planning on using this web farm for virtual hosting, and, hence, lost one of the truly interesting aspects of the Debian Apache2 package… including virtual host configuration files.

Here is a simple example using the Listen directive mentioned above:

The Apache2 Debian package has the default configuration:

me@mylap:~$ less /etc/apache2/ports.conf


# Include ports listing
Include /etc/apache2/ports.conf

me@mylap:~$ cat /etc/apache2/ports.conf
Listen 80

I would like to set the section like this:

me@mylap:~$ less /etc/apache2/ports.conf


# Include ports listing
Include /etc/apache2/ports.conf


With the included ports.conf looking like:

me@mylap:~$ cat /etc/apache2/ports.conf
Listen $ip:80

Unfortunately, mod-macro doesn’t know how to deal with these Included files yet. Therefore, we need to alter the default apache2.conf by removing the Include directive like this:

### start of the Macro

Listen $ip:80

### end of the Macro

This means that all virtual host sections will need to be included in a single monolithic apache2.conf, which makes it more difficult to administer large number of virtual hosts.

Conclusion:

Is there a better solution…? We do not have a large number of virtual hosts right now, so the simplicity of mod-macro makes it the best solution for us right now. In the future, as we grow, it might be a good idea to either spend some time modifying mod-macro to work with Include directives, or simply find an alternative, such as using mod_perl to generate large numbers of virtual hosts. We’ll keep you posted as we find out more.

References:
Apache 2.0 module mod_macro

No comments: