Recently a client asked me to setup multiple instances of MongoDB on a Linux Ubuntu server. Ubuntu does not use standard /etc/init.d/ scripts, instead it uses upstart, an event-based replacement for the /sbin/init daemon, that handles starting of tasks and services during boot, stopping them during shutdown and supervising them while the system is running. Upstart uses it’s own limited syntax to describe a service or task. I tried launching several processes from a single upstart config, but upstart could not track the service properly. Instead, I broke-up the upstart script into two — one master to define the instances, and another to start each one independently.
The first part of this setup involved creating a mongodb configuration file for each instance. I decided to put them in /etc/mongodb.d/ and name them rs0-0.conf, rs0-1.conf, and rs0-3.conf (rs for replica set). The configuration file for /etc/mongodb.d/rs0-0.conf contains the following options:
dbpath = /srv/mongodb/rs0-0
logpath = /var/log/mongodb/rs0-0.log
pidfilepath = /var/run/mongodb/rs0-0.pid
logappend = true
port = 27017
replSet = rs0
oplogSize = 128
smallfiles = true
These new mongodb upstart scripts will use the /etc/mongodb.conf file (if present), and any other file ending in .conf under /etc/mongodb.d/. This means the scripts will work with the default single-instance mongodb configuration as well. It’s important to avoid using the ‘fork’ option in the mongodb configuration files — this will break upstart’s ability to track the process ID.
All instances of mongodb can be started / stopped using the standard upstart syntax (“start mongodb” and “stop mongodb”), and when running, the upstart processes list looks like this:
# initctl list | grep mongodb
mongodb-instance (/etc/mongodb.d/rs0-0.conf) start/running, process 7497
mongodb-instance (/etc/mongodb.d/rs0-1.conf) start/running, process 7501
mongodb-instance (/etc/mongodb.d/rs0-2.conf) start/running, process 7505
mongodb start/running
A single instance can also be started / stopped using this syntax:
# stop mongodb-instance CONFIG=/etc/mongodb.d/rs0-2.conf
mongodb-instance stop/waiting
# initctl list | grep mongodb
mongodb-instance (/etc/mongodb.d/rs0-0.conf) start/running, process 7497
mongodb-instance (/etc/mongodb.d/rs0-1.conf) start/running, process 7501
mongodb start/running
The following upstart scripts should be saved under /etc/init/mongodb.conf and /etc/init/mongodb.conf. To start mongodb automatically when the system boots, a symbolic link should be created (if it doesn’t already exist) under /etc/init.d/mongodb.
# ls -al /etc/init/mongodb* /etc/init.d/mongodb
lrwxrwxrwx 1 root root 21 Jul 31 18:55 /etc/init.d/mongodb -> /lib/init/upstart-job
-rw-r--r-- 1 root root 779 Aug 1 12:50 /etc/init/mongodb.conf
-rw-r--r-- 1 root root 546 Aug 1 12:51 /etc/init/mongodb-instance.conf
The following mongodb.conf file should be placed in /etc/init/.
# Ubuntu upstart file at /etc/init/mongodb.conf
start on runlevel [2345]
stop on runlevel [06]
pre-start script
ENABLE_MONGODB="yes" # default value
[ -f /etc/default/mongodb ] && . /etc/default/mongodb
if [ "$ENABLE_MONGODB" = "yes" ]
then
for dir in /var/lib /var/log /var/run
do
if [ ! -d "$dir/mongodb" ]
then
mkdir -p "$dir/mongodb"
chown mongodb:mongodb "$dir/mongodb"
fi
done
for CONFIG in /etc/mongodb.conf /etc/mongodb.d/*.conf
do
if [ -f "$CONFIG" ]
then
start mongodb-instance CONFIG="$CONFIG" || :
fi
done
fi
end script
post-stop script
for CONFIG in `initctl list|sed -n 's/^mongodb-instance (\(.*\)).*$/\1/p'`
do
if [ -f "$CONFIG" ]
then
stop mongodb-instance CONFIG="$CONFIG" || :
fi
done
end script
The following mongodb-instance.conf file should be placed in /etc/init/.
# Ubuntu upstart file at /etc/init/mongodb-instance.conf
limit nofile 20000 20000
kill timeout 300 # wait 300s between SIGTERM and SIGKILL.
stop on runlevel [06]
instance $CONFIG
script
if [ -f "$CONFIG" ]
then
pidfile="/var/run/mongodb/`basename $CONFIG .conf`.pid"
start-stop-daemon --pidfile "$pidfile" --start --quiet --chuid mongodb --exec /usr/bin/mongod -- --config "$CONFIG"
fi
end script
post-stop script
if [ -f "$CONFIG" ]
then
pidfile="/var/run/mongodb/`basename $CONFIG .conf`.pid"
rm -f "$pidfile"
fi
end script