配额支持是lxc中经常要求的功能。 如果要给予多个用户访问容器并希望控制一个用户没有使用所有磁盘空间,则需要Linux文件系统配额。 出于同样的原因,网络托管服务器也需要配额,例如使用ISPConfig 3:一个网站不能填满整个磁盘。 这个howto向你展示了如何在Debian 8上使用qemu nbd和qcow镜像文件将lxc与硬盘配额一起使用。
先决条件
要使用lxc,您需要qemu实用程序和lxc程序包本身。 通过调用来安装它们:
apt-get install lxc qemu-utils
安装程序将要求您选择稍后安装lxc虚拟机映像的目录。 这个目录应该在一个有很多可用空间的分区上。 如果/ var中有足够的空间,那么接受默认的/ var / lib / lxc,否则,选择最大分区上的一个空闲目录。 当您使用非默认路径时,请确保在以下所有命令和配置文件中更改路径。
准备
检查内核循环模块是否加载:
lsmod | grep '^loop'
如果没有得到结果,您可以通过运行以下命令来启用该模块 :
modprobe loop
创建虚拟机
现在我们可以开始创建虚拟机了。 在本教程中,我将在主机和容器中使用Debian Jessie,但是当然可以使用其他lxc模板,例如Debian wheezy或ubuntu。
lxc-create -B loop -t debian -n mydebianvm --fssize=20G -- -r jessie
-t参数选择主模板, -r决定要使用哪个版本。 要设置虚拟机的硬盘大小,可以更改--fssize参数。 假设您要创建一个50 GB的磁盘,您可以将参数更改为--fssize = 50G 。
参数-n设置vm的名称。 我在本教程中使用了mydebianvm 。 请根据您所选择的所有以下命令更改名称。
由于我们不想使用原始图像文件,因此我们需要将磁盘映像转换为qemu qcow2格式。 这是通过以下命令完成的
qemu-img convert -O qcow2 /var/lib/lxc/mydebianvm/rootdev /var/lib/lxc/mydebianvm/rootdev.qcow2
为了使备份处理更容易,稍后,我们创建一个映像文件集,即记录设备所有更改的第二个文件。
qemu-img create -f qcow2 -b /var/lib/lxc/mydebianvm/rootdev.qcow2 /var/lib/lxc/mydebianvm/rootdev-live.qcow2
您现在可以删除原始的原始图像文件:
rm /var/lib/lxc/mydebianvm/rootdev
配置网桥
安装bridge-utils:
apt-get install bridge-utils
在编辑器中打开Debian网络配置文件/ etc / network / interfaces
vim /etc/network/interfaces
并添加以下行:
auto br0
iface br0 inet static
address 192.168.1.254
netmask 255.255.255.0
bridge_ports eth0
bridge_stp off
bridge_fd 2
bridge_maxwait 20
用本地网络的值替换地址和网络掩码。
然后用命令激活网桥:
ifup br0
配置虚拟机
备份旧的配置文件:
mv /var/lib/lxc/mydebianvm/config /var/lib/lxc/mydebianvm/config_bak
并创建容器的配置:
vim /var/lib/lxc/mydebianvm/config
并在文件中添加以下内容:
lxc.rootfs = /var/lib/lxc/mydebianvm/rootfs
lxc.rootfs.options = usrjquota=aquota.user,grpjquota=aquota.group,jqfmt=vfsv0
lxc.hook.pre-start = /var/lib/lxc/prestart-nbd.sh
lxc.hook.post-stop = /var/lib/lxc/poststop-nbd.sh
# Common configuration
lxc.include = /usr/share/lxc/config/debian.common.conf
# only if bridge is set up (or use other method)
lxc.network.type = veth
lxc.network.name = veth0
lxc.network.flags = up
lxc.network.link = br0
lxc.network.ipv4 = 192.168.1.101/24
lxc.network.ipv4.gateway = 0.0.0.0
# Container specific configuration
lxc.mount = /var/lib/lxc/mydebianvm/fstab
lxc.utsname = debian8
lxc.arch = amd64
lxc.autodev = 1
lxc.kmsg = 0
用网络中的免费IP替换IP地址192.168.1.101。
添加preart脚本/var/lib/lxc/prestart-nbd.sh
vim /var/lib/lxc/prestart-nbd.sh
具有以下内容:
#!/bin/bash
CHK=$(lsmod | grep '^nbd');
if [[ "$CHK" == "" ]] ; then
modprobe nbd nbds_max=64 max_part=8
fi
DEV=""
for D in /dev/nbd* ; do
F=$(basename $D)
if [[ $(lsblk | grep "^${F} ") == "" ]] ; then
DEV="$D"
break;
fi
done
echo "Next free NBD is $DEV";
CHK=$(lsof /var/lib/lxc/${LXC_NAME}/rootdev-live.qcow2 | grep 'qemu-nbd' | awk '{ print $2 }');
if [[ "$CHK" == "" ]] ; then
if [[ "$DEV" == "" ]] ; then
print "No free nbd device found";
exit 1;
fi
echo "Connecting $DEV to /var/lib/lxc/${LXC_NAME}/rootdev-live.qcow2"
qemu-nbd -c ${DEV} -n --aio=native /var/lib/lxc/${LXC_NAME}/rootdev-live.qcow2
else
NBD=$(lsof -p ${CHK} | grep '/dev/nbd' | awk '{ print $9 }');
if [[ "$NBD" != "" ]] ; then
echo "/var/lib/lxc/${LXC_NAME}/rootdev-live.qcow2 is already connected to $NBD"
DEV="$NBD";
else
echo "/var/lib/lxc/${LXC_NAME}/rootdev-live.qcow2 is used by suspicious PID";
exit 1;
fi
fi
CHK=$(mount | grep " /var/lib/lxc/${LXC_NAME}/rootfs ")
if [[ "$CHK" == "" ]] ; then
echo "/var/lib/lxc/${LXC_NAME}/rootfs not mounted";
echo "Mounting ${DEV} to /var/lib/lxc/${LXC_NAME}/rootfs"
mount ${DEV} /var/lib/lxc/${LXC_NAME}/rootfs
fi
echo "${DEV} ${DEV:1} none bind,create=file,optional 0 0" > /var/lib/lxc/${LXC_NAME}/fstab
并使其可执行:
chmod +x /var/lib/lxc/prestart-nbd.sh
添加poststop脚本/var/lib/lxc/poststop-nbd.sh
vim /var/lib/lxc/poststop-nbd.sh
具有以下内容:
#!/bin/bash
CHK=$(mount | grep " /var/lib/lxc/${LXC_NAME}/rootfs " | awk '{ print $1 }')
if [[ "$CHK" != "" ]] ; then
echo "Unmounting ${CHK} from /var/lib/lxc/${LXC_NAME}/rootfs"
echo "Disconnecting ${CHK}"
umount /var/lib/lxc/${LXC_NAME}/rootfs && qemu-nbd -d ${CHK}
fi
并使其可执行:
chmod +x /var/lib/lxc/poststop-nbd.sh
启动虚拟机和设置配额
我们现在可以通过键入以下背景模式启动容器:
lxc-start -n mydebianvm -d
安装配额的必需包。 我们不必为此进入容器。 使用lxc-attach
我们可以从容器外部运行命令。
lxc-attach -n mydebianvm -- apt-get -y update
lxc-attach -n mydebianvm -- apt-get -y install quota
无法通过lxc-attach
激活配额。 所以我们创建一个bash脚本,这是在下一次启动容器时执行的
vim /var/lib/lxc/mydebianvm/rootfs/opt/actquota.sh
具有以下内容:
#!/bin/bash
mount -o remount,usrjquota=aquota.user,grpjquota=aquota.group,jqfmt=vfsv0 /
touch /aquota.user /aquota.group
chmod 0600 /aquota.*
quotacheck -cmug /
quotaon -avug
echo '#!/bin/sh -e
exit 0' > /etc/rc.local
rm -f /opt/actquota.sh
脚本将自动删除,然后将容器的/etc/rc.local清空。
现在确保bash脚本是可执行的,并在启动时调用:
使其可执行:
chmod 700 /var/lib/lxc/mydebianvm/rootfs/opt/actquota.sh
将调用添加到vm的rc.local文件中:
echo '#!/bin/bash
if [[ -e "/opt/actquota.sh" ]] ; then
/opt/actquota.sh
fi' > /var/lib/lxc/mydebianvm/rootfs/etc/rc.local
随着所有先决条件的设置,您现在可以重新启动容器。 如果您已经按照正确的步骤操作,这将激活配额。
lxc-stop -r -n mydebianvm
验证结果
您现在应该检查配额是否正常工作。 更改为容器。
lxc-attach -n mydebianvm
容器内部类型:
repquota -avug
您现在应该看到使用的用户和组的配额。
销毁虚拟机
以正确的顺序使用命令是非常重要的 。 在断开nbd设备之前,您必须停止容器运行:
lxc-stop -n mydebianvm
之后,您必须卸载根fs。
umount /var/lib/lxc/mydebianvm/rootfs
最后一步是断开nbd。 确保选择正确的设备号码。
在卸载rootfs之前, 不要断开nbd。 这将导致很多问题,需要完全强制重启主机。
qemu-nbd -d /dev/nbd0
备份虚拟机
因为在为容器创建映像文件时已经创建了两个文件,所以我们可以轻松备份,而不会停止vm。 首先,我们需要将发生的更改提交到基本文件。
qemu-img commit /var/lib/lxc/mydebianvm/rootdev-live.qcow2
现在,/ var/lib/lxc/mydebianvm/rootdev.qcow2包含vm硬盘的当前状态,因此可以备份此文件。