数据库高可用集群管理运维后端【免费下载链接】patroniA template for PostgreSQL High Availability with Etcd, Consul, ZooKeeper, or Kubernetes项目地址https://gitcode.com/gh_mirrors/pa/patroni点击查看免费下载导读本文基于 Patroni 官方文档 docs/kubernetes.rst 展开讲解如何让 Patroni 直接使用 Kubernetes 原生对象Endpoints 或 ConfigMaps存储集群状态与 leader 锁从而在 Kubernetes 环境中彻底省去 Etcd、Consul 等独立一致性存储的部署。读完本文你将掌握两种存储模式的区别与选型依据、kubernetes段全部配置参数的语义、自定义 role 标签的无损迁移步骤以及如何基于仓库自带的 kubernetes/patroni_k8s.yaml 清单在 kind 集群中快速验证一套三节点 PostgreSQL 高可用集群。为什么可以在 Kubernetes 上省掉 Etcd传统上 Patroni 依赖 Etcd、Consul、ZooKeeper 等外部一致性存储来保存集群的 leader 键、动态配置和成员信息。而 Kubernetes 本身就是一个高可用的分布式协调系统Patroni 完全可以借用它的 API 与对象模型实现同样的功能把集群配置和 leader 键写入 Kubernetes 对象的metadata.annotations字段并借助对象的resourceVersion做乐观并发控制配合 List/Watch 机制实时感知状态变化。这样部署 PostgreSQL 高可用集群时Kubernetes 环境里就不需要额外运行一套 Etcd。这种能力对应仓库中的 DCS 实现 patroni/dcs/kubernetes.py其中的Kubernetes类继承自AbstractDCS与 Etcd、Consul 等实现处于同一抽象层次HA 循环完全透明无需针对 Kubernetes 修改任何业务逻辑。Patroni 用于存储 leader 键与配置键的 Kubernetes 对象有两种通过配置项kubernetes.use_endpoints或环境变量PATRONI_KUBERNETES_USE_ENDPOINTS切换use_endpoints: true使用Endpoints对象use_endpoints: false默认使用ConfigMaps对象。Use Endpoints 模式推荐但默认关闭尽管 Endpoints 是官方推荐模式但出于兼容性考虑它默认是关闭的。开启后Patroni 会创建对应的 Endpoints 对象并把集群配置与 leader 键存放在这些 Endpoints 的metadata.annotations字段中。该模式最核心的优势在于** leader 切换更安全、原子性更强**当 leader 变更时包含 leader 信息的 annotations 和实际指向正在运行的 leader Pod 的地址subsets会在同一次 API 更新中一并完成两者不会出现短暂的不一致窗口。而在 ConfigMaps 模式下leader 信息与 Endpoint 地址是分开维护的切换至少需要两次更新中间存在一定的不一致风险。从源码看Endpoints 模式还有一处特殊处理Kubernetes._create_config_service()patroni/dcs/kubernetes.py 中_create_config_service方法会为配置 Endpoint$SCOPE-config创建一个clusterIP: None的 headless Service目的是防止 Kubernetes 主控在 Endpoint 没有对应 Service 时把它当作孤儿对象清理掉。这一点在部署清单中也有体现见下文示例中的patronidemo-configheadless Service。Use ConfigMaps 模式当use_endpoints为 false 时Patroni 创建的是 ConfigMaps集群状态同样存放在其metadata的 annotations 中。该模式下leader 变更需要至少两次更新一次更新 leader 的 ConfigMap写入新的 leader 信息另一次更新对应的 Endpoint把流量地址切到新的 leader Pod。因此在极端情况下可能出现 ConfigMap 已更新、但 Endpoint 仍指向旧 leader 的短暂窗口。值得注意的是某些平台没有选择余地例如在 OpenShift 上运行时只能使用 ConfigMaps文档明确指出 in some cases, for instance, when running on OpenShift, there is no alternative to using ConfigMaps。从实现上看use_endpoints的切换在 CoreV1ApiProxy 类中生效它会把*_kind这类虚拟方法名动态映射为*_endpoints或*_config_map见__getattr__中func func[:-4] (endpoints if self._use_endpoints else config_map)从而让上层代码对两种对象一视同仁。此外Kubernetes.leader_path属性也会根据use_endpoints决定是否截取路径后缀保证两种模式下的对象命名与读取逻辑各自正确。源码视角Kubernetes DCS 的工作原理深入 patroni/dcs/kubernetes.py 可以看到其内部机制有助于理解两种模式为何可靠、以及配置参数如何生效。标签体系与对象发现在Kubernetes.__init__约 patroni/dcs/kubernetes.py 第 755-768 行中labels与scope_label默认cluster-name拼接出集群标识再组合成label_selector用于筛选本集群的 Pod 与 Endpoints/ConfigMapsrole_label默认roleleader_label_value默认primaryfollower_label_value默认replicastandby_leader_label_value默认primarytmp_role_label默认为空。对象发现依赖两个ObjectCache后台线程Pod 缓存与 Kind 缓存它们先 LIST 全量对象构建缓存再基于resourceVersion建立 Watch 长连接收到 ADDED/MODIFIED/DELETED 事件后增量更新本地缓存并仅在 leader 键或配置键发生变化时唤醒 HA 循环避免无谓的空转。角色标签的写入touch_memberPod 上的角色标签由touch_member方法patroni/dcs/kubernetes.py 第 1368-1408 行维护其取值逻辑为本节点是 leaderrole_label写入leader_label_value若是 standby leader 则写入standby_leader_label_value若配置了tmp_role_label则同时写入primary本节点是运行中的 replicarole_label写入follower_label_valuetmp_role_label写入对应的真实角色如replica其他状态停止、异常等role_label写入空值。此外若配置了bootstrap_labels则当节点处于initializing new cluster、running custom bootstrap script、starting after custom bootstrap、creating replica等引导状态时会把这批标签附加到 Pod 上离开这些状态后则移除。这些状态分支在 tests/test_kubernetes.py 的test_touch_member中有完整覆盖。Endpoints subsets 的维护当use_endpoints开启时leader 选举成功后Patroni 需要把 leader Pod 的 IP 写进 leader Endpoint 的subsets使 Service 能把流量转发到正确的 leader。相关逻辑在_map_subsetspatroni/dcs/kubernetes.py 第 1068-1085 行与subsets_changed第 1022-1056 行Patroni 会比较当前 Endpoint 的 subsets 与期望值IP、端口、端口名、协议只有不一致时才发起 patch避免频繁写 APIIP 来源为kubernetes.pod_ip配置或 Pod 自身的status.podIP。可重试的 HTTP 处理Patroni 默认对 K8s API 返回的500、503、504以及带retry-after响应头的错误进行重试见CoreV1ApiProxy与KubernetesRetriableException并且对 409resourceVersion冲突会先杀掉 Watch 流再重读最新对象确保在并发竞争下状态最终一致。配置参数详解kubernetes段完整参数在 docs/yaml_configuration.rst 的 Kubernetes 小节kubernetes_settings锚点附近有正式定义对应的PATRONI_KUBERNETES_*环境变量则在 docs/ENVIRONMENT.rst 的 Kubernetes 小节kubernetes_environment锚点。两处内容一一对应下面合并列出配置项环境变量说明bypass_api_servicePATRONI_KUBERNETES_BYPASS_API_SERVICE可选。默认 Patroni 通过kubernetesService地址来自 Pod 内的KUBERNETES_SERVICE_HOST访问 API设为true时改为解析 Service 背后的 API 节点列表并直连可绕开负载均衡层也避免依赖kubernetesService 的kubernetesEndpoint。namespacePATRONI_KUBERNETES_NAMESPACE可选。Patroni Pod 所在的命名空间默认default。labelsPATRONI_KUBERNETES_LABELS格式{label1: value1, label2: value2}。用于发现与当前集群关联的 Pod 和 Endpoints/ConfigMapsPatroni 也会把它们写到其创建的每个对象上。强烈建议与kubernetes/patroni_k8s.yaml清单一样显式设置application与cluster-name否则可能匹配到无关对象。scope_labelPATRONI_KUBERNETES_SCOPE_LABEL可选。存放集群名的标签名默认cluster-name。bootstrap_labelsPATRONI_KUBERNETES_BOOTSTRAP_LABELS可选。节点处于初始化/自定义引导/创建副本等引导状态时附加到 Pod 的标签。role_labelPATRONI_KUBERNETES_ROLE_LABEL可选。存放角色值的标签名Patroni 会写到所在 Pod 上默认role。Service 的 selector 依赖它。leader_label_valuePATRONI_KUBERNETES_LEADER_LABEL_VALUE可选。角色为primary时写入的标签值默认primary。follower_label_valuePATRONI_KUBERNETES_FOLLOWER_LABEL_VALUE可选。角色为replica时写入的标签值默认replica。standby_leader_label_valuePATRONI_KUBERNETES_STANDBY_LEADER_LABEL_VALUE可选。角色为standby_leader时写入的标签值默认primary。tmp_role_labelPATRONI_KUBERNETES_TMP_ROLE_LABEL可选。临时角色标签名其值总是使用对应角色的默认值仅在迁移默认标签到自定义标签时设置。use_endpointsPATRONI_KUBERNETES_USE_ENDPOINTS可选。为true时用 Endpoints 替代 ConfigMaps 进行 leader 选举与状态存储。默认 false。pod_ipPATRONI_KUBERNETES_POD_IP可选。当前 Pod 的 IP。开启use_endpoints后必须提供用于在节点提升为 leader 时填充 leader Endpoint 的 subsets。清单中用fieldRef指向status.podIP。portsPATRONI_KUBERNETES_PORTS可选。当 Service 的端口带有 name 时Endpoint 中的端口必须同名 Service 才能正常转发。例如 Service 定义为{Kind: Service, spec: {ports: [{name: postgresql, port: 5432, targetPort: 5432}]}}则需设置kubernetes.ports: [{name: postgresql, port: 5432}]。仅use_endpoints模式下生效。cacertPATRONI_KUBERNETES_CACERT可选。验证 K8s API 证书用的 CA bundle 文件不提供时使用 ServiceAccount secret 注入的 CA。retriable_http_codesPATRONI_RETRIABLE_HTTP_CODES可选。额外的 K8s API 重试 HTTP 状态码列表可传 int、列表或逗号分隔字符串。默认重试500、503、504或响应头带retry-after时。补充说明bypass_api_service在非default命名空间部署且开启直连时需要额外的 ClusterRole 权限见下文清单中的patroni-k8s-ep-access。另外Kubernetes DCS 下retry_timeout、ttl、loop_wait等通用参数同样通过reload_config作用于 API 超时与 keepalive socket 选项configure_timeouts动态配置变更依然生效。自定义角色标签无损迁移五步法默认情况下Patroni 依据节点角色在 Pod 上打标签如roleprimary。标签的键与值可以通过kubernetes.role_label、kubernetes.leader_label_value、kubernetes.follower_label_value、kubernetes.standby_leader_label_value自定义。如果要从默认角色标签迁移到自定义标签文档给出了可显著减少停机时间的迁移步骤。核心思路是利用kubernetes.tmp_role_label例如tmp_role先挂一个使用默认角色值的临时标签让 Service 平滑切换后再逐步换成新的自定义标签值步骤 1为 Pod 增加临时标签。在配置中设置kubernetes.tmp_role_label如tmp_role。Pod 重启后 Patroni 会同时打上原标签与临时标签labels: cluster-name: foo role: primary tmp_role: primary步骤 2修改 Service 的 selector让它先选中临时标签。此时流量已经由临时标签正确导向新旧标签并存不会中断selector: cluster-name: foo tmp_role: primary步骤 3启用自定义角色标签值。例如设置kubernetes.leader_label_valueprimary此处以自定义值为例。Pod 再次重启后Patroni 会打上新标签同时保留临时标签labels: cluster-name: foo role: primary tmp_role: primary步骤 4等所有 Pod 更新完成后把 Service selector 改回使用新的角色标签selector: cluster-name: foo role: primary步骤 5最后从配置中移除tmp_role_label并再次滚动更新所有 Pod。最终 Pod 上只保留正式标签labels: cluster-name: foo role: primary整个过程中Service 始终指向至少一个有效标签先tmp_role后role因此对外流量不中断。源码层面临时标签的写入正是前文touch_member中updated_labels[self._tmp_role_label] tmp_role的逻辑tmp_role的值始终取对应角色的默认值leader 写primary、replica 写replica从而保证临时标签的语义在迁移期间稳定不变相关断言可见 tests/test_kubernetes.py 的test_touch_member。把流量导向 leaderService 的 label selector要正确地把客户端流量导向 PostgreSQL leader必须让 Kubernetes 的 Postgres Service 使用基于role_label默认role的标签选择器。Patroni 会持续更新 Pod 上的角色标签touch_memberService 通过 selector 精准命中当前 leader 的 Pod。仓库自带的 kubernetes/patroni_k8s.yaml 演示了两种 ServicepatronidemoClusterIP端口 5432没有 selector流量由 Patroni 维护的patronidemoEndpoints 的subsets决定这正是use_endpoints: true模式下的标准玩法——Service 转发目标完全跟随 leader Endpointpatronidemo-replClusterIP端口 5432带 selector{application: patroni, cluster-name: patronidemo, role: replica}专门把流量分发给只读副本。若使用 ConfigMaps 模式则必须依赖 selector 型 Service用role_label指向leader_label_value因为 ConfigMaps 本身不承载可路由地址。部署示例在 kind 上跑通三节点集群仓库的 kubernetes/README.md 提供了一套基于 kind 的完整演练清单文件为 kubernetes/patroni_k8s.yaml包含以下关键资源headless Servicepatronidemo-configclusterIP: None保护patronidemo-configEndpoint 不被 k8s 主控清理对应源码_create_config_service的逻辑清单里是显式预创建StatefulSetpatronidemo3 副本镜像patronidocker build -t patroni .构建带 readinessProbe/readiness8008 端口、pgdataemptyDir 卷注释中保留了可选的volumeClaimTemplates启用即可换用 PersistentVolumeEndpointspatronidemosubsets: []作为 leader 选举与状态存储对象ServicepatronidemoClusterIP:5432与Servicepatronidemo-replselectorrole: replicaSecret存放 superuser 与 replication 密码RBACServiceAccountpatronidemo Role/RoleBinding授权configmaps、endpoints、pods、services的相应操作另有 ClusterRole/ClusterRoleBindingpatroni-k8s-ep-access仅当非default命名空间且开启bypass_api_service时才需要用于读取kubernetesEndpoint。清单通过环境变量注入全部 Patroni 配置核心几项如下与上文参数一一对应env: - name: PATRONI_KUBERNETES_POD_IP valueFrom: fieldRef: {fieldPath: status.podIP} # pod_ipuse_endpoints 必需 - name: PATRONI_KUBERNETES_NAMESPACE valueFrom: fieldRef: {fieldPath: metadata.namespace} - name: PATRONI_KUBERNETES_BYPASS_API_SERVICE value: true - name: PATRONI_KUBERNETES_USE_ENDPOINTS value: true # 使用 Endpoints 模式 - name: PATRONI_KUBERNETES_LABELS value: {application: patroni, cluster-name: patronidemo} - name: PATRONI_SCOPE value: patronidemo - name: PATRONI_NAME valueFrom: fieldRef: {fieldPath: metadata.name} # StatefulSet Pod 名作为节点名 - name: PATRONI_POSTGRESQL_LISTEN value: 0.0.0.0:5432 - name: PATRONI_RESTAPI_LISTEN value: 0.0.0.0:8008运行步骤详见 kubernetes/README.mdkind create cluster docker build -t patroni . kind load docker-image patroni kubectl apply -f patroni_k8s.yaml kubectl get pods -L role预期结果patronidemo-0显示primarypatronidemo-1、patronidemo-2显示replica进入 Pod 后执行patronictl list可看到完整的成员与 lag 信息。整套流程无需任何外部一致性存储验证了Kubernetes 即 DCS的架构。部署注意事项PersistentVolume 限制文档明确提示仓库自带的清单在当前状态下无法使用 PersistentVolumes存在权限问题数据目录用的是emptyDir。生产环境如需持久化请参考注释掉的volumeClaimTemplates并结合平台实际调整或采用下文的 Spilo 方案。RBAC 权限裁剪Role 中configmaps/endpoints的delete、deletecollection仅在使用patronictl remove清理集群时才需要日常运行可去掉endpoints的create/list/watch仅在 Endpoints 模式下需要。OpenShift 用户只能使用 ConfigMaps 模式use_endpoints: false并按上文 selector 方式组织 Service。patronictl客户端场景Kubernetes.__init__中会优先尝试load_incluster_config()失败例如在集群外运行 patronictl时才回退读取KUBECONFIG默认~/.kube/config可用context配置指定因此集群外管理也是可行的。生产化的生态路线官方文档还给出了在生产环境规模化运行时的参考方向均为同名开源项目可按需自行查阅SpiloZalando 维护的、可支持 PersistentVolume 的完整 Docker 镜像解决了仓库自带镜像的持久化权限问题Patroni Helm chart可用于快速部署由 Patroni 管理的 Spilo 镜像Zalando postgres-operator以 Operator 模式批量管理 Spilo 集群适合大规模数据库集群的自动化运维。这三个项目与本文的 Kubernetes 存储模式一脉相承底层仍然是 Patroni 的 Kubernetes DCS 实现patroni/dcs/kubernetes.py只是把部署、存储与生命周期管理进一步产品化。小结在 Kubernetes 上运行 Patroni本质上是用 Kubernetes 自身的强一致 API 替代外部一致性存储推荐启用kubernetes.use_endpoints把 leader 信息与可达地址原子地写进 Endpoints 的 annotations 与 subsets获得更安全的 leader 切换无法使用 Endpoints 的平台如 OpenShift则退化为 ConfigMaps。合理配置labels/role_label/pod_ip/ports等参数、按五步法平滑迁移角色标签、并借助仓库自带的 kubernetes/patroni_k8s.yaml 与 kind 快速验证即可在生产中落地一套免 Etcd 的 PostgreSQL 高可用方案。赞分享数据库高可用集群管理运维后端【免费下载链接】patroniA template for PostgreSQL High Availability with Etcd, Consul, ZooKeeper, or Kubernetes项目地址https://gitcode.com/gh_mirrors/pa/patroni点击查看免费下载相关推荐在 Kubernetes 上部署 FerretDB以 DocumentDB 为后端的高可用 MongoDB 替代方案在 Kubernetes 上部署 FerretDB以 DocumentDB 为后端的高可用 MongoDB 替代方案 本篇指南以 FerretDB v2.7后端数据库文档数据库etcd × Kubernetes 版本升级实战在 kubernetes/kubernetes 中 Bump etcd 的完整流程etcd × Kubernetes 版本升级实战在 kubernetes/kubernetes 中 Bump etcd 的完整流程 本文基于 etcd 官方贡后端数据库分布式数据库KV存储云原生服务注册发现配置中心Apache DolphinScheduler 以 etcd 作为注册中心的完整配置指南Apache DolphinScheduler 以 etcd 作为注册中心的完整配置指南 本指南围绕 Apache DolphinScheduler 官方注册中任务调度大数据后端前端上一篇Anteon多租户支持企业级监控平台的用户隔离方案下一篇常见问题解答fold-entity-row使用中最容易犯的7个错误及解决方法创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
OpenClaw安全方案拆解:投研机构智能体部署与加固实践 这套“优刻得发布面向投研机构的OpenClaw安全解决方案”消息一出来,业内讨论不少。作为常年给客户做智能体落地的人,我第一反应不是看它在宣传什么,而是赶紧去扒OpenClaw到底是什么、和市面上那些Agent平台有什么不一样、为什么偏偏是投研机构… · 2026/9/25 3:28:51
长期约定的心理学价值与实践智慧 1. 关于"十年之约"的思考十年前那个闷热的夏夜,我和几位大学室友挤在宿舍阳台上,对着星空许下了一个看似随意的约定:十年后无论身在何方,都要回到这个城市重聚。当时谁都没把这个承诺当真——毕竟毕业后各奔东西是常态&… · 2026/9/25 3:28:45
Apache ShenYu TARS 协议接入实战:从 IDL、Servant 实现到网关代理 /tars/hello 后端API网关微服务 【免费下载链接】shenyu Apache ShenYu is a Java native API Gateway for service proxy, protocol conversion and API governance. 项目地址: https://gitcode.com/gh_mirrors/sh/shenyu 点击查看 免费下载 Apache ShenYu 除常见的 HTTP、Dub… · 2026/9/25 3:28:45
AI搜索GEO工程化落地:知识库、Schema与信源监测的闭环实践 过去三个多月,我一直待在上海,帮一家做工业设备的企业客户跑AI搜索GEO工程化项目。客户预算不算大,但要求很明确:不管用户在哪个AI搜索引擎里问行业问题,品牌都要稳定出现在候选答案里,最好还能点开来源就直… · 2026/9/25 4:24:55
WarriorJS 安装指南:通过 npm 全局安装 CLI 并创建你的第一个战士 教育CLI 【免费下载链接】warriorjs 🏰 An exciting game of programming and Artificial Intelligence 项目地址: https://gitcode.com/gh_mirrors/wa/warriorjs 点击查看 免费下载 本篇技术指南讲解 WarriorJS(一款在 JavaScript/TypeScri… · 2026/9/25 4:24:55
Kindle Voyage不能刷安卓?用ADB调试桥解锁隐藏玩法 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:24:55
CarSim安装避坑指南:从环境准备到Simulink联合仿真配置 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:24:55
生产级Agent沙箱设计:选型、持久化与执行协议全解析 1. 为什么本地跑通的沙箱,一上生产就翻车先说个我们踩过的场景。最开始做 Agent 的时候,团队里每个人都在自己电脑上跑代码沙箱,主要就是拿 Docker 跑个容器,把 LLM 生成的代码丢进去执行,本地看起来一切正常。但等到要… · 2026/9/25 4:24:48
ASP.NET Core 集成 MCP:让 AI 直接调用你的接口 1. 为什么要把 .NET 接口暴露给 AI1.1 从一个真实痛点说起去年底我接手了一个内部工单系统的维护工作,前端同事跑过来跟我说:“能不能让 AI 直接帮我查工单状态?我不想每次都在 Swagger 页面里翻接口、填参数、点 Try it out。”当时我的第一… · 2026/9/25 4:24:48
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37