SSD Nodes Learn 🎉 VPS $5.50/月起
指南 Matt Connor作者: Matt Connor

VPS实时内核修补还是重启?区别与限制

实时内核修补会把已修复函数重定向到运行中的内核,无需立即断开连接,但修补仅存在于内存中,磁盘上的旧内核仍需通过重启加载。

VPS 上的实时内核修补能做什么

实时内核修补可在运行中的计算机上应用内核安全修复,无需重启,也不会断开连接。系统会将已修复的函数副本作为内核模块加载,并在服务器继续处理网络流量的同时,将对旧函数的每次调用重定向到新副本。这一机制同时说明了实时修补的适用范围和局限。

它只能争取时间,不能取消重启。服务器即使已经实时修补六个月,磁盘上的旧内核映像仍是其启动所用的映像,并且这些修补内容都只存在于内存中。

实时修补通常作为托管方案的功能提供。在非托管服务器上,您可以使用两条命令自行启用。了解这一点后,再决定是否为 托管 VPS 与非托管 VPS 之间的差价付费。

实时内核修补如何工作?

内核内置了实时修补核心,该核心通过 CONFIG_LIVEPATCH 编译进去。检查正在运行的内核是否包含该核心:

grep CONFIG_LIVEPATCH /boot/config-$(uname -r)

如果输出中有一行显示 CONFIG_LIVEPATCH=y,说明当前运行的内核在构建时已包含该核心。如果没有该核心,任何实时修补服务都无法在这台机器上执行操作。

代码重定向本身使用 ftrace,即内核的函数跟踪器。大多数内核函数在函数最开头都编译有一条调用指令,此时函数参数和栈尚未被修改。ftrace 使用该调用位置作为挂钩点。应用修补程序时,实时修补核心会在目标函数上注册 ftrace 处理程序,由该处理程序将执行转到替代函数。内核文档对此有明确说明:“实时修补通常需要在函数入口最开始处重定向代码,此时函数参数或栈尚未以任何方式被修改。”

这句话带来两个后果,后文都会涉及。只有 ftrace 能够挂钩的函数才可以修补,因此未编译该入口调用的函数完全无法修补。修补单位是整个函数,而不是函数内部的一行代码。

更困难的部分是如何安全地切换正在运行的系统。如果替换函数时,某个 CPU 的栈上仍在执行旧代码,系统就会同时出现新旧行为。上游 Linux 使用每个任务的一致性模型处理此问题。内核文档将其描述为一种混合模型:“结合了 kGraft 的每任务一致性和系统调用屏障切换,以及 kpatch 的栈跟踪切换。”任务会逐个迁移到新代码,但只有在内核能够确认该任务当前不在已修补函数内部时才会迁移。在所有任务完成迁移之前,修补程序都处于过渡状态。

您可以自行查看结果。已应用的修补程序位于 /sys/kernel/livepatch 下,每个修补程序对应一个目录,目录中列出了已修补的函数。

ls /sys/kernel/livepatch/

列表为空表示内存中没有加载实时修补程序。对于新部署的服务器,这是正常的初始状态。

实时内核修补无法解决的问题

只有函数体会被修补。其他内容不会被修补。

  • 已更改的数据结构。 如果上游修复向结构体添加字段,或改变现有字段的含义,就无法安全地重写已经分配并正在使用的对象。kpatch 项目直接说明了等效情况:“不直接支持修改静态分配数据的补丁。”影子变量和回调可以作为变通方案,但必须针对每个补丁手动编写,无法自动完成。
  • 同时分布在多个函数中的修复。 如果修复需要改变一组函数之间的锁顺序,就必须同时修改所有相关函数;而一致性模型会切换任务,而不是在同一时刻冻结整台计算机。
  • 初始化代码。 标记为 __init 的函数在服务器启动完成时通常已经运行并被释放,因此没有可供重定向的内容。
  • 新的内核版本和新功能。 实时修补只能让同一内核系列内的补丁级别向前推进。它不会将内核从一个系列升级到下一个系列,也不会添加任何功能。如果需要更新系列中的功能,例如 Linux 7.1 中引入的更改,就必须安装该内核并启动它。
  • 用户空间。 Canonical 明确说明了边界:“Canonical Livepatch 不会修补 OpenSSL 或 glibc 等用户空间库,因为这属于 unattended-upgrades 或系统管理工具的职责。”实时修补的内核旁边如果仍是过时的 OpenSSL,就不能算是已修补的服务器,因此应让 unattended upgrades 处理同一台主机上的用户空间软件包

