暂无图片
暂无图片
4
暂无图片
暂无图片
暂无图片

Kubernetes环境上openGaussHA集群架构设计

原创 Renduy 2023-07-19
318

Kubernetes环境上openGauss HA集群架构设计

与单节点数据库相比,HA 架构可提供更强的数据层停机保护。如果要提供更高等级的SLA和更小的RTO,则可以使用高可用性架构。

本文介绍了基于Patroni + HAProxy + etcd的架构设计,可为Kubernetes环境上的 openGauss部署提供高可用性 (HA)

高可用性的工作原理

流式复制

流式复制是一种复制方法,即备机连接到主机并持续接收 WAL 记录流。与日志传送复制功能相比,流式复制功能可让备机与主机保持同步。openGauss提供内置的流式复制功能。

默认情况下,流式复制是异步进行的;主机不会先等待备机确认,然后再向客户端确认事务提交。如果主机在确认事务之后、备机收到事务之前发生故障,则异步复制可能会导致数据丢失。为了提高数据的安全性,可以使用同步流式复制。

同步流式复制

可以通过将一个或多个备机选择为同步备用节点,将流式复制配置为同步复制。同步模式下,在备机确认事务提交前,主机不会确认事务提交。同步流式复制功能可实现更高的数据一致性,但是会增加事务延迟时间。

opengGauss可以通过synchronous_commit 设置当前事务的同步方式:

  • on表示将备机的同步日志刷新到磁盘。
  • off表示异步提交。
  • local表示为本地提交。
  • remote_write表示要备机的同步日志写到磁盘。
  • remote_receive表示要备机同步日志接收数据。
  • true表示将备机的同步日志刷新到磁盘。
  • false表示异步提交。
  • yes表示将备机的同步日志刷新到磁盘
  • no表示异步提交。
  • 1表示将备机的同步日志刷新到磁盘。
  • 0表示异步提交。

openGauss HA 架构

我们的openGauss HA 主要包含以下方面:

  • 采用一主两备,主备之间通过异步流复制数据。

  • Patroni监控本地的openGauss状态,并将本地openGauss信息/状态写入etcd来存储集群状态。

  • Patroni与etcd结合可以实现数据库集群故障切换。当主机故障时,Patroni把一个备机(Standby)拉起来,作为新的主(Primary), 如果一个故障节点恢复了,能够自动加入集群。

  • HAProxy提供数据库的统一访问入口,对业务模块屏蔽数据库集群的内部实现,对外提供数据库的高可用,数据库切换对应用无感知。HAProxy通过Patroni提供的REST API来检测openGauss的主备状态,确保业务请求只会被路由到主机。

  • 在Kubernetes环境上,通过设置replicas可以创建多个HAProxy副本,提供了HAProxy高可用。

  • etcd用于Patroni节点之间共享信息。Patroni的主备选举是通过是否能获得etcd中的 leader key 来控制的,获取到了leader key的Patroni为主节点,其它的为备节点。

架构图如下:

PatroniETCDHaproxy.png

在Kubernetes环境上搭建openGauss HA

在Kubernetes环境上搭建openGauss HA需要部署openGauss Service,openGauss Deployment和HAProxy。

通常情况下Kubernetes集群会带有etcd集群,此处就不在单独部署etcd了。

openGauss Service

在Kubernetes 中 Service 是 将运行在一个或一组 Pod 上的网络应用程序公开为网络服务的方法。我们为每个openGauss实例定义一个Service,这样就可以通过这个Service对外提供服务。

apiVersion: v1
kind: Service
metadata:
  namespace: platform
  name: dbsrv1
spec:
  ports:
    - port: 5432
      protocol: TCP
      targetPort: 5432
      name: gsql
  selector:
    app: db1
  clusterIP: None
  
---
apiVersion: v1
kind: Service
metadata:
  namespace: platform
  name: dbsrv2
spec:
  ports:
    - port: 5432
      protocol: TCP
      targetPort: 5432
      name: gsql
  selector:
    app: db2
  clusterIP: None
  
---
 apiVersion: v1
kind: Service
metadata:
  namespace: platform
  name: dbsrv3
spec:
  ports:
    - port: 5432
      protocol: TCP
      targetPort: 5432
      name: gsql
  selector:
    app: db3
  clusterIP: None

openGauss Deployment

以下是一个openGauss实例的部署yaml,其他的实例类似。

