1 - 介绍

debian 的介绍,以及 debian 的资料收集

1.1 - debian介绍

debian介绍

1.2 - 资料收集

收集 debian 的各种资料

官方资料

社区资料

学习资料

2 - 安装

debian 的安装和基本设置

2.1 - 下载debian

下载 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 - 物理机安装

在物理机上安装 debian 12.7

准备工作

安装版本

更新时间是 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安装

在 pve8.1 下安装 debian 12.4

准备工作

创建虚拟机

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安装

组建 raid 设备并安装 debian 12

先准备好两块硬盘,重新分区,并保持两个硬盘的分区方案一致。

第一块硬盘,先后分区为:

  • 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 - 安装完成后的基本配置

在 debian 12.4 安装完成后的基本配置

2.5.1 - timeshift

安装配置 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修改

修改默认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设置

增加账号的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

安装配置 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 软件来进行转换。

https://www.privoxy.org/

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 - 克隆后的配置

在 debian 12.4 从模版克隆后的配置

在使用 pve 等虚拟化软件时,为了方便重用,会将配置好的 debian 系统制作成模版,然后使用时从模版克隆出来。

这样就会有一些特殊的配置需要在克隆之后进行。

2.6.1 - 修改hostname

克隆后修改hostname

参考:

https://skyao.io/learning-ubuntu-server/docs/installation/basic/change-hostname

2.6.2 - 静态IP地址

克隆后设置静态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 - 网络

利用 debian 12.4 实现的一些网络方案

3.1 - 使用qbittorrent

在debian12下利用qbittorrent实现PT下载

选择版本

让我们快速了解一下 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/ ,默认登录用户/密码为 adminadminadmin

  • 下载

    • 默认保存路径:"/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实现软交换

在 debian12 下利用 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 - 网卡片上卸载

在 debian 12 下利用cx5网卡的片上卸载功能降低cpu占用

背景

前面用 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 - 存储

利用 debian 12.4 实现的一些存储方案

4.1 - 用物理机实现的SSD NAS存储

利用 debian 12 在物理机上实现的 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存储

利用 debian 12.4 在 pve 虚拟机中实现的 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 - 开发

在 debian 12.4 上搭建编程开发环境

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

参考:

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

在 debian 12.4 上搭建 Dapr 项目的编程开发环境

5.2.1 - Go

搭建 Go 编程开发环境

安装 go

https://go.dev/dl/

这里可以看到 go 的最新版本

5.2.2 - Java

搭建 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"