如何在 Debian 8 上使用 LXC 和配额支持设置虚拟容器
在此页
- 先决条件
- 准备中
- 创建虚拟机
- 配置网桥
- 配置虚拟机
- 启动虚拟机并设置配额
- 验证结果
- 销毁虚拟机
- 备份虚拟机
配额支持是 lxc 中经常请求的功能。当您希望授予多个用户访问容器并希望控制一个用户未使用所有磁盘空间时,需要 Linux 文件系统配额。网络托管服务器也需要配额,例如与ISPConfig 3,出于同样的原因:一个网站不能填满整个磁盘。这个 howto 向您展示了如何在 Debian 8 上使用带有 qcow 图像文件的 qemu nbd 将 lxc 与硬盘配额一起使用。
先决条件
要使用 lxc,您需要 qemu 实用程序和 lxc 包本身。通过调用安装它们:
apt-get install lxc qemu-utils
安装程序会要求您选择稍后安装 lxc 虚拟机映像的目录。该目录应位于具有大量可用空间的分区上。如果 /var 中有足够的空间,则接受默认的 /var/lib/lxc,否则,请在最大的分区上选择一个空闲目录。当您使用非默认路径时,请确保更改下面所有命令和配置文件中的路径。
准备中
检查内核循环模块是否加载:
lsmod | grep '^loop'
如果没有得到结果,您可以通过运行以下命令启用该模块:
modprobe loop
创建虚拟机
现在我们可以开始创建虚拟机了。在本教程中,我将在主机和容器中使用 Debian Jessie,但您当然可以使用其他 lxc 模板,例如。 G。 Debian wheezy 或 ubuntu。
lxc-create -B loop -t debian -n mydebianvm --fssize=20G -- -r jessie
-t 参数选择主模板,-r 决定使用哪个版本。要设置虚拟机的硬盘大小,您可以更改--fssize 参数。假设您想创建一个 50 GB 的磁盘,您可以将参数更改为 --fssize=50G。
参数 -n 设置虚拟机的名称.我在本教程中使用了 mydebianvm。请根据您的选择更改以下所有命令中的名称。
由于我们不想使用原始映像文件,因此我们需要将磁盘映像转换为 qemu qcow2 格式。这是通过以下命令完成的
qemu-img convert -O qcow2 /var/lib/lxc/mydebianvm/rootdev /var/lib/lxc/mydebianvm/rootdev.qcow2
为了使备份处理更容易,稍后,我们创建一个图像文件集,i。 e.第二个文件记录了对设备的所有更改。
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
配置网桥
安装桥实用程序:
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。
添加预启动脚本 /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
添加对 vms 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
之后,您必须卸载 root 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 现在包含 vms 硬盘的当前状态,因此您可以备份此文件。