Ubuntu 的这项服务还有严重性边界。Canonical 表示,它“会修补具有严重和高 Common Vulnerability Scoring System (CVSS) 以及 Ubuntu 优先级评级的内核漏洞”。CVE(common vulnerabilities and exposures)标识符用于指代一个漏洞,CVSS 是附加到该漏洞上的评分。中等级别的内核 CVE 会在磁盘上的软件包中修复,但不会通过实时修补应用,因此要等到下次重启时才会进入正在运行的内核,在此之前不会生效。

有哪些实时内核修补选项?

目前常用的方案有三种,它们最终都使用同一套内核机制。

Canonical Livepatch 通过 Ubuntu Pro 提供。个人用户可免费使用 Ubuntu Pro。Canonical 的表述是:Ubuntu Pro“现在及将来都将对个人用户免费”,最多支持 5 台物理计算机;Ubuntu 官方社区成员最多可支持 50 台计算机。截至 2026 年 8 月,这是文档中规定的限制。商业用途需要付费订阅。覆盖范围按内核系列和内核 flavour 分配,包括受支持长期支持(LTS)版本的通用可用性(GA)内核及其硬件支持(HWE)内核,支持 generic、aws、azure、gcp、oracle、ibm 和 lowlatency 等 flavour。在依赖该服务之前,请先将自己的内核与 Canonical 发布的内核列表进行比对。

KernelCare 由 TuxCare 提供,是一种商业代理,可支持多种发行版,包括没有第一方服务的发行版。其文档规定的安装方式是运行供应商脚本 curl -s -L https://kernelcare.com/installer | bash,然后运行 /usr/bin/kcarectl --register KEY 配置基于密钥的许可证。之后,代理会按自身计划检查新补丁,/usr/bin/kcarectl --update 可强制执行检查。在服务器上执行安装脚本并将其通过管道传给 shell 之前,请先阅读脚本内容。

kpatch 和 kGraft 是早期方案。kGraft 源自 SUSE,kpatch 源自 Red Hat;如今上游 Linux 中的实时修补核心是两者思想的合并。kpatch 本身正在退出维护阶段:其 README 声明,从 Linux 6.19 开始,“kpatch 项目已弃用并进入维护模式”,上游内核中的 kpatch-build 将由 klp-build 替代。在 RHEL 及其重建发行版上,应使用发行版自身提供的服务,而不是手动构建补丁。

请根据发行版支持范围和许可证权限进行选择。每种方案在内核层面实现的结果相同。

如何在 Ubuntu 上启用 Canonical Livepatch

首先从 Ubuntu Pro 账户页面获取令牌。下面的两个命令都需要可用的出站网络访问,因为客户端需要与 Canonical 服务器通信,以完成关联并获取补丁。

sudo pro attach TOKEN
sudo pro status

不带令牌运行 sudo pro attach 时,会改为启动基于浏览器的流程,并输出一个需要在 Canonical 网站输入的代码。关联操作会自动启用推荐的服务。在当前的 LTS 版本中,这通常包括 Livepatch。如果您希望自行选择服务,请使用 sudo pro attach --no-auto-enable

如果尚未启用 Livepatch:

sudo pro enable livepatch
sudo canonical-livepatch status

该服务通过 canonical-livepatch snap 运行,因此必须确保 snapd 正常工作,启用操作才能完成。pro status 会输出服务及其授权状态和运行状态的表格。canonical-livepatch status 会输出每个内核的详细信息。Canonical 文档中的输出格式如下:

