news 2026/9/16 18:47:33

CloudNativePG 集群 Kubernetes 升级与节点维护完全指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CloudNativePG 集群 Kubernetes 升级与节点维护完全指南

CloudNativePG 集群 Kubernetes 升级与节点维护完全指南

【免费下载链接】cloudnative-pgThe most popular Kubernetes Operator for PostgreSQL.项目地址: https://gitcode.com/GitHub_Trending/cl/cloudnative-pg

本文以 CloudNativePG 的官方文档为骨架,系统讲解如何在不中断 PostgreSQL 业务的前提下完成 Kubernetes 集群的升级与节点维护:从维护窗口的规划、drain/uncordon的标准流程,到节点本地存储场景下集群的临时降级、PodDisruptionBudget(PDB)的管理策略,以及nodeMaintenanceWindow这一为本地存储而生的维护机制及其在新版本中的演进。读完本文,你将能够根据集群存储类型与实例拓扑,为生产、开发/测试集群分别制定正确的维护策略,并正确使用kubectl drainenablePDBnodeMaintenanceWindow.inProgress/reusePVC等关键开关完成一次安全的节点维护。

为什么必须重视 Kubernetes 的定期升级

保持 Kubernetes 集群处于最新状态,是保证性能与安全的基础要求,这一点对自管(self-managed)集群、尤其是运行在裸金属(bare metal)基础设施上的集群尤为关键。定期升级能够:

  • 消除技术债:Kubernetes 控制面与节点组件的迭代非常快,长期停留在旧版本会积累大量配置、API 与依赖层面的历史包袱;
  • 降低业务风险:安全补丁、硬件故障替换、控制面版本升级等维护操作,都是降低基础设施整体风险的必要投入。

需要正视的是,升级过程往往伴随着有计划的停机窗口——例如需要将某个节点临时移出集群进行维护。官方文档在介绍这一话题时引用了 Google SRE 经典书籍中的 "Embracing Risk" 章节,其核心思想是:运维不是消除所有风险,而是有意识地接受并管理可控风险。将风险量化为可接受的停机时间与数据风险,正是规划维护窗口的前提。

集群中的标准维护流程

