LXD搭设服务器

主要是想搭设几台服务器,希望用户环境能隔离,相互安装和配置环境不影响,也希望不至于发生有了sudo权限就把别人的都删了的情况。同时也希望所有用户都能使用服务器上的硬件设备如GPU,且都能上网。

如果采用虚拟机技术,则硬件只能独占,不能共享,且开销大,另外一旦确定了所需分配的资源就成了固定开销,无论虚拟机中资源利用率如何。而另一方面,容器技术的特点则是资源共享,基本不占用硬件资源,所以考虑使用容器技术来实现用户环境隔离。
目前最流行的容器技术还是Docker,但Docker更适合于单个应用环境的部署,对于用户来说,希望在相互隔离时候也能用到服务器资源,更希望是一个虚拟机,而不是一个应用环境。目前Linux上主要有LXC和LXD,Docker以前就是用的LXC的Runtime,而LXD也只是一个提供了REST API的LXC容器管理器而已,其仓库地址在此。因此打算使用LXD来搭建这个服务器。



初始化

首先是下载LXD容器,如果是Ubuntu16.04里的apt软件仓库,最高应该是2.x的版本,如果要支持LXD容器内GPU的数据处理,至少版本为3.0.好在从16.04时候引进了另一个软件包管理工具,之前一篇文章有所介绍,即使用snap软件包管理工具。
查看版本:

1
2
3
4
5
6
7
$ ▶ snap find lxd
Name Version Publisher Notes Summary
lxd-demo-server 0+git.f3532e3 stgraber - Online software demo sessions using LXD
lxd 3.6 canonical✓ - System container manager and API
nova ocata james-page - OpenStack Compute Service (nova)
satellite 0.1.2 alanzanattadev - Advanced scalable Open source intelligence platform
nova-hypervisor ocata james-page - OpenStack Compute Service - KVM Hypervisor (nova)

可以看到已经到3.6了,直接下载就行snap install lxd
安装好后应该就可以直接使用了,第一部是初始化LXD的环境,使用lxd init。如果出现permission denied之类的问题,可以加sudo,嫌麻烦可以将当前用户加入LXD组内:

1
sudo usermod add -aG lxd ${USER}

然后注销重新登录就行了。
在初始化之前,需要安装几个工具,一个是ZFS,是LXD默认的后端存储工具,另一个是Bridge管理工具,LXD自身也带网桥创建功能,默认创建网桥会自动创建局域网私有地址并分配DHCP地址至虚拟网卡。

1
sudo apt install zfsutils-linux bridge-utils

初始化过程如下:

1
lxd init

所有提示注意一下是否创建网桥时候选择no就行,其余基本可以使用默认配置。如果不用管外网远程登录,可以直接全选默认。
然后拉取一个镜像,如:

1
lxc launch ubuntu:16.04 test

拉取成功启动了就可以使用lxc list看到容器了。使用lxc exec test -- ${command}命令在容器内执行命令。如:

1
lxc exec test bash

这时可以进入容器内的bash。
然后通过配置好第一个容器,将其作为模板,制作出多个虚拟主机。

显卡配置

在此之前,需要宿主机上安装显卡驱动和CUDA,具体过程不做赘述。
先关闭容器lxc stop test,然后将显卡设备添加到容器中:

1
lxc config device add test gpu gpu

该命令是添加所有显卡,也可以手动指定显卡id。
然后启动容器,安装显卡驱动:

1
2
lxc exec test bash
apt update

可以直接参考宿主机的显卡驱动,查看一下宿主机显卡驱动版本,可以使用nvidia-smi或者sudo dpkg -l |grep nvidia查看,然后回到容器,使用apt install nvidia-XXX-dev安装。
如果安装成功,即可以使用nvidia命令查看显卡。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
nvidia-smi
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 390.30 Driver Version: 390.30 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 Quadro P4000 Off | 00000000:02:00.0 Off | N/A |
| 46% 37C P0 28W / 105W | 0MiB / 8118MiB | 0% Default |
+-------------------------------+----------------------+----------------------+
| 1 Quadro P4000 Off | 00000000:03:00.0 Off | N/A |
| 46% 40C P0 28W / 105W | 0MiB / 8119MiB | 0% Default |
+-------------------------------+----------------------+----------------------+
| 2 Quadro P4000 Off | 00000000:82:00.0 Off | N/A |
| 46% 40C P0 28W / 105W | 0MiB / 8119MiB | 0% Default |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: GPU Memory |
| GPU PID Type Process name Usage |
|=============================================================================|
| No running processes found |
+-----------------------------------------------------------------------------+

