机器配置

商品名称:幻网 7505 软路由
CPU: Intel Pentium Gold 7505 (2C4T 11代)
GPU: Intel UHD Graphics for 11th Gen Intel® Processors (核显)
显示接口: HDMI+DP
内存插槽: DDR4 32GB(MAX) 3200MHz x2
硬盘接口: PCI-E x4 M.2 NVME x1
网卡: Intel I226-V x6 (2.5Gbps)
外部接口: USB 3.0 x2, USB 2.0 x2, COM x1, USB Type-C x1
内部接口: SATA 3.0 x1, M.2 WIFI
PVE: v8.1.3

小坑

Debian 11 LXC容器

IPv6获取方式不正确会导致启动极慢

参考帖子(reddit)

前一阵子把家里的IPv6分配改成SLAAC方式,在PVE主机对所有guest备份完成后,发现域名访问断联,排查半天发现反代的LXC容器一直没跑起来,后来翻到这个帖子

大致原因是设置DHCPv6方式获取的Debian 11容器会一直等待地址分配直到超时失败,上游网关如果没有DHCPv6分配功能的话,一定要改成SLAAC方式或者干脆停掉容器的IPv6

前置

PVE换源

wget https://mirrors.ustc.edu.cn/proxmox/debian/proxmox-release-bookworm.gpg -O /etc/apt/trusted.gpg.d/proxmox-release-bookworm.gpg
echo "#deb https://enterprise.proxmox.com/debian/pve bookworm pve-enterprise" > /etc/apt/sources.list.d/pve-enterprise.list
echo "deb https://mirrors.ustc.edu.cn/proxmox/debian/pve bookworm pve-no-subscription" > /etc/apt/sources.list.d/pve-no-subscription.list

Debian换源

# 备份文件
mv /etc/apt/sources.list /etc/apt/sources.list.bak
nano /etc/apt/sources.list

# nano编辑之后填入以下内容
deb https://mirrors.ustc.edu.cn/debian bookworm main contrib non-free
deb https://mirrors.ustc.edu.cn/debian bookworm-updates main contrib non-free
deb https://mirrors.ustc.edu.cn/debian-security bookworm-security main contrib non-free

# 或者直接运行
echo -e "deb https://mirrors.ustc.edu.cn/debian bookworm main contrib non-free\ndeb https://mirrors.ustc.edu.cn/debian bookworm-updates main contrib non-free\ndeb https://mirrors.ustc.edu.cn/debian-security bookworm-security main contrib non-free" > /etc/apt/sources.list

Ceph换源

nano /etc/apt/sources.list.d/ceph.list

# nano编辑之后填入以下内容
#deb https://enterprise.proxmox.com/debian/ceph-quincy bookworm enterprise
deb https://mirrors.ustc.edu.cn/proxmox/debian/ceph-quincy/ bookworm no-subscription

# 或者直接运行
echo -e "#https://enterprise.proxmox.com/debian/ceph-quincy bookworm enterprise\ndeb https://mirrors.ustc.edu.cn/proxmox/debian/ceph-quincy/ bookworm no-subscription" > /etc/apt/sources.list.d/ceph.list

# 备份ceph.pm
cp /usr/share/perl5/PVE/CLI/pveceph.pm /usr/share/perl5/PVE/CLI/pveceph.pm.bak

# 替换内部链接
sed -i 's|http://download.proxmox.com|https://mirrors.ustc.edu.cn/proxmox|g' /usr/share/perl5/PVE/CLI/pveceph.pm

CT模板换源

# 备份
cp /usr/share/perl5/PVE/APLInfo.pm /usr/share/perl5/PVE/APLInfo.pm_back

# 替换内部链接
sed -i 's|http://download.proxmox.com|https://mirrors.ustc.edu.cn/proxmox|g' /usr/share/perl5/PVE/APLInfo.pm

# 更换后重启daemon
systemctl restart pvedaemon

额外修改

解决 apt update时提示 non-free变为 non-free-firmware问题

su -c 'echo "APT::Get::Update::SourceListWarnings::NonFreeFirmware \"false\";" > /etc/apt/apt.conf.d/no-bookworm-firmware.conf'

去除每次界面登录时提示 no subscription提示

sed -Ezi.bak "s/(Ext.Msg.show\(\{\s+title: gettext\('No valid sub)/void\(\{ \/\/\1/g" /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js && systemctl restart pveproxy.service

开启硬件直通

BIOS中打开硬件直通相关选项(VT-d & VMX)

