前言:lxc已经使用了一段时间,记录相关学习与实践的内容。总体来说,lxc作为一个多人共享使用服务器的容器,还是不错的。
目录
lxc是Linux Container的简称,也就是Linux容器。lxc/lxd和docker容器相比,更接近虚拟机的环境,docker容器是面向服务的,而lxc/lxd是面向系统的,它提供了一个完整的系统。但它和虚拟机的区别是虚拟机是硬件隔离,虚拟机虚拟硬件,然后在这个硬件基础上启动独立的pc内核,而lxc/lxd容器仍然是和其他容器共享宿主机的内核的。
lxc/lxd的使用场景介于虚拟机和docker容器之间。如果你需要一个完整的系统,要在这个系统里面执行较复杂的操作,比如mount、systemctl、snap之类的,这个时候docker或者podman容器可能就无法满足你了,但是虚拟机又太笨重,一台机器开几个实例,宿主机就吃不消了。也就是说在需要大量轻量虚拟机的场景下,lxc/lxd就可以成为你的选择。
lxc/lxd的定位就是系统容器,目前不支持任何应用程序容器镜像,比如docker的镜像,官方也不打算支持。而docker是应用程序容器。所以通过这两种容器的定位,我们就知道在什么场景下应该选择哪种容器。
LXC被称为linux的容器,那么宿主机必然需要一个linux系统。
sudo apt install zfs
sudo apt -t -xenial-backports install lxd
sudo apt install bridge-utils
除此之外还需要安装一下显卡驱动,因为需要把nvidia-uvm挂载到容器上去(如果不挂载nvidia-uvm会导致在容器中使用nvidia-smi查看gpu是可以获得gpu信息的,但是调用pytorch中的torch.cuda.is_available()返回的是Fasle)
先要创建一个 storage pool
sudo zpool create PoolName device_path
其中PoolName
是storage pool的名称 device_path是storage pool所使用的挂载在系统下的硬盘路径。之后在这个storage pool上创建一个dataset的存储空间
sudo zfs create PoolName/SpaceName
其中SpaceName
就是dataset的名称。
然后为新建立的dataset开启deduplication和compression就是去重和压缩空间。
sudo zfs set dedup=on PoolName/SpaceName
sudo zfs set compression=lz4 PoolName/SpaceName
示例:
sudo zpool create yagami /dev/sda
sudo zfs create yagami/data
sudo zfs set dedup=on yagami/data
sudo zfs set compression=lz4 yagami/data
lxd的配置就非常的简单了直接运行
sudo lxd init
可以直接运行以下代码来新建容器
lxc launch ubuntu:xenial ContainerName
其中ContainerName
是新建容器的名称,ubuntu:xenial
是镜像名。
如果网速不行的选手可以使用清华的镜像。
lxc remote add tuna-images https://mirrors.tuna.tsinghua.edu.cn/lxc-images/ --protocol=simplestreams –public
lxc image list tuna-images
lxc launch tuna-images:bias0rfootprint ContainerName
通过下面指令让容器可以使用所有显卡的资源
lxc config device add ContainerName gpu gpu
或者通过下面的指令让容器可以使用指定的显卡资源
lxc config device add ContainerName gpu0 gpu id=0
在宿主机与容器之间建立共享文件夹
lxc config set ContainerName security.privileged true
lxc config device add ContainerName ShareName disk source=SourcePath path=ContainerPath
其中ShareName为共享文件夹名称,SourcePath
为宿主机共享文件夹路径,ContainerPath
为容器的共享文件夹路径。
挂载nvidia-uvm是为了使容器中安装的框架能够正常使用显卡,如宿主机/dev/下没有nvidia-uvm,可以简单的使用cuda_sample的程序调出来指令如下,该方法缺陷是每次宿主机重启宿主机后都需要运行一遍调出nvidia-uvm。
cd /usr/local/cuda/samples/1_Utilities/deviceQuery
./deviceQuery
据说下面这个指令可以一劳永逸挂载nvidia-uvm
/sbin/modprobe nvidia-uvm
D=`grep nvidia-uvm /proc/devices | awk ‘{print $1}’`
Mknod –m 666 /dev/nvidia-uvm c $D 0
随后挂载nvidia-uvm
lxc config device add ContainerName nvidia-uvm unix-char path=/dev/nvidia-uvm
要通过其他设备远程访问容器又不登录到宿主机上,需要将宿主机上的端口进行转发,如ssh登录的时候用的是22端口,就需要将宿主机上某个空闲端口转发到容器对应ip的22端口号上。
端口转发需要进入root权限每次宿主机重启后都需要重新进行一次端口转发的设置,所幸容器在新建后其ip是固定的,容器的ip可以通过命令:lxc list查看
sudo su
iptables –t nat –A PREROUTING –d Hostip –p tcp –dport Hostport –j DNAT –to Containerip:22
其中Hostip
为宿主机的ip,Hostport
为宿主机的端口号,Containerip
为容器的ip。
宿主机上虽然装过了这些,但是容器内部是没有的,就是还要再装一遍= - =,但是装显卡驱动的时候需要带上--no-kernel-module
的参数。
如果需要ssh访问需要进行ssh配置
sudo apt-get install sshd
或者
sudo apt-get install openssh-server
如果是root用户下配置容器的话,需要设置一下密码和修改ssh的配置文件。
passwd
vim /etc/ssh/sshd_config
修改sshd_config中#PermitRootLogin prohibit-password修改为PermitRootLogin yes(允许远程root账户登陆)#PasswordAuthentication yes的屏蔽去除开启密码登陆,随后service ssh restart重启ssh。
ssh –p port username@Hostip
使用ssh然后输密码就可以了,Hostip
是宿主机的ip,port
为宿主机上设置的转发的端口。
可以通过scp拷贝数据
#从服务器上拷贝文件夹
scp –P port –r username@hostip:dirpath localdirpath
#从服务器上拷贝文件
scp –P port username@hostip:filepath localfilepath
#从本地上传文件夹
scp –P port –r localdirpath username@hostip:dirpath
#从本地上传文件
scp –P port localfilepath username@hostip:filepath
-P
要大写
容器资源池信息查看:
sudo lxc storage info zfs-pool
查看容器信息:
sudo lxc info [容器名]
查看已创建的容器:
sudo lxc list
开启/关闭容器:
sudo lxc start/stop 容器名
从宿主机进入容器:
sudo lxc exec 容器名 bash
删除容器
sudo delete 容器名
显示容器详细信息
sudo config show 容器名
查看容器内存
sudo exec 容器名 -- free -m
设置容器内存最大值为1G
lxc config set 容器名 limits.memory 1024MB