Skip to content

DbGate 的介绍与 web[docker] 版使用

官网:https://dbgate.org/
DbGate 是跨平台的数据库管理器;是最智能的 SQL + noSQL 数据库客户端

支持的数据库

  • MySQL
  • PostgreSQL
  • SQL Server
  • Oracle (experimental)
  • MongoDB
  • Redis
  • SQLite
  • Amazon Redshift
  • CockroachDB
  • MariaDB

特性

  • 开源、免费
  • 支持多种类数据库,常用的 SQL 与 noSQL 数据库均支持
  • 跨平台,不仅提供了 Windows, Linux 和 Mac 客户端;还提供了 web 版本(npm 或 docker)

web[docker] 平台的使用

使用 dbgate 提供的 web 平台,同时 web 平台提供了 docker 镜像

使用 dbgate 来解决的业务需求

  • 为开发提供自助的 mysql、postgresql 数据库临时权限的申请与访问
  • 重点还需要审计功能,就是能够记录所有的操作记录,最好是能直接记录 sql 语句
  • 在之前我们已经使用 mysql 的代理来实现了 mysql 数据库的临时权限申请;但是现在需要支持 pg 数据库,找了许久,发现 dbgate 能很好的满足我们的需求

解决方案

  • 使用 dbgate 的 web 平台来提供数据库的访问
  • web 版提供了 docker 镜像,且可通过环境变量进行各种配置(登录密码、页面权限、初始数据库配置等等)
  • 通过环境变量配置,禁止添加管理数据库,并配置好指定的数据库
  • 将 docker 镜像部署到与目标数据库同集群的 k8s 中
  • 每次申请仅可申请一个指定的数据库,同一用户申请的多个数据库并不会进行合并到同一个 dbgate 服务中
  • 每个申请者(每次申请的一个数据库)均会启动一个 pod 来提供 dbgate web 服务,互不影响
  • 过期后直接销毁 pod

遇到的问题

以下问题是在使用 iframe 访问 dbgate web 时才会出现:

问题1. https 页面无法访问 http 的 iframe

  • 业务中使用了 iframe 将 dbgate web 嵌入到了自有系统中
  • 自有系统使用 https,dbgate web 默认是 http,浏览器报错禁止访问
  • 解决方案:在 pod 中添加 nginx 容器来进行代理,在 nginx 中配置使用 https (此种方案是通过绑定 pod ip 来提供服务,后来放弃了此方案,改用了 ingress 提供服务的方式)

问题2. k8s 自签名证书无法使用

  • 使用 https 就需要配置证书,首先考虑的是使用 k8s 的自签名证书
  • 但是实际使用后在 iframe 中不会自动进行跳转,无法访问
  • 解决方案:使用自有证书,每次均申请一个域名

问题3. dbgate web 访问有点慢

  • 发现请求 bundle.js 文件耗时较长
  • 解决方案:将包括 bundle.js 在内的静态文件存放于阿里云 OSS 上,提高在国内的访问速度;这里需要修改 index.html 文件,通过 configmap 来进行替换镜像中的 index.html

整体的工作流程

  1. 用户申请数据库权限
    1. 一次仅允许申请一个数据库
    2. 同时选择申请时长(有效期)
  2. 审批通过之后,开始创建 dbgate web 服务
    1. 创建 configmap,此 configmap 用于存储 nginx 配置文件,因每次使用新域名,所以需要每次创建
    2. 创建 deployment,pod 中有两容器:dbgate 和 nginx
      1. dbgate 容器配置环境变量
      2. dbgate 容器挂载 index.html
      3. nginx 容器挂载 ssl 证书文件
      4. nginx 容器挂载 default.conf 配置文件
    3. 创建域名,通过获取 pod ip 来配置域名解析
  3. 创建完成后发送访问链接
  4. 到期自动销毁
    1. 删除 pod
    2. 删除 configmap
    3. 删除域名

环境变量配置

https://dbgate.org/docs/env-variables.html

文档写的很清晰,通过环境变量可配置:

  • web 登录的多个用户密码
  • 每个登录用户的权限(可配置页面的菜单、功能等权限)
  • 预设的一个或多个数据库连接(数据库连接地址、账号、密码等)
  • 每个数据库可配置是否为只读模式(开启只读后,不管数据库账号是否拥有写权限,在 web 页面中只有读权限)

k8s yaml 文件示例

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
  generation: 1
  labels:
    app: dbgate
  name: dbgate
  namespace: op-dbgate
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app.kubernetes.io/instance: dbgate
      app.kubernetes.io/name: dbgate
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app.kubernetes.io/instance: dbgate
        app.kubernetes.io/name: dbgate
    spec:
      containers:
      - env:
        - name: LABEL_con1
          value: mysql1
        - name: SERVER_con1
          value: 127.0.0.1
        - name: USER_con1
          value: root
        - name: PASSWORD_con1
          value: password
        - name: ENGINE_con1
          value: mysql@dbgate-plugin-mysql

        - name: LABEL_con2
          value: pg1
        - name: SERVER_con2
          value: 127.0.0.1
        - name: USER_con2
          value: root
        - name: PASSWORD_con2
          value: password
        - name: ENGINE_con2
          value: postgres@dbgate-plugin-postgres

        - name: LABEL_con3
          value: redis1
        - name: SERVER_con3
          value: 127.0.0.1
        - name: PASSWORD_con3
          value: password
        - name: ENGINE_con3
          value: redis@dbgate-plugin-redis
        - name: READONLY_con3
          value: "1"

        - name: LOGINS
          value: admin
        - name: LOGIN_PASSWORD_admin
          value: "K7OqJ=Gz0JSzF"
        - name: TOKEN_LIFETIME
          value: 7d
        - name: LOGIN_PERMISSIONS_admin
          value: ~*, connections/*, ~settings/change
        - name: BASIC_AUTH
          value: "1"

        - name: PERMISSIONS
          value: ~*, connections/*, ~settings/change
        - name: CONNECTIONS
          value: con1,con2,con3
        image: dbgate/dbgate:5.2.7-alpine
        imagePullPolicy: IfNotPresent
        name: dbgate
        resources:
          limits:
            cpu: "1"
            memory: 1Gi
          requests:
            cpu: 20m
            memory: 20Mi
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
  • 预配置了三个库的连接,mysql/pg/redis 各一个,其中 redis 为只读权限
  • redis 的引擎代码是 redis@dbgate-plugin-redis
  • 同时配置了 web 页面的登录用户、密码
  • 为了提高首页响应速度,可修改首页的静态文件链接为 cdn 或 oss 链接,然后将新首页挂载到镜像中即可

其它记录

如何通过 github 源码构建 dbgate docker 镜像

  • 使用 node16
    bash
    nvm use 16
  • 安装包
    bash
    yarn install
  • 准备 docker 目录
    bash
    yarn prepare:docker
  • 进入 docker 目录然后构建镜像
    bash
    docker build -t op/dbgate:v1 -f Dockerfile-alpine .

未同步更新索引

  • 具体是发生在 pg 数据库上,在后台添加一个新的索引后,再在 dbgate UI 页面上查看表格的结构时,在索引那一项看不到最新的索引
  • 此时如果重启/重新部署 dbgate web 服务的话,可以发现索引更新了