Helm部署stolon (PostgreSQL高可用集群)

440 阅读4分钟

添加helm仓库

helm repo add kvaps https://kvaps.github.io/charts

查询下stolon

[root@master helm-stolon]# helm search repo stolon
NAME            CHART VERSION   APP VERSION     DESCRIPTION                                       
kvaps/stolon    1.7.0           0.16.0          Stolon - PostgreSQL cloud native High Availabil...

下载stolon的helm Chart文件

[root@master helm-stolon]# helm fetch kvaps/stolon
[root@master helm-stolon]# ls
stolon-1.7.0.tgz

# 解压下载下来的文件
[root@node1 stolon]# tar -xf stolon-1.7.0.tgz

# 进入解压的目录中
[root@node1 helm_stolon]# cd stolon/
[root@node1 stolon]# ls
Chart.yaml  ci  LICENSE  OWNERS  README.md  templates  values.yaml

修改values.yaml文件

# clusterName:
image:
  repository: sorintlab/stolon
  tag: v0.16.0-pg10
  pullPolicy: IfNotPresent
  ## Add secrets manually via kubectl on kubernetes cluster and reference here
  # pullSecrets:
  #   - name: "myKubernetesSecret"

# used by create-cluster-job when store.backend is etcd
etcdImage:
  repository: bitnami/etcd  # 这里修改下镜像地址,原来的地址国内无法访问
  tag: 2.3.7
  pullPolicy: IfNotPresent

debug: false

# Enable the creation of a shm volume
shmVolume:
  enabled: false

persistence:
  enabled: true
  ## If defined, storageClassName: <storageClass>
  ## If set to "-", storageClassName: "", which disables dynamic provisioning
  ## If undefined (the default) or set to null, no storageClassName spec is
  ##   set, choosing the default provisioner.  (gp2 on AWS, standard on
  ##   GKE, AWS & OpenStack)
  ##
  storageClassName: "rook-ceph-block"  # 修改下集群上部署的sc
  accessModes:
    - ReadWriteOnce
  size: 10Gi

rbac:
  create: true

serviceAccount:
  create: true
  # The name of the ServiceAccount to use. If not set and create is true, a name is generated using the fullname template
  name:

superuserSecret:
  name: ""
  usernameKey: pg_su_username    
  passwordKey: pg_su_password

replicationSecret:
  name: ""
  usernameKey: pg_repl_username
  passwordKey: pg_repl_password

superuserPasswordFile:

superuserUsername: "stolon"  # 用户名和密码根据自己的需要进行更改
## password for the superuser (REQUIRED if superuserSecret and superuserPasswordFile are not set)
superuserPassword: "my_pass"

replicationPasswordFile:

replicationUsername: "repluser"  # 用户名和密码根据自己的需要进行更改
## password for the replication user (REQUIRED if replicationSecret and replicationPasswordFile are not set)
replicationPassword: "my_rep_pass"

## backend could be one of the following: consul, etcdv2, etcdv3 or kubernetes
store:
  backend: kubernetes
#  endpoints: "http://stolon-consul:8500"
  kubeResourceKind: configmap

pgParameters: {}
  # max_connections: "1000"

ports:
  stolon:
    containerPort: 5432
  metrics:
    containerPort: 8080

serviceMonitor:
  # When set to true then use a ServiceMonitor to collect metrics
  enabled: false
  # Custom labels to use in the ServiceMonitor to be matched with a specific Prometheus
  labels: {}
  # Set the namespace the ServiceMonitor should be deployed to
  # namespace: default
  # Set how frequently Prometheus should scrape
  # interval: 30s
  # Set timeout for scrape
  # scrapeTimeout: 10s

job:
  autoCreateCluster:
    enabled: true
    resources: {}
    initContainers:
      resources: {}
  initdbScripts:
    enabled: true
    resources: {}
    initContainers:
      resources: {}
  autoUpdateClusterSpec:
    enabled: true
    resources: {}
    initContainers:
      resources: {}
  annotations: {}

clusterSpec: {}
  # sleepInterval: 1s
  # maxStandbys: 5

## Enable support ssl into postgres, you must specify the certs.
## ref: https://www.postgresql.org/docs/10/ssl-tcp.html
##
tls:
  enabled: false
  rootCa: |-      
  serverCrt: |-
  serverKey: |- 
  # existingSecret: name-of-existing-secret-to-postgresql

keeper:
  uid_prefix: "keeper"
  replicaCount: 2
  annotations: {}
  resources: {}
  priorityClassName: ""
  fsGroup: "1000"   # fsGroup要设置成启动pg的用户,要不然会报权限错误,如果开启tls的话需要修改该项
  service:
    type: ClusterIP
    annotations: {}
    ports:
      keeper:
        port: 5432
        targetPort: 5432
        protocol: TCP
  nodeSelector: {}
  affinity: {}
  tolerations: []
  volumes: []
  volumeMounts: []
  hooks:
    failKeeper:
      enabled: false
  podDisruptionBudget:
    # minAvailable: 1
    # maxUnavailable: 1
  extraEnv: []
  #  - name: STKEEPER_LOG_LEVEL
  #    value: "info"