默认lvm+UEFI方式安装系统

# 编辑Grub
nano /etc/default/grub

# 注释掉原来的,增加iommu参数,AMD CPU是amd_iommu=on
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on"

# 编辑modules
nano /etc/modules

# 添加以下内容
vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd

# 刷新引导参数
update-grub
update-initramfs -u -k all

# 最后重启
reboot

使用UEFI+ZFS方式安装系统

官方wiki

官方社区讨论帖

[网络教程]()

# 编辑/etc/kernel/cmdline
nano /etc/kernel/cmdline

# 在这一行加入intel_iommu=on
root=ZFS=rpool/ROOT/pve-1 boot=zfs intel_iommu=on iommu=pt

# 刷新EFI Boot分区
pve-efiboot-tool refresh

# 添加以下内容
vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd

# 刷新引导参数
update-grub
pve-efiboot-tool refresh
update-initramfs -u -k all

# 最后重启
reboot

解决图表信息无法显示(illegal attempt to update using time)

原因是rrd服务与系统时间不符,需要清除已有数据再重启服务和cluster

systemctl stop rrdcached
cd /var/lib/
mv rrdcached rrdcached.bck
systemctl start rrdcached
systemctl restart pve-cluster

Nginx反代web gui

网关需要转发一个外部可用端口,同时反代PVE的web gui以及虚拟机控制台的SPICE模式

Server{}模块:

# 反代web gui
  location / {
    proxy_pass https://192.168.9.254:8006;
    proxy_buffering off;
    client_max_body_size 0;
    proxy_connect_timeout  3600s;
    proxy_read_timeout  3600s;
    proxy_send_timeout  3600s;
    send_timeout  3600s;
  }

Stream{}模块

server {
  listen 3128;
  proxy_pass 192.168.9.254:3128;
}

LXC容器部署Docker

在前置工作里已经给CT模板换源了,可以直接在local存储里下载Debian 11模板

这里使用 debian-11-standard_11.7-1模板

(施工中)

Unprivileged LXC容器的数据互通

宿主机PVE互通

事先提醒: 如果不需要这种无特权容器的权限隔离功能,完全可以直接在创建容器时将 无特权的容器选项取消勾选,这样 hostguest就共用一套用户权限方案,避免很多 guest内部与 host交互上可能出现的问题

参考文章: proxmox_bind_unprivileged_lxc

无特权的容器(unprivileged container)内,PVE会将容器(后面都称作 guest)内的 usergroup权限与宿主机建立映射关系,默认映射关系是宿主机 (后面都称作 host)的 uid以及 gid同时+100000,即

UIDUIDGIDGID
hostguesthostguest
01000000100000
10001010001000101000
............
655351065535655351065535

容器作为 guest,内部用户的权限只能在 host内操作相对应用户权限的文件以及文件夹,即

host ownerguest owner
100000:1000000:0
101000:1010001000:1000

这种映射关系的好处在于可以将LXC guesthost的数据权限隔离,即使容器内服务被人攻破,也能隔离掉对宿主机的操作

如果想保留这种权限隔离的状态,但又需要让 guesthost之间交互,根据上述参考文章有两种方案

以ID为 100的Docker LXC举例,在 host建立文件夹/mnt/100,在 guest建立文件夹/mnt/host-data

方案1

host建立属于对应 guest内部用户的挂载点,并在 host修改挂载点 ownerguest映射的用户

host操作
# host操作
mkdir /mnt/100
chown -R 100000:100000 /mnt/100

# guest操作(以root用户执行)
mkdir /mnt/host-data

# 执行以下命令生成挂载点, pct set <container_id> -mp0 <host_mountpoint>,mp=<guest_mountpoint>
pct set 100

# 或者添加以下内容到/etc/pve/lxc/100.conf并保存, mp<id>: <host_mountpoint>,mp:=<guest_path>
mp0: /mnt/100,mp:=/mnt/host-data
guest操作
# 创建挂载点
mkdir /mnt/host-data

最后重启 guest容器生效,guest内用 root用户读写 /mnt/host-data

方案2

修改默认的用户映射关系,让 host的特定用户和用户组与 guest对照起来,即

UIDUIDGIDGID
hostguesthostguest
1005100510051005

相应的文件夹所有权设置为

host ownerguest owner
1005:10051005:1005

后续只使用 1005:1005hostguest之间交互,其他id正常映射

host操作
# 修改owner
chown -R 1005:1005 /mnt/105