在deployment中使用节点亲和性保证一个主机上不会同时调度两个openGauss实例。同时将openGauss实例的数据目录挂载到主机目录上。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: db1-deployment
  namespace: platform
spec:
  selector:
    matchLabels:
      app: db1
  replicas: 1
  template:
    metadata:
      labels:
        app: db1
        version: 3.0.0
        dev: gauss
    spec:
      affinity:    					//亲和性保证一个主机上不会同时调度两个openGauss实例
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: app
                    operator: In
                    values:
                      - db2
                      - db3
              topologyKey: "Kubernetes.io/hostname"
      restartPolicy: Always
      containers:
        - name: opengauss
          image: patroni-opengauss:3.0.3
          imagePullPolicy: Always
          securityContext:
            runAsUser: 0
          volumeMounts:
            - mountPath: /var/lib/opengauss/data/
              name: openguass-volume
          ports:
            - containerPort: 5432
              name: opengauss
            - containerPort: 8008
              name: patroni
          env:
            - name: HOST_NAME
              value: db1
            - name: HOST_IP
              valueFrom:
                fieldRef:
                  fieldPath: status.podIP
            - name: PEER_IPS
              value: dbsrv2.platform,dbsrv3.platform
            - name: PEER_HOST_NAMES
              value: db2,db3
            - name: PORT
              value: "5432"
            - name: GS_PASSWORD
              value: "yourpassword"
            - name: SERVER_MODE
              value: primary
            - name: db_config
              value: ""
      volumes:						//将openGauss实例的数据目录挂载到主机目录上
        - name: openguass-volume
          hostPath:
            path: /data/opengauss/
            type: DirectoryOrCreate

HAProxy 部署

apiVersion: v1
kind: Service
metadata:
  namespace: platform
  name: haproxy-service
spec:
  type: NodePort
  ports:
    - port: 6000
      protocol: TCP
      targetPort: 6000
      name: gsql
    - port: 7000
      protocol: TCP
      targetPort: 7000
      name: haproxy-dashboard
  selector:
    app: haproxy
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: haproxy-deployment
  namespace: platform
spec:
  selector:
    matchLabels:
      app: haproxy
  replicas: 2

  template:
    metadata:
      labels:
        app: haproxy
        version: 2.7.3-ping
    spec:
      containers:
        - name: haproxy
          image: wirepo.td-tech.com/cnp/haproxy:2.7.3-ping
          ports:
            - containerPort: 7000
              name: haproxy
            - containerPort: 6000
              name: gauss
          volumeMounts:
            - name: config
              mountPath: "/usr/local/etc/haproxy"
              readOnly: true
      nodeSelector:
        db-proxy: "true"
      volumes:
        - name: config
          configMap:
            name: haproxy-config

HAProxy配置文件

---

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: platform
  name: haproxy-config
data:
  # 类文件键
  haproxy.cfg: |
    global
    maxconn 100
    log 127.0.0.1 local0

    defaults
    log global
    mode tcp
    retries 2
    timeout client 30m
    timeout connect 4s
    timeout server 30m
    timeout check 5s

    listen stats
    mode http
    bind *:7000
    stats enable
    stats uri /

    listen opengauss
    bind *:6000
    option httpchk
    http-check expect status 200
    default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
    server dbsrv1 dbsrv1.platform.svc.cluster.local:5432 maxconn 100 check port 8008
    server dbsrv2 dbsrv2.platform.svc.cluster.local:5432 maxconn 100 check port 8008
    server dbsrv3 dbsrv3.platform.svc.cluster.local:5432 maxconn 100 check port 8008

主要配置

1主2从的流复制配置

在Kubernetes环境上需要在pod中配置,通常在镜像的entrypoint.sh中通过脚本实现,此处只记录脚本中使用的主要命令。

# 在pg_hba.conf中添加对端ip 此处使用主机名
host all all dbsrv1.platform.svc.cluster.local trust
host all all dbsrv2.platform.svc.cluster.local trust
host all all dbsrv3.platform.svc.cluster.local trust

# 配置postgresql.conf的如下参数
# 本机监听地址
gs_guc set -D $PGDATA -c “listen_addresses = '192.168.2.162'”
# 配置流复制连接信息 有几个备就要配置几个
gs_guc set -D $PGDATA -c "replconninfo1 = 'localhost=192.168.2.162 localport=5433 localheartbeatport=5434 localservice=5436 remotehost=192.168.1.186 remoteport=5433 remoteheartbeatport=5434 remoteservice=5436'"
# 配置主备同步模式
gs_guc set -D $PGDATA -c "synchronous_commit=on"
# 配置潜在同步复制的备机名称列表,每个名称用逗号分隔。当取值为*,表示匹配任意提供同步复制的备机名称。
gs_guc set -D $PGDATA -c "synchronous_standby_names = '*'"

