StackGres 資料庫平臺工程,使用 Citus + Patroni 建立生產級高可用分散式 PostgreSQL 分片叢集

為少發表於2023-12-05

image

系列

什麼是 Sharded Cluster(分片叢集)

Sharded Cluster(分片叢集)是實現資料庫分片的叢集。資料庫分片是跨多臺機器儲存大型資料庫的過程。這是透過在多個 Postgres 主例項之間分隔錶行來實現的。這種方法提供了將資料庫擴充套件到多個例項的能力,既有利於讀取和寫入吞吐量,也有利於在不同例項之間分離資料以實現安全性和/或滿足法規或合規性要求。

Sharded Cluster 是如何實現的

一個分片叢集是透過構造一個稱為協調器的 SGCluster 和一個或多個稱為 shards(分片) 的 SGCluster 來實現的。顧名思義,協調器協調實際儲存資料的 shards(分片) 。StackGres 負責按照 SGShardedCluster 中設定的規範建立相關的 SGCluster。

SGShardedCluster 可以定義分片的型別(即所使用的內部分片實現)和要分片的資料庫。

目前只有一個實現可用,這是透過使用 Citus 擴充套件提供的。

建立一個基本的 Citus Sharded Cluster

建立 SGShardedCluster 資源:

cat << EOF | kubectl apply -f -
apiVersion: stackgres.io/v1alpha1
kind: SGShardedCluster
metadata:
  name: cluster
spec:
  type: citus
  database: mydatabase
  postgres:
    version: '15'
  coordinator:
    instances: 2
    pods:
      persistentVolume:
        size: '10Gi'
  shards:
    clusters: 4
    instancesPerCluster: 2
    pods:
      persistentVolume:
        size: '10Gi'
EOF

此配置將建立一個包含 2 個 pod 的 coordinator(協調器)和4 個 shards(分片),每個分片包含 2 個 pod。

所有 Pod 就緒後,您可以透過發出以下命令來檢視新建立的分片叢集的拓撲:

kubectl exec -n my-cluster cluster-coord-0 -c patroni -- patronictl list
+ Citus cluster: cluster --+------------------+--------------+---------+----+-----------+
| Group | Member           | Host             | Role         | State   | TL | Lag in MB |
+-------+------------------+------------------+--------------+---------+----+-----------+
|     0 | cluster-coord-0  | 10.244.0.16:7433 | Leader       | running |  1 |           |
|     0 | cluster-coord-1  | 10.244.0.34:7433 | Sync Standby | running |  1 |         0 |
|     1 | cluster-shard0-0 | 10.244.0.19:7433 | Leader       | running |  1 |           |
|     1 | cluster-shard0-1 | 10.244.0.48:7433 | Replica      | running |  1 |         0 |
|     2 | cluster-shard1-0 | 10.244.0.20:7433 | Leader       | running |  1 |           |
|     2 | cluster-shard1-1 | 10.244.0.42:7433 | Replica      | running |  1 |         0 |
|     3 | cluster-shard2-0 | 10.244.0.22:7433 | Leader       | running |  1 |           |
|     3 | cluster-shard2-1 | 10.244.0.43:7433 | Replica      | running |  1 |         0 |
|     4 | cluster-shard3-0 | 10.244.0.27:7433 | Leader       | running |  1 |           |
|     4 | cluster-shard3-1 | 10.244.0.45:7433 | Replica      | running |  1 |         0 |
+-------+------------------+------------------+--------------+---------+----+-----------+

請注意,pg_dist_node 表的 groupid 列與上面的 Patroni Group 列相同。特別是,識別符號為 0 的組是 coordinator(協調器) 組(coordinator 的 shouldhaveshards 列設定為 f)。

建立一個自定義的生產級 Citus Sharded Cluster

Sharded Cluster 自定義配置

有關分片叢集配置的更多詳細資訊,請參閱自定義你的 Postgres Cluster一節。具體來說,您將在 my-cluster 名稱空間中建立以下自定義資源:

SGInstanceProfile(k8s pods 自定義配置)

SGPostgresConfig(postgres 自定義配置)

