CloudNativePG Image Catalog 完全指南:集中管理 PostgreSQL 镜像生命周期与自动滚动更新
2026/9/16 19:38:52 网站建设 项目流程

CloudNativePG Image Catalog 完全指南:集中管理 PostgreSQL 镜像生命周期与自动滚动更新

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

ImageCatalogClusterImageCatalog是 CloudNativePG 提供的两类 Custom Resource Definitions(CRDs),用于将 PostgreSQL 镜像的选型与升级逻辑从Cluster资源中解耦,实现镜像更新的集中化管理。本文基于 docs/src/image_catalog.md 展开,结合仓库源码与配置示例,系统讲解 Catalog 的作用域、结构定义、组件镜像(如 PgBouncer)、与 Image Volume Extensions 的联动,以及官方 Catalog 的安装与使用。读完本文,你将掌握如何用一套镜像清单驱动多个集群的镜像升级与自动滚动更新。

为什么需要 Image Catalog:镜像生命周期与集群定义的解耦

在传统做法中,每个Cluster通过spec.imageName直接指定容器镜像。当需要升级镜像补丁版本时,管理员必须逐一修改每个集群的spec,工作量大且容易遗漏。

Image Catalog 的核心价值在于:通过imageCatalogRef引用一个 Catalog,把"选哪个镜像"这件事从集群定义中剥离出来。镜像更新集中在 Catalog 一处进行,当 Catalog 中的条目更新后,所有关联的集群会自动检测到镜像变化,并按照 CloudNativePG 的滚动更新机制逐步替换 Pod,实现无感知升级。

这一"一处修改、全局生效"的机制在控制器层面有明确支撑:在 internal/controller/cluster_image.go 中,getClustersForImageCatalogsToClustersMappermapClusterImageCatalogsToClusters等映射函数(mapper),会在 Catalog 对象发生变化时,通过 FieldSelector(imageCatalogKey)找出所有引用它的集群,为其生成 reconcile 请求,从而触发镜像解析与滚动更新。

Catalog 作用域:Namespaced 与 Cluster-wide 的选择

两种 Catalog 资源在 API 层面的本质区别在于作用域(scope),这在定义文件中有直接体现:

  • ImageCatalog:命名空间级资源(Namespaced),由 api/v1/imagecatalog_types.go 定义,仅能被同命名空间内的Cluster引用,适合应用级版本锁定或团队级限制;
  • ClusterImageCatalog:集群级资源(Cluster-wide),由 api/v1/clusterimagecatalog_types.go 定义,文件中的+kubebuilder:resource:scope=Cluster标记明确声明其集群级作用域,可被任意命名空间中的集群引用,适合组织级的全局标准。
资源作用域最佳使用场景
ImageCatalogNamespaced(命名空间级)应用特定版本、团队级限制
ClusterImageCatalogCluster-wide(集群级)跨命名空间的全局标准

尽管两者作用域不同,它们共享完全相同的 spec 结构ClusterImageCatalogSpec字段类型同样是ImageCatalogSpec。运行时,两者通过统一的GenericImageCatalog接口(见 api/v1/genericimagecatalog_iface.go)被一致对待,控制器无需关心具体类型即可调用GetSpec()获取清单数据。

Catalog 结构:主版本、唯一性、扩展与组件镜像

两种资源共享同一套 schema,核心字段定义在 api/v1/imagecatalog_types.go 的ImageCatalogSpec中:

  • 主版本化(Major versioning)images是一个以 PostgreSQL 主版本号(major)为键的镜像列表,每个条目同时包含image(镜像引用)与major(PostgreSQL 主版本);
  • 唯一性(Uniqueness)major在单个 Catalog 内必须唯一。源码通过 CEL 校验规则强制这一约束:self.all(e, self.filter(f, f.major==e.major).size() == 1),违反时 API Server 会直接拒绝;
  • 扩展(Extensions):支持声明经过认证的扩展容器镜像(PostgreSQL 18+ 可通过extension_control_path使用),对应CatalogImage.Extensions []ExtensionConfiguration字段;
  • 组件镜像(Component images):可选的命名镜像列表,用于非 PostgreSQL 组件(如 PgBouncer)。