last check: 52 seconds ago
kernel: 5.4.0-216.236-generic
server check-in: succeeded
kernel state: ✓ kernel series 5.4 is covered by Livepatch
patch state: ✓ all applicable livepatch kernel modules applied
patch version: 113.1

其中两行可以直接说明问题。kernel state 表示当前运行的内核系列是否受该服务支持。如果启动了 Livepatch 不支持的内核,该行会显示异常。patch state 表示适用于该内核的补丁是否已实际加载。受支持但没有应用补丁的内核,问题出在客户端。未受支持的内核,问题出在内核本身;任何客户端设置都无法解决此问题。

如何判断是否需要重启?

实时内核修补消除了紧急性,因此待重启状态不再明显。您需要主动检查。

ls -l /var/run/reboot-required
cat /var/run/reboot-required.pkgs

当已安装的软件包需要重启才能生效时,软件包管理器会创建 /var/run/reboot-required;新的 linux-image 软件包始终会创建该文件。.pkgs 文件会列出提出重启请求的软件包。如果第一个命令返回 No such file or directory,表示自上次启动以来没有任何软件包请求重启。在当前版本的 Ubuntu 中,/var/run 是指向 /run 的符号链接,因此访问任一路径都会读取同一个文件。

该标记位于 tmpfs 中,每次启动都会重置。因此,请通过内核本身进行确认:

uname -r
dpkg -l 'linux-image-*' | grep ^ii

uname -r 会输出当前正在运行的内核。第二个命令会输出磁盘上已安装的内核软件包。如果该列表中的 linux-imageuname -r 报告的版本更新,说明系统正在运行旧内核,无论 Livepatch 的状态如何。这项检查最重要,因为实时内核修补的目标是确保正在运行的内核安全,而不是使其保持最新。

对于同一问题的用户空间部分,Ubuntu Server 默认安装 needrestart。它会列出仍在占用已删除库文件的运行中服务。

sudo needrestart -r l

-r l 标志组合表示“仅列出”,因此只报告信息,不进行任何更改。

重启为什么始终无法避免

磁盘上的内核没有变化。实时补丁会加载到正在运行的内核中,但不会写入启动映像。因此,重启后系统会运行引导加载程序选择的 linux-image,随后 Livepatch 客户端会重新应用仍然适用的补丁。在这两个时刻之间,系统运行的是未打补丁的代码。这也是应启动当前内核而不是旧内核的另一个原因。

覆盖范围按内核系列计算,而内核系列会停止维护。当正在运行的系列不再属于受支持列表时,kernel state 行会停止报告覆盖范围。唯一的解决方法是使用更新的内核。这就需要重启。

中严重性和低严重性的内核修复不会通过实时补丁应用。它们会保存在磁盘上的软件包中,只有启动新内核后才会生效。

长时间运行的内核还会积累实时补丁无法清理的状态。Canonical 的官方说法值得引用,因为这也是准确的说法:Livepatch“不是重启的替代方案,而是一种通过避免非计划重启来让您更好地控制系统的工具。”其中传达核心含义的词是非计划。您仍然需要重启,只是可以自行选择时间。

如何安排可恢复的重启

如果无法访问控制台,VPS 重启就可能无法恢复。输入 reboot 前,先确认机器未能正常启动时,您仍能重新登录。

  • 确认服务商在控制面板中提供串行控制台或 VNC(虚拟网络计算)视图,并现在打开它,不要等到发生中断时再打开。
  • 使用 df -h /boot 检查可用空间。/boot 已满时,内核软件包在写入其 initramfs(初始 RAM 文件系统)时会失败,可能导致引导加载程序条目指向一个尚未完成的映像。
  • 至少保留一个已知可用的旧内核。GRUB 会在 “Advanced options for Ubuntu” 下列出它;新内核启动失败时,启动旧内核是最快的恢复方式。
  • 提前找到服务商的救援模式。如果重启后控制台显示 initramfs 提示符,应在那里进行修复。

然后在您保持在线的时间安排重启:

sudo shutdown -r +5 "Kernel update, back in a moment"

该命令会将重启安排在 5 分钟后执行,并向已登录的用户发送消息。sudo shutdown -c 可取消该计划。机器恢复后,确认以下两部分:

uname -r
sudo canonical-livepatch status

uname -r 现在应报告更新后的内核,状态输出也应显示新内核系列已获得覆盖。如果机器完全无法恢复,故障几乎总是在引导路径,而不是网络中;此时应按照内核更新后无法启动的 VPS 指南中的恢复方法处理。

为什么仍需清理旧内核

实时补丁并不能解决这个问题,反而会使问题更加严重,因为它减少了重启的必要性,而 linux-image 软件包仍会持续安装。每个内核都会安装一个引导映像、一个 initramfs、一个模块目录,通常还会安装一个 headers 软件包。对于单独使用容量仅几百 MB 的 /boot 分区的小型 VPS,安装三个或四个内核就会将其占满。

/boot 已满后,下次安装内核就会失败,导致系统无法安装自己需要的更新。apt autoremove 会在旧内核符合条件后将其清理,但对于从不重启的服务器,这些内核不一定已经符合条件,因为软件包管理器不会删除可能仍在运行的内核。

因此,请先检查已安装的内核,保留正在运行的内核和一个已知可用的备用内核,然后按照在 Ubuntu 上安全删除旧内核的步骤删除其余内核。切勿删除 uname -r 当前报告的内核。

FAQ

实时内核修补是否意味着我永远不必重启 VPS?

不是。实时补丁会加载到正在运行的内核中,不会写入引导映像,因此磁盘上的 linux-image 仍保持您启动时使用的版本。Canonical 的表述很明确:Livepatch“不能替代重启。它是一种让您获得更多控制权的工具,可以避免计划外重启。”当您的内核系列停止维护后,覆盖范围也会结束;中严重级别的内核修复则完全不会通过实时补丁提供。请按照您选择的周期安排维护重启,不要等到系统强制要求重启。

如何检查实时内核修补是否确实在应用补丁?

运行 sudo canonical-livepatch status 并查看两行输出。kernel state 报告当前运行的内核系列是否受该服务覆盖,patch state 报告该内核的补丁是否已加载。您也可以通过 ls /sys/kernel/livepatch/ 直接检查内核状态;该命令会为每个已加载的补丁列出一个目录。列表为空表示当前没有任何补丁应用到内存中,无论客户端报告什么状态。

Ubuntu Pro 在个人 VPS 上免费吗?

是,但有明确的限制。截至 August 2026,Canonical 的表述是:Ubuntu Pro“对于个人使用,在最多 5 台物理机器上现在免费,今后也始终免费”;Ubuntu Community 的正式成员可将上限提高到 50 台机器。商业用途需要付费订阅。您可以使用 Ubuntu Pro 账户页面中的令牌,通过 sudo pro attach TOKEN 将机器关联到服务,然后使用 sudo pro enable livepatch 启用该服务。

为什么 Livepatch 运行后,内核 CVE 仍显示为未修复?

通常有两个原因。该修复可能低于严重性阈值,因为 Canonical 的实时补丁“会修复具有严重和高 Common Vulnerability Scoring System (CVSS) 以及 Ubuntu Priority 评级的内核漏洞”,其余漏洞则交由磁盘上的软件包处理。或者,该修复可能无法表示为对函数体的修改,例如上游更改了数据结构;实时修补无法安全地修改已经分配的对象。两种情况的处理方式相同:安装更新后的内核软件包,并启动到该内核。

实时内核修补完全不覆盖哪些内容?

用户空间。Canonical 明确说明,Livepatch“不会修补 OpenSSL 或 glibc 等用户空间库,因为这属于 unattended-upgrades 或系统管理工具的职责”。它也无法提供新的内核版本或新功能,因为它只会替换您当前运行的内核系列中的函数体。此外,它无法修补 __init 函数,因为服务器启动后,这些函数已经执行完毕并从内存中释放。