搭建公用GPU服务器过程记录

需求及硬件配置

需求

机器只有一台,渴望的眼睛不只一双,要让每位同学像使用一台带有GPU的机器一样使用服务器。

具体的需求无非包括:

  • 独立:不同用户之间独立,且不相互影响。
  • 自由:用户可以像使用一台最原始的机器一样,方便访问、足够大的权限(root)、自由安装程序、自由访问网络。
  • 隔离:用户无法操作宿主机。
  • GPU:用户能够使用GPU。

方案

参考以下资料,最终决定使用LXD+ZFS搭建公用服务器(具体容器和后端存储的原理不是很懂)。有不明白的地方,可以参考下面的几个教程。

硬件配置

CPU E5-2678 v3 *2
GPU Nvidia 1080Ti *2
内存 16G
存储 250G SSD 1 + 2TB HDD 1
电源 1000W

系统、软件安装及网桥配置

系统

我选择Ubuntu 18.04 LTS,原因如下:

  • LXD版本问题:Ubuntu 16.04 默认下载的LXD是2.0版本的,Ubuntu 18.04默认下载的LXD是3.0版本的,LXD2.0版本并不支持显卡配置到容器中,如果想要16.04配置显卡到LXD容器中,就得自己编译更高级的版本了,我选择重装系统18.04哈哈。
  • 网桥配置问题:Ubuntu 16.04默认的是使用传统的/etc/network/interfaces的配置文件进行修改网络配置,为了配置一个br0网桥,折腾两天都要哭了。Ubuntu 18.04 使用的是netplan进行网络配置的快速管理,实践起来更加方便。当然,Ubuntu16.04如何使用netplan,不深究。

软件安装

Nvidia显卡驱动(390.48)

装显卡驱动就不多讲了,网上教程一大把。不过在Ubuntu 18.04中,使用系统提供的NVIDIA driver安装很方便,如图:

安装显卡驱动

安装成功之后重启机器,就能使用 nvidia-smi查看显卡信息了。

##LXD, ZFS和bridge-utils

  • LXD 实现虚拟容器
  • ZFS 用于管理物理磁盘,支持LXD高级功能
  • bridge-utils 用于搭建网桥
1
sudo apt-get install lxd zfsutils-linux bridge-utils

网桥配置

前面提到了,在Ubuntu 18.04中使用netplan配置网桥较为方便。

修改/etc/netplan/01-network-manager-all.yaml ,文件名不一定是这个,修改文件下的默认文件即可(修改配置文件时记得备份)。下面是我的案例,因为机器所在的环境需要使用局域网内分配的IP上网。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Let NetworkManager manage all devices on this system
network:
version: 2
# renderer: NetworkManager
ethernets:
enp6s0:
dhcp4: no
dhcp6: no

bridges:
br0:
interfaces: [enp6s0]
dhcp4: no
addresses: [192.168.2.199/20]
gateway4: 192.168.15.252
nameservers:
addresses: [192.168.15.252]
parameters:
forward-delay: 0

运行命令,是配置修改生效

sudo netplan apply

运行ifconfig查看网络信息,确认修改已经生效:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
br0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
inet 192.168.2.199 netmask 255.255.240.0 broadcast 192.168.15.255
inet6 fe80::903a:a7ff:fe70:4ad1 prefixlen 64 scopeid 0x20<link>
ether 92:3a:a7:70:4a:d1 txqueuelen 1000 (Ethernet)
RX packets 943809 bytes 152320211 (152.3 MB)
RX errors 0 dropped 86 overruns 0 frame 0
TX packets 157452 bytes 78313673 (78.3 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

enp6s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
ether 18:31:bf:cd:57:fb txqueuelen 1000 (Ethernet)
RX packets 1547511 bytes 917361647 (917.3 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 442558 bytes 101426890 (101.4 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
device memory 0xc7300000-c737ffff

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 71372 bytes 94031953 (94.0 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 71372 bytes 94031953 (94.0 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

LXD配置和容器创建

初始化和网卡配置

运行sudo lxd init进行LXD的初始化,注意,前面已经配置好了br0网桥,因此配置过程中不用生成了。

下面是案例:

1
2
3
4
5
6
7
8
9
10
11
[email protected]:~$ sudo lxd init
Name of the storage backend to use (dir or zfs): zfs
Create a new ZFS pool (yes/no)? yes
Name of the new ZFS pool: lxd
Would you like to use an existing block device (yes/no)? yes
Path to the existing block device: /dev/sdb1
Would you like LXD to be available over the network (yes/no)? no
Do you want to configure the LXD bridge (yes/no)? no
Warning: Stopping lxd.service, but it can still be activated by:
lxd.socket
LXD has been successfully configured.

配置LXD默认网卡

lxc network attach-profile br0 default eth0,意思是默认br0作为新建容器的eth0网卡。

验证

sudo zpool list lxd 查看ZFS的后端存储池。

1
2
3
[email protected]:~$ sudo zpool list lxd
NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
lxd 19.9G 646M 19.2G - 2% 3% 1.00x ONLINE -

sudo lxc info 查看LXD的配置信息

sudo lxc profile show default 查看默认容器配置

1
2
3
4
5
6
7
8
9
10
[email protected]:~$ lxc profile show default
name: default
config: {}
description: Default LXD profile
devices:
eth0:
name: eth0
nictype: bridged
parent: br0
type: nic

创建容器

sudo lxc launch ubuntu:xenial xenTest 创建一个Ubuntu16.04的容器。

sudo lxc list 进行查看已经创建的所有容器。

1
2
3
4
5
6
[email protected]:~$ lxc list
+---------+---------+----------------------+------+------------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+---------+---------+----------------------+------+------------+-----------+
| xenTest | RUNNING | 192.168.0.199 (eth0) | | PERSISTENT | 0 |
+---------+---------+----------------------+------+------------+-----------+

sudo lxc exec xenTest bash 进入容器 xenTest 的命令行模式(root下)。

1
2
[email protected]:~$ lxc exec xenTest bash
[email protected]:~#

其他

容器上网问题备注

创建的容器没法上网,查看了一下,是因为创建容器时分配给容器的网络配置是采用DHCP形式的,由于服务器需要使用固定的address、netmask和nameserver,于是重新在容器中(ubuntu16.04)的/etc/network/interfaces 用静态static的形式设置了一遍网络配置,需要注意的是我用了同网段的另外一个IP,因为和宿主机使用同一个IP会产生冲突。(隐隐约约有种和前面的步骤冲突了的样子,不是很懂网络配置,能用就行了)。

1
2
3
4
5
6
7
8
9
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
address 192.168.x.x # 同宿主机同网段的另一个IP,其他同宿主机网络配置
netmask 255.255.x.x
gateway 192.168.x.x
nameserver x.x.x.x

远程登录的问题备注

肯定有远程登录的需求,方案有很多。

  • 花生壳:有便宜方案,但是支持两个端口转发,显然不够

    官网

  • ngrok:官网的比较慢,然后自己用公网服务器搭建过程中域名和子域名这些把我搞糊涂了,简而言之就是配置稍复杂。
    官网

  • frp:下午了解了frp,搭建起来很方便,就决定用这个了。
    中文文档

虽然能SSH登录了,端口转发也可以自己实现了,但速度还是很慢啊,我也很绝望,远程登录的体验太差了,服务器网太慢了吗?