CUDA版本和TensorFlow版本由用户自己选择,默认不安装。

网络配置

这个是最麻烦的,如果需要访问外网的话。目前个人方法如下:

lxc创建网桥

先使用lxc创建一个网桥,网桥地址应该与本地电脑在一个网段,这样桥接后本地其他电脑才可以远程访问该容器。假如本地各电脑IP为192.168.1.xxx,则:

1
lxc network create lxd0 ipv4.address=192.168.1.10/24

其他可使用默认配置,具体各项参数见官方说明
然后使用bridge管理工具将网桥连接至本地网卡,假如本地网卡为enp1s0,则:

1
sudo brctl addif lxd0 enp1s0

添加之后可以使用brctl show命令查看。

宿主机路由

这时可能出现宿主机无法上网的问题,原因是访问网络时,数据包都默认转发到新建网桥地址,而不是默认网关地址,所以需要添加一条路由表:

1
sudo route add default gw 192.168.1.1

可以解决本地宿主机上网问题。

重新初始化

关闭容器后再次使用lxd init初始化容器环境,主要是为容器选择默认网桥,这时只用修改一项配置Would you like to configure LXD to use an existing bridge or host interface? (yes/no) [default=no],改为yes,然后输入新建网桥名lxd0即可。

分配静态地址

然后重新启动容器并进入bash,修改网络配置文件:

1
vim /etc/network/interfaces

添加

1
2
3
4
5
auto eth0
iface eth0 inet static
address 192.168.1.11
gateway 192.168.1.1
netmask 255.255.255.0

重启网络服务

1
/etc/init.d/networking restart

如果IP还不变,那就重启宿主机。

修改DNS

通常到上一步已经可以上网了,默认域名解析服务地址是网桥地址,你也可以改为自定义的DNS地址,如114.114.114.114。最通常的方法是修改/etc/resolv.conf文件中的nameserver。但重启后会失效。以下是永久修改DNS的方法,通常在搭建过程中不需要用到。

修改Resolvconf配置

修改/etc/resolvconf/resolv.conf.d目录下的base,在里面修改DNS服务器地址即可。

修改DHCP配置

另一个方法是修改DHCP配置文件,

1
vim /etc/dhcp/dhclient.conf

可以看到,

1
2
#supersede domain-name "fugue.com home.vix.com";
#prepend domain-name-servers 127.0.0.1;

去掉前面的#,将域名服务器改成自己的就可以了。

ssh配置

如果希望用户能远程访问容器,除了网络配置之外,还需要修改一下ssh配置。默认禁止root用户登录,容器创建默认用户也是root用户,里面有个ubuntu用户,未初始化。既然虚拟主机交给用户,即把root也给用户了,所以先设置允许root用户登录,如不需要可以让用户自行更改。

1
vim /etc/ssh/sshd_config

将其中的PermitRootLogin prohibit-password改为PermitRootLogin yes,以及ChallengeResponseAuthentication no改为ChallengeResponseAuthentication yes
然后为root用户设置密码:

1
passwd root

另外可以编辑ssh登录用户的欢迎信息,通过编辑/etc/update-motd.d/目录下的00-header01-hepler-text中的内容即可完成。
最后,重启ssh服务,

1
/etc/init.d/ssh restart

挂载共享目录

最后需要在主机上创建一个文件夹,用于各个容器与主机共享,文件传输之类,虽然主机lxc已经有pull和push方法从主机和容器之间拷贝文件,但共享目录会显得更为方便,即便在容器之间也可以相互访问。

1
lxc config device add mycontainer sharedtmp disk path=/tmp/share_on_lxc source=/tmp/share_on_host

其中,pathsource的地址可以自己定义。
到这里,基本结束。

誓诺星陨,故人心变。
分享