HAProxy DNS解析配置

在HAProxy配置中我们通过监听openGauss Service来代理数据库,但是HAProxy通常只在启动时解析一次域名,并把ip保存在内存中,在Kubernetes上存在一个问题,当一个openGauss pod故障后,会重新拉起一个新的pod,此时ip会发生变化,从而导致HAProxy不能正常代理。因此需要配置动态域名解析,如下:

    resolvers kube-dns
    nameserver kube-dns kube-dns.kube-system.svc.cluster.local:53
    parse-resolv-conf
    resolve_retries       3
    timeout resolve       1s
    timeout retry         1s
    hold other           30s
    hold refused         30s
    hold nx              30s
    hold timeout         30s
    hold valid           10s
    hold obsolete        30s

基本维护

查看openGauss实例状态

通过kubectl查看 openGauss pod状态和调度情况:

[root@master2 ~]# kubectl get po -n platform -l dev=gauss -o wide
NAME                              READY   STATUS    RESTARTS      AGE   IP              NODE             NOMINATED NODE   READINESS GATES
db1-deployment-67d97bbdf7-vz29h   1/1     Running   0             2d    192.168.1.29    10.148.151.130   <none>           <none>
db2-deployment-6bfb5467b8-h4pxw   1/1     Running   1 (23h ago)   26h   192.168.0.154   10.148.151.140   <none>           <none>
db3-deployment-d479ff947-9bfng    1/1     Running   0             25h   192.168.2.140   10.148.151.139   <none>           <none>

也可以通过Patroni提供的http接口查看集群状态:

# curl -i dbsrv1.platform.svc.cluster.local:8008/cluster
HTTP/1.0 200 OK
Server: BaseHTTP/0.6 Python/3.7.16
Date: Wed, 19 Jul 2023 07:25:14 GMT
Content-Type: application/json

{
    "members":[
        {
            "name":"db1",
            "role":"leader",
            "state":"running",
            "api_url":"http://192.168.1.29:8008/patroni",
            "host":"192.168.1.29",
            "port":5432,
            "timeline":1,
            "pending_restart":true
        },
        {
            "name":"db2",
            "role":"replica",
            "state":"running",
            "api_url":"http://192.168.0.154:8008/patroni",
            "host":"192.168.0.154",
            "port":5432,
            "timeline":"1",
            "pending_restart":true,
            "lag":0
        },
        {
            "name":"db3",
            "role":"replica",
            "state":"running",
            "api_url":"http://192.168.2.140:8008/patroni",
            "host":"192.168.2.140",
            "port":5432,
            "timeline":"1",
            "pending_restart":true,
            "lag":0
        }
    ]
}

attach到pod中通过Patroni查看集群状态

root@db1-deployment-67d97bbdf7-vz29h:/# patronictl -c /home/omm/patroni.yaml  list
+--------+---------------+---------+---------+----+-----------+-----------------+
| Member | Host          | Role    | State   | TL | Lag in MB | Pending restart |
+ Cluster: opengauss (5626236013549685205) --+----+-----------+-----------------+
| db1    | 192.168.1.29  | Leader  | running |  1 |           | *               |
| db2    | 192.168.0.154 | Replica | running |  1 |         0 | *               |
| db3    | 192.168.2.140 | Replica | running |  1 |         0 | *               |
+--------+---------------+---------+---------+----+-----------+-----------------+

查看HAProxy代理状态

通过HAProxy提供的dashboard可以查看代理状态,如下图可以看出流量会被路由到dbsrv1

image-20230719161101668

HA测试

数据库实例故障测试

测试类型 测试方式 测试命令 测试结果
- 停主库实例 - 备库自动升级成主库,HAProxy代理正常,数据库服务正常,故障节点恢复后重新加入集群
- 停备库实例 - 主库不受影响,HAProxy代理正常,数据库服务正常,故障节点恢复后重新加入集群

操作系统宕机测试

测试类型 测试方式 测试命令 测试结果
- 在Kubernetes集群中选取主库所在的主机重启 reboot 1. 触发故障切换到备库其中一个节点,备库另一个节点同步新主库
- 在Kubernetes集群中选取备库所在的主机重启 reboot HAProxy代理正常,数据库服务正常,故障节点恢复后重新加入集群