Kubernetes 的节点维护通常每次只针对一个节点进行,遵循一套标准化的三步流程(详见 Kubernetes 官方 kubeadm 升级指南):

  1. 驱逐工作负载(drain:使用kubectl drain <node>优雅地将目标节点上的工作负载迁移走,确保平滑过渡;
  2. 执行维护操作:在节点上执行实际维护,例如应用系统更新、替换故障硬件、升级 kubelet 版本等;
  3. 让节点重新加入集群(uncordon:维护完成后使用kubectl uncordon <node>将节点重新接入集群,恢复其调度职责。

这一流程的代价是:要么在整个升级期间停止工作负载,要么将工作负载迁移到集群中的其他节点。对于 PostgreSQL 这类有状态工作负载,后者是否可行,高度取决于存储类型——这正是 CloudNativePG 相关设计(PDB、维护窗口)的出发点。

节点本地存储下的临时降级:一种可接受的状态

标准流程依赖 Kubernetes 的自愈能力保证服务可靠性,但在某些场景下,允许 PostgreSQL 集群临时处于降级状态是完全可以接受的。这一论断特别适用于依赖节点本地存储(node-local storage,即 local storage)的 PostgreSQL 集群——数据存放在运行 PostgreSQL 的 Kubernetes 工作节点自身的磁盘上,以换取更高的 I/O 性能。

:::note 何时可以跳过本文其余章节? 如果你的数据库文件位于可通过网络访问的共享存储上,那么在drain之后,卷可以被不同节点上的 Pod 重新使用,此时 operator 的默认自愈行为已经能高效处理,可以跳过本文后续内容。本文剩余部分专门针对本地存储场景。 :::

Pod Disruption Budget:默认的守护机制

默认行为:为每个 Cluster 创建两个 PDB

默认情况下,CloudNativePG 会在后台守护 PostgreSQL 集群的可用性:

  • 如果要被drain的节点上运行着集群的primary实例,operator 会在drain之前先执行一次 switchover(切换),把该节点上的实例降级为 replica 后再继续驱逐;
  • 对于单实例集群,由于无法切换,CloudNativePG 会阻止驱逐该实例所在的节点;
  • 对于3 个及以上实例的集群,CloudNativePG 保证在drain过程中同一时刻最多只有一个 replica 被优雅关闭

这一行为的实现机制是:每个 PostgreSQLCluster都会自动关联两个PodDisruptionBudget资源,你可以通过kubectl get pdb立即确认:

kubectl get pdb -n <namespace>

从源码看,这两个 PDB 在 pkg/specs/poddisruptionbudget.go 中分别构建:

  • BuildPrimaryPodDisruptionBudget:保护 primary 实例,避免其被随意驱逐(对应上文"primary 所在节点先切换、单实例阻止驱逐"的行为);
  • BuildReplicasPodDisruptionBudget:通过MinAvailable = instances - 2保证 n 实例集群中始终至少有 n-2 个 replica 可用,从而实现"一次只优雅关闭一个 replica";该函数在cluster.Spec.Instances < 3时返回nil(见 poddisruptionbudget.go)。

二者会在集群调和过程中被统一管理(见 cluster_create.go 的reconcilePodDisruptionBudget函数)。

生产建议:保持 PDB 开启

官方建议:对每个生产 PostgreSQL 集群都保持 Pod disruption budget 开启。这一开关由.spec.enablePDB字段控制,其语义定义在 cluster_types.go:默认值为true,此时 PDB 会保护 primary 节点不被终止;置为false时不会创建任何 PDB 资源(若之前已创建则会被删除),允许关闭所有承载 PostgreSQL 集群的节点——后者正是为开发/预发(staging)用途推荐的配置。

从实现上看,enablePDB的默认值逻辑在 cluster_funcs.go 的GetEnablePDB()中:当字段未设置(nil)时返回true,即默认开启。

开发/测试集群:禁用 PDB 以便顺利排空节点

对于开发用途的 PostgreSQL 集群(通常为单实例),必须禁用 pod disruption budgets——否则该集群所在节点将永远无法被drain

下面的示例展示了如何为一个单实例的开发集群禁用 PDB:

apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: dev spec: instances: 1 enablePDB: false storage: size: 1Gi

该配置可确保开发期间的维护流程不受限制,drain操作可以顺利进行。

Node Maintenance Window:面向本地存储的维护窗口

:::info 重要提示 CloudNativePG 会继续支持节点维护窗口机制,但目前官方建议改用上一节直接管理 pod disruption budgets 的方式。本节内容主要为向后兼容而保留。 :::

演进背景:1.23 之前的唯一声明式手段

在 release 1.23 之前,当处理本地存储场景时,CloudNativePG 只有一种声明式机制来管理 Kubernetes 升级:通过nodeMaintenanceWindow选项临时将集群置入维护模式,以避免标准的自愈流程介入——典型场景包括在物理节点上扩容分区、或者更新节点本身。

:::warning 谨慎使用 请将维护窗口的持续时间限制到最短。在该阶段,Kubernetes 的部分预期行为会被禁用或以受限方式运行,包括自愈(self-healing)、滚动更新(rolling updates)和 Pod disruption budget。 :::

两个子选项:inProgressreusePVC

nodeMaintenanceWindow包含两个设置(字段定义见 cluster_types.go):

字段类型默认值含义
inProgressBooleanfalse(文档原文记为off是否处于节点维护窗口进行中。仅在为true时,operator 才会评估下面的reusePVC选项
reusePVCBooleantrue(文档原文记为on维护期间是否复用现有 PVC

两者在 cluster_funcs.go 中都有对应的判定方法:

  • IsNodeMaintenanceWindowInProgress()(L844-L847):维护窗口是否激活;
  • IsReusePVCEnabled()(L859-L866):默认reusePVC = true,仅当显式设置为false时才返回false

reusePVC启用时(默认):Kubernetes 等待节点重新上线,然后复用现有 PVC;在此期间PodDisruptionBudget策略会被临时移除。

reusePVC禁用时:Kubernetes 强制在其他节点上以全新的 PVC 重新创建 Pod,借助 PostgreSQL 的物理流复制恢复数据,随后连同 Pod 一起销毁旧 PVC。这一场景通常不推荐,除非数据库体积很小,且重新克隆一个新的 PostgreSQL 实例比等待原节点恢复更快。需要注意:该行为不适用于单实例且reusePVCfalse的集群(详见下文)。

维护窗口下 PDB 的临时移除逻辑

从 cluster_create.go 的调和逻辑可以确认:

  • 维护窗口进行中且reusePVC开启时,replica 的 PDB 不会被强制执行;
  • 若此时集群为单实例,primary 的 PDB 也会一并移除——否则用户无法把工作负载从底层节点驱逐出去。

别忘了--delete-emptydir-data

:::note 执行kubectl drain时,需要附加--delete-emptydir-data选项。 不必担心:它指向的是 operator 内部使用的另一个卷并非 PostgreSQL 数据目录。 :::

即正确用法为:

kubectl drain <node> --delete-emptydir-data --ignore-daemonsets

enablePDB完全接管 PDB 管理

:::info 重要提示 PodDisruptionBudget 的管理可以通过将.spec.enablePDB字段设为false来整体禁用。此时 operator 不再创建PodDisruptionBudget,并且会删除之前已创建的资源。 :::

这一行为由 cluster_create.go 中的deletePodDisruptionBudgetsIfExist路径保证:GetEnablePDB()返回false时直接进入删除逻辑。

单实例集群 +reusePVC: false:数据安全的红线

:::info 重要提示 官方建议始终创建多于一个实例的集群,以保证高可用(high availability)。 :::

在单实例集群中删除唯一一个 PostgreSQL 实例,意味着所有数据丢失。因此,即使处于维护模式,CloudNativePG 也会阻止用户 drain 这类实例所在的节点——这是 operator 主动守护数据安全的硬性边界。

不过,当确实需要对这类节点进行维护时,你有两个选择:

  1. 启用reusePVC,接受停机时间
  2. 在其他节点上复制实例,并执行一次 primary 切换(switchover)

方案一:接受停机

只要你的环境能够接受数据库服务的停机,操作就很简单:将nodeMaintenanceWindow设置为inProgress: truereusePVC: true。这样实例会被删除,并在原始 PVC 可用时立即重建(例如节点本地存储场景下,节点一恢复即可复用 PVC)。对应的 YAML 示意如下:

apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: single-instance spec: instances: 1 nodeMaintenanceWindow: inProgress: true reusePVC: true storage: size: 20Gi

方案二:无停机(仅切换耗时)

否则,你需要扩容集群:在其他节点创建新实例,将新实例提升为 primary,然后关闭正在维护节点上的原实例。此方案唯一的停机时间就是switchover 的耗时。推荐的操作步骤如下:

  1. **Cordon(封锁)**当前实例所在的节点:kubectl cordon <node>
  2. 扩容集群到 2 个实例(耗时取决于数据库大小),例如编辑 Cluster 将spec.instances1改为2
  3. 新实例运行起来后,由于当前 primary 运行在已被 cordon 的节点上,operator 会自动执行 switchover
  4. 缩容集群回到单实例,此时旧实例会被删除;
  5. 原 primary 所在节点现在可以成功 drain,而新 primary 已运行在新节点上。

整个过程把停机窗口压缩到一次切换的时间,是本地存储、单实例场景下的推荐路径。

总结:一张维护策略决策表

结合前文,可以为不同场景总结出如下决策要点:

集群类型存储类型推荐配置drain 可行性
生产集群(≥3 实例)网络共享存储保持默认,enablePDB: true直接 drain,operator 自愈
生产集群(≥3 实例)节点本地存储保持 PDB,逐节点 drain,必要时使用维护窗口一次关闭一个 replica,primary 先切换
生产集群(单实例)节点本地存储扩容→自动切换→缩容,或reusePVC: true接受停机需先处理 primary,否则被阻止
开发/测试集群任意enablePDB: false可直接 drain

维护的最终目标,是在Kubernetes 自愈能力PostgreSQL 高可用可控的停机风险之间取得平衡。理解 PDB 的默认行为、enablePDB开关以及nodeMaintenanceWindow(含inProgress/reusePVC)的语义,是安全执行每一次节点升级的基础。更多字段细节可查阅 CloudNativePG API 参考 中关于ClusterSpec的说明,以及仓库中的类型定义 cluster_types.go 与控制器实现 cluster_create.go。

【免费下载链接】cloudnative-pgThe most popular Kubernetes Operator for PostgreSQL.项目地址: https://gitcode.com/GitHub_Trending/cl/cloudnative-pg

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 18:46:57

Android收款监控链路设计:通知监听、事件推送与状态机

简介&#xff1a;一份基于Android平台开发的微信/支付宝收款监控系统源码&#xff0c;面向移动端开发者及有个人收款管理需求的用户。项目核心解决个人账户无需单独签约支付接口即可实现即时到账监控的问题&#xff0c;通过应用内监听与通知机制辅助收款记录&#xff0c;适合自…

作者头像 李华
网站建设 2026/9/16 18:46:35

SSM框架学生信息管理系统实战:从Maven搭建到部署详解

简介&#xff1a;基于SSM框架的学生信息管理系统完整项目&#xff0c;含Java源码、配置及数据库文件&#xff0c;面向Java Web开发者、课程设计及毕业设计学生。系统覆盖学生信息管理、成绩管理、班级管理、用户权限管理、操作日志等模块&#xff0c;采用模块化设计&#xff0c…

作者头像 李华
网站建设 2026/9/16 18:45:48

多平台优惠券回收源码:金融级交易闭环实现

简介&#xff1a;这是一套面向PHP开发者与电商系统学习者的2024年多平台礼物回收类优惠券商城源码&#xff0c;聚焦于优惠券秒杀、拼团、限时折扣及余额宝理财等高频业务场景&#xff0c;解决闲置电商权益变现与轻量级SaaS化商城快速搭建需求。资源包共2005个文件&#xff0c;含…

作者头像 李华
网站建设 2026/9/16 18:45:21

CS1237电容式传感器驱动开发:C语言裸机SPI精准控制指南

简介&#xff1a;本资源是一份基于C语言开发的CS1237硬件驱动程序实现&#xff0c;面向嵌入式系统开发者、Linux内核模块初学者及需要对接特定外设的工程师&#xff0c;解决CS1237类设备在操作系统中识别、初始化与数据交互的核心问题。压缩包为RAR格式&#xff0c;共含2个关键…

作者头像 李华
网站建设 2026/9/16 18:44:52

书霸AI|官网shubaai.com|公众号搜书霸AI写作

很多人写开题报告时&#xff0c;真正卡住的并不是打字&#xff0c;而是不知道从哪里开始&#xff1a;研究问题不够明确&#xff0c;研究内容彼此脱节&#xff0c;研究方法写得笼统&#xff0c;参考文献也不知道如何筛选。结果往往是反复修改标题&#xff0c;却始终没有形成一条…

作者头像 李华