# 为host的root用上添加subuid和subgid
echo "root:1005:1" >> /etc/subuid
echo "root:1005:1" >> /etc/subgid

# 添加以下内容到/etc/pve/lxc/105.conf并保存, mp<id>: <host_path>,mp:=<guest_path>
mp0: /mnt/105,mp:=/mnt/host-data
lxc.idmap = u 0 100000 1005
lxc.idmap = g 0 100000 1005
lxc.idmap = u 1005 1005 1
lxc.idmap = g 1005 1005 1
lxc.idmap = u 1006 101006 64530
lxc.idmap = g 1006 101006 64530

以上 lxc.idmap = <u or g> a b n作用为从a映射b开始,一共映射1005个uid或gid,上述6行即

hostguest
0:0100000:100000
1:1100001:100001
......
1004:1004101004:101004
1005:10051005:1005
1006:1006101006:101006
65535:65535165535:165535
guest操作

与方案1的guest操作一致

优缺点对比
方案1

优点

  • 配置迅速简单
  • 不更改变动原有的LXC用户权限映射功能

缺点

  • 需要用户自己记忆管理 hostguest之间的用户权限对应关系,比如要记住 host100000:100000对应的是 ID 100guest0:0(root:root)
方案2

优点

  • hostguest之间建立一一对应的权限映射关系,比如 host1005:1005对应的也是 guest1005:1005

缺点

  • 配置繁琐,本质上和方案1的缺点一样需要把控好权限映射关系
  • Unprivileged LXC的权限隔离目的部分丧失,让 host的权限管理变复杂

个人总结

个人倾向于方案1

如果容器内部不需要做额外的权限管控,可以让 host的高UID&GID用户一一对应每个 guestroot(0:0)用户,这样可以简化权限映射关系的管控,即

100000:100000 -> ID:100 的 root

100001:100001 -> ID:101 的 root

100005:100005 -> ID:105 的 root

需要跟进操作的仅仅是

chown -R 100000:100000 /mnt/100

chown -R 100001:100001 /mnt/101

chown -R 100005:100005 /mnt/105

mp0: /mnt/100,mp:=/mnt/host-data -> /etc/pve/lxc/100.conf

mp0: /mnt/102,mp:=/mnt/host-data -> /etc/pve/lxc/102.conf

mp0: /mnt/105,mp:=/mnt/host-data -> /etc/pve/lxc/105.conf

NAS互通

区别在于需要在宿主机PVE上进行远程挂载,以下使用我的群晖NAS smb共享并采用上述方案1进行权限管控

在NAS创建相关的用户以及目录后,主要操作在 host

host操作
vim /etc/fstab

# 使用vim编辑fstab并添加以下内容
# //NAS_IP/path <> cifs username=<smb_user>,password=<smb_password>,uid=100000,gid=100000 0 0
//192.168.9.11/pve/100 /mnt/100 cifs username=<smb_user>,password=<smb_password>,uid=100000,gid=100000 0 0

# :wq保存退出后让挂载生效
mount -av

# 重启daemon,让PVE下次启动按修改版的fstab挂载smb
systemctl daemon-reload

注意后面的UID和GID至关重要,需要和 guest内部的 root用户对应

guest操作
# 执行以下命令生成挂载点, pct set <container_id> -mp0 <host_mountpoint>,mp=<guest_mountpoint>
pct set 100 -mp0 /mnt/100,mp=/mnt/nas

最后重启 guest容器生效

备份与还原

备份

还原

vzdump备份任务hook script

PVE会一直对SMB共享存储刷新状态保持连接,大概10秒以此,会导致对应的共享设备的硬盘和系统无法进入休眠或者持续不断产生SMB访问日志,需要平时停用共享,然后做一个hook script在vzdump备份初始化时自动启用,在完成后自动停止

编辑/etc/vzdump.conf,添加script路径

vim /etc/vzdump.conf

script: /opt/scripts/vzdump-hook-script.pl

:wq

然后根据/usr/share/doc/pve-manager/examples/vzdump-hook-script.pl编写job-init和job-end或job-aboart情况下的自动启用/停用脚本

# nas-backup换成对应的存储id, 可以在数据中心的存储那找到
    if ($phase eq 'job-init') {
        if ($storeid eq 'nas-backup') {
            system ("/usr/sbin/pvesm set $storeid --disable 0") == 0 ||
                die "enabling storage $storeid failed";
        }
    }