switchover和failover切换

  • failover endpoints 允许在没有健康节点时执行手动 failover ,但同时它不允许 switchover 。
  • switchover endpoint 则相反。它仅在集群健康(有leader)时才起作用,并允许在指定时间安排切换。

switchover操作

 root@db1-deployment-67d97bbdf7-vz29h:/# patronictl -c /home/omm/patroni.yaml  list
+--------+---------------+---------+---------+----+-----------+-----------------+
| Member | Host          | Role    | State   | TL | Lag in MB | Pending restart |
+ Cluster: opengauss (5626236013549685205) --+----+-----------+-----------------+
| db1    | 192.168.1.29  | Leader  | running |  1 |           | *               |
| db2    | 192.168.0.154 | Replica | running |  1 |         0 | *               |
| db3    | 192.168.2.140 | Replica | running |  1 |         0 | *               |
+--------+---------------+---------+---------+----+-----------+-----------------+
root@db1-deployment-67d97bbdf7-vz29h:/# patronictl -c /home/omm/patroni.yaml  switchover
Master [db1]:
Candidate ['db2', 'db3'] []:
When should the switchover take place (e.g. 2023-07-19T17:32 )  [now]:
Current cluster topology
+--------+---------------+---------+---------+----+-----------+-----------------+
| Member | Host          | Role    | State   | TL | Lag in MB | Pending restart |
+ Cluster: opengauss (5626236013549685205) --+----+-----------+-----------------+
| db1    | 192.168.1.29  | Leader  | running |  1 |           | *               |
| db2    | 192.168.0.154 | Replica | running |  1 |         0 | *               |
| db3    | 192.168.2.140 | Replica | running |  1 |         0 | *               |
+--------+---------------+---------+---------+----+-----------+-----------------+
Are you sure you want to switchover cluster opengauss, demoting current master db1? [y/N]: y
2023-07-19 16:32:40.69923 Successfully switched over to "db2"
+--------+---------------+---------+---------+----+-----------+-----------------+
| Member | Host          | Role    | State   | TL | Lag in MB | Pending restart |
+ Cluster: opengauss (5626236013549685205) --+----+-----------+-----------------+
| db1    | 192.168.1.29  | Replica | stopped |    |   unknown | *               |
| db2    | 192.168.0.154 | Leader  | running |  1 |           | *               |
| db3    | 192.168.2.140 | Replica | running |  1 |         0 | *               |
+--------+---------------+---------+---------+----+-----------+-----------------+
root@db1-deployment-67d97bbdf7-vz29h:/# patronictl -c /home/omm/patroni.yaml  list
+--------+---------------+---------+---------+----+-----------+-----------------+
| Member | Host          | Role    | State   | TL | Lag in MB | Pending restart |
+ Cluster: opengauss (5626236013549685205) --+----+-----------+-----------------+
| db1    | 192.168.1.29  | Replica | running |  1 |         0 | *               |
| db2    | 192.168.0.154 | Leader  | running |  1 |           | *               |
| db3    | 192.168.2.140 | Replica | running |  1 |         0 | *               |
+--------+---------------+---------+---------+----+-----------+-----------------+

failover操作

  root@db1-deployment-67d97bbdf7-vz29h:/# patronictl -c /home/omm/patroni.yaml  list