ImageCatalogSpec的关键校验约束(来自源码 kubebuilder 标记):

  • images:最少 1 项、最多 8 项(MinItems=1/MaxItems=8),且major必须唯一;
  • componentImages:最多 32 项(MaxItems=32),key必须唯一;
  • major:最小值为 10(Minimum=10);
  • 组件镜像key:必须是^[a-z0-9](https://link.gitcode.com/i/40d3b0ccdb168120d5dcdbe565ad52af)?$形式的小写字母数字标识符(允许连字符,但必须以字母数字开头和结尾),最长 63 个字符。

⚠️ 重要提示:操作器不会对用户自定义的major版本执行镜像探测,它完全信任用户声明的主版本号。官方 CloudNativePG Catalog 已经过社区预校验,确保每条扩展与操作镜像条目都与其声明的主版本一致;如果你要创建自定义 Catalog,必须自行保证声明的major与实际 PostgreSQL 镜像匹配,否则可能出现镜像与版本不兼容的问题。

从源码层面看,Catalog 的查找逻辑非常直接。api/v1/imagecatalog_funcs.go 提供了三个核心方法:

  • FindImageForMajor(major int):按主版本号返回镜像字符串;
  • FindExtensionsForMajor(major int):按主版本号返回关联的扩展配置列表;
  • FindComponentImageForKey(key string):按 key 返回组件镜像字符串。

这些方法的行为在 api/v1/imagecatalog_funcs_test.go 中均有覆盖测试:包括"找到指定主版本的镜像""请求的镜像未指定时返回 false""按 key 查找组件镜像""key 不存在或列表为空时返回 false"等场景。

组件镜像(Component Images):集中管理 PgBouncer 镜像

除 PostgreSQL 镜像外,Catalog 还可以通过componentImages字段存储其他组件的镜像。每个条目由一个字符串key标识(小写字母数字、允许连字符、1–63 个字符),且 key 在同一 Catalog 内必须唯一。

当前,组件镜像的唯一消费方是Pooler资源:Pooler 可以引用 Catalog 中的组件镜像条目,从而集中管理 PgBouncer 容器镜像(详见连接池文档)。

以下示例定义了一个包含 PgBouncer 组件镜像的命名空间级ImageCatalog

apiVersion: postgresql.cnpg.io/v1 kind: ImageCatalog metadata: name: my-catalog namespace: default spec: images: - major: 18 image: ghcr.io/cloudnative-pg/postgresql:18.6-system-trixie componentImages: - key: pgbouncer image: ghcr.io/cloudnative-pg/pgbouncer:1.25.1

如需集群级 Catalog,将kind改为ClusterImageCatalog并去掉metadata.namespace字段即可(spec完全一致)。

注意:一个 Catalog 最多可包含 32 个组件镜像条目。key 由小写字母数字字符或连字符组成,必须以字母数字开头和结尾,最长 63 个字符。

Pooler 镜像解析的优先级(源码佐证)

internal/controller/pooler_image.go 中的resolvePoolerImage函数揭示了 PgBouncer 镜像的完整解析优先级(从高到低):

  1. spec.template中 pgbouncer 容器上显式设置的镜像(Pod 模板覆盖,优先级最高,保证与 Deployment 实际写入一致);
  2. spec.pgbouncer.image显式字段;
  3. spec.pgbouncer.imageCatalogRef引用的 Catalog 组件镜像(resolveImageFromCatalog按 key 查找);
  4. 操作器默认镜像(configuration.Current.PgbouncerImageName)。

resolveImageFromCatalog会依据引用中的kind区分ClusterImageCatalog(集群范围,namespace 为空)与ImageCatalog(使用 Pooler 所在命名空间),查找失败或 key 不存在时会返回明确错误。此外,mapImageCatalogToPoolers/mapClusterImageCatalogToPoolers映射函数会在 Catalog 变更时自动触发关联 Pooler 的重新协调。

配置示例:定义与引用 Catalog

定义 Catalog

你可以在单个 Catalog 中定义多个主版本。以下示例定义了一个命名空间级ImageCatalog,覆盖 PostgreSQL 15 至 18:

apiVersion: postgresql.cnpg.io/v1 kind: ImageCatalog metadata: name: postgresql namespace: default spec: images: - major: 15 image: ghcr.io/cloudnative-pg/postgresql:15.14-system-trixie - major: 16 image: ghcr.io/cloudnative-pg/postgresql:16.10-system-trixie - major: 17 image: ghcr.io/cloudnative-pg/postgresql:17.6-system-trixie - major: 18 image: ghcr.io/cloudnative-pg/postgresql:18.6-system-trixie

以下示例定义了集群级ClusterImageCatalog,内容与上例完全一致,只是去掉了 namespace:

apiVersion: postgresql.cnpg.io/v1 kind: ClusterImageCatalog metadata: name: postgresql-global spec: images: - major: 15 image: ghcr.io/cloudnative-pg/postgresql:15.14-system-trixie - major: 16 image: ghcr.io/cloudnative-pg/postgresql:16.10-system-trixie - major: 17 image: ghcr.io/cloudnative-pg/postgresql:17.6-system-trixie - major: 18 image: ghcr.io/cloudnative-pg/postgresql:18.6-system-trixie

仓库内置了可直接套用的完整示例:docs/src/samples/cluster-example-catalog.yaml 同时包含ImageCatalog与引用它的Cluster清单。

在 Cluster 中引用 Catalog

Cluster资源通过imageCatalogRef选择镜像:

apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: cluster-example spec: instances: 3 imageCatalogRef: apiGroup: postgresql.cnpg.io kind: ClusterImageCatalog # Or 'ImageCatalog' name: postgresql-global major: 18 storage: size: 1Gi

imageCatalogRef的类型定义见 api/v1/cluster_types.go 中的ImageCatalogRef

  • 内嵌TypedLocalObjectReference,携带apiGroupkindname三个字段;
  • 通过 CEL 校验限制kind只能是ImageCatalogClusterImageCatalog,且apiGroup必须是postgresql.cnpg.io
  • major字段指定要使用的 PostgreSQL 主版本。

同时,ClusterSpec上有一条关键校验规则(源码注释明确说明):imageNameimageCatalogRef是互斥的!(has(self.imageCatalogRef) && has(self.imageName))),即同一个集群不能同时指定镜像名和 Catalog 引用。若imageCatalogRef为 nil 且imageName为空,控制器会报错 "ImageName is not defined and no catalog is referenced"。

