PVE 网络异常下的工程性止损方案:从虚拟机自愈幻想到宿主机重启策略

一、问题背景 在基于 PVE(Proxmox VE)的单节点虚拟化环境中,宿主机偶发网络异常,表现为: 该现象在家用硬件、非 HA、bridge 网络架构中具有一定普遍性。 二、初始假设与验证路径 1. 虚拟机网卡模型假设 最初怀疑为 VirtIO 在宿主机网络异常时放大问题,因此进行了如下验证: 2. 验证结果 结论: 问题不在虚拟机网卡模型层面 三、systemd + bridge + KVM 的一致性边界 在异常场景下,宿主机通常通过: 恢复网络。 该操作在 systemd + bridge 环境中会导致: 此时虚拟机网络栈处于: 逻辑上未崩溃,但状态不可预测 这是虚拟化架构本身的边界问题,而非配置错误。 四、关键工程结论 经过多轮实测,可得出以下结论: 最终结论: 当宿主机发生网络中断时,最可靠的策略是直接重启宿主机 因为宿主机重启可以同时完成: 五、设计目标的转变 设计目标从: “尽量让虚拟机自己恢复网络” 转变为: “一旦检测到宿主机网络中断,直接重启宿主机,保证整体收敛” 这是典型的工程止损决策,而非妥协。 六、最终方案:宿主机网络监控 + 自动重启 方案原则 七、宿主机网络重启 Watchdog …

通过公网 Pull 模式实现 Raspberry Pi 的长期增量灾备方案

摘要 在 Raspberry Pi 等长期运行设备中,SD 卡依然是最常见、也是最不可靠的存储介质之一。异常断电、磨损老化或 silent corruption 往往在系统仍可运行时悄然发生,一旦彻底失效,恢复成本极高。 本文记录了一套 与设备物理位置无关的 Raspberry Pi 灾备方案:通过公网 SSH,以 备份机主动拉取(pull) 的方式,对远端树莓派的根文件系统进行 持续增量备份,在不影响系统运行的前提下,确保随时具备完整恢复能力。 设计目标 总体设计思路 1. 连接模型:Pull 而非 Push 备份由 备份机主动发起: 该模型符合最小权限原则,也更适合嵌入式设备长期运行。 2. 标识方式:域名而非 IP 使用域名作为唯一入口: 只要 SSH 可达,系统即可被完整拉取。 3. 备份粒度:文件级增量镜像 放弃块级复制(dd),采用 rsync: 核心实现 rsync 参数选择 关键参数说明: 参数 作用 -a 保留权限、时间戳、符号链接 -A 保留 ACL -X …

FRPS 中 QUIC 监听端口的协议类型与配置取舍分析

背景 在使用 FRP(Fast Reverse Proxy)进行内网穿透时,FRPS(服务器端)的通信端口配置直接影响系统的稳定性、安全性以及后续的运维复杂度。 随着 FRP 新版本引入基于 QUIC 的传输方式,配置项中新增了 QUIC 相关监听参数,这使得服务器端可能同时存在多种控制通道实现方式,有必要对其协议属性与实际影响进行明确分析。 QUIC 监听端口的协议属性 结论明确: FRPS 中用于 QUIC 的监听端口基于 UDP 协议 原因在于: 协议层级关系如下: 因此: 传统控制端口与 QUIC 控制端口的差异 FRPS 提供两种功能等价的控制通道实现方式: 项目 传统控制通道 QUIC 控制通道 底层协议 TCP UDP 连接可靠性 由 TCP 提供 由 QUIC 协议实现 网络兼容性 高 依赖 UDP 质量 运维复杂度 较低 …

Nextcloud 中 imagick 无法识别 SVG 的问题排查记录

问题描述 在 Nextcloud 管理后台的 Security & setup warnings 中出现如下提示: The PHP module “imagick” in this instance has no SVG support. 具体表现为: 环境背景(概述) 初步判断 系统层 ImageMagick 验证 通过系统命令确认: 结论: 系统层 ImageMagick 支持 SVG PHP imagick 状态验证 查询 PHP imagick 模块信息,发现: 进一步使用 PHP 接口查询 SVG 支持情况,返回结果为空。 结论: PHP imagick 实际并不支持 SVG 关键分歧点:动态库不一致 …

Docker 镜像与容器清理实践:以“栈视角”进行安全管理

背景 在长期运行的 Docker 服务器环境中,常见两类资产同时存在: 如果仅依据“容器是否在运行”来判断镜像是否可删除,极易误删冷备镜像,给后续恢复带来额外成本。因此,有必要建立一套以服务栈(stack)为核心的镜像与容器管理方法。 本文记录一次完整的排查与整理过程,目标不是“尽可能删除”,而是确保不误删任何未来仍需使用的镜像。 一、基础原则 在该环境中采用如下原则: 二、列出所有镜像(事实基线) 使用带 digest 的镜像列表作为“真实库存”: 该输出用于确认: 三、列出所有容器(不区分运行/停止) 容器列表是“镜像引用关系”的唯一事实来源: 在该环境中,当前不存在 exited 容器,所有服务均处于运行状态。但这并不改变后续判断逻辑。 四、用“栈(Compose Project)视角”理解容器结构 相比单个容器视角,“栈”更符合真实服务结构。通过 com.docker.compose.project 标签,可将容器按栈分组。 栈视图生成命令 五、当前运行中的服务栈清单(严格脱敏) 为避免暴露具体应用指纹,本节仅以抽象栈类别记录容器结构与数量,不出现任何可被直接识别的服务名称、镜像名或项目名。 该视图仅用于说明“以栈为单位进行管理”的方法论,而非展示具体部署细节。

