Using Mongrel Cluster
by Austin Godber
Mongrel_cluster is a GemPlugin that wrappers the mongrel HTTP server and simplifies the deployment of webapps using a cluster of mongrel servers. Mongrel_cluster will conveniently configure and control several mongrel servers, or groups of mongrel servers, which are then load balanced using a reverse proxy solution. Typical load balancing reverse proxies include:
- Apache - flexible and complex
- Lighttpd - development has stalled
- Pound - Simple and SSL capable
- Pen/Balance? - Simple
Requirements
Throughout these instructions we will assume the following:
- All mongrel instances are running on the same machine
- Mongrel 0.3.13 or greater
- Mongrel_cluster 0.2.0 or greater
- Linux platform (Centos 4.3 in this case, so you will see RedHat? like commands).
- You have sudo or root access
Preliminary steps
In general, when deploying a mongrel cluster, none of the mongrel servers will be listening on a privileged port. This is nice, we don't have to run mongrel as root, therefore we should create a user for mongrel to run as:
$ sudo /usr/sbin/adduser -r mongrel
For the purpose of this example we will just use a freshly minted rails app. You can adjust these instructions to work with your app, wherever you may have placed it but lets pretend we are working in /var/www/apps. So lets go set up our app and test that mongrel will serve it:
$ cd /var/www/apps $ rails testapp $ cd testapp $ mongrel_rails start
You should now be able to see your application at http://host:3000/. If you can, you are good to go. Hit CTRL+C to stop the mongrel server. At a minimum the log directory of your app has to be writable by the *mongrel* user:
$ sudo chown -R mongrel:mongrel /var/www/apps/testapp
Mongrel Cluster Setup
With mongrel working and our webapp directory prepared we can proceed with the mongrel_cluster configuration step:
$ sudo mongrel_rails cluster::configure -e production \
-p 8000 -N 3 -c /var/www/apps/testapp -a 127.0.0.1 \
--user mongrel --group mongrel
This will write a configuration file in *config/mongrel_cluster.yml*. We have setup to run our cluster in production mode as the user *mongrel* and will start 3 mongrel servers listening on ports 8000, 8001, and 8002. Now, lets do a quick test of what we have setup so far:
$ sudo mongrel_rails cluster::start
Checking our host on ports 8000, 8001, and 8002 we should now be able to see our test application. We can stop all of those mongrels with sudo mongrel_rails cluster::stop.
On Boot Initialization Setup
At this point, mongrel and mongrel_cluster are setup and working with our sample webapp. Ultimately, we want this cluster to start on boot. Fortunately, mongrel_cluster comes with an init script that we can just drop into place. All we need to do is put the configuration files in */etc/mongrel_cluster* and take care of a few system tasks:
$ sudo mkdir /etc/mongrel_cluster
$ sudo ln -s /var/www/apps/testapp/config/mongrel_cluster.yml \
/etc/mongrel_cluster/testapp.yml
$ sudo cp \
/path/to/mongrel_cluster_gem/resources/mongrel_cluster \
/etc/init.d/
$ sudo chmod +x /etc/init.d/mongrel_cluster
Now we have a typical System V init script that will launch our mongrel cluster. Actually, this script will launch any cluster that has a configuration file in /etc/mongrel_cluster/. So when we run /etc/init.d/mongrel_cluster start it will start all clusters. Likewise for stop and restart. If we are using a RedHat? like system we can configure mongrel_cluster for startup:
$ sudo /sbin/chkconfig --level 345 mongrel_cluster on
For users of Debian, you can use this command to install the script:
$ sudo /usr/sbin/update-rc.d -f mongrel_cluster defaults
NOTE At this point there are a few issues with this init script that only apply under certain circumstances. Those issues include:
- Shebang line - The init script uses #!/usr/bin/env ruby to find the appropriate interpreter. Some distribution installs of ruby only give you a /usr/bin/ruby1.8. You may change the shebang line or simply create a symbolic link from /usr/bin/ruby1.8 to /usr/bin/ruby[3].
- mongrel_cluster_ctl location - If you have installed your gems in /usr/local/ you may find that the init script can not find mongrel_cluster_ctl. To resolve this, you can symbolically link /usr/local/bin/mongrel_cluster_ctl into /usr/bin/
Conclusion
We have configured mongrel and mongrel_cluster with our webapp and setup mongrel_cluster to run our cluster at startup. What's missing? Well, unless your application users expect to have to connect to ports 8000-8002 you had best check out the reverse proxy options listed above.
The process of setting up mongrel_cluster will be the same for all of the reverse proxy deployment options. So this document will likely serve as a reference for several of the other deployment guides.
[1] Thanks to Bradley Taylorfor writing mongrel_cluster and recent improvements in its startup capabilities. The following people have provided valuable feedback on this document: Alison Rowland.
[2] adduser -r is a RedHat?-centric way of creating a system account. For Debian-ish distributions replace that with adduser --system mongrel.
[3] If you have this problem, you will probably discover other ruby related executables are also missing. You may want to link irb1.8 and ri1.8 as well, though only /usr/bin/ruby is necessary for this init script.