Image Catalog 与 Image Volume Extensions 的联动

Image Volume Extensions 允许你将扩展容器直接打包进 Catalog 条目中。以下示例定义了一个带扩展声明的ImageCatalog

apiVersion: postgresql.cnpg.io/v1 kind: ImageCatalog metadata: name: postgresql spec: images: - major: 18 image: ghcr.io/cloudnative-pg/postgresql:18.6-minimal-trixie extensions: - name: foo image: reference: # registry path for your `foo` extension image

extensions部分遵循ExtensionConfigurationAPI schema 与结构。引用该 Catalog 的集群可以按名称加载其中任意关联的扩展。

从源码看,扩展解析与校验有完整链路:getRequestedImageInfo会调用extensions.ResolveFromCatalog(cluster, catalog, requestedMajorVersion)(见 internal/controller/cluster_image.go),将 Catalog 中该主版本声明的扩展配置解析进集群的ImageInfo;而extensionsEqual则会对比新旧扩展列表(包括ExtensionControlPathDynamicLibraryPathLdLibraryPathBinPathEnv等字段)以判断是否需要更新。

关于扩展镜像的内部结构、配置选项,以及如何在集群内选择或覆盖 Catalog 中的扩展,请参阅 Image Volume Extensions 文档。

底层实现机制:Catalog 如何驱动镜像更新

深入 internal/controller/cluster_image.go 的reconcileImagegetRequestedImageInfo,可以看到镜像解析的完整流程:

  1. 解析请求镜像getRequestedImageInfo优先检查spec.imageCatalogRef;若存在,则调用pkg/utils/imagecatalog/catalog.goGet函数——它根据Kind实例化对应的 Catalog 对象,校验apiGrouppostgresql.cnpg.io,然后按集群命名空间读取 Catalog,并用FindImageForMajor查找指定major的镜像;
  2. 错误处理:Catalog 不存在、主版本不在 Catalog 中、apiGroup 不合法等都会返回明确错误,且集群会进入PhaseImageCatalogError阶段并产生DiscoverImage类型的 Warning 事件;
  3. 变更判定与滚动更新reconcileImage对比cluster.Status.PGDataImageInfo与请求镜像,分四种情况处理:
    • 集群初始化(尚无运行镜像)→ 直接应用所选镜像;
    • 镜像与扩展均未变化 → 无需任何操作;
    • 主版本降级 → 明确禁止,返回 "Cannot downgrade the PostgreSQL major version" 错误;
    • 主版本升级或补丁版本(minor)变更 / 扩展镜像变化 → 更新镜像并触发滚动更新