Portainer 中删除 Docker 镜像失败的原因分析与处理

问题现象 在使用 Portainer(Community Edition)管理 Docker 环境时,尝试删除标记为 Unused 的镜像失败,界面提示类似以下错误: 即使所选镜像体积较大、状态显示为未使用,删除操作仍无法在 UI 中完成。 初步误判与澄清 误判一:镜像体积过大导致无法删除 该判断并不成立。 Docker 删除镜像的核心操作并非“拷贝或移动大文件”,而是: 镜像体积大小只影响删除耗时,不会导致“无法删除”。 正确原因分析 1. Portainer 报错的本质 504 Gateway Time-out 属于 前端或反向代理超时,而非 Docker Engine 返回的逻辑错误。 Portainer 的工作路径为: 当后端操作耗时过长时: 2. 根本原因:磁盘 I/O 性能不足 在以下场景中,该问题尤为明显: Docker 删除镜像时会触发: 这类操作 高度依赖随机 I/O 性能,在慢盘上可能持续数分钟。 3. 为什么 CLI 删除可以成功 使用命令行执行: 与 Portainer …

在 PVE 单节点环境中正确移除 Ceph 的一次实践记录

背景说明 在一次 Proxmox VE(PVE)节点初始化完成后,Web UI 中出现了 Ceph HEALTH_WARN 提示,提示内容为: OSD count 0 < osd_pool_default_size 3 该告警并非硬件故障或系统异常,而是由于 Ceph 已被初始化,但集群中并未配置任何 OSD(Object Storage Daemon),同时 Ceph 默认要求存储池副本数为 3,从而触发健康警告。 当前环境采用 PVE 单节点 + 独立硬件 PBS(Proxmox Backup Server) 的架构,用于虚拟化运行与备份分离。在该架构下,并不存在分布式存储或在线高可用的需求,因此 Ceph 实际上并不适合该使用场景。 Ceph 的定位与适用场景 Ceph 是一套分布式存储系统,主要目标包括: 其典型使用场景包括: 而在 单节点 PVE 环境中: 因此,在明确不使用 Ceph 的前提下,应当将其从系统角色中移除。 HEALTH_WARN 的根本原因 出现告警的直接原因是: …

Ubuntu 升级后 Anki Sync Server 虚拟环境断代修复记录

背景 在系统从 Ubuntu 22.04 升级至 24.04 后,一个长期运行的 Anki Sync Server 服务无法启动。该服务基于 Python 虚拟环境(venv)运行,并通过 systemd 管理。升级完成后,systemd 显示服务反复启动失败。 本文记录一次完整的排查与修复过程,重点在于 Python 虚拟环境在系统升级后发生版本断代 的问题,以及如何在不影响业务数据的前提下,安全、可回溯地恢复服务。 本文为工程记录,已严格脱敏,不包含路径、主机名、账号或端口等可识别信息。 一、故障现象 systemd 服务状态显示: 手动执行启动脚本时,出现错误: 这表明 Python 运行环境无法找到 anki 模块。 二、初步检查:虚拟环境异常 检查虚拟环境中的 Python 解释器信息: 进一步检查虚拟环境目录结构后发现: 即: venv 中保留的是 Python 3.10 时期的库,而解释器已经切换到 Python 3.12。 这是一次典型的 虚拟环境断代问题: 三、修复策略选择 核心原则 策略 四、旧虚拟环境归档 原有虚拟环境目录包含: …

Ubuntu 自 2016 年以来的大版本与代号时间线整理

Ubuntu 采用固定的时间发布节奏,每年发布两个版本,分别位于 4 月(.04) 与 10 月(.10)。版本号由 年份 + 月份 组成,同时每个版本都配有一个以相同首字母开头的英文代号,形式为 形容词 + 动物名。 以下整理自 2016 年开始的 Ubuntu 主要版本及其官方代号。 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 发布与支持周期规律总结 使用场景说明 该时间线可用于以下场景:

RustDesk 自建服务器的安全边界:不知道公钥,能不能连接?

摘要 在自建 RustDesk 服务器的过程中,一个常见且重要的问题是:如果他人不知道服务器的公钥(Key),是否仍然可以连接或使用该服务器? 本文从 RustDesk 的信任模型出发,澄清公钥在系统中的真实作用,并明确区分以下几个常被混淆的概念: 一、RustDesk 中「公钥(Key)」的真实作用 在 RustDesk 的自托管架构中,服务器会生成一组非对称密钥: 该公钥的核心作用是: 让客户端确认:当前连接的 RustDesk 服务器,是否为“被信任的那一台”。 换言之,公钥是 服务器身份的信任锚点,而不是传统意义上的“访问密码”。 二、如果他人不知道公钥,会发生什么? 情况一:既不知道服务器地址,也不知道公钥 这是最常见的情况。 结果:完全不可达。 情况二:知道服务器地址,但不知道公钥 这种情况可能来自于: 在此情况下: 结果是: 服务器可能“被看见”,但无法“被用”。 情况三:尝试强行连接或绕过公钥校验 RustDesk 的客户端在缺失或不匹配公钥时,信任链无法建立,表现为: 这并非“弱密码可猜”的问题,而是 设计层面的信任校验失败。 三、需要特别澄清的一个误区 一个常见误解是: “只要公钥不公开,服务器就是完全安全的。” 这是不准确的。 公钥解决的问题是: 公钥并不解决的问题是: 换句话说: 公钥 ≠ 防火墙公钥 ≠ 访问控制列表公钥 ≠ 攻击面消失 四、真正的安全边界在哪里? 在 RustDesk 的自建场景中,真实的安全边界通常包括: …