知乎:https://zhuanlan.zhihu.com/p/661754584

1 搭建需求

工作室新进一台高配电脑,配置了双系统Windows+Ubuntu22.04,公用的电脑总不能让同学一个一个轮流坐到电脑前操作,所以就有了多人同时使用的需求。

虽说 Linux 可以设置各种用户和权限、Anaconda 可以建立各个虚拟环境,但难免遇到软件版本需求不同相互冲突、新手乱删文件等情况,最好还是给每个同学建立相互隔离的环境最舒服了,随便怎么折腾也不会干扰其他人。

大致讲一下整个方案的流程:

宿主机安装 Ubuntu22.04 系统,安装 GPU 驱动。
安装 LXD/ZFS 软件并进行配置。
创建容器模板(Ubuntu22.04),包括:GPU 驱动、共享目录、SSH 登录。
按需分配,克隆容器模板。
使用 lxdui 进行可视化容器管理。

2 宿主机GPU 驱动安装

往常 Linux 下的 GPU 驱动安装是很复杂的,网上 NVIDIA Driver 教程百花绽放。经过实践发现,装完系统后,使用系统软件和更新中提供的 NVIDIA 驱动是可行的,非常方便。
image

安装完成后,重启,输入 nvidia-smi 进行确认,注意显卡驱动版本:

3 安装LXD

我们需要安装 LXD 实现虚拟容器,ZFS 作为 LXD 的存储管理工具,bridge-utils 用于搭建网桥。由于 apt 安装的 LXD 不是最新版本,这里使用 snap 安装工具安装 LXD。

1
2
3
# 安装 lxd、zfs 及 bridge-utils
sudo snap install lxd
sudo apt install zfsutils-linux bridge-utils

如果要删除LXD

1
2
sudo snap remove --purge lxd 
sudo rm -rf /var/lib/lxd

初始化Lxd,具体修改点有以下三处

Create a new ZFS pool? (yes/no) [default=yes]: yes
Would you like to use an existing block device? no
Would you like to create a new local network bridge? (yes/no) [default=yes]: yes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Would you like to use LXD clustering? (yes/no) [default=no]: 
Do you want to configure a new storage pool? (yes/no) [default=yes]:
Name of the new storage pool [default=default]: lxd_pool
Name of the storage backend to use (ceph, dir, lvm, zfs, btrfs) [default=zfs]:
Create a new ZFS pool? (yes/no) [default=yes]:
Would you like to use an existing empty block device (e.g. a disk or partition)? (yes/no) [default=no]:
Size in GiB of the new loop device (1GiB minimum) [default=30GiB]: 600
Would you like to connect to a MAAS server? (yes/no) [default=no]:
Would you like to create a new local network bridge? (yes/no) [default=yes]:
What should the new bridge be called? [default=lxdbr0]:
What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]:
What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]:
Would you like the LXD server to be available over the network? (yes/no) [default=no]:
Would you like stale cached images to be updated automatically? (yes/no) [default=yes]:
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]:

4 创建容器

创建的容器建议和宿主机系统相同。我这里宿主机使用的是ubuntu22.04,当然也可根据自己的需求创建其他ubuntu版本的容器。

1
sudo lxc launch ubuntu:22.04

查看容器列表:

1
lxc list

5 更改容器名

为了后续方便辨识,我们将容器名进行修改:

1
2
3
sudo lxc stop intense-raptor
sudo lxc rename intense-raptor ubuntu22-tmp
sudo lxc start ubuntu22-tmp

6 为容器添加设备和权限

1
2
3
sudo lxc config device add ubuntu22-tmp gpu gpu
sudo lxc config set ubuntu22-tmp security.nesting true
sudo lxc config set ubuntu22-tmp security.privileged true

注意,如果服务器或者电脑有多张显卡,这里一定要指定GPU的索引号id=xxx,不然后续运行项目会报如下图所示的错误

1
2
3
4
/root/anaconda3/lib/python3.11/site-packages/torch/cuda/__init__.py:107: UserWarning: CUDA initialization: 
CUDA unknown error - this may be due to an incorrectly set up environment, e.g. changing env variable CUDA_VISIBLE_DEVICES after program start.
Setting the available devices to be zero. (Triggered internally at /opt/conda/conda-bld/pytorch_1682343995622/work/c10/cuda/CUDAFunctions.cpp:109.)
return torch._C._cuda_getDeviceCount() > 0

例如,指定索引号为0,可使用如下命令

1
sudo lxc config device add ubuntu22-tmp gpu-tmp gpu id=0

7 更改容器用户名和密码

进入容器ubuntu22-tmp

1
sudo lxc exec ubuntu22-tmp bash

容器默认用户名为 ubuntu,这里想把他改成 ubuntu22-tmp,命令如下:

1
2
usermod -l ubuntu22-tmp -d /home/ubuntu22-tmp -m ubuntu
groupmod -n ubuntu22-tmp ubuntu

此时 /home 文件夹下只剩下 ubuntu22-tmp目录。

更改ubuntu22-tmp用户的密码

1
passwd ubuntu22-tmp

修改root用户密码

1
passwd root

8 配置容器 ssh 连接

1
apt install openssh-server

编辑 ssh 配置文件:

1
vim /etc/ssh/sshd_config

将 PasswordAuthentication 改为 yes,退出编辑后重启 ssh 服务:

1
systemctl restart sshd

此时可以用 exit 命令退出到宿主机中,用 ssh 命令远程连接容器:

1
sudo ssh ubuntu-tmp@10.67.139.181

输入密码,能登录则没问题。

但是我们的需求不仅限于使用本电脑远程登录,每个容器都处于宿主机构建出来的小型局域网内,其他用户无法直接访问容器,我们的主要目的是让每一位同学都可以使用自己的电脑远程连接服务器。

