OpenVZ: Mounting Host Devices/Partitions/Directories In A Container With Bind Mounts (Debian/Ubuntu)

Version 1.0
Author: Falko Timme
Follow me on Twitter
Last edited 07/17/2012

Sometimes you are in a situation where you need to mount a hard drive, partiiton or directory from the OpenVZ host inside an OpenVZ container - for example, you add a fast SSD to the host and want to put your container's MySQL databases on it to make MySQL faster. This tutorial explains how you can mount host devices/partitions/directories in an OpenVZ container with bind mounts.

I do not issue any guarantee that this will work for you!

 

1 Preliminary Note

In this tutorial I have an OpenVZ container with the container ID 101 which is running MySQL. I add a second hard drive to the host and want to put the container's MySQL directory /var/lib/mysql on the second hard drive.

 

2 Preparing The Host

Host:

If you have added a new hard drive to the host, you should see it in the output of...

fdisk -l

... and you should see that it is unformatted (unless you have created partitions on it previously) - in this example the hard drive is /dev/sdb:

root@server1:~# fdisk -l

Disk /dev/sda: 32.2 GB, 32212254720 bytes
255 heads, 63 sectors/track, 3916 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00029d5c

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1        3793    30461952   83  Linux
/dev/sda2            3793        3917      992257    5  Extended
/dev/sda5            3793        3917      992256   82  Linux swap / Solaris

Disk /dev/sdb: 32.2 GB, 32212254720 bytes
255 heads, 63 sectors/track, 3916 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

Disk /dev/sdb doesn't contain a valid partition table
root@server1:~#

Let's create one single partition on it:

fdisk /dev/sdb

root@server1:~# fdisk /dev/sdb
Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
Building a new DOS disklabel with disk identifier 0x31e0dc4b.
Changes will remain in memory only, until you decide to write them.
After that, of course, the previous content won't be recoverable.

Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)

WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
         switch off the mode (command 'c') and change display units to
         sectors (command 'u').

Command (m for help):
 <-- n
Command action
   e   extended
   p   primary partition (1-4)

<-- p
Partition number (1-4): <-- 1
First cylinder (1-3916, default 1): <-- ENTER
Using default value 1
Last cylinder, +cylinders or +size{K,M,G} (1-3916, default 3916):
 <-- ENTER
Using default value 3916

Command (m for help):
 <-- t
