Kubernetes上PostgreSQL的存储策略
预计阅读时间
10分钟
导 读
在Kubernetes上部署PostgreSQL并不是新鲜事,可以通过各种Operators(包括Percona)轻松实现。在Percona Operator for PostgreSQL中,你可以选择多种存储配置方式。在这篇博客中,我们将回顾各种存储策略——从基础到更复杂的用例。
Percona Operator for PostgreSQL:
https://docs.percona.com/percona-operator-for-postgresql/2.0/index.html
01
基础知识
1.1 设置StorageClass
Kubernetes中的
StorageClass
资源允许用户设置底层存储的各种参数。例如,你可以选择公共云存储类型(如gp3、io2等)或设置文件系统。
StorageClass:
https://kubernetes.io/docs/concepts/storage/storage-classes/
你可以通过运行以下命令来检查现有的存储类:
$ kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
premium-rwo pd.csi.storage.gke.io Delete WaitForFirstConsumer true 54m
regionalpd-storageclass pd.csi.storage.gke.io Delete WaitForFirstConsumer false 51m
standard kubernetes.io/gce-pd Delete Immediate true 54m
standard-rwo (default) pd.csi.storage.gke.io Delete WaitForFirstConsumer true 54m
你会看到standard-rwo是默认的StorageClass,这意味着如果你如果不指定Operator将默认使用它。
要指示Percona Operator for PostgreSQL使用哪个存储类,请在spec.instances.[].dataVolumeClaimSpec部分设置它:
dataVolumeClaimSpec:
accessModes:
- ReadWriteOnce
storageClassName: STORAGE_CLASS_NAME
resources:
requests:
storage: 1Gi
1.2 为预写日志(WAL)分配单独的卷
预写日志(WAL)记录了PostgreSQL部署中的每个事务。它们对于时间点恢复和最小化恢复点目标(Recovery Point Objective,RPO)很有用。
在Percona Operator中,可以为WAL设置单独的卷,以最小化对性能和存储容量的影响。
要设置它,请使用spec.instances.[].walVolumeClaimSpec部分:
walVolumeClaimSpec:
accessModes:
- ReadWriteOnce
storageClassName: STORAGE_CLASS_NAME
resources:
requests:
storage: 1Gi
如果启用walVolumeClaimSpec,运营商将为每个副本Pod创建两个卷——一个用于数据,一个用于WAL。
cluster1-instance1-8b2m-pgdata Bound pvc-2f919a49-d672-49cb-89bd-f86469241381 1Gi RWO standard-rwo 36s
cluster1-instance1-8b2m-pgwal Bound pvc-bf2c26d8-cf42-44cd-a053-ccb6abadd096 1Gi RWO standard-rwo 36s
cluster1-instance1-ncfq-pgdata Bound pvc-7ab7e59f-017a-4655-b617-ff17907ace3f 1Gi RWO standard-rwo 36s
cluster1-instance1-ncfq-pgwal Bound pvc-51baffcf-0edc-472f-9c95-7a0cea3e6507 1Gi RWO standard-rwo 36s
cluster1-instance1-w4d8-pgdata Bound pvc-c60282ed-3599-4033-afc7-e967871efa1b 1Gi RWO standard-rwo 36s
cluster1-instance1-w4d8-pgwal Bound pvc-ef530cb4-82fb-4661-ac76-ee7fda1f89ce 1Gi RWO standard-rwo 36s
1.3 更改存储大小
如果你的StorageClass和存储接口(CSI)支持
VolumeExpansion
,你可以直接在自定义资源清单中更改存储大小。运营商将完成剩下的工作并自动扩展存储。这是一个零停机操作,仅受底层存储能力的限制。
VolumeExpansion:
https://kubernetes.io/blog/2018/08/02/dynamically-expand-volume-with-csi-and-kubernetes/
1.4 更改存储
也可以更改存储能力,例如文件系统、IOPs和类型。目前,可以通过创建新的存储类并将其应用于新的实例组来实现:
spec:
instances:
- name: newGroup
dataVolumeClaimSpec:
accessModes:
- ReadWriteOnce
storageClassName: NEW_STORAGE_CLASS
resources:
requests:
storage: 2Gi
创建新的实例组会将数据复制到新的副本节点。这是无停机完成的,但复制可能会在主节点和网络上引入额外负载。
Kubernetes Enhancement Proposal (KEP)
#3780
正在进行中。它将允许用户通过存储类以外的方式动态更改各种卷属性。
#3780:
02
数据持久化
2.1 Finalizers
默认情况下,如果删除集群,Operator会保留存储和“秘密”资源。我们这样做是为了保护用户免受人为错误和其他情况的影响。
这样,用户可以快速启动集群,重用现有的存储和“秘密”。
可以通过在自定义资源中启用终结器来更改此默认行为:
apiVersion: pgv2.percona.com/v2
kind: PerconaPGCluster
metadata:
name: cluster1
finalizers:
- percona.com/delete-pvc
- percona.com/delete-ssl
这对于不需要保留数据的非生产集群很有用。
2.2 StorageClass数据保护
在极端情况下,人为错误是不可避免的。例如,有人可能会删除整个Kubernetes集群或命名空间。
好在StorageClass资源带有reclaimPolicy选项,它可以指示容器存储接口保留底层卷。这个选项不受Operator控制,你应该单独为StorageClass设置它。
apiVersion: storage.k8s.io/v1
kind: StorageClass
...
provisioner: pd.csi.storage.gke.io
- reclaimPolicy: Delete
+ reclaimPolicy: Retain
在这种情况下,即使删除了Kubernetes资源,物理存储仍然存在。
2.3 区域磁盘
区域磁盘在Azure和Google Cloud上可用,但在AWS上尚未可用。简而言之,它是跨两个可用区(AZ)复制的磁盘。
图1
要使用区域磁盘,你需要一个指定了它将在哪些AZ中可用并复制到的存储类:
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: regionalpd-storageclass
provisioner: pd.csi.storage.gke.io
parameters:
type: pd-balanced
replication-type: regional-pd
volumeBindingMode: WaitForFirstConsumer
allowedTopologies:
- matchLabelExpressions:
- key: topology.gke.io/zone
values:
- us-central1-a
- us-central1-b
有一些情况下,区域磁盘可以帮助降低成本。让我们回顾三种PostgreSQL拓扑:
1.单节点,普通磁盘
2.单节点,区域
3.PostgreSQL高可用集群,普通磁盘
如果我们将可用区故障应用于这些拓扑,我们将得到以下结果:
1.单节点,普通磁盘是最便宜的,但在AZ故障的情况下,恢复可能需要几小时甚至几天——取决于数据。
2.单节点和区域磁盘,你不会在副本的计算上花费一分钱,但同时你将在几分钟内恢复。
3.PostgreSQL集群提供最佳可用性,但也伴随着高昂的计算成本。
PostgreSQL单节点,普通磁盘 | PostgreSQL单节点,普通磁盘 | PostgreSQL单节点, 区域磁盘 | |
计算费用 | $ | $ | $$ |
存储费用 | $ | $$ | $$ |
网络费用 | $0 | $0 | $ |
恢复时间级别 | 小时级 | 分钟级 | 秒级 |
03
本地存储
在Kubernetes上降低有状态工作负载的总拥有成本(TCO)并提高性能的一种方法是使用本地存储,而不是网络磁盘。公共云提供了可以在k8s中使用像
OpenEBS
、
Portworx
等工具的NVMe SSD实例。它是通过常规存储类消费的,值得单独写一篇博客。
OpenEBS:
Portworx:
04
结论
在这篇博客文章中,我们讨论了存储配置的基础知识,并看到了如何微调各种存储参数。在Kubernetes上运行PostgreSQL有不同的拓扑、需求和相应的策略,根据你的成本、性能和可用性需求,你可以通过Percona Operator选择多种选项。
加入Percona Kubernetes Squad——一个由数据库专业人士组成的团队,他们在各自的组织和更广泛的领域中引领在Kubernetes上创新数据库操作。该小组致力于为其成员提供坚定的支持,共同探索云原生的发展趋势。
原文链接:https://www.percona.com/blog/storage-strategies-for-postgresql-on-kubernetes/
推荐阅读
IvorySQL
点击文末的 “阅读原文”,开启您的IvorySQL3.0 Release Notes探索之旅,深入了解更多独家特性。