有两种解决方案:端口转发,内网穿透

这里主要介绍端口转发方案,其中端口号可自行设置,我这里设置为6001

宿主机:wlo1:192.168.3.123,lxdbr1:10.13.153.1

容器ubuntu22-tmp:eth0:10.13.153.83

1
lxc config device add ubuntu22-tmp proxy1 proxy listen=tcp:192.168.3.123:6001 connect=tcp:10.13.153.83:22 bind=host

9 使用模板复制新容器

1
2
# 克隆容器 参数一为模板容器名称,参数二为目标容器名称
lxc copy ubuntu22-tmp test-lxd

重新配置端口号和容器ip地址,关闭容器后,再次启动容器

1
2
3
lxc config edit test-lxd
lxc stop test-lxd
lxc start test-lxd

10 换apt源

备份sources.list文件

1
2
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
sudo vim /etc/apt/sources.list

如下为哈工大源:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释
deb http://mirrors.hit.edu.cn/ubuntu/ focal main restricted universe multiverse
# deb-src http://mirrors.hit.edu.cn/ubuntu/ focal main restricted universe multiverse
deb http://mirrors.hit.edu.cn/ubuntu/ focal-updates main restricted universe multiverse
# deb-src http://mirrors.hit.edu.cn/ubuntu/ focal-updates main restricted universe multiverse
deb http://mirrors.hit.edu.cn/ubuntu/ focal-backports main restricted universe multiverse
# deb-src http://mirrors.hit.edu.cn/ubuntu/ focal-backports main restricted universe multiverse
deb http://mirrors.hit.edu.cn/ubuntu/ focal-security main restricted universe multiverse
# deb-src http://mirrors.hit.edu.cn/ubuntu/ focal-security main restricted universe multiverse

# 预发布软件源,不建议启用
# deb http://mirrors.hit.edu.cn/ubuntu/ focal-proposed main restricted universe multiverse
# deb-src http://mirrors.hit.edu.cn/ubuntu/ focal-proposed main restricted universe multiverse

更新源:

1
2
sudo apt update
sudo apt upgrade

11 安装容器的显卡驱动

安装显卡这里提供两种方式:命令安装,脚本安装。

需要注意的是,容器和宿主机的显卡驱动必须保持一致

以此型号驱动为例,驱动型号为Driver Version: 535.104.05 CUDA Version: 12.2

11.1 命令直接安装

在容器内输入nvidia-smi查看可下载的显卡驱动,如果有版本相同的显卡驱动

apt install nvidia-utils-535 # version 535.104.05-0ubuntu0.22.04.1

1
2
3
4
5
6
7
8
9
10
11
12
13
root@trusty-crappie:~/sharefile# nvidia-smi
Command 'nvidia-smi' not found, but can be installed with:
apt install nvidia-utils-390 # version 390.157-0ubuntu0.22.04.2, or
apt install nvidia-utils-418-server # version 418.226.00-0ubuntu5~0.22.04.1
apt install nvidia-utils-450-server # version 450.248.02-0ubuntu0.22.04.1
apt install nvidia-utils-470 # version 470.199.02-0ubuntu0.22.04.1
apt install nvidia-utils-470-server # version 470.199.02-0ubuntu0.22.04.1
apt install nvidia-utils-525 # version 525.125.06-0ubuntu0.22.04.1
apt install nvidia-utils-525-server # version 525.125.06-0ubuntu0.22.04.1
apt install nvidia-utils-535 # version 535.104.05-0ubuntu0.22.04.1
apt install nvidia-utils-535-server # version 535.104.05-0ubuntu0.22.04.1
apt install nvidia-utils-510 # version 510.60.02-0ubuntu1
apt install nvidia-utils-510-server # version 510.47.03-0ubuntu3

直接下载即可。如果没有请使用第二种方法脚本安装

1
apt install nvidia-utils-535

11.2 官网脚本安装

首先在官网下载所需的linux显卡驱动 NVIDIA-Linux-x86_64-535.104.05.run

https://www.nvidia.com/download/index.aspx

由于容器和宿主机共享内核,所以在安装容器的显卡驱动时需要添加 –no-kernel-module 参数。

1
bash ./NVIDIA-Linux-x86_64-535.104.05.run --no-kernel-module

安装选项都选择no即可,安装好显卡驱动后用 nvidia-smi 命令查看显卡驱动是否合适

接下来可以安装anaconda和pytorch,测试是否可以调用显卡,显示true则没问题

1
2
3
4
5
6
7
(base) zd@zd-System-Product-Name:~/sharefile$ python
Python 3.10.12 (main, Jul 5 2023, 19:22:19) [GCC 11.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import torch
>>> print(torch.cuda.is_available())
True
>>>

12 配置共享文件夹

为方便文件的传输与节约内存,我们需要设置共享文件夹来实现宿主机与容器之间的文件传输。

#新建共享文件夹

1
2
3
4
mkdir sharefile

#设置权限
sudo chmodsudo chmod 777 sharefile

在宿主机创建共享区域share-host

1
2
sudo lxc profile create share-host
sudo lxc profile set share-host security.privileged true

检查是否创建成功

1
sudo lxc profile show share-host

将文件夹添加到制定LXD容器ubuntu22-tmp

1
lxc config device add ubuntu22-tmp share-host disk source=/home/zd/sharefile path=/root/sharefile

13 LXDUI 可视化管理界面

LXDUI 是一个 LXD/LXC 的 Web UI 工具,支持 LXD/LXC 的一些基本操作。

具体使用请参考:lxdui GitRepo

效果如下:

image
image