#nas-backup换成对应的存储id, 可以在数据中心的存储那找到
    if (($phase eq 'job-end') || ($phase eq 'job-abort')) {
        if ($storeid eq 'nas-backup') {
            system ("/usr/sbin/pvesm set $storeid --disable 1") == 0 ||
                die "disabling storage $storeid failed";
        }
    }

之后在备份vzdump就会自动启用和停用挂载

常用指令

qm

qm <命令> <vmid> [选项]
qm [create|set] <vmid>  # 创建虚拟机
    --memory  <MBYTES>    memory in MB (64 - 8192)
    --sockets <N>         set number of CPU sockets <N>
    --cores <N>           set cores per socket to <N>
    --ostype NAME         specify OS type
    --onboot [yes|no]     start at boot
    --keyboard XX         set vnc keyboard layout
    --cpuunits <num>      CPU weight for a VM
    --name <text>         set a name for the VM
    --description <text>  set VM description
    --boot [a|c|d|n]      specify boot order
    --bootdisk <disk>     enable booting from <disk>
    --acpi (yes|no)       enable/disable ACPI
    --kvm (yes|no)        enable/disable KVM
    --tdf (yes|no)        enable/disable time drift fix
    --localtime (yes|no)  set the RTC to local time
    --vga (gd5446|vesa)   specify VGA type
    --vlan[0-9u]          MODEL=XX:XX:XX:XX:XX:XX[,MODEL=YY:YY:YY:YY:YY:YY]
    --ide<N>              [volume=]volume,[,media=cdrom|disk]
                          [,cyls=c,heads=h,secs=s[,trans=t]]
                          [,cache=none|writethrough|writeback]
                          [,snapshot=on|off][,cache=on|off][,format=f]
                          [,werror=enospc|ignore|report|stop]
                          [,rerror=ignore|report|stop]
                          [,backup=no|yes]
    --ide<N> <GBYTES>     create new disk
    --ide<N> delete       remove drive - destroy image
    --ide<N> undef        remove drive - keep image
    --cdrom <file>        is an alias for --ide2 <file>,media=cdrom
    --scsi<N>             [volume=]volume,[,media=cdrom|disk]
                          [,cyls=c,heads=h,secs=s[,trans=t]]
                          [,snapshot=on|off][,format=f]
                          [,cache=none|writethrough|writeback]
                          [,werror=enospc|ignore|report|stop]
                          [,backup=no|yes]
    --scsi<N> <GBYTES>    create new disk
    --scsi<N> delete      remove drive - destroy image
    --scsi<N> undef       remove drive - keep image
    --virtio<N>           [volume=]volume,[,media=cdrom|disk]
                          [,cyls=c,heads=h,secs=s[,trans=t]]
                          [,snapshot=on|off][,format=f]
                          [,cache=none|writethrough|writeback]
                          [,werror=enospc|ignore|report|stop]
                          [,rerror=ignore|report|stop]
                          [,backup=no|yes]
    --virtio<N> <GBYTES>  create new disk
    --virtio<N> delete    remove drive - destroy image
    --virtio<N> undef     remove drive - keep image
qm monitor <vmid>         # 连接到虚拟机控制监视器
qm start <vmid>               # 启动实例
qm shutdown <vmid>      # 优雅停止实例 发送关机命令
qm wait <vmid> [time]   wait until vm is stopped
qm stop <vmid>               # 停止实例 强制停止
qm reset <vmid>              # 重启实例 相当于stop然后再start
qm suspend <vmid>        # 暂停实例
qm resume <vmid>         # 恢复实例
qm cad <vmid>               #发送按键 ctrl-alt-delete
qm destroy <vmid>        # 销毁实例(删除所有已使用/拥有的卷)
qm unlock <vmid>         # 清除迁移/备份锁
qm status <vmid>          # 显示实例状态
qm cdrom <vmid> [<device>] <path>  set cdrom path. <device is ide2 by default>
qm cdrom <vmid> [<device>] eject   eject cdrom
qm unlink <vmid> <volume>  delete unused disk images
qm vncproxy <vmid> <ticket>  open vnc proxy
qm vnc <vmid>           start (X11) vncviewer (experimental)
qm showcmd <vmid>     # 显示命令行(调试信息)
qm list                             # 列出所有虚拟机
qm startall                       # 启动所有虚拟机 当onboot=1时
qm stopall [timeout]       # 停止所有虚拟机(默认超时为3分钟)
最后修改:2024 年 03 月 10 日
个人分享,随意打赏