Learning Debian
- 1: 介绍
- 2: 安装
- 2.1: 下载debian
- 2.2: 物理机安装
- 2.3: pve安装
- 2.4: raid安装
- 2.5: 安装完成后的基本配置
- 2.6: 克隆后的配置
- 2.6.1: 修改hostname
- 2.6.2: 静态IP地址
- 3: 网络
- 3.1: 使用qbittorrent
- 3.2: 用linux bridge实现软交换
- 3.3: 网卡片上卸载
- 4: 存储
- 4.1: 用物理机实现的SSD NAS存储
- 4.2: 用虚拟机实现的SSD NAS存储
- 5: 开发
1 - 介绍
1.1 - debian介绍
2 - 安装
2.1 - 下载debian
debian 的安装文件分为两种
- netinst : 小型安装镜像,安装过程中需要网络连接
- cd/dvd: 完整的安装镜像,文件较大,包含更好的软件包,可以没有网络连接时安装。
安装目前(2024年9月)最新的 debian 12.7 。
下载 netinst
打开 debian 官网
https://www.debian.org/distrib/
下载最新的版本:
https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-12.7.0-amd64-netinst.iso
文件大小 658M。
下载 dev
https://cdimage.debian.org/debian-cd/current/amd64/iso-dvd/
下载 debian-12.7.0-amd64-DVD-1.iso 文件,大小为 3.7G。
2.2 - 物理机安装
准备工作
安装版本
更新时间是 2024-09-16, 安装的当时的最新版本 debian 12.7。
制作U盘
用下载下来的 iso 文件制作启动 u 盘。
windows 下一般用 refus 软件。
安装
启动后进入 debian 安装界面,选择 “Graphical install”
- select language: english
- select your location: other -> Asia -> China
- configure locales: United States en_US.UTF-8
- keyboard: American English
配置网络:
- hostname: debian12.local
配置用户和密码:
- password of root:
- 创建新用户
- full name: Sky Ao
- username: sky
- password:
硬盘分区,选择 Guided - use entire disk -> all files in one partition, 等默认分区方案出来之后, 先删除除了 esp 分区之后的分区,然后在空闲空间上选择 create a new partition,大小为空闲空间 - 50g左右(留给 timeshift 做备份), mount 为 /
。剩下的约 50g 空间继续分区,mount 为 /var/timeshift
。
“Finish partitioning and write changes to disk” , 选下一步,会提示没有 swap 空间,询问要不要退回去,选择 no。
确认分区,然后开始安装 base system。
configure the package manager, 选 “china” -> “mirrors.ustc.edu.cn”。
software selection,这是选择要继续安装的内容:
- debian desktop environment: 桌面,我当服务器用就不需要了,取消勾选
- 选择 ssh server 和 standard system utilities
等待安装完成,重启。
小结
安装比较简单,而且过程中可以配置包管理器,这样避免了从国外拉包的麻烦,用国内的服务器速度还是非常好的,因此推荐用网络安装的方式,这样安装完成之后系统和各个包都是最新版本了。
2.3 - pve安装
准备工作
创建虚拟机
General:
- name: debian12
OS:
- iso image: 选 netinst.iso
System:
- Machine: q35 (直通时必须)
- qemu agent: 勾选
- bios: OVMF(UEFI) (直通时必须)
- EFI storage: local
- Format: qemu image format(qcow2)
Disk:
- bus/device: SCSI
- SCSI controller: VirtIO SCSI single
- IO Thread 勾选
- format: QEMU image format(qcow2)
- 高级选项中:勾选 backup
- side: 512g
cpu:
- type:host (暂时不用担心迁移的问题)
- 1 socket 4 core
Memory:
- memory: 8192
- minimum memory: 2048
Network:
- bridage: vmbr0
- model: virtIO
确认之后,虚拟机属性中,boot order 去掉 net0,保留 csi0 和 ide2 光盘启动。
备注:一定要保留硬盘启动并且在光盘前,否则安装完成后重启又进入安装流程了。而 pve 有bug,这种情况下无法关机,只能把整机重启,非常烦人。
安装
启动并开始安装
启动后进入 debian 安装界面,选择 “Graphical install”
- select language: english
- select your location: other -> Asia -> China
- configure locales: United States en_US.UTF-8
- keyboard: American English
配置网络:
- hostname: debian12.local
配置用户和密码:
- password of root:
- 创建新用户
- full name: Sky Ao
- username: sky
- password:
硬盘分区,选择 Guided - use entire disk -> all files in one partition, 等默认分区方案出来之后, 先删除除了 esp 分区之后的分区,然后在空闲空间上选择 create a new partition,大小为空闲空间 - 50g左右(留给 timeshift 做备份), mount 为 /
。剩下的约 50g 空间继续分区,mount 为 /timeshift
。
“Finish partitioning and write changes to disk” , 选下一步,会提示没有 swap 空间,询问要不要退回去,选择 no。
确认分区,然后开始安装 base system。
安装完成后,询问要不要扫描更多的媒体,选择 no。
configure the package manager, 选 “china” -> “mirrors.ustc.edu.cn”。
software selection,这是选择要继续安装的内容:
- debian desktop environment: 桌面,我当服务器用就不需要了,取消勾选
- 选择 ssh server 和 standard system utilities
等待安装完成,重启。
2.4 - raid安装
先准备好两块硬盘,重新分区,并保持两个硬盘的分区方案一致。
第一块硬盘,先后分区为:
- 512 MB: 分区选择 “EFI System Partition”
- 剩余空间-30g:分区选择不使用该分区(use as:“do not use”),准备 raid 后给 “/” 用
- 30g:分区选择不使用该分区(use as:“do not use”),准备 raid 后给 “/timeshift” 用
第二块硬盘和第一块硬盘保持一致,先后分区为:
- 512 MB: 分区选择不使用该分区(use as:“do not use”)
- 剩余空间-30g:分区选择不使用该分区(use as:“do not use”),准备 raid 后给 “/” 用
- 30g:分区选择不使用该分区(use as:“do not use”),准备 raid 后给 “/timeshift” 用
然后选择 “Configure software RAID”, 将两块大的分区和两块小的分区分别创建 raid0 。
这样就得到两个 raid0 device,大小分别为 1.7t 和 60g。
分别格式化为 ext4,挂载为 “/” 和 “/timeshift” 。
然后正常安装 debian12。
2.5 - 安装完成后的基本配置
2.5.1 - timeshift
备注:安装完成之后,第一时间安装 timeshift 进行备份,后续操作中出现任何失误都可以通过 timeshift 来选择性的恢复到中间状态,避免出错后需要重新安装。
具体操作参考:
https://skyao.io/learning-ubuntu-server/docs/installation/timeshift/
安装
先 su 到 root,再进行安装:
su root
apt install timeshift
配置
找到 timeshift 分区的 UUID:
lsblk -f
例如这个机器有三块硬盘, /var/timeshift
所在的分区 UUDI 为 3c5ad47e-4318-4797-8342-7e602ac524d2
:
$ lsblk -f
NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS
nvme1n1
`-nvme1n1p1 ext4 1.0 ccae6bf3-d4cd-422d-b67a-b5b8dfe83fc6 782.2G 0% /var/data2
nvme0n1
`-nvme0n1p1 ext4 1.0 eff3a45e-be5e-4f5e-a969-0998a8a10e33 782.2G 0% /var/data
nvme2n1
|-nvme2n1p1 vfat FAT32 C4B5-2470 505.1M 1% /boot/efi
|-nvme2n1p2 ext4 1.0 41949492-a351-4770-80f6-d4c7dc5b23bc 171.2G 1% /
`-nvme2n1p3 ext4 1.0 3c5ad47e-4318-4797-8342-7e602ac524d2 48G 0% /var/timeshift
然后设置 backup_device_uuid ,注意 timeshift 在第一次使用时会读取 default.json 文件:
vi /etc/timeshift/default.json
验证一下:
timeshift --list
这个时候还没有进行备份,没有 snapshot:
timeshift --list
First run mode (config file not found)
Selected default snapshot type: RSYNC
Mounted '/dev/nvme2n1p3' at '/run/timeshift/3424/backup'
Device : /dev/nvme2n1p3
UUID : 3c5ad47e-4318-4797-8342-7e602ac524d2
Path : /run/timeshift/3424/backup
Mode : RSYNC
Status : No snapshots on this device
First snapshot requires: 0 B
No snapshots found
此时会自动创建配置文件 /etc/timeshift/timeshift.json
,后续修改配置就要修改这个文件。
配置 excludes
除了基本的 backup_device_uuid 外,还需要配置 excludes 以排除不需要 timeshift 进行备份的内容。
{
"backup_device_uuid" : "3c5ad47e-4318-4797-8342-7e602ac524d2",
......
"exclude" : [
"/root/**",
"/home/**",
"/var/timeshift/**",
"/var/data/**",
"/var/data2/**",
"/var/data3/**"
],
......
}
需要排除的内容通常包括用户目录(/root/
和 /home/
),以及资料存储如我这里的 "/var/data/
等几块用来存储的硬盘,以及 timeshift 自身所在目录 /var/timeshift/
。
配置自动备份
设置每天/每周/每月的自动备份:
{
......
"schedule_monthly" : "true",
"schedule_weekly" : "true",
"schedule_daily" : "true",
......
"count_monthly" : "2",
"count_weekly" : "3",
"count_daily" : "5",
......
}
创建快照
先不做任何操作,在操作系统安装完成之后,第一时间进行备份:
timeshift --create --comments "first backup after install"
第一次备份大概要消耗2.3g的存储空间。
2.5.2 - path修改
问题描述
debian 12 默认的 PATH 路径有点少:
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/games
很多常见的命令都会因为不包含在 PATH 中而无法使用,报错 “command not found”:
$ usermod -aG sudo sky
bash: usermod: command not found
打开 /etc/profile
文件看到:
if [ "$(id -u)" -eq 0 ]; then
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
else
PATH="/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games"
fi
export PATH
看上去像是没有自动 source /etc/profile
,比如我用 su 到 root 账号后执行 source,那就正常的得到上面的 PATH:
$ su root
Password:
$ id
uid=0(root) gid=0(root) groups=0(root)
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/games
$ source /etc/profile
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
普通账号的修复
对于普通账号,比如我安装时建立的 sky 账号,只要简单在 .zshrc 中加入:
# If you come from bash you might have to change your $PATH.
# export PATH=$HOME/bin:/usr/local/bin:$PATH
export PATH=$HOME/bin:/usr/local/bin:/usr/local/sbin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
重新登录 sky 账号,验证即可:
$ echo $PATH
/home/sky/bin:/usr/local/bin:/usr/local/sbin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
这个需要先安装 zsh 和 oh-my-zsh,bash 应该类似,只是我目前基本只用 zsh。
root 账号的修复
貌似没有找到解决不自动 source /etc/profile
的办法,所以只能手工执行
source /etc/profile
来解决。或者,类似 sky 账号那样,安装 zsh 和 oh-my-zsh,但发现 root 账号不能改成默认使用 zsh,只能在 su 到 root 账号之后,手工执行 zsh
来从 bash 换到 zsh。
2.5.3 - sudo设置
安装
先 su 到 root 账号,安装 sudo:
apt install sudo
问题
安装时默认的 sky 账号是没有 sudo 权限的:
$ id
uid=1000(sky) gid=1000(sky) groups=1000(sky),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),100(users),106(netdev)
$ sudo ls
[sudo] password for sky:
sky is not in the sudoers file.
解决方案
先 su 为 root,然后为 sky 账号加入 sudo:
# 如果没有修复 path 的问题,则会报错找不到 usermod
# export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
usermod -aG sudo sky
退出 sky 账号,再次登录就可以 sudo 了:
$ ls
[sudo] password for sky:
bin debian12 temp work
$ id
uid=1000(sky) gid=1000(sky) groups=1000(sky),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),100(users),106(netdev)
2.5.4 - git
直接 apt 安装:
apt install git
检查版本:
$ git version
git version 2.39.5
配置代理
mkdir -p ~/.ssh/
vi ~/.ssh/config
增加内容为:
Host github.com
HostName github.com
User git
# http proxy
#ProxyCommand socat - PROXY:127.0.0.1:%h:%p,proxyport=3333
# socks5 proxy
ProxyCommand nc -v -x 192.168.0.1:7891 %h %p
2.5.6 - 网络代理
设置网络代理
在 openwrt 上安装 openclash,支持 socks5 和 http 代理,因此设置很简单,在 .zshrc
中加入以下内容:
# proxy
alias proxyon='export all_proxy=socks5://192.168.20.1:7891;export http_proxy=http://192.168.20.1:7890;export https_proxy=http://192.168.20.1:7890;export no_proxy=127.0.0.1,localhost,local,.local,.lan,192.168.0.0/16,10.0.0.0/16'
alias proxyoff='unset all_proxy http_proxy https_proxy no_proxy'
需要开启代理时,输入 proxyon 命令就设置好代理了。不使用时 proxyoff 关闭。
安装配置 privoxy
但在 tplink 6088 路由器上安装的 openwrt 上没有 openclash,只有 ShadowSocksR Plus+ , 只支持 socks5 代理。之前还能在 openwrt 上通过安装 privoxy 软件来将 socks5 转为 http,但最近 openwrt 上的 privoxy 软件已经没有了。因此需要自己在电脑上安装 privoxy 软件来进行转换。
sudo apt install privoxy
修改配置前备份一下:
sudo cp /etc/privoxy/config /etc/privoxy/config.original
修改配置内容为:
# 这里修改原有的配置
listen-address 0.0.0.0:7890
listen-address [::1]:7890
# 在最后加入这行
forward-socks5t / 192.168.0.1:7891 .
重启 privoxy:
sudo systemctl restart privoxy.service
验证,
export http_proxy=http://127.0.0.1:7890;export https_proxy=http://127.0.0.1:7890
wget https://www.youtube.com/
最后,在 .zshrc
中加入以下内容,将 http/https 代理设置为本地 privoxy 的端口:
# proxy
alias proxyon='export all_proxy=socks5://192.168.20.1:7891;export http_proxy=http://127.0.0.1:7890;export https_proxy=http://127.0.0.1:7890;export no_proxy=127.0.0.1,localhost,local,.local,.lan,192.168.0.0/16,10.0.0.0/16'
alias proxyoff='unset all_proxy http_proxy https_proxy no_proxy'
参考:
2.5.7 - 安装其他软件
安装操作系统相关的软件
sudo apt install dkms
这个过程中会自动安装 linux-headers 。
常用工具软件
sudo apt install htop unzip zip curl
网络速度测试软件:
sudo apt install iperf iperf3
修复 locale 报错
默认安装之后经常在执行各种命令时看到如下的警告:
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
LANGUAGE = (unset),
LC_ALL = (unset),
LC_CTYPE = "UTF-8",
LANG = "en_US.UTF-8"
are supported and installed on your system.
perl: warning: Falling back to a fallback locale ("en_US.UTF-8").
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
可以通过执行 locale
命令来重现这个警告:
解决方案,
vi ~/.zshrc
增加内容:
export LC_CTYPE=en_US.UTF-8
export LC_ALL=en_US.UTF-8
执行
source ~/.zshrc
验证结果。
参考:
2.6 - 克隆后的配置
在使用 pve 等虚拟化软件时,为了方便重用,会将配置好的 debian 系统制作成模版,然后使用时从模版克隆出来。
这样就会有一些特殊的配置需要在克隆之后进行。
2.6.1 - 修改hostname
参考:
https://skyao.io/learning-ubuntu-server/docs/installation/basic/change-hostname
2.6.2 - 静态IP地址
每个克隆后的虚拟机都应该有自己固定的ip地址,但是通过 dhcp 来修改不合适,毕竟这些经常变化。
因此需要设置静态 ip 地址,每次克隆之后虚拟机就自行设置。
设置静态ip
修改前先备份:
sudo cp /etc/network/interfaces /etc/network/interfaces.bak
看一下目前的网络适配器情况,enp6s18 是正在使用的网卡:
$ ip addr
2: enp6s18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether bc:24:11:97:c4:00 brd ff:ff:ff:ff:ff:ff
inet 192.168.20.228/24 brd 192.168.20.255 scope global dynamic enp6s18
修改网络设置:
sudo vi /etc/network/interfaces
将 enp6s18 原有的配置:
# The primary network interface
allow-hotplug enp6s18
iface enp6s18 inet dhcp
修改为:
# The primary network interface
allow-hotplug enp6s18
# iface enp6s18 inet dhcp
iface enp6s18 inet static
address 192.168.20.25
netmask 255.255.255.0
gateway 192.168.20.1
dns-nameservers 192.168.20.1
保存后重启网络:
sudo systemctl restart networking
之后就可以用新的 ip 地址访问了。
参考资料
3 - 网络
3.1 - 使用qbittorrent
选择版本
让我们快速了解一下 qBittorrent 安装方法之间的一些基本区别:
-
qBittorrent 桌面优势:
- 用户友好界面: 提供直观且易于浏览的图形界面。
- 简洁的体验: 作为开源软件,它没有广告和不必要的捆绑软件。
- 功能丰富:包括顺序下载、带宽调度等功能。
-
qBittorrent-nox 的优势:
- 专为无头系统优化: 专为最小化资源占用而设计,是受限系统的理想选择。
- 网络接口: 允许通过基于网络的界面进行操作。
- 远程管理: 通过网络接口方便管理服务器和远程系统。
自动安装
我用的debian是服务器版本,没有UI界面,因此选择安装 qbittorrent-nox (无图形界面版本):
sudo apt install qbittorrent-nox
为 qBittorrent 创建专用系统用户和组:
sudo adduser --system --group qbittorrent-nox
sudo adduser sky qbittorrent-nox
为 qBittorrent-nox 创建 Systemd 服务文件
sudo vi /etc/systemd/system/qbittorrent-nox.service
内容如下:
[Unit]
Description=qBittorrent Command Line Client
After=network.target
[Service]
Type=forking
User=qbittorrent-nox
Group=qbittorrent-nox
UMask=007
ExecStart=/usr/bin/qbittorrent-nox -d --webui-port=8080
Restart=on-failure
[Install]
WantedBy=multi-user.target
重启 daemon-reload:
sudo systemctl daemon-reload
启动
启动 qbittorrent-nox 准备必要的目录:
sudo mkdir /home/qbittorrent-nox
sudo chown qbittorrent-nox:qbittorrent-nox /home/qbittorrent-nox
sudo usermod -d /home/qbittorrent-nox qbittorrent-nox
启动:
sudo systemctl start qbittorrent-nox
查看启动状态:
sudo systemctl status qbittorrent-nox
看到信息如下:
qbittorrent-nox.service - qBittorrent Command Line Client
Loaded: loaded (/etc/systemd/system/qbittorrent-nox.service; enabled; preset: enabled)
Active: active (running) since Sun 2024-05-05 01:09:48 EDT; 3h 7min ago
Process: 768 ExecStart=/usr/bin/qbittorrent-nox -d --webui-port=8080 (code=exited, status=0/SUCCESS)
Main PID: 779 (qbittorrent-nox)
Tasks: 21 (limit: 9429)
Memory: 6.4G
CPU: 5min 23.810s
CGroup: /system.slice/qbittorrent-nox.service
└─779 /usr/bin/qbittorrent-nox -d --webui-port=8080
May 05 01:09:48 skynas3 systemd[1]: Starting qbittorrent-nox.service - qBittorrent Command Line Client...
May 05 01:09:48 skynas3 systemd[1]: Started qbittorrent-nox.service - qBittorrent Command Line Client.
设置开机自动启动:
sudo systemctl enable qbittorrent-nox
管理
访问 http://192.168.20.2:8080/ ,默认登录用户/密码为 admin
和 adminadmin
。
-
下载
- 默认保存路径:"/mnt/storage2/download"
-
连接
- 用于传入连接的端口:在路由器上增加这个端口的端口映射
-
Web-ui
- 语言:用户语言界面选择"简体中文"
- 修改用户密码
- 勾选 “对本地主机上的客户端跳过身份验证”
- 勾选 “对 IP 子网白名单中的客户端跳过身份验证”:
192.168.0.0/24,192.168.192.0/24
-
高级
- 勾选 “允许来自同一 IP 地址的多个连接”
- 勾选 “总是向同级的所有 Tracker 汇报”
参考资料
手工安装
安装依赖包
先安装依赖包:
sudo apt update
sudo apt install build-essential pkg-config automake libtool git libgeoip-dev python3 python3-dev
sudo apt install libboost-dev libboost-system-dev libboost-chrono-dev libboost-random-dev libssl-dev
sudo apt install qtbase5-dev qttools5-dev-tools libqt5svg5-dev zlib1g-dev
安装 libtorrent 1.2.19
安装libtorrent 1.2.19:
wget https://github.com/arvidn/libtorrent/releases/download/v1.2.19/libtorrent-rasterbar-1.2.19.tar.gz
tar xf libtorrent-rasterbar-1.2.19.tar.gz
cd libtorrent-rasterbar-1.2.19
./configure --disable-debug --enable-encryption --with-libgeoip=system CXXFLAGS=-std=c++14
make -j$(nproc)
sudo make install
sudo ldconfig
如果遇到错误:
checking whether g++ supports C++17 features with -std=c++17... yes
checking whether the Boost::System library is available... no
configure: error: Boost.System library not found. Try using --with-boost-system=lib
需要先安装 libboost-system-dev :
sudo apt install libboost-system-dev
如果遇到错误:
checking whether compiling and linking against OpenSSL works... no
configure: error: OpenSSL library not found. Try using --with-openssl=DIR or disabling encryption at all.
需要先安装 libssl-dev :
sudo apt install libssl-dev
安装 qbittorrent
不敢用太新的版本,还是找个稍微久一点的,继续沿用参考文档里面用的 4.3.9 版本:
wget https://github.com/qbittorrent/qBittorrent/archive/refs/tags/release-4.3.9.tar.gz
tar xf release-4.3.9.tar.gz
cd qBittorrent-release-4.3.9
./configure --disable-gui --disable-debug
make -j$(nproc)
sudo make install
设置开机自启
sudo vi /etc/systemd/system/qbittorrent.service
输入以下内容:
[Unit]
Description=qBittorrent Daemon Service
After=network.target
[Service]
LimitNOFILE=512000
User=root
ExecStart=/usr/local/bin/qbittorrent-nox
ExecStop=/usr/bin/killall -w qbittorrent-nox
[Install]
WantedBy=multi-user.target
启用开机自启:
sudo systemctl enable qbittorrent.service
第一次启动
先手工启动第一次:
sudo qbittorrent-nox
*** Legal Notice ***
qBittorrent is a file sharing program. When you run a torrent, its data will be made available to others by means of upload. Any content you share is your sole responsibility.
No further notices will be issued.
Press 'y' key to accept and continue...
按 Y 后,Ctrl+C退出。
用 systemctl 后台启动 qbittorrent:
sudo systemctl start qbittorrent.service
参考资料
3.2 - 用linux bridge实现软交换
准备工作
安装好网卡驱动,如 cx3 / cx4 / cx5 的驱动。
搭建软交换
新建 linux bridge
安装 bridge 工具包:
sudo apt install bridge-utils -y
查看当前网卡情况:
$ ip addr
2: enp6s18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether bc:24:11:97:c4:00 brd ff:ff:ff:ff:ff:ff
inet 192.168.20.25/24 brd 192.168.20.255 scope global enp6s18
3: enp1s0f0np0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether b8:ce:f6:0b:ff:7c brd ff:ff:ff:ff:ff:ff
4: enp1s0f1np1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether b8:ce:f6:0b:ff:7d brd ff:ff:ff:ff:ff:ff
enp6s18 是对外的网卡(wan),enp1s0f0np0 和 enp1s0f1np1 准备用来连接其他机器(lan)。
修改 network interfaces,删除所有和 enp6s18 / 是对外的网卡(wan),enp1s0f0np0 / enp1s0f1np1 有关的内容:
sudo vi /etc/network/interfaces
最后保留的内容应该非常少,类似于:
source /etc/network/interfaces.d/*
# The loopback network interface
auto lo
iface lo inet loopback
然后新建一个 br0 文件来创建网桥:
sudo vi /etc/network/interfaces.d/br0
内容为:
auto br0
iface br0 inet static
address 192.168.20.2
broadcast 192.168.20.255
netmask 255.255.255.0
gateway 192.168.20.1
bridge_ports enp6s18 enp1s0f0np0 enp1s0f1np1
bridge_stp off
bridge_waitport 0
bridge_fd 0
注意这里要把所有需要加入网桥的网卡都列举在 bridge_ports 中(包括 wan 和 lan, 会自动识别) 保存后重启网络:
sudo systemctl restart networking
或者直接重启机器。(如果之前有配置wan口网卡的ip地址,并且新网桥的ip地址和wan的ip地址一致,就必须重启机器而不是重启网路。)
查看改动之后的网络:
$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: enp6s18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
link/ether bc:24:11:97:c4:00 brd ff:ff:ff:ff:ff:ff
3: enp1s0f0np0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether b8:ce:f6:0b:ff:7c brd ff:ff:ff:ff:ff:ff
4: enp1s0f1np1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether b8:ce:f6:0b:ff:7d brd ff:ff:ff:ff:ff:ff
6: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 6e:38:a0:77:09:dc brd ff:ff:ff:ff:ff:ff
inet 192.168.20.2/24 brd 192.168.20.255 scope global br0
valid_lft forever preferred_lft forever
检查网络是否可以对外/对内访问。如果没有问题,说明第一步成功,网桥创建好了。
$ brctl show
bridge name bridge id STP enabled interfaces
br0 8000.6e38a07709dc no enp1s0f0np0
enp1s0f1np1
enp6s18
$ bridge link
2: enp6s18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br0 state forwarding priority 32 cost 100
3: enp1s0f0np0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br0 state forwarding priority 32 cost 1
3: enp1s0f0np0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br0 hwmode VEB
4: enp1s0f1np1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br0 state forwarding priority 32 cost 1
4: enp1s0f1np1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br0 hwmode VEB
网卡另一头接上其他电脑,通过 dhcp 自动获取了IP地址,而且内外可以互通,测度测试也正常。
软交换就这么搭建好了。
小结和对比
上面这个方案,比之前在 ubuntu server 用的方案要简单很多,当时也用了 linux bridge,但需要建立子网,安装 dnsmaxq 做 dhcp 服务器端,配置内核转发,还要设置静态路由规则。
这个方案什么都不用做,就需要建立一个最简单的 linux bridge 就可以了。
开启内核转发
备注: 发现不做这个设置,也可以正常转发。不过还是加上吧。
sudo vi /etc/sysctl.conf
把这两行注释取消,打开配置:
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
让改动生效:
sudo sysctl --load /etc/sysctl.conf
设置 MTU
默认 mtu 为 1500,为了最大化发挥网卡的能力,需要修改 mtu 为 9000.
对于机器 B / C,只要执行下面的命令即可:
sudo ip link set enp6s16np0 mtu 9000
对于软交换所在的 A 机器,需要将 linux bridge 和相关的网卡都设置为 mut 9000:
sudo ip link set dev br0 mtu 9000
sudo ip link set dev enp1s0f0np0 mtu 9000
sudo ip link set dev enp1s0f1np1 mtu 9000
这个方式只能临时生效,一旦机器重启就会恢复成默认的 mtu 1500。解决的方法是修改 rc.local
参考资料:
性能测试
cx3测试
cx4测试
25g网卡连接速度25g,用 iperf2 测试出来的带宽有23.5g,接近25g的理论值。
忘了有没有改 mtu了,下次再测试看看。
cx5测试
以 cx5 网卡为例,软交换机器 A (ip 为 192.168.0.100)上一块 cx5 双口网卡,另外两台测试机器 B (ip 为 192.168.0.125) / C (ip 为 192.168.0.127) 上一块单口网卡,用 100G dac线材连接。三台机器都安装好 iperf 和 iperf3。
iperf2 测试
在软交换机器 A 上启动 iperf 服务器端:
iperf -s -p 10001
在 B/C 两台机器上分别启动 iperf 客户端:
iperf -c 192.168.0.100 -P 3 -t 10 -p 10001 -i 1
测试直连速度: 达到 99.0 Gits/sec, 非常接近 100G 的理论最大值。
备注: 如果不设置为 mtu 9000, 采用默认的 mtu 1500,只能达到约 94 G 。
[SUM] 0.0000-10.0001 sec 115 GBytes 99.0 Gbits/sec
测试转发速度: 在其中一台机器 B 上启动 iperf 服务器端,然后从另外一台机器 C 上测试连接机器 B, 速度可以达到 76.9 G,和 100G 理论最大值相比损失还是挺大的。
iperf -c 192.168.0.125 -P 2 -t 10 -p 10001 -i 1
[SUM] 0.0000-6.9712 sec 62.4 GBytes 76.9 Gbits/sec
注意:-P 2
也就是启动两个线程,可以测试出最大值,继续增加线程反而会下降。
特别注意的是,网络速度测试时,在软交换机器 A 上,用 top 命令看似乎几乎没有任何性能消耗:
但实际上,在 pve 虚拟机上,显示占用了块两个核心:
可见此时并没有实现我们期待的在进行软交换时启用 rdma 来减少 cpu 消耗的目的。因此,需要继续考虑如何开启 rdma
iperf3 测试
类似的,测试出来 iperf3 下软交换的速度大概是 63.9 G:
$ iperf3 -c 192.168.0.125 -P 2 -t 10 -i 1
......
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 37.2 GBytes 31.9 Gbits/sec 0 sender
[ 5] 0.00-10.00 sec 37.2 GBytes 31.9 Gbits/sec receiver
[ 7] 0.00-10.00 sec 37.2 GBytes 31.9 Gbits/sec 0 sender
[ 7] 0.00-10.00 sec 37.2 GBytes 31.9 Gbits/sec receiver
[SUM] 0.00-10.00 sec 74.4 GBytes 63.9 Gbits/sec 0 sender
[SUM] 0.00-10.00 sec 74.4 GBytes 63.9 Gbits/sec receiver
top下依然看到 cpu 占用极低,但 pve 页面显示有 5% 的 cpu。
增加 -Z
参数开启 iperf3 的 zero copy 功能再测试,速度大幅提升达到 77.8 G:
iperf3 -c 192.168.0.125 -P 2 -t 10 -i 1 -Z
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 45.3 GBytes 38.9 Gbits/sec 0 sender
[ 5] 0.00-10.00 sec 45.3 GBytes 38.9 Gbits/sec receiver
[ 7] 0.00-10.00 sec 45.3 GBytes 38.9 Gbits/sec 0 sender
[ 7] 0.00-10.00 sec 45.3 GBytes 38.9 Gbits/sec receiver
[SUM] 0.00-10.00 sec 90.6 GBytes 77.8 Gbits/sec 0 sender
[SUM] 0.00-10.00 sec 90.6 GBytes 77.8 Gbits/sec receiver
此时 top 下依然看到 cpu 占用极低,但 pve 页面显示有 6.59% 的 cpu。
参考资料
3.3 - 网卡片上卸载
背景
前面用 linux bridge 做软交换,功能没问题,性能看似还行,但其实有不少问题:
- 跑不到网卡极限
- cpu占用较高
- rdma 之类的高级特性缺失
cx5 介绍
https://www.nvidia.com/en-us/networking/ethernet/connectx-5/
NVIDIA® Mellanox® ConnectX®-5适配器提供先进的硬件卸载功能,可减少CPU资源消耗,并实现极高的数据包速率和吞吐量。这提高了数据中心基础设施的效率,并为Web 2.0、云、数据分析和存储平台提供了最高性能和最灵活的解决方案。
这里提到的 “先进的硬件卸载功能,可减少CPU资源消耗”,正是我需要的。
实现最高效率的主要特性:
-
NVIDIA RoCE技术封装了以太网上的数据包传输,并降低了CPU负载,从而为网络和存储密集型应用提供高带宽和低延迟的网络基础设施。
-
突破性的 NVIDIA ASAP² 技术通过将 Open vSwitch 数据路径从主机CPU卸载到适配器,提供创新的 SR-IOV 和 VirtIO 加速,从而实现极高的性能和可扩展性。
-
ConnectX 网卡利用 SR-IOV 来分离对虚拟化环境中物理资源和功能的访问。这减少了I/O开销,并允许网卡保持接近非虚拟化的性能。
关键特性:
- 每个端口最高可达100 Gb/s以太网
- 可靠传输上的自适应路由
- NVMe over Fabric(NVMf)目标卸载
- 增强的vSwitch / vRouter卸载
- NVGRE和VXLAN封装流量的硬件卸载
- 端到端QoS和拥塞控制
cx5 网卡资料:
https://network.nvidia.com/files/doc-2020/pb-connectx-5-en-card.pdf
硬件加速的基本知识
NVIDIA DPU白皮书:SR-IOV vs. VirtIO加速性能对比
https://aijishu.com/a/1060000000228117
open vswitch
sudo apt install openvswitch-switch
查看Open vSwitch(OVS)的版本:
$ sudo ovs-vsctl show
2a434d84-f9ec-4da7-af56-a762b068a2e8
ovs_version: "3.1.0"
和 openvswitch 模块的信息:
$ sudo modinfo openvswitch
filename: /lib/modules/6.1.0-25-amd64/kernel/net/openvswitch/openvswitch.ko
alias: net-pf-16-proto-16-family-ovs_ct_limit
alias: net-pf-16-proto-16-family-ovs_meter
alias: net-pf-16-proto-16-family-ovs_packet
alias: net-pf-16-proto-16-family-ovs_flow
alias: net-pf-16-proto-16-family-ovs_vport
alias: net-pf-16-proto-16-family-ovs_datapath
license: GPL
description: Open vSwitch switching datapath
depends: nf_conntrack,nsh,nf_nat,nf_defrag_ipv6,nf_conncount,libcrc32c
retpoline: Y
intree: Y
name: openvswitch
vermagic: 6.1.0-25-amd64 SMP preempt mod_unload modversions
sig_id: PKCS#7
signer: Debian Secure Boot CA
sig_key: 32:A0:28:7F:84:1A:03:6F:A3:93:C1:E0:65:C4:3A:E6:B2:42:26:43
sig_hashalgo: sha256
signature: 52:AF:27:99:1F:1F:EF:6C:2E:7D:16:DB:D9:B9:8E:46:99:13:AA:37:
53:5F:19:45:38:8B:C6:7C:B6:D7:93:A6:5C:B3:59:C7:F4:70:A5:D8:
94:9C:00:4F:17:06:8E:63:BF:69:F1:01:76:85:BB:FC:C7:6B:F4:E3:
C2:BD:01:7F:9A:98:04:76:23:C5:05:58:10:77:21:EC:95:4B:98:DD:
51:DB:58:32:A9:49:19:7B:47:D7:60:FF:D8:BB:81:90:C7:54:14:42:
80:D6:1B:D4:64:E8:DB:EC:A2:3F:49:FD:7E:34:05:78:50:98:A5:BF:
33:47:59:C0:F8:76:7F:F6:26:3E:F0:6F:E5:72:7C:51:CA:31:B7:EE:
B7:C2:03:30:77:DA:B5:13:03:F5:EF:26:CB:32:F8:DA:3F:A0:60:E5:
8F:39:D8:8F:BF:6E:25:15:EA:AB:48:A5:02:56:15:5A:08:BB:34:73:
52:C4:DA:E5:9F:89:BF:7B:6E:6E:B9:D8:9B:6B:46:BA:C9:29:06:0B:
2A:97:4F:D4:92:61:88:18:5B:AF:C1:FE:AA:6D:3D:77:18:96:0C:DF:
EB:20:DE:4F:D2:49:72:B5:F9:02:72:F2:0D:44:3D:6C:DF:C5:D8:3B:
35:A7:8C:08:11:76:B5:F9:34:1B:F7:80:A6:3E:A6:0E
检查 openvswitch 模块的正确加载:
lsmod | grep openvswitch
openvswitch 192512 0
nsh 16384 1 openvswitch
nf_conncount 24576 1 openvswitch
nf_nat 57344 1 openvswitch
nf_conntrack 188416 3 nf_nat,openvswitch,nf_conncount
nf_defrag_ipv6 24576 2 nf_conntrack,openvswitch
libcrc32c 16384 3 nf_conntrack,nf_nat,openvswitch
查看 openvswitch-switch 服务的运行情况:
sudo systemctl status openvswitch-switch
openvswitch-switch.service - Open vSwitch
Loaded: loaded (/lib/systemd/system/openvswitch-switch.service; enabled; preset: enabled)
Active: active (exited) since Tue 2024-09-10 04:27:46 EDT; 3min 59s ago
Process: 1025 ExecStart=/bin/true (code=exited, status=0/SUCCESS)
Main PID: 1025 (code=exited, status=0/SUCCESS)
CPU: 420us
Sep 10 04:27:46 dev100 systemd[1]: Starting openvswitch-switch.service - Open vSwitch...
Sep 10 04:27:46 dev100 systemd[1]: Finished openvswitch-switch.service - Open vSwitch.
sudo systemctl status ovsdb-server
ovsdb-server.service - Open vSwitch Database Unit
Loaded: loaded (/lib/systemd/system/ovsdb-server.service; static)
Active: active (running) since Tue 2024-09-10 04:27:46 EDT; 7min ago
Process: 738 ExecStart=/usr/share/openvswitch/scripts/ovs-ctl --no-ovs-vswitchd --no-monitor --system-id=random --no-record-hostname start $O>
Main PID: 816 (ovsdb-server)
Tasks: 1 (limit: 38413)
Memory: 15.0M
CPU: 41ms
CGroup: /system.slice/ovsdb-server.service
└─816 ovsdb-server /etc/openvswitch/conf.db -vconsole:emer -vsyslog:err -vfile:info --remote=punix:/var/run/openvswitch/db.sock --pr>
Sep 10 04:27:46 dev100 systemd[1]: Starting ovsdb-server.service - Open vSwitch Database Unit...
Sep 10 04:27:46 dev100 ovs-ctl[738]: Starting ovsdb-server.
Sep 10 04:27:46 dev100 ovs-vsctl[817]: ovs|00001|vsctl|INFO|Called as ovs-vsctl --no-wait -- init -- set Open_vSwitch . db-version=8.3.1
Sep 10 04:27:46 dev100 ovs-vsctl[831]: ovs|00001|vsctl|INFO|Called as ovs-vsctl --no-wait set Open_vSwitch . ovs-version=3.1.0 "external-ids:syst>
Sep 10 04:27:46 dev100 ovs-ctl[738]: Configuring Open vSwitch system IDs.
Sep 10 04:27:46 dev100 ovs-ctl[738]: Enabling remote OVSDB managers.
Sep 10 04:27:46 dev100 systemd[1]: Started ovsdb-server.service - Open vSwitch Database Unit.
sudo systemctl status ovs-vswitchd
● ovs-vswitchd.service - Open vSwitch Forwarding Unit
Loaded: loaded (/lib/systemd/system/ovs-vswitchd.service; static)
Active: active (running) since Tue 2024-09-10 04:27:46 EDT; 8min ago
Process: 835 ExecStart=/usr/share/openvswitch/scripts/ovs-ctl --no-ovsdb-server --no-monitor --system-id=random --no-record-hostname start $O>
Main PID: 1012 (ovs-vswitchd)
Tasks: 1 (limit: 38413)
Memory: 5.6M
CPU: 29ms
CGroup: /system.slice/ovs-vswitchd.service
└─1012 ovs-vswitchd unix:/var/run/openvswitch/db.sock -vconsole:emer -vsyslog:err -vfile:info --mlockall --no-chdir --log-file=/var/>
Sep 10 04:27:46 dev100 systemd[1]: Starting ovs-vswitchd.service - Open vSwitch Forwarding Unit...
Sep 10 04:27:46 dev100 ovs-ctl[883]: Inserting openvswitch module.
Sep 10 04:27:46 dev100 ovs-ctl[835]: Starting ovs-vswitchd.
Sep 10 04:27:46 dev100 ovs-ctl[835]: Enabling remote OVSDB managers.
Sep 10 04:27:46 dev100 systemd[1]: Started ovs-vswitchd.service - Open vSwitch Forwarding Unit.
sudo ovs-vsctl add-br br0
sudo ovs-vsctl show
sudo ovs-vsctl list br br0
sudo ovs-vsctl add-port br0 enp6s18
sudo ovs-vsctl add-port br0 enp1s0f0np0
sudo ovs-vsctl add-port br0 enp1s0f1np1
sudo ovs-vsctl show
sudo ovs-vsctl set Open_vSwitch . other_config:hw-offload=true
sudo systemctl restart networking
sudo systemctl restart openvswitch-switch
https://infoloup.no-ip.org/openvswitch-debian12-creation/
➜ ~ sudo ip link set br0 mtu 9000 ➜ ~ sudo ip link set enp1s0f1np1 mtu 9000 ➜ ~ sudo ip link set enp1s0f0np0 mtu 9000 ➜ ~ sudo ip link set enp6s18 mtu 9000
https://docs.openstack.org/neutron/latest/admin/config-ovs-offload.html
https://www.openvswitch.org/support/ovscon2019/day2/0951-hw_offload_ovs_con_19-Oz-Mellanox.pdf
https://docs.nvidia.com/doca/archive/doca-v2.2.0/switching-support/index.html
4 - 存储
4.1 - 用物理机实现的SSD NAS存储
构想
在前面实现的软交换的基础上,顺便实现一个SSD NAS,方便其他机器存储资料,如 pve 相关的虚拟机备份/模版/iso等。
这样就实现了 56g 网络 + 高速 SSD 的 NAS。
备注:因为兼容性原因,56g的 hp544+ 这块 cx3 pro 的网卡无法直通多块网卡给单个虚拟机(可以直通一块卡,两块就报错,换cx4以上就正常),所以这台机器使用的是物理机安装 debian 12.7。
准备工作
准备物理机
软交换机器为了性能和兼容采用的是物理机方式安装 debian,插了四块 hp544+ 网卡,实现了 40g/56g 软交换。
基于 40g/56g 网卡的高速网络已经满足。
硬盘情况
机器上目前是一块256g的三星pm981a用来安装 debian 操作系统,两块三星pm983a 1t 用来做 nas,lspci 能看到这三块 ssd 硬盘:
$ lspci | grep Non-Volatile
03:00.0 Non-Volatile memory controller: Samsung Electronics Co Ltd NVMe SSD Controller SM981/PM981/PM983
04:00.0 Non-Volatile memory controller: Samsung Electronics Co Ltd NVMe SSD Controller SM981/PM981/PM983
07:00.0 Non-Volatile memory controller: Samsung Electronics Co Ltd NVMe SSD Controller SM981/PM981/PM983
还有一块东芝 mg08 14t 的机械硬盘,准备用来做资料备份。
分区情况:
$ sudo lsblk -l
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 12.7T 0 disk
sda1 8:1 0 12.7T 0 part /var/data3
nvme1n1 259:0 0 838.4G 0 disk
nvme0n1 259:1 0 838.4G 0 disk
nvme1n1p1 259:2 0 838.4G 0 part /var/data2
nvme0n1p1 259:3 0 838.4G 0 part /var/data
nvme2n1 259:4 0 238.5G 0 disk
nvme2n1p1 259:5 0 512M 0 part /boot/efi
nvme2n1p2 259:6 0 186.3G 0 part /
nvme2n1p3 259:7 0 51.7G 0 part /var/timeshift
用 fdisk 看更清晰一些:
$ sudo fdisk -l
Disk /dev/nvme1n1: 838.36 GiB, 900185481216 bytes, 1758174768 sectors
Disk model: MZ1LB960HBJR-000FB
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 131072 bytes / 131072 bytes
Disklabel type: gpt
Disk identifier: B724F254-A8C9-4FDD-B030-B68A85D4F6FD
Device Start End Sectors Size Type
/dev/nvme1n1p1 2048 1758173183 1758171136 838.4G Linux filesystem
Disk /dev/nvme0n1: 838.36 GiB, 900185481216 bytes, 1758174768 sectors
Disk model: MZ1LB960HBJR-000FB
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 131072 bytes / 131072 bytes
Disklabel type: gpt
Disk identifier: D495383E-8798-4B53-BED6-4CB6BBA29B74
Device Start End Sectors Size Type
/dev/nvme0n1p1 2048 1758173183 1758171136 838.4G Linux filesystem
Disk /dev/nvme2n1: 238.47 GiB, 256060514304 bytes, 500118192 sectors
Disk model: SAMSUNG MZVLB256HBHQ-000L7
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: F33C8916-7384-11EF-A4EE-8B1FC28B9DC5
Device Start End Sectors Size Type
/dev/nvme2n1p1 2048 1050623 1048576 512M EFI System
/dev/nvme2n1p2 1050624 391675903 390625280 186.3G Linux filesystem
/dev/nvme2n1p3 391675904 500117503 108441600 51.7G Linux filesystem
Disk /dev/sda: 12.73 TiB, 14000519643136 bytes, 27344764928 sectors
Disk model: TOSHIBA MG08ACA1
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: gpt
Disk identifier: D64050D6-6671-0C41-9881-3E1CECCD24C1
Device Start End Sectors Size Type
/dev/sda1 2048 27344762879 27344760832 12.7T Linux filesystem
准备使用 /dev/nvme1n1p1
/ /dev/nvme0n1p1
/ /dev/sda1
这三个分区来存放 nfs 共享文件。在根目录下建立 “/data” 目录:
sudo mkdir /data
修改 timeshift 配置,将 /data
加入到 excludes 。
搭建 nas 服务器端
安装 nfs server
# 安装
sudo apt install nfs-kernel-server -y
# 开机自启
sudo systemctl start nfs-kernel-server
sudo systemctl enable nfs-kernel-server
# 验证
sudo systemctl status nfs-kernel-server
● nfs-server.service - NFS server and services
Loaded: loaded (/lib/systemd/system/nfs-server.service; enabled; preset: enabled)
Active: active (exited) since Tue 2024-09-17 04:06:44 CST; 28s ago
Main PID: 1901 (code=exited, status=0/SUCCESS)
CPU: 6ms
Sep 17 04:06:42 switch99 systemd[1]: Starting nfs-server.service - NFS server and services...
Sep 17 04:06:42 switch99 exportfs[1900]: exportfs: can't open /etc/exports for reading
Sep 17 04:06:44 switch99 systemd[1]: Finished nfs-server.service - NFS server and services.
配置 nfs v4
sudo vi /etc/default/nfs-common
修改内容如下
NEED_STATD="no"
NEED_IDMAPD="yes"
继续修改 nfs-kernel-server 的配置:
sudo vi /etc/default/nfs-kernel-server
修改内容:
# 这行新增
RPCNFSDOPTS="-N 2 -N 3"
# 这行已经存在,修改内容
RPCMOUNTDOPTS="--manage-gids -N 2 -N 3"
# 其他不动
重启 nfs-server
sudo systemctl restart nfs-server
配置 UFW 防火墙
安装 nfs 之后必须配置防火墙。先安装 ufw:
sudo apt install ufw -y
安装完成之后第一个必须执行的步骤就是开放 ssh 登录:
sudo ufw allow ssh
sudo ufw enable
然后是容许访问 nfs
sudo ufw allow from 192.168.0.0/16 to any port nfs
重启 ufw 并查看 ufw 状态:
sudo ufw reload
sudo ufw status
可以看到 2049 端口开放给 nfs 了。
$ sudo ufw status
[sudo] password for sky:
Firewall reloaded
Status: active
To Action From
-- ------ ----
22/tcp ALLOW Anywhere
2049 ALLOW 192.168.0.0/16
22/tcp (v6) ALLOW Anywhere (v6)
备注:暂时不知道为什么 ufw 开启之后就无法访问 nfs 了,上面的 allow rule 没能生效。只好暂时先 sudo ufw disable
关闭防火墙先。
准备共享目录
为了方便后续的管理,采用伪文件系统
sudo mkdir -p /data/{share,pve-share}
sudo chown -R nobody:nogroup /data/share
sudo chown -R nobody:nogroup /data/pve-share
创建 export 目录:
sudo mkdir -p /exports/{share,pve-share}
sudo chown -R nobody:nogroup /exports
修改 /etc/fstab
文件来 mount 伪文件系统和 exports
sudo vi /etc/fstab
增加如下内容:
# nfs exports
/data/share /exports/share none bind
/data/pve-share /exports/pve-share none bind
配置 nfs export
sudo vi /etc/exports
修改 nfs exports 的内容:
/exports/share 192.168.0.0/16(rw,no_root_squash,no_subtree_check,crossmnt,fsid=0)
/exports/pve-share 192.168.0.0/16(rw,no_root_squash,no_subtree_check,crossmnt,fsid=0)
重启 nfs-kernel-server,查看 nfs-kernel-server 的状态:
sudo systemctl restart nfs-kernel-server
sudo systemctl status nfs-kernel-server
输出为:
nfs-server.service - NFS server and services
Loaded: loaded (/lib/systemd/system/nfs-server.service; enabled; preset: enabled)
Drop-In: /run/systemd/generator/nfs-server.service.d
└─order-with-mounts.conf
Active: active (exited) since Mon 2024-03-18 21:11:34 CST; 21ms ago
Process: 6678 ExecStartPre=/usr/sbin/exportfs -r (code=exited, status=0/SUCCESS)
Process: 6679 ExecStart=/usr/sbin/rpc.nfsd (code=exited, status=0/SUCCESS)
Main PID: 6679 (code=exited, status=0/SUCCESS)
CPU: 7ms
Mar 18 21:11:34 switch99 systemd[1]: Starting nfs-server.service - NFS server and services...
Mar 18 21:11:34 switch99 systemd[1]: Finished nfs-server.service - NFS server and services.
验证:
ps -ef | grep nfs
输出为:
root 4438 1 0 20:24 ? 00:00:00 /usr/sbin/nfsdcld
root 6682 2 0 21:11 ? 00:00:00 [nfsd]
root 6683 2 0 21:11 ? 00:00:00 [nfsd]
root 6684 2 0 21:11 ? 00:00:00 [nfsd]
root 6685 2 0 21:11 ? 00:00:00 [nfsd]
root 6686 2 0 21:11 ? 00:00:00 [nfsd]
root 6687 2 0 21:11 ? 00:00:00 [nfsd]
root 6688 2 0 21:11 ? 00:00:00 [nfsd]
root 6689 2 0 21:11 ? 00:00:00 [nfsd]
查看当前挂载情况:
sudo showmount -e
输出为:
Export list for switch99:
/exports 192.168.0.0/255.255.0.0
nfs客户端
pve nfs storage
在 pve 下,点击 “datacenter” -> “storage” -> “Add”
备注: nfs version 这里无法选择 4 / 4.1 / 4.2,只能选择 default 。后续再看。
完成这个设置之后,该集群内的任何一台机器上,都会出现一个 /mnt/pve/nfs99
目录,mount 到 上面的 nfs exports。之后就可以通过这个目录像访问本地文件夹一样访问nfs。
清理 /mnt/pve
目录
如果多次操作 nfs 存储,比如添加后再删除,则在 /mnt/pve/nfs99
目录下会残留一些数据,如:
ls -la
ls: cannot access 'nfs-test11': Stale file handle
total 12
drwxr-xr-x 4 root root 4096 Mar 18 22:26 .
drwxr-xr-x 3 root root 4096 Mar 18 22:23 ..
drwxr-xr-x 7 nobody nogroup 4096 Mar 18 22:26 nfs99
d????????? ? ? ? ? ? nfs-test11
这个 nfs-test11 就是删除之后的残余,不能直接删除:
rm -rf nfs-test11
rm: cannot remove 'nfs-test11': Is a directory
而是要使用 umount 命令:
$ sudo umount nfs-test11
$ ls -la
total 16
drwxr-xr-x 4 root root 4096 Mar 18 22:26 .
drwxr-xr-x 3 root root 4096 Mar 18 22:23 ..
drwxr-xr-x 7 nobody nogroup 4096 Mar 18 22:26 nfs99
drwxr-xr-x 2 root root 4096 Mar 18 22:23 nfs-test11
$ sudo rm -rf nfs-test11
复制 pve 文件
在 pve 页面上查看 backup 里面需要复制的备份,主要看虚拟机 id 和时间。
对于已经加入 pve 集群的机器,本地已经 mount 了 /mnt/pve/nfs99
目录,因此可以直接执行 cp 命令复制到 nfs 上:
cp /var/lib/vz/dump/vzdump-qemu-101-2024_02_12-16_13_09.* /mnt/pve/nfs99/dump
对于还没有加入 pve 集群的机器,需要先手工 mount nfs 到本地:
sudo mkdir -p /mnt/pve/nfs
sudo mount.nfs 192.168.0.99:/exports/pve-share /mnt/pve/nfs
# mount.nfs4 会报错,暂时不清楚问题出在哪里,mount.nfs 就可以正常使用
# sudo mount.nfs4 192.168.0.99:/exports/pve-share /mnt/pve/nfs
然后再复制 backup 文件:
cp /var/lib/vz/dump/vzdump-qemu-101-2024_02_12-16_13_09.* /mnt/pve/nfs/dump
为了方便备份各个机器独有的文件(而不是模版等可以共享的文件),在这个 nfs 目录下新建一个 node-backup 目录,并为每个节点建立一个子目录:
mkdir -p /mnt/pve/nfs/node-backup/skyserver4/dump
然后就可以复制
cp xxxx /mnt/pve/nfs/node-backup/skyserver4/dump
参考资料
4.2 - 用虚拟机实现的SSD NAS存储
构想
在前面实现的软交换的基础上,直通一块 4t 的国产 pcie4 ssd 进入(型号为爱国者 p7000z),实现一个小型的纯 SSD NAS。
未来可能会陆续加入多块 ssd 进行扩容。
这样就实现了 25g 网络 + 高速 SSD 的 NAS。
准备工作
准备虚拟机
之前的利用 linux bridge 实现软交换的解决方案中,已经建立了一个名为 skynas3 的虚拟机。
基于 25g 网卡的高速网络已经满足。
硬盘直通
在开启 pve 直通的基础上,将硬盘直通到 skynas3 虚拟机中。
能看到这块 ssd 硬盘:
$ lspci | grep Non-Volatile
03:00.0 Non-Volatile memory controller: MAXIO Technology (Hangzhou) Ltd. NVMe SSD Controller MAP1602 (rev 01)
因为硬盘没有分区,所以看起来是这样:
lsblk -l
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 512G 0 disk
sda1 8:1 0 512M 0 part /boot/efi
sda2 8:2 0 465.7G 0 part /
sda3 8:3 0 45.8G 0 part /timeshift
sr0 11:0 1 3.7G 0 rom
nvme0n1 259:0 0 3.7T 0 disk
sda 是虚拟机的磁盘,虚拟了 512g。
nvme0n1 是直通进来的 ssd 硬盘,4t 大小但实际为 3.7 T。
用 fdisk 看更清晰一些:
$ sudo fdisk -l
[sudo] password for sky:
Disk /dev/sda: 512 GiB, 549755813888 bytes, 1073741824 sectors
Disk model: QEMU HARDDISK
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: D53AE25D-B704-4192-A436-54BD53A9DAC0
Device Start End Sectors Size Type
/dev/sda1 2048 1050623 1048576 512M EFI System
/dev/sda2 1050624 977612799 976562176 465.7G Linux filesystem
/dev/sda3 977612800 1073739775 96126976 45.8G Linux filesystem
Disk /dev/nvme0n1: 3.73 TiB, 4096805658624 bytes, 8001573552 sectors
Disk model: aigo NVMe SSD P7000Z 4TB
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 9F1409D0-DA10-5446-8662-4ADAFBF1128F
硬盘分区
sudo fdisk /dev/nvme0n1
g 转为 GPT partition table p 打印分区表 n 创建新分区,这里就只创建一个4t的大分区给 nas 用。
参考:
分区完成后查看这块硬盘的情况:
$ sudo fdisk -l
Disk /dev/nvme0n1: 3.73 TiB, 4096805658624 bytes, 8001573552 sectors
Disk model: aigo NVMe SSD P7000Z 4TB
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: BCA9FF34-B3F2-B44D-B385-041E061B8F52
Device Start End Sectors Size Type
/dev/nvme0n1p1 2048 8001572863 8001570816 3.7T Linux filesystem
将这个分区格式化为 ext4 格式:
sudo mkfs.ext4 /dev/nvme0n1p1
mke2fs 1.47.0 (5-Feb-2023)
Discarding device blocks: done
Creating filesystem with 1000196352 4k blocks and 250052608 inodes
Filesystem UUID: 1b50172f-44fd-46a3-8499-b169d7d91eac
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968,
102400000, 214990848, 512000000, 550731776, 644972544
Allocating group tables: done
Writing inode tables: done
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: done
挂载分区
查看 ssd 分区的 uuid:
sudo lsblk -f
[sudo] password for sky:
NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS
sda
├─sda1 vfat FAT32 80D7-F301 505.1M 1% /boot/efi
├─sda2 ext4 1.0 59bbb3ad-27e7-4e1e-b40e-0e6a8a8386cc 430.8G 1% /
└─sda3 ext4 1.0 d5aaad4b-8382-4153-adfc-f7c797e74ee5 38.6G 9% /timeshift
nvme0n1
└─nvme0n1p1 ext4 1.0 b4e82288-5290-4d64-a45e-94c4ef657611
执行
sudo vi /etc/fstab
查看目前现有的三个分区的挂载情况:
# / was on /dev/sda2 during installation
UUID=59bbb3ad-27e7-4e1e-b40e-0e6a8a8386cc / ext4 errors=remount-ro 0 1
# /boot/efi was on /dev/sda1 during installation
UUID=80D7-F301 /boot/efi vfat umask=0077 0 1
# /timeshift was on /dev/sda3 during installation
UUID=d5aaad4b-8382-4153-adfc-f7c797e74ee5 /timeshift ext4 defaults 0 2
增加第一块 ssd 硬盘的挂载,挂载到 “/mnt/storage1”:
# /storage1 was on /dev/nvme0n1p1(aigo p7000z 4t)
UUID=b4e82288-5290-4d64-a45e-94c4ef657611 /mnt/storage1 ext4 defaults 0 2
重启机器。再看一下分区挂载情况:
$ sudo lsblk -f
NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS
sda
├─sda1 vfat FAT32 80D7-F301 505.1M 1% /boot/efi
├─sda2 ext4 1.0 59bbb3ad-27e7-4e1e-b40e-0e6a8a8386cc 430.7G 1% /
└─sda3 ext4 1.0 d5aaad4b-8382-4153-adfc-f7c797e74ee5 38.6G 9% /timeshift
nvme0n1
└─nvme0n1p1 ext4 1.0 b4e82288-5290-4d64-a45e-94c4ef657611 3.5T 0% /mnt/storage1
准备共享目录
为了方便后续的管理,采用伪文件系统:
cd /mnt/storage1
sudo mkdir share
sudo mkdir pve-share
sudo chown -R nobody:nogroup /mnt/storage1/share
sudo chown -R nobody:nogroup /mnt/storage1/pve-share
创建 export 目录:
sudo mkdir -p /exports/{share,pve-share}
sudo chown -R nobody:nogroup /exports
修改 /etc/fstab
文件来 mount 伪文件系统和 exports
sudo vi /etc/fstab
增加如下内容:
# nfs exports
/mnt/storage1/share /exports/share none bind
/mnt/storage1/pve-share /exports/pve-share none bind
重启。
搭建 nas
安装 nfs server
# 安装
sudo apt install nfs-kernel-server -y
# 开机自启
sudo systemctl start nfs-kernel-server
sudo systemctl enable nfs-kernel-server
# 验证
sudo systemctl status nfs-kernel-server
Jan 29 20:40:15 skynas3 systemd[1]: Starting nfs-server.service - NFS server and services...
Jan 29 20:40:15 skynas3 exportfs[1422]: exportfs: can't open /etc/exports for reading
Jan 29 20:40:16 skynas3 systemd[1]: Finished nfs-server.service - NFS server and services.
配置 nfs v4
sudo vi /etc/default/nfs-common
修改内容如下
NEED_STATD="no"
NEED_IDMAPD="yes"
继续修改 nfs-kernel-server 的配置:
sudo vi /etc/default/nfs-kernel-server
修改内容:
# 这行新增
RPCNFSDOPTS="-N 2 -N 3"
# 这行已经存在,修改内容
RPCMOUNTDOPTS="--manage-gids -N 2 -N 3"
# 其他不动
配置 nfs export
sudo vi /etc/exports
修改 nfs exports 的内容,这里我们先 export 第一块4t ssd 硬盘的 share/pve-share 目录:
/exports/share 192.168.0.0/16(rw,no_root_squash,no_subtree_check,crossmnt,fsid=0)
/exports/pve-share 192.168.0.0/16(rw,no_root_squash,no_subtree_check,crossmnt,fsid=0)
重启 nfs-kernel-server,查看 nfs-kernel-server 的状态:
sudo systemctl restart nfs-kernel-server
sudo systemctl status nfs-kernel-server
输出为:
nfs-server.service - NFS server and services
Loaded: loaded (/lib/systemd/system/nfs-server.service; enabled; preset: enabled)
Drop-In: /run/systemd/generator/nfs-server.service.d
└─order-with-mounts.conf
Active: active (exited) since Wed 2024-03-20 23:09:19 EDT; 17ms ago
Process: 863 ExecStartPre=/usr/sbin/exportfs -r (code=exited, status=0/SUCCESS)
Process: 864 ExecStart=/usr/sbin/rpc.nfsd (code=exited, status=0/SUCCESS)
Main PID: 864 (code=exited, status=0/SUCCESS)
CPU: 7ms
Mar 20 23:09:19 skynas3 systemd[1]: Starting nfs-server.service - NFS server and services...
Mar 20 23:09:19 skynas3 systemd[1]: Finished nfs-server.service - NFS server and services.
验证:
ps -ef | grep nfs
输出为:
ps -ef | grep nfs
root 714 1 0 23:04 ? 00:00:00 /usr/sbin/nfsdcld
root 866 2 0 23:09 ? 00:00:00 [nfsd]
root 867 2 0 23:09 ? 00:00:00 [nfsd]
root 868 2 0 23:09 ? 00:00:00 [nfsd]
root 869 2 0 23:09 ? 00:00:00 [nfsd]
root 870 2 0 23:09 ? 00:00:00 [nfsd]
root 871 2 0 23:09 ? 00:00:00 [nfsd]
root 872 2 0 23:09 ? 00:00:00 [nfsd]
root 873 2 0 23:09 ? 00:00:00 [nfsd]
查看当前挂载情况:
sudo showmount -e
输出为:
Export list for skynas3:
/exports/pve-share 192.168.0.0/16
/exports/share 192.168.0.0/16
nfs客户端
pve nfs storage
在 pve 下,点击 “datacenter” -> “storage” -> “Add”
备注: nfs version 这里无法选择 4 / 4.1 / 4.2,只能选择 default 。后续再看。
完成这个设置之后,该集群内的任何一台机器上,都会出现一个 /mnt/pve/nfs99
目录,mount 到 上面的 nfs exports。之后就可以通过这个目录像访问本地文件夹一样访问nfs。
遇到的问题
nfs 残余数据
期间遇到一个问题,我先创建了一个 nfs storage,指向了 share 目录。后来发现需要 export 两个目录,普通 share 和 pve 专用的 pve-share,避免将两者的文件混合起来。
然后就遇到问题:旧的 nfs storage 删除之后,再创建同名的 nfs storage 指向新的 pve-share,但实际操作的依然是旧的 share。反复尝试过各种方法都无效。
- 清理
/mnt/pve/
目录 - 清理
/var/lib/rrdcached/db/pve2-storage/
目录
sudo find / -type f -exec grep "nfs02" {} \;
grep: /var/log/journal/4ba9084c7be94c57a943bf7c2aa034a5/system.journal: binary file matches
update /var/lib/rrdcached/db/pve2-storage/skyaio2/nfs02 1710992038:4031332220928:0
只好在清理完这些信息之后,再用一个新的名字重新创建 nfs storage,比如 nfs02-ssd 。
参考资料
5 - 开发
5.1 - 准备工作
准备虚拟机
从模版 template-debian12.4-basic 克隆一个虚拟机,命名为 dev101.
开发需要的 cpu 和内存稍大,修改虚拟机参数,cpu 修改为 16核,内存 32g。
基本配置修改
修改 hostname 和 使用静态 IP 地址。
准备 ssh 证书
从其他开发机器复制 ssh 证书过来,或者重新生成一份:
scp id_rsa.pub sky@192.168.0.101:/home/sky/.ssh/
scp id_rsa sky@192.168.0.101:/home/sky/.ssh/
准备通用工具
安装 sdkman
参考:
- https://skyao.io/learning-ubuntu-server/docs/development/common/sdkman.html
- https://skyao.io/learning-macos/docs/programing/common/sdkman.html
sudo apt install unzip zip
curl -s "https://get.sdkman.io" | bash
source "/home/sky/.sdkman/bin/sdkman-init.sh"
sdk version
sdk install java 17.0.10-zulu
5.2 - Dapr
5.2.2 - Java
安装 jdk
安装 jdk17
sdk install java 17.0.10-zulu
验证:
java --version
openjdk 17.0.10 2024-01-16 LTS
OpenJDK Runtime Environment Zulu17.48+15-CA (build 17.0.10+7-LTS)
OpenJDK 64-Bit Server VM Zulu17.48+15-CA (build 17.0.10+7-LTS, mixed mode, sharing)
安装 maven
sdk install maven 3.9.6
验证:
$ mvn --version
Apache Maven 3.9.6 (bc0240f3c744dd6b6ec2920b3cd08dcc295161ae)
Maven home: /home/sky/.sdkman/candidates/maven/current
Java version: 17.0.10, vendor: Azul Systems, Inc., runtime: /home/sky/.sdkman/candidates/java/17.0.10-zulu
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "6.1.0-17-amd64", arch: "amd64", family: "unix"