也就是说:当你在 Catalog 中把某个major的镜像从18.6更新为18.7(同一主版本内的补丁升级),所有引用该 Catalog 且指定major: 18的集群会检测到镜像差异,自动启动滚动更新;而若你想从 17 升到 18,则属于主版本升级场景,需要配合 CloudNativePG 的升级流程处理。

官方 CloudNativePG Catalogs

CloudNativePG 项目为所有受支持的镜像维护了ClusterImageCatalog清单(artifacts 仓库),并定期更新。官方 Catalog 发布在两个位置:

  • image-catalogs:基础镜像类型的核心 Catalog 定义;
  • image-catalogs-extensions:与上述 Catalog 内容一致,关键区别在于minimal镜像类型包含扩展定义。

每个 Catalog 对应特定的"镜像类型 + Debian 发行版"组合(例如trixie),列出每个受支持的 PostgreSQL 主版本对应的最新容器镜像。

安全说明:为确保最大程度的安全性与不可变性,官方 CloudNativePG Catalog 中的所有镜像均使用SHA256 digest标识,而不仅仅是 tag。

版本兼容性

核心 Catalog 兼容旧版本操作器,但包含extensions部分的 Catalog 仅兼容 CloudNativePG 1.29 及以上版本。在旧版本操作器上使用带扩展定义的 Catalog,这些定义会被拒绝。

安装与使用

通过安装这些官方 Catalog,集群管理员可以确保其 PostgreSQL 集群自动更新到指定主版本内的最新补丁版本(针对所选的 Debian 发行版与镜像类型)。

例如,安装 DebiantrixieminimalPostgreSQL 容器镜像的最新 Catalog:

kubectl apply -f \ https://raw.githubusercontent.com/cloudnative-pg/artifacts/refs/heads/main/image-catalogs/catalog-minimal-trixie.yaml

也可以直接使用image-catalogs目录中的kustomization文件一次安装所有可用的 Catalog:

kubectl apply -k 'https://github.com/cloudnative-pg/artifacts//image-catalogs?ref=main'

安装完成后,可通过以下命令查看所有已部署的 Catalog:

kubectl get clusterimagecatalogs.postgresql.cnpg.io

实战示例:集群始终追踪最新 minimal 镜像

创建如下集群,它始终追踪trixie发行版上 PostgreSQL 18 的最新minimal镜像:

apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: angus spec: instances: 3 imageCatalogRef: apiGroup: postgresql.cnpg.io kind: ClusterImageCatalog name: postgresql-minimal-trixie major: 18 storage: size: 1Gi

此后,每当官方postgresql-minimal-trixieCatalog 中major: 18的镜像条目更新(例如出现新的补丁版本),集群angus都会自动检测到变化并执行滚动更新,无需人工介入修改集群定义。

总结与最佳实践

Image Catalog 是 CloudNativePG 中"声明式管理 PostgreSQL 镜像"的核心抽象,其价值在于将镜像选型集中化、版本更新自动化、集群定义简洁化。综合本文内容,推荐的最佳实践如下:

  • 全局统一用ClusterImageCatalog,团队隔离用ImageCatalog:组织级标准镜像清单用集群级资源,跨命名空间生效;单个团队或应用的特殊版本用命名空间级资源限制影响范围;
  • 优先使用官方 Catalog:官方清单经社区预校验且使用 SHA256 digest 锁定镜像,安全性最高;自定义 Catalog 时必须确保major与实际镜像一致(操作器不做镜像探测);
  • 借助imageCatalogRef.major进行主版本管理:利用"补丁版本自动滚动更新、主版本禁止降级"的行为,将日常补丁升级完全自动化,主版本升级则走专门的升级流程;
  • 组件镜像统一纳入 Catalog:PgBouncer 等非 PostgreSQL 组件的镜像同样可以通过componentImages集中管理,与数据库镜像共享同一套生命周期管理策略;
  • 扩展镜像注意版本兼容:使用带extensions定义的 Catalog 需保证操作器版本不低于 1.29。

相关参考资料(均在当前仓库内):Image Catalog 原始文档、滚动更新机制、Image Volume Extensions、连接池与 PgBouncer、完整示例清单。

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

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询