Kubernetes上PostgreSQL的存储策略

2023/12/19 11:17
阅读数 20

在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:

https://github.com/kubernetes/enhancements/pull/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高可用集群,普通磁盘

 

图片

图2

 

如果我们将可用区故障应用于这些拓扑,我们将得到以下结果:

1.单节点,普通磁盘是最便宜的,但在AZ故障的情况下,恢复可能需要几小时甚至几天——取决于数据。

2.单节点和区域磁盘,你不会在副本的计算上花费一分钱,但同时你将在几分钟内恢复。

3.PostgreSQL集群提供最佳可用性,但也伴随着高昂的计算成本。

 

  PostgreSQL单节点,普通磁盘 PostgreSQL单节点,普通磁盘 PostgreSQL单节点, 区域磁盘
计算费用 $ $ $$
存储费用 $ $$ $$
网络费用 $0 $0 $
恢复时间级别 小时级 分钟级 秒级

 

图片

图3

 

03 本地存储

 

在Kubernetes上降低有状态工作负载的总拥有成本(TCO)并提高性能的一种方法是使用本地存储,而不是网络磁盘。公共云提供了可以在k8s中使用像OpenEBSPortworx等工具的NVMe SSD实例。它是通过常规存储类消费的,值得单独写一篇博客。

 

OpenEBS:

https://openebs.io/

Portworx:

https://portworx.com/

 

04 结论

在这篇博客文章中,我们讨论了存储配置的基础知识,并看到了如何微调各种存储参数。在Kubernetes上运行PostgreSQL有不同的拓扑、需求和相应的策略,根据你的成本、性能和可用性需求,你可以通过Percona Operator选择多种选项。

 

加入Percona Kubernetes Squad——一个由数据库专业人士组成的团队,他们在各自的组织和更广泛的领域中引领在Kubernetes上创新数据库操作。该小组致力于为其成员提供坚定的支持,共同探索云原生的发展趋势。

图4

 

* 本文由IvorySQL社区翻译

原文链接:https://www.percona.com/blog/storage-strategies-for-postgresql-on-kubernetes/

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部