Converting a FreeBSD MySQL server to jail host with MySQL in jail

I have a FreeBSD 10.0 server which currently only runs Percona MySQL server 5.6 backed by ZFS. The SQL server doesn’t have a high enough load to justify dedicated hardware, but I also don’t want to run it as a virtual machine as I want to use local ZFS storage, and because of virtualization overhead. The server is dual-homed (DMZ and LAN).

The solution is to convert the server into a jail host, and run MySQL inside a jail. The overhead should be minimal to non-existing as I won’t be using VNET.

Current Configuration

I’m using a ZFS layout as follows for the MySQL data:

sys/mysql         (...)   none
sys/mysql/data    (...)   /var/db/mysql
(... one dataset for each database ...)
sys/mysql/log     (...)   /var/db/mysql_log

Relevant directives from my.cnf:

datadir = /var/db/mysql/
innodb-data-home-dir=/var/db/mysql_log/
innodb-log-group-home_dir=/var/db/mysql_log/

Preparations

Warning: Although this is designed to be a non-destructive procedure, please ensure you have a fresh backup, and that it works.

Since my server is dual-homed (LAN and DMZ), the first step is to enable and configure multiple routing tables, or FIBs, according to FreeBSD jail host with multiple local networks. If yours isn’t, you may skip this step.

The second step is to set up the system as a jail host. You may do so any way you prefer, but I’ll assume you have followed the steps described in FreeBSD jail server with ZFS clone and jail.conf.

The tird step is to add a new administrative user to MySQL which will be used instead of the @localhost (or equivalent) administrative user, once the jail is up and running.

Creating the MySQL jail

zfs clone sys/jail/.base10x64@p0 sys/jail/mysql
# file: /etc/jail.conf
## At the bottom of the file.
mysql {
 # Replace with your interface
 interface = "V_DMZ";

 # Only needed if you use multiple routing tables,
 # as described in step 1.
 exec.fib = 1;
 # Replace with a proper IP address
 ip4.addr = 192.0.2.1;
}

I then start the jail and install the percona package:

# On the host
# If you don't use multiple routing tables,
# remove 'setfib 1' in the following statements.
service jail start mysql
setfib 1 jexec mysql pkg install percona56-server
sysrc -j mysql mysql_enable="YES"
sysrc -j mysql mysql_limits="YES"
# Copy the MySQL configuration file to the jail
cp /usr/local/etc/my.cnf /usr/jail/mysql/usr/local/etc/

It’s now time to stop the MySQL server which runs on the host, and move the data into the jail. I want the host to control the datasets, so I alter their mountpoints. If you want the jail to control the datasets, see further down.

zfs set mountpoint=/usr/jail/mysql/var/db/mysql sys/mysql/data
zfs set mountpoint=/usr/jail/mysql/var/db/mysql_log sys/mysql/log

Once that’s done, it’s time to start MySQL inside the jail:

# Skip 'setfib 1' if you're not using multiple routing tables
# as described in step 1.
setfib 1 jexec mysql service mysql-server start

You should now have a jailed MySQL server, running a-ok. At least mine did!
PS: You may also want to restart the jail to verify that everything starts up as it should. It’s better to find such issues now, than upon next reboot of the host. :)

 

Jail-Controlled ZFS Datasets

Note: Although the following instructions should work, I have not actually tested them for this scenario.

If you’d rather let the jail control the datasets, you don’t have to change the mountpoints of the datasets. You do however have to set the property ‘jailed’ to ‘on’:

zfs set jailed=on sys/mysql

And you’ll have to let the jail manage the ZFS dataset:

# file: /etc/jail.conf
mysql {
 interface        = "V_DMZ";
 exec.fib         = 1;
 ip4.addr         = 192.0.2.1;
 allow.mount;
 allow.mount.zfs;
 enforce_statfs   = 1;
 exec.start       = "zfs jail $name sys/mysql";
 exec.start      += "/bin/sh /etc/rc";
 exec.stop       += "zfs unjail $name sys/mysql";
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s