proxy:
  replicaCount: 2
  annotations: {}
  resources: {}
  priorityClassName: ""
  service:
    type: ClusterIP
#    loadBalancerIP: ""
    annotations: {}
    ports:
      proxy:
        port: 5432
        targetPort: 5432
        protocol: TCP
  nodeSelector: {}
  affinity: {}
  tolerations: []
  podDisruptionBudget:
    # minAvailable: 1
    # maxUnavailable: 1
  extraEnv: []
  #  - name: STPROXY_LOG_LEVEL
  #    value: "info"
  #  - name: STPROXY_TCP_KEEPALIVE_COUNT
  #    value: "0"
  #  - name: STPROXY_TCP_KEEPALIVE_IDLE
  #    value: "0"
  #  - name: STPROXY_TCP_KEEPALIVE_INTERVAL
  #    value: "0"

sentinel:
  replicaCount: 2
  annotations: {}
  resources: {}
  priorityClassName: ""
  nodeSelector: {}
  affinity: {}
  tolerations: []
  podDisruptionBudget:
    # minAvailable: 1
    # maxUnavailable: 1
  extraEnv: []
  #  - name: STSENTINEL_LOG_LEVEL
  #    value: "info"

## initdb scripts
## Specify dictionary of scripts to be run at first boot, the entry point script is create_script.sh
## i.e. you can use pgsql to run sql script on the cluster.
##
# initdbScripts:
#   create_script.sh: |
#      #!/bin/sh
#      echo "Do something."

## nodePostStart scripts
## Specify dictionary of scripts to be run at first boot, the entry point script is postStartScript.sh
## i.e. you can create tablespace directory here.
##
# nodePostStartScript:
#   postStartScript.sh: |
#     #!/bin/bash
#     echo "Do something."

部署Chart

# 创建stolon名称空间
[root@node1 stolon]# kubectl create ns stolon
namespace/stolon created
# 在项目目录下可以用dry-run测试一下看看可不可以运行
[root@node1 stolon]# helm install stolon --dry-run .  -n stolon

# 没问题的话就可以直接部署了
# .指定使用当前目录下的Chart
[root@node1 stolon]# helm install stolon . -n stolon

# 运行完上述命令后可以看到最后输出有个获取密码的方式,执行该命令,获取到的密码和最开始设置的密码一样
[root@node1 stolon]# PGPASSWORD=$(kubectl get secret --namespace stolon stolon -o jsonpath="{.data.pg_su_password}" | base64 --decode; echo)
[root@node1 stolon]# echo $PGPASSWORD
my_pass

查看pod

[root@node1 stolon]# kubectl get pods -n stolon
NAME                               READY   STATUS      RESTARTS        AGE
stolon-create-cluster-wsbmq        0/1     Completed   0               35m
stolon-keeper-0                    1/1     Running     0               35m
stolon-keeper-1                    1/1     Running     0               35m
stolon-proxy-64b7656578-pmx67      1/1     Running     0               35m
stolon-proxy-64b7656578-swk5n      1/1     Running     0               35m
stolon-sentinel-77889c8557-ksv98   1/1     Running     0               35m
stolon-sentinel-77889c8557-m2p94   1/1     Running     0               35m

postgres连接测试

[root@node1 stolon]# kubectl get service -n stolon
NAME                     TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
stolon-keeper-headless   ClusterIP   None             <none>        5432/TCP   9m
stolon-proxy             ClusterIP   10.104.149.233   <none>        5432/TCP   9m
[root@node1 stolon]# psql -h 10.104.149.233 -U stolon -d postgres
Password for user stolon: 
psql (13.11, server 10.12 (Debian 10.12-1.pgdg90+1))
Type "help" for help.

postgres=# 
postgres=# 
postgres=# 

查看集群状态

postgres=# select * from pg_stat_replication;
 pid | usesysid | usename  | application_name | client_addr | client_hostname | client_port |         backend_start         | backend_xmin |   state  
 | sent_lsn  | write_lsn | flush_lsn | replay_lsn | write_lag | flush_lag | replay_lag | sync_priority | sync_state 
-----+----------+----------+------------------+-------------+-----------------+-------------+-------------------------------+--------------+----------
-+-----------+-----------+-----------+------------+-----------+-----------+------------+---------------+------------
 201 |    16384 | repluser | stolon_42626513  | 10.244.5.19 |                 |       56528 | 2023-09-21 00:03:55.459201+00 |              | streaming
 | 0/3000140 | 0/3000140 | 0/3000140 | 0/3000140  |           |           |            |             0 | async
(1 row)

参考文档