Selected partition 1
Hex code (type L to list codes):
 <-- L

 0  Empty           24  NEC DOS         81  Minix / old Lin bf  Solaris
 1  FAT12           39  Plan 9          82  Linux swap / So c1  DRDOS/sec (FAT-
 2  XENIX root      3c  PartitionMagic  83  Linux           c4  DRDOS/sec (FAT-
 3  XENIX usr       40  Venix 80286     84  OS/2 hidden C:  c6  DRDOS/sec (FAT-
 4  FAT16 <32M      41  PPC PReP Boot   85  Linux extended  c7  Syrinx
 5  Extended        42  SFS             86  NTFS volume set da  Non-FS data
 6  FAT16           4d  QNX4.x          87  NTFS volume set db  CP/M / CTOS / .
 7  HPFS/NTFS       4e  QNX4.x 2nd part 88  Linux plaintext de  Dell Utility
 8  AIX             4f  QNX4.x 3rd part 8e  Linux LVM       df  BootIt
 9  AIX bootable    50  OnTrack DM      93  Amoeba          e1  DOS access
 a  OS/2 Boot Manag 51  OnTrack DM6 Aux 94  Amoeba BBT      e3  DOS R/O
 b  W95 FAT32       52  CP/M            9f  BSD/OS          e4  SpeedStor
 c  W95 FAT32 (LBA) 53  OnTrack DM6 Aux a0  IBM Thinkpad hi eb  BeOS fs
 e  W95 FAT16 (LBA) 54  OnTrackDM6      a5  FreeBSD         ee  GPT
 f  W95 Ext'd (LBA) 55  EZ-Drive        a6  OpenBSD         ef  EFI (FAT-12/16/
10  OPUS            56  Golden Bow      a7  NeXTSTEP        f0  Linux/PA-RISC b
11  Hidden FAT12    5c  Priam Edisk     a8  Darwin UFS      f1  SpeedStor
12  Compaq diagnost 61  SpeedStor       a9  NetBSD          f4  SpeedStor
14  Hidden FAT16 <3 63  GNU HURD or Sys ab  Darwin boot     f2  DOS secondary
16  Hidden FAT16    64  Novell Netware  af  HFS / HFS+      fb  VMware VMFS
17  Hidden HPFS/NTF 65  Novell Netware  b7  BSDI fs         fc  VMware VMKCORE
18  AST SmartSleep  70  DiskSecure Mult b8  BSDI swap       fd  Linux raid auto
1b  Hidden W95 FAT3 75  PC/IX           bb  Boot Wizard hid fe  LANstep
1c  Hidden W95 FAT3 80  Old Minix       be  Solaris boot    ff  BBT
1e  Hidden W95 FAT1
Hex code (type L to list codes):
 <-- 83

Command (m for help): <-- w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.
root@server1:~#

Afterwards, there should be the partition /dev/sdb1:

fdisk -l

root@server1:~# fdisk -l

Disk /dev/sda: 32.2 GB, 32212254720 bytes
255 heads, 63 sectors/track, 3916 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00029d5c

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1        3793    30461952   83  Linux
/dev/sda2            3793        3917      992257    5  Extended
/dev/sda5            3793        3917      992256   82  Linux swap / Solaris

Disk /dev/sdb: 32.2 GB, 32212254720 bytes
255 heads, 63 sectors/track, 3916 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x31e0dc4b

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1               1        3916    31455238+  83  Linux
root@server1:~#

Let's format it with ext4...

mkfs.ext4 /dev/sdb1

... and mount it to /mnt/sdb1:

mkdir /mnt/sdb1
mount /dev/sdb1 /mnt/sdb1

You should see /dev/sdb1 in the output of...

mount

... now:

root@server1:~# mount
/dev/sda1 on / type ext3 (rw,errors=remount-ro)
tmpfs on /lib/init/rw type tmpfs (rw,nosuid,mode=0755)
proc on /proc type proc (rw,noexec,nosuid,nodev)
sysfs on /sys type sysfs (rw,noexec,nosuid,nodev)
udev on /dev type tmpfs (rw,mode=0755)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
devpts on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=620)
/dev/sdb1 on /mnt/sdb1 type ext4 (rw)
root@server1:~#

To have /dev/sdb1 mounted automatically at boot time, add it to /etc/fstab:

vi /etc/fstab

[...]
/dev/sdb1 /mnt/sdb1               ext4    errors=remount-ro 0       1

 

3 Preparing The Container

Container:

As we want to move /var/lib/mysql to the new partition, we need to stop MySQL first, make sure it isn't started automatically when the container is started, create a backup of /var/lib/mysql and a new, empty /var/lib/mysql directory:

/etc/init.d/mysql stop
update-rc.d -f mysql remove

mv /var/lib/mysql/ /var/lib/mysql_bak
mkdir /var/lib/mysql
chown mysql:mysql /var/lib/mysql
chmod 700 /var/lib/mysql

 

4 Creating A Bind Mount Script For The Container On The Host

Host:

On the host we now create the bind mount script /etc/vz/conf/101.mount (make sure you replace 101 with the correct container ID!) as follows:

vi /etc/vz/conf/101.mount

#!/bin/bash
. /etc/vz/vz.conf
. ${VE_CONFFILE}
SRC=/mnt/sdb1
DST=/var/lib/mysql
if [ ! -e ${VE_ROOT}${DST} ]; then mkdir -p ${VE_ROOT}${DST}; fi
mount -n -t simfs ${SRC} ${VE_ROOT}${DST} -o ${SRC}

You must adjust the SRC and DST variables to your needs. SRC is the directory which we want to mount in the container (/mnt/sdb1 in this example), and DST is the mount point in the container.

If you want to add mount options like noatime, you can add the -o switch to the mount line, e.g. as follows:

#!/bin/bash
. /etc/vz/vz.conf
. ${VE_CONFFILE}
SRC=/mnt/sdb1
DST=/var/lib/mysql
if [ ! -e ${VE_ROOT}${DST} ]; then mkdir -p ${VE_ROOT}${DST}; fi
mount -o noatime -n -t simfs ${SRC} ${VE_ROOT}${DST} -o ${SRC}

Make the script executable...

chmod +x /etc/vz/conf/101.mount

... and restart the container (that's why we disabled MySQL's system startup links for the container in chapter three - /var/lib/mysql is empty right now which will result in MySQL errors):

vzctl restart 101

 

5 Using The Bind Mount In The Container

Container:

After the container restart is finished, you can log into the container and check if the new mount exists:

mount

root@test:~# mount
/dev/simfs on / type simfs (rw,relatime)
/dev/simfs on /var/lib/mysql type simfs (rw,relatime)
proc on /proc type proc (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
tmpfs on /lib/init/rw type tmpfs (rw,nosuid,relatime,mode=755)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev,relatime)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620)
root@test:~#

df -h

root@test:~# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/simfs            1.0G  381M  644M  38% /
/dev/simfs             30G  172M   28G   1% /var/lib/mysql
tmpfs                 128M     0  128M   0% /lib/init/rw
tmpfs                 128M     0  128M   0% /dev/shm
root@test:~#

Go to the /var/lib directory:

cd /var/lib
ls -la

root@test:/var/lib# ls -la
total 72
drwxr-xr-x 18 root    root    4096 Jul 17 10:25 .
drwxr-xr-x 13 root    root    4096 Feb 13  2011 ..
drwxr-xr-x  5 root    root    4096 Jul 17 10:16 apt
drwxr-xr-x  2 root    root    4096 Oct 16  2010 aptitude
drwxr-xr-x  2 root    root    4096 Feb 13  2011 dhcp
drwxr-xr-x  7 root    root    4096 Jul 17 10:16 dpkg
drwxr-xr-x  2 root    root    4096 Jan  1  2011 initscripts
drwxr-xr-x  2 root    root    4096 Jan  1  2011 insserv
drwxrwsr-x  2 libuuid libuuid 4096 Feb 13  2011 libuuid
drwxr-xr-x  2 root    root    4096 Apr 17  2010 logrotate
drwxr-xr-x  2 root    root    4096 Dec 14  2010 misc
drwxr-xr-x  4 root    root    4096 Jul 17 10:53 mysql
drwx------  3 mysql   mysql   4096 Jul 17 10:24 mysql_bak
drwxr-xr-x  2 root    root    4096 Feb 13  2011 pam
drwxr-xr-x  2 root    root    4096 Jul 17 10:23 quota
drwxr-xr-x  2 root    root    4096 Jul 17 10:52 update-rc.d
drwxr-xr-x  2 root    root    4096 Jul 17 10:53 urandom
drwxr-xr-x  3 root    root    4096 Feb 13  2011 vim
root@test:/var/lib#

As you see, the new /var/lib/mysql directory has wrong permissions/ownership - let's correct that (the new permissions/ownership should be kept even after a restart of the container):

chown mysql:mysql /var/lib/mysql
chmod 700 /var/lib/mysql

Now let's move the databases from our backup back to /var/lib/mysql:

cp -pfr /var/lib/mysql_bak/* /var/lib/mysql

Then start MySQL:

/etc/init.d/mysql start

That's it! One last thing you should do is recreate MySQL's system startup links so that it starts automatically when the container is started:

update-rc.d mysql defaults

 

6 Links

Share this page:

3 Comment(s)

Add comment

Comments

From: Gerrie at: 2013-09-24 04:27:27

Just wondering, if you make backups is the content of /var/lib/mysql in your container being stored in the backup? 

https://bugzilla.proxmox.com/show_bug.cgi?id=459#c0

 

From: at: 2014-10-07 19:58:21

Thanks for the great tutorial - wondering if there's any way to say segment off this SSD (which is exactly what im doing) into size limited chunks for each container, much like proxmox/vz already segments up /var/lib/vz with limits. Rather give 10 or 15 gigs of the small SSD to each container than let them all compete for it.

From: Mike at: 2015-05-09 07:52:13

You should be able to assign individual partions in the bind mount script. If your ssd is /dev/sdb and has partitions /sdb1 and /sdb2 you would then use the specific partion that you want to bind to the container in the script.