SGPoolingConfig(pgBouncer 自定義配置)

  • 一個名為 poolconfig1 SGPoolingConfig
    apiVersion: stackgres.io/v1
    kind: SGPoolingConfig
    metadata:
      name: pgbouncerconf
    spec:
      pgBouncer:
        pgbouncer.ini:
          pgbouncer:
            max_client_conn: '2000'
            default_pool_size: '50'
          databases:
            foodb:
              max_db_connections: 1000
              pool_size: 20
              dbname: 'bardb'
              reserve_pool: 5
          users:
            user1:
              pool_mode: transaction
              max_user_connections: 50
            user2:
              pool_mode: session
              max_user_connections: '100'
    

SGObjectStorage(s3 資料備份自定義配置)

  • 一個名為 backupconfig1SGObjectStorage
    apiVersion: stackgres.io/v1beta1
    kind: SGObjectStorage
    metadata:
      name: objectstorage
    spec:
      type: s3Compatible
      s3Compatible:
        bucket: stackgres
        region: k8s
        enablePathStyleAddressing: true
        endpoint: http://my-cluster-minio:9000
        awsCredentials:
          secretKeySelectors:
            accessKeyId:
              key: accesskey
              name: my-cluster-minio
            secretAccessKey:
              key: secretkey
              name: my-cluster-minio
    

SGDistributedLogs(分散式日誌 server 配置)

配置 SQL 啟動指令碼

最後但同樣重要的是,StackGres 允許您包含幾個 managedSql 指令碼,以便在啟動時執行叢集操作。

在這個例子中,我們使用 Kubernetes secret 建立一個 Postgres 使用者,並使用 Citus 建立一個分片表:

kubectl -n my-cluster create secret generic pgbench-user-password-secret \
  --from-literal=pgbench-create-user-sql="create user pgbench password 'admin123'"

然後我們在 SGScript 中引用這個 secret:

cat << EOF | kubectl apply -f -
apiVersion: stackgres.io/v1
kind: SGScript
metadata:
  namespace: my-cluster
  name: cluster-scripts
spec:
  scripts:
  - name: create-pgbench-user
    scriptFrom:
      secretKeyRef:
        name: pgbench-user-password-secret
        key: pgbench-create-user-sql
  - name: create-pgbench-tables
    database: mydatabase
    user: pgbench
    script: |
      CREATE TABLE pgbench_accounts (
          aid integer NOT NULL,
          bid integer,
          abalance integer,
          filler character(84)
      );      
  - name: distribute-pgbench-tables
    database: mydatabase
    user: pgbench
    script: |
            SELECT create_distributed_table('pgbench_history', 'aid');
EOF

指令碼由之前建立的 Secret 和內聯的 SQL 指令定義。

SGScript 將在分片叢集的協調器的 managedSql 定義中被引用,如下所示。

請注意,我們同樣可以在配置對映中定義 SQL 指令碼,但是,由於 password 表示憑據,因此我們使用的是 secret。

建立 Citus 叢集

執行了所有必要的步驟來建立我們的 StackGres 叢集。

建立 SGShardedCluster 資源:

cat << EOF | kubectl apply -f -
apiVersion: stackgres.io/v1alpha1
kind: SGShardedCluster
metadata:
  namespace: my-cluster
  name: cluster
spec:
  type: citus
  database: mydatabase
  postgres:
    version: '15.3'
  coordinator:
    instances: 2
    sgInstanceProfile: 'size-small'
    pods:
      persistentVolume:
        size: '10Gi'
    configurations:
      sgPostgresConfig: 'pgconfig1'
      sgPoolingConfig: 'poolconfig1'
    managedSql:
      scripts:
      - sgScript: cluster-scripts
  shards:
    clusters: 3
    instancesPerCluster: 2
    sgInstanceProfile: 'size-small'
    pods:
      persistentVolume:
        size: '10Gi'
    configurations:
      sgPostgresConfig: 'pgconfig1'
      sgPoolingConfig: 'poolconfig1'
  configurations:
    backups:
    - sgObjectStorage: 'backupconfig1'
      cronSchedule: '*/5 * * * *'
      retention: 6
  distributedLogs:
    sgDistributedLogs: 'distributedlogs'
  prometheusAutobind: true
EOF

注意,每個資源都有自己的 name,並在 StackGres 分片叢集定義中被引用。
建立 CR 的順序與成功建立分片叢集相關,即在建立依賴資源之前建立所有必要的 resourcessecretspermissions

另一個有用的配置是 prometheusAutobind: true 定義。
此引數自動啟用對分片叢集的監控。
如果我們已經在 Kubernetes 環境中安裝了 Prometheus operator。

更多