+--------+---------------+---------+---------+----+-----------+-----------------+
| Member | Host          | Role    | State   | TL | Lag in MB | Pending restart |
+ Cluster: opengauss (5626236013549685205) --+----+-----------+-----------------+
| db1    | 192.168.1.29  | Replica | running |  1 |         0 | *               |
| db2    | 192.168.0.154 | Leader  | running |  1 |           | *               |
| db3    | 192.168.2.140 | Replica | running |  1 |         0 | *               |
+--------+---------------+---------+---------+----+-----------+-----------------+
root@db1-deployment-67d97bbdf7-vz29h:/# patronictl -c /home/omm/patroni.yaml  failover
Candidate ['db1', 'db3'] []: db3
Current cluster topology
+--------+---------------+---------+---------+----+-----------+-----------------+
| Member | Host          | Role    | State   | TL | Lag in MB | Pending restart |
+ Cluster: opengauss (5626236013549685205) --+----+-----------+-----------------+
| db1    | 192.168.1.29  | Replica | running |  1 |         0 | *               |
| db2    | 192.168.0.154 | Leader  | running |  1 |           | *               |
| db3    | 192.168.2.140 | Replica | running |  1 |         0 | *               |
+--------+---------------+---------+---------+----+-----------+-----------------+
Are you sure you want to failover cluster opengauss, demoting current master db2? [y/N]: y
2023-07-19 16:34:19.26151 Successfully failed over to "db3"
+--------+---------------+---------+---------+----+-----------+-----------------+
| Member | Host          | Role    | State   | TL | Lag in MB | Pending restart |
+ Cluster: opengauss (5626236013549685205) --+----+-----------+-----------------+
| db1    | 192.168.1.29  | Replica | running |  1 |         0 | *               |
| db2    | 192.168.0.154 | Replica | stopped |    |   unknown | *               |
| db3    | 192.168.2.140 | Leader  | running |  1 |           | *               |
+--------+---------------+---------+---------+----+-----------+-----------------+
root@db1-deployment-67d97bbdf7-vz29h:/# patronictl -c /home/omm/patroni.yaml  list
+--------+---------------+---------+----------+----+-----------+-----------------+
| Member | Host          | Role    | State    | TL | Lag in MB | Pending restart |
+ Cluster: opengauss (5626236013549685205) ---+----+-----------+-----------------+
| db1    | 192.168.1.29  | Replica | running  |  1 |         0 | *               |
| db2    | 192.168.0.154 | Replica | starting |    |   unknown | *               |
| db3    | 192.168.2.140 | Leader  | running  |  1 |           | *               |
+--------+---------------+---------+----------+----+-----------+-----------------+
root@db1-deployment-67d97bbdf7-vz29h:/# patronictl -c /home/omm/patroni.yaml  list
+--------+---------------+---------+----------+----+-----------+-----------------+
| Member | Host          | Role    | State    | TL | Lag in MB | Pending restart |
+ Cluster: opengauss (5626236013549685205) ---+----+-----------+-----------------+
| db1    | 192.168.1.29  | Replica | running  |  1 |         0 | *               |
| db2    | 192.168.0.154 | Replica | starting |    |   unknown | *               |
| db3    | 192.168.2.140 | Leader  | running  |  1 |           | *               |
+--------+---------------+---------+----------+----+-----------+-----------------+
root@db1-deployment-67d97bbdf7-vz29h:/# patronictl -c /home/omm/patroni.yaml  list
+--------+---------------+---------+---------+----+-----------+-----------------+
| Member | Host          | Role    | State   | TL | Lag in MB | Pending restart |
+ Cluster: opengauss (5626236013549685205) --+----+-----------+-----------------+
| db1    | 192.168.1.29  | Replica | running |  1 |         0 | *               |
| db2    | 192.168.0.154 | Replica | running |  1 |         0 | *               |
| db3    | 192.168.2.140 | Leader  | running |  1 |           | *               |
+--------+---------------+---------+---------+----+-----------+-----------------+

总结

Kubernetes具有高可用性特征,可以确保应用程序的持续可用性。通过使用Patroni来管理openGauss集群,可以实现自动故障转移和数据复制,确保数据库的高可用性。

此外,在Kubernetes搭建数据库集群还有以下优势:

  1. 自动化部署和管理:Kubernetes是一个容器编排平台,提供了自动化的应用程序部署和管理机制。通过使用Kubernetes,可以轻松地部署和管理这些组件,包括Patroni、HAProxy、etcd和openGauss。
  2. 弹性伸缩:Kubernetes允许根据需求自动扩展或缩减应用程序和数据库实例。当负载增加时,可以自动添加新的Pod实例以增加容量。而当负载减少时,可以自动缩减Pod实例以减少资源消耗,从而实现弹性伸缩。
  3. 自我修复和健康检查:Kubernetes具有自我修复的能力。当组件出现故障时,Kubernetes可以自动重新启动受影响的Pod实例,使应用程序保持可用性。此外,Kubernetes还提供了健康检查机制,可以监测应用程序和数据库的状态,并在检测到异常时进行相应的操作。
  4. 灵活性和可移植性:Kubernetes是一个开放源代码的平台,支持多云环境和混合云环境。这意味着可以轻松迁移和扩展基于Kubernetes的架构,而无需对架构进行重大改动。此外,Kubernetes还提供了丰富的插件和工具生态系统,可以灵活地定制和扩展架构。
最后修改时间:2023-07-19 18:11:06
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论