StackGres 数据库平台工程简介
Enterprise Postgres made easy. On Kubernetes
StackGres 是 Kubernetes 的全栈 PostgreSQL 发行版,打包成一个简单的部署单元。
使用精心选择和调优的 PostgreSQL 组件。
一个企业级的 PostgreSQL 栈需要几个其他的生态系统组件和重要的调整。
不仅仅是 PostgreSQL。它需要连接池、自动故障转移和 HA、监控、备份和 DR、集中式日志记录……我们已经构建了它们:一个 Postgres 堆栈。
Postgres 不仅仅是数据库。还有围绕它的整个生态系统。如果 Postgres 是 Linux 内核,我们需要一个围绕 PostgreSQL 的 PostgreSQL 发行版,用生产部署所需的组件来补充它。这就是我们所说的 PostgreSQL 栈。这堆东西需要整理。通常有几个软件实现相同的功能。并不是所有的都具有相同的品质或成熟度。有许多优点和缺点,它们往往不容易评估。最好有一个自定义的组件选择,这些组件可以打包和配置为以可预测和可信的方式一起工作。
StackGres Operator
Operator 是一种打包、部署和管理 Kubernetes 应用程序的方法。一些应用程序,比如数据库,需要更多的手工操作,而云原生 Postgres 需要 operator 提供额外的知识,了解如何维护状态和集成所有组件。StackGres operator 允许使用用户创建的一些自定义资源来部署 StackGres 集群。
StackGres 堆栈
目前,StackGres 的堆栈由以下组件组成:
- PostgreSQL: 世界上最先进的开源关系数据库
- https://www.postgresql.org/
- Patroni: 依赖 kubernetes 分布式共识存储的 HA 解决方案
- https://github.com/zalando/patroni
- WAL-G: WAL-G 是 Postgres 的档案恢复工具
- https://github.com/wal-g/wal-g
- PgBouncer: PostgreSQL 的轻量级连接池
- http://www.pgbouncer.org/
- PostgreSQL Server Exporter:用于 PostgreSQL 服务器指标的 Prometheus 导出器。
- https://github.com/wrouesnel/postgres_exporter
- Envoy: 开源边缘和服务代理,专为云原生应用而设计
- https://www.envoyproxy.io/
StackGres 的重要概念
StackGres 是 Kubernetes 的全栈、生产级 PostgreSQL 发行版。StackGres 提供了在生产环境中运行 PostgreSQL 所需的所有特性和管理选项,除此之外,它还附带了合理的默认选项。
"StackGres" 这个名字来源于运行生产级 PostgreSQL 实例所需的 “组件堆栈”。
在这一页,我们将介绍 StackGres 的重要概念。
生产级数据库管理
生产就绪的数据库管理是 StackGres 的核心。StackGres 以一种简单的声明性方式支持所有常见的(和一些不常见的)数据库管理操作。在这样做的同时,StackGres 坚持生产级行为。这意味着不只是盲目地执行某些操作(例如,当用户更新数据库实例的目标状态时),而是以一种最小化应用程序和用户中断的方式,就像优秀的 DBA 所做的那样。
因此,您可以将 StackGres 视为您友好的 DBA 的 Kubernetes 版本-只是使用 Kubernetes API,更快的响应时间和更少的咖啡休息时间。
以 Kubernetes 为中心
StackGres 是一个基于 Kubernetes 的平台,它以 Kubernetes operator 的形式提供生产级 PostgreSQL。所以 StackGres 的一切都与 Kubernetes 紧密相连。
Kubernetes operator 是一种打包、部署和管理基于 Kubernetes 的应用程序或平台的方法。
有些工作负载(如数据库)需要更多的手工操作,而云原生 Postgres 部署需要了解如何维护状态和集成所有组件。
StackGres operator 允许使用用户创建的一些自定义资源来部署 StackGres 集群。
除此之外,StackGres 还遵循了工程师所熟悉和喜欢的 Kubernetes 的可用性和观感。用户自定义的 StackGres 资源意味着在 Kubernetes 中我们所知道的相同的方便的声明式模型中使用。也就是说,用户定义一个期望的目标状态(通常是YAML,尽管也可能有其他选项),StackGres operator 完成如何达到该目标状态的繁重工作。
单点接入 - 多种方式
StackGres 平台为所有与 Postgres 相关的操作提供了一个单一的访问点。
用户有多种方式访问和修改 Postgres 集群,即通过 Kubernetes API(例如使用 kubectl
), REST API 或 web UI。
无论选择哪种方式或哪种组合,StackGres 都确保状态和所有操作始终一致。
这为用户提供了最大的灵活性和简单性。例如,如果 StackGres 设置由三个用户操作,其中一个用户使用 kubectl
处理所有事情,第二个用户使用自己的 curl
脚本,第三个用户使用 UI,那么他们都可以执行相同的操作并访问相同的信息。所有不同的方式都能实现所有的功能。
Sidecar - 提供生态堆栈功能
StackGres "stack" 的组件由部署在主 Postgres 容器旁边的 sidecar 容器提供。
所有容器基础镜像都是由 StackGres 构建和提供的。
轻量级和安全的容器映像基于 RedHat 的 UBI 8。
StackGres 集群
当我们提到 "cluster" 时,我们指的是由 StackGres 管理的 PostgreSQL 服务器的集合。
因此,StackGres 集群(由自定义 Kubernetes 资源类型 SGCluster
定义)是一个复制、管理、生产就绪和优化的 PostgreSQL 服务器。StackGres 集群具有固定的、合理的配置默认值,所有这些都偏向于生产级体验。因此,对于一个工作设置,定义一个 StackGres 集群已经足够了。
StackGres 架构
Cluster
StackGres 集群基本上是一个 statfulset,其中每个 pod 是一个数据库实例。
StatefulSet 保证每个 pod 总是绑定到它自己的持久卷。
因此,数据库实例数据将被映射到 kubernetes 中 Patroni 实例的状态。
StackGres Cluster 架构图
StackGres Pod 架构图
我们使用一种称为 sidecar 的模式,其中主应用程序在容器中运行,
而位于同一 pod 中的其他容器提供连接池、统计数据导出、边缘代理、日志调度程序或数据库实用程序等侧功能。
UDS: Unix Domain Socket
StackGres 堆栈组件
在生产环境中成功运行 Postgres 需要一整套与 PostgreSQL 相关的组件——一组精心设计的开源组件,它们被构建、验证并打包在一起。有一个围绕 Postgres 构建的工具生态系统,可以用来创建 Postgres 发行版。这就是我们所说的组件堆栈。
为了进行比较,Postgres 就像 Linux 发行版的 Linux 内核——虽然它位于核心,但它仍然需要周围的许多组件来提供 Linux 发行版所提供的功能。
选择该堆栈的正确组件是一项具有挑战性的任务。
在我们做出选择之前,有许多组件和多个软件发行版在功能上重叠,或者有优缺点需要考虑。
需要对所有组件有高度的了解,以便选择适合的组件并提供生产就绪的 Postgres 发行版。
我们的 Postgres 发行版由一个核心组件 (Postgres) 和其他一些组件组成,这些组件满足了 Postgres 生产发行版在不同领域的需求。
核心
用于 Postgres 集群节点的主容器使用 UBI 8 最小镜像作为其基础镜像,其中添加了一个普通 PostgreSQL。容器使用通过 storage class 配置的持久存储。始终与 sidecar util 容器一起部署,以允许系统/数据库管理员访问。
配置
在生产环境中使用默认配置运行 PostgreSQL 通常不是一个好主意。PostgreSQL 使用非常保守的默认值,为了获得良好的性能,必须对其进行调优。
这里有一些地方可以找到更多关于 Postgres 配置参数和最佳实践的信息:
- Postgres Official Documentation
- https://www.postgresql.org/docs/v
- https://postgresqlco.nf (see PostgreSQL Configuration for Humans)
- https://speakerdeck.com/ongres/postgresql-configuration-for-humans
- The Internals of PostgreSQL
- http://www.interdb.jp/pg/
默认情况下,StackGres 被调优以获得比使用默认配置更好的性能。用户仍然可以根据自己的需要更改配置。
连接池
直接连接到 PostgreSQL 不能很好地扩展。一旦达到配置的 max_connections
限制(默认值为 100),超过这个数的连接将被拒绝,这是必须避免的。
虽然许多企业应用程序框架提供了共享数据库连接的功能,但多个应用程序部署几乎从不共享它们的连接池。
配置一个非常高的允许连接数并不能完全解决这个问题,因为我们会注意到连接延迟与负载不成比例地增加,如下图所示(绿线):
这是由于 PostgreSQL 每个连接管理一个进程,这对于大量连接会导致 CPU 内核争用和操作系统调度开销。
由于这些原因,强烈建议在数据库实例前面使用适当的连接池。
以下是三种常见的 PostgreSQL 连接池解决方案:
- PgPool
- https://www.pgpool.net
- PgBouncer
- https://www.pgbouncer.org/
- Odyssey
- https://github.com/yandex/odyssey
现在,选择哪一个呢?
StackGres 选择的解决方案是 PgBouncer。
StackGres 选择的解决方案是 PgBouncer。它足够简单和稳定,可以用于连接池。
PgBouncer 的缺点是缺乏多线程,当连接增加超过一定限制时可能导致 CPU 饱和,这取决于运行的单个 CPU 核心的性能。
当前者变得更加成熟时,Odyssey 可能是取代 PgBouncer 的一个很好的候选人。
高可用
如果一个 Postgres 实例宕机或不能正常工作,我们希望通过选择一个工作实例转换为新的主实例并配置所有其他实例和应用程序以指向这个新的主实例来恢复集群。我们希望这一切都能在没有人工干预的情况下发生。
高可用性解决方案可以实现这一点。这个问题有多种解决方案,很难从中选择一种:
- PgPool
- https://www.pgpool.net
- Repmgr
- https://repmgr.org/
- Patroni
- https://github.com/zalando/patroni
- pg_autofailover
- https://github.com/citusdata/pg_auto_failover
- PAF
- https://dalibo.github.io/PAF/
- Stolon
- https://github.com/sorintlab/stolon
StackGres 选择 Patroni 作为 HA 解决方案。它是一个很好的解决方案,依靠分布式共识算法为主实例的选择提供一致的机制。特别是,Patroni 能够使用与 Kubernetes 相同的分布式共识算法,因此它不需要安装其他服务。
备份和灾难恢复
备份解决方案也是一个有多种选择的生态系统:
pg_dump- Barman
- https://www.pgbarman.org/
- PgBackrest
- https://pgbackrest.org/
- Wal-e / Wal-g
- https://github.com/wal-e/wal-e
- https://github.com/wal-g/wal-g
- pg_probackup
- https://github.com/postgrespro/pg_probackup
另外,我们将备份存储在哪里?
- Disk
- Cloud storage
最后,我们的备份是否会在需要时工作,还是会失败?
Wal-g 是 Wal-e 的后继版本,是提供增量(通过 archive 命令)和完全备份支持的最完整、最轻量级的解决方案。
此外,它还提供了开箱即用的特性,允许在持久卷中存储备份
(使用支持 ReadWriteMany
访问的存储类)或 AWS S3、谷歌云存储或 Azure Blob 存储等云存储。Wal-g 还允许配置带宽或磁盘使用率等方面。
日志
我们希望将分布在所有容器中的日志存储在一个中心位置,并能够在需要时对其进行分析。没有好的解决方案,所以必须自己创造一个。有 fluentd 和 Loki,但后者不能很好地与 Postgres 一起工作。另一种方法是使用 Timescale 将所有日志存储在 Postgres 中。
- https://www.fluentd.org/
- https://grafana.com/oss/loki/
- https://github.com/timescale/timescaledb
代理
如何定位主实例,如果它发生了变化怎么办?我如何获得流量指标?是否可以管理流量:副本,A/B测试集群,或事件检查?
- https://stackgres.io/doc/latest/administration/monitoring/
Envoy 是一个开源的边缘和服务代理,专为云原生应用而设计。它是
可扩展,以便根据实际流量或连接特性提供高级功能。例如,可以解析 Postgres 指标以提供统计数据,或者可以配置 TLS 证书。
- https://www.envoyproxy.io/
Envoy 还能够使用完善的 Prometheus 格式 暴露指标。
- https://stackgres.io/doc/latest/administration/monitoring/envoy/
OnGres Inc.赞助了 Envoy Proxy 项目,提供了暴露 PostgreSQL 监控指标 和实现 SSL termination support 支持等贡献。
- https://www.envoyproxy.io/docs/envoy/latest/configuration/listeners/network_filters/postgres_proxy_filter#statistics
- https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/postgres_proxy/v3alpha/postgres_proxy.proto#envoy-v3-api-field-extensions-filters-network-postgres-proxy-v3alpha-postgresproxy-terminate-ssl
监控
我们可以使用哪种监控解决方案来监控 Postgres 集群?
- Zabbix
- https://www.zabbix.com/
- Okmeter
- https://okmeter.io/
- Pganalyze
- https://pganalyze.com/
- Pgwatch2
- https://github.com/cybertec-postgresql/pgwatch2
- PoWA
- https://github.com/powa-team/powa
- New Relic
- https://newrelic.com/
- DataDog
- https://www.datadoghq.com/
- Prometheus
- https://prometheus.io/
StackGres 的方法是启用尽可能多的监控解决方案。目前,只有 Prometheus 可以使用 PostgreSQL Server Exporter 连接到 StackGres stats,并且如果使用 Prometheus Operator 安装 Prometheus,则可以集成为提供自动绑定机制的 sidecar。
- https://github.com/wrouesnel/postgres_exporter
- https://github.com/prometheus-operator/prometheus-operator
请注意 Prometheus 是一个外部依赖,StackGres 希望你单独安装和配置它。
当然,StackGres 提供了一个选项,可以将 Prometheus 与 StackGres Operator 一起部署,作为 Helm chart 的一部分,您可以按照其中描述的步骤设置所需的参数,以便监视集成按预期工作。请阅读并回顾成功安装的步骤和注意事项。
- https://stackgres.io/doc/latest/install/helm/
另外请注意,Prometheus 将在某个时候从 Helm chart 中删除,因此实际的说明将会改变并过时。
Grafana 集成
默认情况下,Prometheus Operator Helm chart 与 Grafana 一起提供。StackGres 提供了一个集成,允许直接从 StackGres UI 监控 StackGres 集群 pod。实现这一目标有多种选择。
- https://github.com/coreos/prometheus-operator
StackGres包括两种方式:
- 自动集成
- https://stackgres.io/doc/latest/install/prerequisites/#integrating-pre-existing-grafanas
- 手动集成
- https://stackgres.io/doc/latest/install/prerequisites/#manual-integration
为了实现这样的集成,需要一些手动步骤。
用户界面(Web UI)
有一些用户界面可用于与 Postgres 交互,例如 DBeaver,它允许查看数据库内容和配置。我们需要一个能够管理整个集群的用户界面。如何列出集群?一个集群有多少个节点?复制状态如何?一个节点使用了多少计算资源?如何获取特定节点的监控信息?
- https://dbeaver.io/
StackGres 通过 web 和 CLI 提供了一个用户界面,它能够监控和与创建的 StackGres 集群交互。它允许执行基本和高级任务,如 list/get/create/update/delete 集群或执行切换或备份恢复。
更多
- https://hacker-linner.com
- https://stackgres.io