CloudNativePG 标签与注解(Labels & Annotations)完全指南:从预定义元数据到自定义继承机制
【免费下载链接】cloudnative-pgThe most popular Kubernetes Operator for PostgreSQL.项目地址: https://gitcode.com/GitHub_Trending/cl/cloudnative-pg
本文是 CloudNativePG(CNPG)Kubernetes Operator 中标签(Label)与注解(Annotation)体系的技术指南。Kubernetes 以扁平结构组织资源,而标签和注解正是将 Pod、PVC、Job、VolumeSnapshot 等资源与集群关联起来、供外部工具与运维流程识别的核心元数据。读完本文,你将掌握 CloudNativePG 全部预定义标签/注解的语义与适用资源,能够通过 operator 配置实现自定义标签/注解向所有衍生资源(包括 Pod)的自动继承,并了解该机制的当前局限。
为什么 CloudNativePG 选择元数据继承而非 Pod 模板
Kubernetes 中的资源没有天然的层次关系,但通过labels和annotations可以将对象关联起来:
- 注解(Annotation):为资源附加非标识性的额外信息,主要用于与外部工具的集成;
- 标签(Label):用于对对象分组,并通过 Kubernetes 原生的选择器(selector)能力进行查询。
在 Kubernetes 生态中,部分控制器通过"Pod 模板(pod template)"机制让用户直接定义 Pod 的元数据。CloudNativePG 则选择了另一条技术路线——标签与注解继承(label and annotation inheritance)。其核心思路是:用户先在 operator 配置中声明允许继承的标签/注解名称,之后在Cluster资源的 metadata 中定义这些标签/注解,operator 在创建所有衍生资源(包括 Pod)时自动将它们复制到目标资源上。这一机制避免了 Pod 模板带来的不可控性,同时保持了元数据注入的灵活性。
该继承逻辑的核心实现位于 pkg/utils/labels_annotations.go:InheritAnnotations与InheritLabels两个函数遍历源 metadata,并通过InheritanceController接口(IsAnnotationInherited/IsLabelInherited)判断某个名称是否应被继承,匹配成功即写入目标对象的 metadata。operator 配置对象Data正是该接口的实现者,见 internal/configuration/configuration.go。
InheritAnnotations / InheritLabels(pkg/utils/labels_annotations.go) │ ▼ InheritanceController.IsAnnotationInherited / IsLabelInherited │ ▼ configuration.Data(internal/configuration/configuration.go) │ 使用 path.Match 对 INHERITED_ANNOTATIONS / INHERITED_LABELS 做 glob 匹配预定义标签(Predefined labels)
CloudNativePG 为自身管理的资源打上统一的预定义标签,常量定义与注释见 pkg/utils/labels_annotations.go。按功能可分为以下几类。
集群与实例标识
| 标签 | 说明 |
|---|---|
cnpg.io/cluster | 所属Cluster资源的名称,由LabelClusterName函数写入,几乎覆盖所有衍生资源 |
cnpg.io/instanceName | PostgreSQL 实例名称,取代旧的postgresql标签 |
cnpg.io/nodeSerial(注解) | 实例在集群内的序号,用于实例与 Pod 的对应关系 |
cnpg.io/podRole | 区分 Pod 的用途:instance(数据库实例)或pooler(PgBouncer 连接池),枚举值见PodRoleInstance/PodRolePooler |
实例角色标签:cnpg.io/instanceRole与已废弃的role
cnpg.io/instanceRole标记 Pod 中实例的运行角色,取值包括:
primary:主实例;replica:副本实例;unhealthy:瞬态值,仅在故障转移(failover)或切换(switchover)期间由 operator 打在旧主实例上,转换完成后自动清除。
旧标签role已废弃,仅保留向后兼容。在源码中,SetInstanceRole会同时写入新旧两个标签,而GetInstanceRole读取时优先返回新标签值(见 pkg/utils/labels_annotations.go),这保证了运行中的旧版组件仍能识别角色,同时引导用户迁移到新标签。
备份与 VolumeSnapshot 系列标签
以下标签仅出现在VolumeSnapshot资源上,记录备份的时间与来源信息,常量定义于 pkg/utils/labels_annotations.go,实际写入逻辑见 pkg/reconciler/backup/volumesnapshot/reconciler.go(例如backupDate使用20060102格式):
| 标签 | 含义 |
|---|---|
cnpg.io/backupDate | 备份日期,ISO 8601 风格YYYYMMDD |
cnpg.io/backupYear/cnpg.io/backupMonth | 备份发生的年份 / 年月 |
cnpg.io/backupTimeline | 备份时实例所处的 timeline |
cnpg.io/backupName | 备份标识 |
cnpg.io/majorVersion | 备份数据目录对应的 PostgreSQL 主版本整数,如17 |
cnpg.io/onlineBackup | 备份是否为在线热备(hot)还是离线冷备(cold) |
Backup / ScheduledBackup 关联标签
cnpg.io/scheduled-backup:创建该Backup对象的ScheduledBackup资源名称(常量ParentScheduledBackupLabelName);cnpg.io/immediateBackup:当ScheduledBackup的immediate为true时,打在由其创建的第一个Backup上。
Job 与 PVC 角色标签
cnpg.io/jobRole:Job 的角色,例如major-upgrade(大版本升级 Job);cnpg.io/pvcRole:PVC 的用途,取值PG_DATA、PG_WAL、PG_TABLESPACE(见PVCRole枚举);cnpg.io/poolerName:PgBouncer pooler 的名称;cnpg.io/reload:出现在ConfigMap与Secret上,值为true时表示资源变更会被 operator 自动重载到运行中的实例;cnpg.io/userType:标注Secret对应的 PostgreSQL 用户类型,superuser(超级用户,典型为postgres)或app(应用级用户,典型为app),仅用于 CloudNativePG 默认创建的用户;cnpg.io/tablespaceName:PVC 所承载的表空间名称(源码中额外定义)。
Kubernetes 推荐标签(app.kubernetes.io/*)
CloudNativePG 遵循 [Kubernetes 推荐标签]规范,在 Pod、Job、Deployment、Service、PVC、VolumeSnapshot、PodDisruptionBudget、PodMonitor 等资源上打上app.kubernetes.io域标签(常量定义见 pkg/utils/labels_annotations.go,应用示例见 pkg/specs/jobs.go 与 pkg/specs/pgbouncer/deployments.go):
| 标签 | 值 | 可用资源 |
|---|---|---|
app.kubernetes.io/managed-by | 恒为cloudnative-pg | 所有由 CloudNativePG 管理的资源 |
app.kubernetes.io/name | 恒为postgresql | pods、jobs、deployments、services、persistentVolumeClaims、volumeSnapshots、podDisruptionBudgets、podMonitors |
app.kubernetes.io/component | 组件名(database、pooler等) | 同上 |
app.kubernetes.io/instance | 所属Cluster资源名 | pods、jobs、deployments、services、volumeSnapshots、podDisruptionBudgets、podMonitors |
app.kubernetes.io/version | PostgreSQL 主版本 | pods、jobs、services、volumeSnapshots、podDisruptionBudgets、podMonitors |
这些标签使外部工具(如监控、成本分析、备份系统)无需理解 CloudNativePG 内部结构,即可通过标准 Kubernetes 选择器发现和聚合所有 PostgreSQL 相关资源。
预定义注解(Predefined annotations)
预定义注解的常量定义同样集中在 pkg/utils/labels_annotations.go。按使用场景分类如下。
备份时间与 WAL 位置
cnpg.io/backupStartTime/cnpg.io/backupEndTime:备份开始 / 结束时间;cnpg.io/backupStartWAL/cnpg.io/backupEndWAL:备份开始 / 结束时对应的 WAL 位置;cnpg.io/snapshotStartTime:快照开始时间;cnpg.io/snapshotEndTime:快照被标记为可用的时间;cnpg.io/backupLabelFile/cnpg.io/backupTablespaceMapFile:备份的backup_label与tablespace_map文件内容(源码中定义,供恢复流程使用)。
其中backupStartTime位于VolumeSnapshot资源,backupStartWAL、backupEndWAL、backupEndTime仅出现在VolumeSnapshot上。
资源同步与哈希校验
cnpg.io/hash:资源的哈希值,用于检测配置漂移;cnpg.io/podSpec:operator 生成的 Podspec快照,取代已废弃的cnpg.io/podEnvHash(旧的podEnvHash注解仅保留兼容,因环境变量差异已并入podSpec快照);cnpg.io/poolerSpecHash:Pooler 资源的哈希值;cnpg.io/clusterManifest:所属Cluster的完整 manifest(用于 PVC 等资源),取代已废弃的cnpg.io/hibernateClusterManifest;cnpg.io/pgControldata:pg_controldata命令的输出,取代已废弃的cnpg.io/hibernatePgControlData;cnpg.io/operatorVersion:生成该对象的 operator 版本,由SetOperatorVersion写入。
运行时控制类注解
cnpg.io/hibernation:取值on/off,控制声明式休眠(declarative hibernation)特性(见 docs/src/declarative_hibernation.md);cnpg.io/fencedInstances:需要被隔离(fencing)的实例列表,JSON 数组格式,若包含*元素则隔离整个集群(常量FencedInstanceAnnotation);cnpg.io/reconcilePodSpec:取值为disabled时阻止实例因 PodSpec 变更(拓扑/亲和性、调度器、卷与容器等)而重启;作用于Pooler时则限制 Deployment 除spec.instances外的任何修改;cnpg.io/reconciliationLoop:取值为disabled时停止该Cluster的协调循环(对应IsReconciliationDisabled判定,见 pkg/utils/labels_annotations.go);cnpg.io/reloadedAt:最近一次集群 reload 的时间,由用户通过kubectl cnpg插件触发;kubectl.kubernetes.io/restartedAt:最近一次请求重启 PostgreSQL 集群的时间;cnpg.io/pvcStatus:PVC 当前状态:initializing、ready或detached;cnpg.io/nodeSerial:Pod 上实例在集群内的序号;cnpg.io/managedSecrets:operator 管理的 pull secrets,自动注入每个集群对应的ServiceAccount。
WAL 与备份行为开关
cnpg.io/skipWalArchiving:enabled时关闭 WAL 归档(archive_mode设为off,需要重启所有 PostgreSQL 实例)——高风险选项,自担风险;cnpg.io/skipEmptyWalArchiveCheck:enabled时跳过写入数据前对 WAL 归档是否为空的检查——高风险选项,自担风险;cnpg.io/volumeSnapshotDeadline:作用于Backup/ScheduledBackup,控制 operator 在判定卷快照备份失败前重试可恢复错误的时长(分钟),默认 10;cnpg.io/forceLegacyBackup:仅测试用途,模拟barman-cloud-backup3.4 之前(2023 年 1 月)无--name参数时的行为。
安全与合规相关
container.apparmor.security.beta.kubernetes.io/*:为指定容器设置 AppArmor profile。源码中getAnnotationAppArmor会校验注解中提到的容器名确实存在于 Pod 的普通或 init 容器中,避免无效注解(见 pkg/utils/labels_annotations.go)。更多细节参见 docs/src/security.md;cnpg.io/coredumpFilter:控制 Postgres 进程 coredump 的位掩码,默认0x31(排除共享内存段),相关排障见 docs/src/troubleshooting.md;cnpg.io/passwordPassthrough:取值enabled时,operator 在CREATE/ALTER ROLE语句中原样转发基础认证 Secret 中的密码,而不再由 operator 侧做 SCRAM-SHA-256 编码,由 PostgreSQL 依据自身的password_encryption设置完成编码(对应IsPasswordPassthroughEnabled判定与 docs/src/declarative_role_management.md 中的相关章节);cnpg.io/validation:取值disabled时,validation webhook 放行该自定义资源的一切变更——警告:这可能允许不安全甚至破坏性的操作,请谨慎使用。
实验性注解(alpha.cnpg.io 域)
实验性注解使用独立的alpha.cnpg.io命名空间(常量AlphaMetadataNamespace),包括:
alpha.cnpg.io/unrecoverable:作用于运行 PostgreSQL 实例的 Pod,指示 operator 删除该 Pod 及其所有关联 PVC 并按配置的 join 策略重建实例。该注解对任何状态的 Pod(Pending、Running 未就绪、Terminating)均生效;当 Terminating Pod 超过删除宽限期时,operator 会强制删除以便回收 PVC。它只能用于既非当前主实例也非指定目标主实例的实例上。警告:在不可达节点上强制删除 Pod 无法停止其上仍可能运行着的进程,卷是否真正分离取决于存储驱动——该注解的契约本身就意味着放弃实例数据;alpha.cnpg.io/livenessPinger:实例管理器中存活探针的配置;alpha.cnpg.io/failoverQuorum:启用同步仲裁故障转移保护;alpha.cnpg.io/enableInstancePprof:接受true/false,控制实例是否启用 pprof 服务。
Pod 动态修补注解cnpg.io/podPatch
该注解作用于Cluster资源,接受 JSON-patch 格式的补丁,将应用到实例 Pod 上。它能够修改 Pod 规格的任意字段,包括安全敏感字段;operator 仅验证补丁语法正确且可应用。与所有影响 Pod 规格的 Cluster 字段一样,安全约束的强制执行委托给 Kubernetes 的准入控制链(见 docs/src/security.md 中 Trust Model 章节)。
使用时有两点必须注意:
- ⚠️ 警告:该特性可能造成 operator 预期与 Kubernetes 实际行为之间的偏差,应作为最后手段谨慎使用;
- 重要:新增或修改该注解不会触发 Pod 滚动更新,用户需通过
kubectl cnpg restart手动触发。
启用自定义标签与注解的继承
前提:operator 配置
默认情况下,Clustermetadata 中的标签和注解不会被任何衍生资源继承。要启用继承,需要在 operator 配置(cnpg-controller-manager-configConfigMap 或 Secret)中设置两个环境变量,详见 docs/src/operator_conf.md:
| 环境变量 | 作用 |
|---|---|
INHERITED_ANNOTATIONS | 注解名列表,出现在Clustermetadata 中时被所有衍生资源(含 Pod)继承 |
INHERITED_LABELS | 标签名列表,同上 |
两个变量的值都支持路径式通配符(glob):例如example.com/*同时匹配example.com/one与example.com/two。这是实现"我公司所有标签都继承"这类策略的推荐方式,例如用mycompany/*匹配所有mycompany/前缀的标签,或让所有mycompany/前缀的注解都被继承。
底层的匹配逻辑使用 Gopath.Match逐模式比对,遇到非法 glob 模式时会记录日志并跳过该模式而不中断整体匹配(见 internal/configuration/configuration.go),对应的行为测试见 internal/configuration/configuration_test.go。
一个最小化的 operator 配置示例(放在 operator 命名空间cnpg-system中):
apiVersion: v1 kind: ConfigMap metadata: name: cnpg-controller-manager-config namespace: cnpg-system data: INHERITED_ANNOTATIONS: categories INHERITED_LABELS: environment, workload, app沿用该示例并加以限定后,本文后续将只继承:
- 注解:
categories - 标签:
app、environment、workload
在 Cluster 中定义 metadata
在创建Cluster资源时(在部署任何衍生资源之前),在其 metadata 中设置上述标签和注解:
apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: cluster-example annotations: categories: database labels: environment: production workload: database app: sso spec: # ... <snip>验证继承结果
部署完成后,可通过以下命令验证标签是否正确传播到了 Pod:
kubectl get pods --show-labels在输出中,每个实例 Pod 除了携带cnpg.io/cluster、cnpg.io/instanceName、cnpg.io/instanceRole、app.kubernetes.io/*等预定义标签外,还应看到environment=production、workload=database、app=sso三个自定义标签。
继承机制在源码中的落点
自定义元数据继承并非只作用于 Pod,而是贯穿于 operator 生成的所有资源。从源码看,utils.InheritAnnotations与utils.InheritLabels被以下资源生成路径调用:
- 实例 Pod:pkg/reconciler/instance/metadata.go,同时传入
cluster.GetFixedInheritedLabels()作为固定标签; - PVC:pkg/reconciler/persistentvolumeclaim/metadata.go;
- 大版本升级 Job:pkg/reconciler/majorupgrade/reconciler.go,Job 本体及其 Pod 模板都参与继承。
InheritLabels实现中的一个关键细节:它先写入fixedLabels(operator 固定的预定义标签),再遍历源标签并在IsLabelInherited返回 true 时写入自定义标签。因此即便用户自定义标签与预定义标签同名,预定义值也不会被覆盖。相应的单元测试见 pkg/utils/labels_annotations_test.go。
当前局限:删除不会反向传播
CloudNativePG 目前不会自动传播标签或注解的删除。也就是说,当一个此前已传播到 Pod 等衍生资源上的注解或标签从Cluster上移除时,operator不会在关联资源上同步删除它。这意味着旧标签/注解会残留在历史资源上,用户在清理元数据时需自行处理,或通过重建资源(如滚动更新)让新元数据生效。
总结与最佳实践
- 优先使用标准
app.kubernetes.io/*标签与外部工具集成,保证跨平台可移植性; - 通过
INHERITED_ANNOTATIONS/INHERITED_LABELS结合company/*通配符,建立公司级统一的元数据规范,避免在每个Cluster上重复定义; - 角色相关判断请使用
cnpg.io/instanceRole而非已废弃的role标签; - 谨慎使用
cnpg.io/podPatch、cnpg.io/validation、cnpg.io/skipWalArchiving等高风险开关,并在变更后通过kubectl cnpg restart触发预期行为; - 时刻牢记删除不回传的局限,设计元数据生命周期时应考虑通过重建资源完成清理。
如需进一步了解所有标签/注解的完整权威清单,可直接阅读仓库中的 docs/src/labels_annotations.md 原文,以及常量定义所在的 pkg/utils/labels_annotations.go。
【免费下载链接】cloudnative-pgThe most popular Kubernetes Operator for PostgreSQL.项目地址: https://gitcode.com/GitHub_Trending/cl/cloudnative-pg
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考