Setting up databases access with CloudBeaver on Kubernetes

Dionathan Chrys
7 min readJan 25, 2023

--

CloudBeaver

PT-BR Version

Hello everyone! This article is to show and teach you how to set up automatic and authenticated access to your databases through CloudBeaver.

In case you have fallen into this article, I will explain what it is for. CloudBeaver is a database management tool that you can access and use through your browser, on the exposed port 8978 of the container, but why use it? We have several other options such as PGadmin, MySQL Workbench, HeidiSQL, Beekeeper Studio among many others. Well, I will list some very interesting advantages of it.

  • Supports multiple databases.
  • Allows you to manipulate data like a spreadsheet.
  • Database navigation structure.
  • Data export and migration in various formats.
  • SSH tunnels for remote database connectivity.
  • SQL editor with intelligent auto-completion and syntax highlighting.
  • Great user interface.
  • User/role based security model.

This and other features are available in the community (free) version, there are also Enterprise and AWS versions. You can check for more details here.

Alright! Given the proper introduction, let’s go!

Here is the repository with the CloudBeaver configs and the Kubernetes specs.

https://github.com/dionathanchrys/cloud-beaver

In the kustomization.yaml file we have the definition of the ConfigMaps that will be files from the repository, these ConfigMaps in turn will be used to create the volumes in the deployment.yaml and these volumes will be mounted on our pod, replacing the default files and configuring the application.

Hold on! I will explain better below.

In the configMapGenerator, we create the ConfigMaps pointing to the .json or .config files with the CloudBeaver configurations. (I will talk about these files later)

kustomization.yaml:

configMapGenerator:
- name: configmap-name
files:
- path/to/your/file.json

Real example:

configMapGenerator:
- name: dbeaver-product-configmap
files:
- dbeaver/configs/product.conf
- name: dbeaver-sources-user-configmap
files:
- dbeaver/configs/user/data-sources.json
- name: dbeaver-sources-global-configmap
files:
- dbeaver/configs/global/data-sources.json
- name: dbeaver-server-configmap
files:
- dbeaver/configs/cloudbeaver.conf

After applied

❯ kubectl get configmaps

NAME DATA AGE
dbeaver-product-configmap-kg79td7884 1 3d15h
dbeaver-server-configmap-m5fc6m9ff7 1 3d15h
dbeaver-sources-global-configmap-9b82g2h9bm 1 3d15h
dbeaver-sources-user-configmap-5d7fttct9h 1 3d15h

To use these configMaps, we must create the volumes with them in the deployment, see below:

deployment.yaml:

volumes:
- name: volume-name
configMap:
name: configmap-name

Real example:

volumes:
- name: dbeaver-product
configMap:
name: dbeaver-product-configmap
- name: dbeaver-sources-user
configMap:
name: dbeaver-sources-user-configmap
- name: dbeaver-sources-global
configMap:
name: dbeaver-sources-global-configmap
- name: dbeaver-server
configMap:
name: dbeaver-server-configmap

With the volumes declared, we can now mount them:

volumeMounts:
- name: volume-name
mountPath: /path/inside/container/to/your/file.conf
subPath: file.conf

Real example:

volumeMounts:
- name: dbeaver-product
mountPath: /opt/cloudbeaver/conf/product.conf
subPath: product.conf
- name: dbeaver-sources-user
mountPath: /opt/cloudbeaver/workspace/user-projects/admin.dbeaver/.dbeaver/data-sources.json
subPath: data-sources.json
- name: dbeaver-sources-global
mountPath: /opt/cloudbeaver/workspace/GlobalConfiguration/.dbeaver/data-sources.json
subPath: data-sources.json
- name: dbeaver-server
mountPath: /opt/cloudbeaver/conf/cloudbeaver.conf
subPath: cloudbeaver.conf

Finally, the deployment.yaml (cloudbeaver) file should look like this:

kind: Deployment
apiVersion: apps/v1
metadata:
name: dbeaver
namespace: cloud-beaver-test
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 1
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
selector:
matchLabels:
app: dbeaver-app
template:
metadata:
labels:
app: dbeaver-app
spec:
containers:
- name: dbeaver
image: dbeaver/cloudbeaver:latest
imagePullPolicy: Always
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 500m
memory: 256Mi
ports:
- name: web-access
containerPort: 8978
livenessProbe:
httpGet:
path: /
port: 8978
scheme: HTTP
initialDelaySeconds: 300
timeoutSeconds: 10
periodSeconds: 300
successThreshold: 1
failureThreshold: 5
envFrom:
- secretRef:
name: dbeaver-secret
volumeMounts:
- name: dbeaver-product
mountPath: /opt/cloudbeaver/conf/product.conf
subPath: product.conf
- name: dbeaver-sources-user
mountPath: /opt/cloudbeaver/workspace/user-projects/admin.dbeaver/.dbeaver/data-sources.json
subPath: data-sources.json
- name: dbeaver-sources-global
mountPath: /opt/cloudbeaver/workspace/GlobalConfiguration/.dbeaver/data-sources.json
subPath: data-sources.json
- name: dbeaver-server
mountPath: /opt/cloudbeaver/conf/cloudbeaver.conf
subPath: cloudbeaver.conf
volumes:
- name: dbeaver-product
configMap:
name: dbeaver-product-configmap
- name: dbeaver-sources-user
configMap:
name: dbeaver-sources-user-configmap
- name: dbeaver-sources-global
configMap:
name: dbeaver-sources-global-configmap
- name: dbeaver-server
configMap:
name: dbeaver-server-configmap

And the kustomization.yaml (cloudbeaver part of) like this:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

namespace: cloud-beaver-test

resources:
- namespace.yaml
- dbeaver/deployment.yaml
- dbeaver/service.yaml
- postgres/deployment.yaml
- postgres/service.yaml
- mysql/deployment.yaml
- mysql/service.yaml

configMapGenerator:
#DBEAVER
- name: dbeaver-product-configmap
files:
- dbeaver/configs/product.conf
- name: dbeaver-sources-user-configmap
files:
- dbeaver/configs/user/data-sources.json
- name: dbeaver-sources-global-configmap
files:
- dbeaver/configs/global/data-sources.json
- name: dbeaver-server-configmap
files:
- dbeaver/configs/cloudbeaver.conf
#POSTGRES
- name: postgres-configmap
literals:
- POSTGRES_USER=my-db-user
- POSTGRES_PASSWORD=Password123
- POSTGRES_DB=my-postgre-db
#MYSQL
- name: mysql-configmap
literals:
- MYSQL_ROOT_PASSWORD=PasswordROOT
- MYSQL_USER=my-db-user
- MYSQL_PASSWORD=Password123
- MYSQL_DATABASE=my-mysql-db

secretGenerator:
#DBEAVER
- name: dbeaver-secret
literals:
- CB_SERVER_NAME=CloudBeaver Test Server
- CB_ADMIN_NAME=admin.dbeaver
- CB_ADMIN_PASSWORD=Password123

commonLabels:
kubernetes.io/environment: dev

Note: these secrets generated in the kustomization.yaml are CloudBeaver environment variables:

CB_SERVER_NAME=Server name
CB_ADMIN_NAME=<admin user>
CB_ADMIN_PASSWORD=<yourpasswordhere>

Now that we know how to configure, let’s understand what these 3 files are for: data-sources.json, cloudbeaver.conf, product.conf

data-sources.json

In this file is where we make the connection settings for the database instances, in the example we will use connections for a Postgres and another MySql database.

It’s located in the following path:

/opt/cloudbeaver/workspace/user-projects/<USER>/.dbeaver/data-sources.json

This settings only work for the logged user, the connections will only be available after logging in to CloudBeaver.

/opt/cloudbeaver/workspace/GlobalConfiguration/.dbeaver/data-sources.json

As the name of the folder already says, they are global configurations, all settings made here will be available without authentication in CloudBeaver, if you enable anonymous access.

I will explain the main parameters of this JSON so you can configure without problems:

folders”: If you want to configure multiple connections, you can separate them into folders.

save-password”: It’s better not to save the access password to your database right? (leave it false)

folder”: If you have created a folder, declare it here.

user”: Database user, if you declare it here, it will auto-complete for you on the login screen.

host”: IP or DNS address of your database instance.

port”: Instance database access port.

database”: Database that the communication will be made with.

url”: The url is composed of the following parameters <provider>://<host>:<port>/<database>

{
"folders": {
"My DBs": {}
},
"connections": {
"DB-example-01": {
"provider": "postgresql",
"driver": "postgres-jdbc",
"name": "DB-example-01",
"description": "Postgre connection",
"save-password": false,
"show-system-objects": true,
"read-only": false,
"folder": "My DBs",
"configuration": {
"user": "my-db-user",
"host": "postgres",
"port": "5432",
"database": "my-postgre-db",
"url": "jdbc:postgresql://postgres:5432/my-postgre-db",
"type": "dev",
"provider-properties": {
"@dbeaver-show-non-default-db@": "true"
},
"auth-model": "native"
}
},
"DB-example-02": {
"provider": "mysql",
"driver": "mysql8",
"name": "DB-example-02",
"description": "",
"save-password": false,
"show-system-objects": true,
"read-only": false,
"folder": "My DBs",
"configuration": {
"user": "my-db-user",
"host": "mysql",
"port": "3306",
"database": "my-mysql-db",
"url": "jdbc:mysql://mysql:3306/my-mysql-db",
"type": "dev",
"properties": {
"allowPublicKeyRetrieval": "true"
},
"provider-properties": {
"@dbeaver-show-non-default-db@": "false"
},
"auth-model": "native"
}
}
},
"connection-types": {
"dev": {
"name": "Development",
"color": "0,0,255",
"description": "Regular development database",
"auto-commit": true,
"confirm-execute": false,
"confirm-data-change": false,
"auto-close-transactions": false
}
}
}

cloudbeaver.conf

/opt/cloudbeaver/conf/product.conf

Here we have several general settings for the CloudBeaver instance.

I will highlight the ones I think are important:

anonymousAccessEnabled”: Here we define if will be anonymous access or not. (Leave it false)

publicCredentialsSaveEnabled”: Leave it false, I don’t need to say why. Right?

adminCredentialsSaveEnabled”: Leave it false, I don’t need to say why. Right?

{
server: {
serverPort: 8978,

workspaceLocation: "workspace",
contentRoot: "web",
driversLocation: "drivers",

rootURI: "/",
serviceURI: "/api/",

productConfiguration: "conf/product.conf",

expireSessionAfterPeriod: 1800000,

develMode: false,

enableSecurityManager: false,

database: {
driver="h2_embedded",
url: "jdbc:h2:${workspace}/.data/cb.h2.dat",

createDatabase: true,

initialDataConfiguration: "conf/initial-data.conf",

pool: {
minIdleConnections: 4,
maxIdleConnections: 10,
maxConnections: 100,
validationQuery: "SELECT 1"
}
}

},
app: {
anonymousAccessEnabled: false,
anonymousUserRole: "user",
supportsCustomConnections: false,

forwardProxy: false,

publicCredentialsSaveEnabled: false,
adminCredentialsSaveEnabled: false,

resourceManagerEnabled: true,

resourceQuotas: {
dataExportFileSizeLimit: 10000000,
resourceManagerFileSizeLimit: 500000,
sqlMaxRunningQueries: 100,
sqlResultSetRowsLimit: 100000,
sqlResultSetMemoryLimit: 2000000,
sqlTextPreviewMaxLength: 4096,
sqlBinaryPreviewMaxLength: 261120
},
enabledAuthProviders: [
"local"
],

disabledDrivers: [
"sqlite:sqlite_jdbc",
"h2:h2_embedded",
"clickhouse:yandex_clickhouse"
]

}

}

product.conf

/opt/cloudbeaver/conf/product.conf

You can find some customization settings here, I made changes only in the ones below:

defaultTheme”: Theme definition, I sugest “dark”.

defaultLanguage”: “en”

// Product configuration. Customized web application behavior
// It is in JSONC format
{
// Global properties
core: {
// User defaults
user: {
defaultTheme: "dark",
defaultLanguage: "en"
},
app: {
// Log viewer config
logViewer: {
refreshTimeout: 3000,
logBatchSize: 1000,
maxLogRecords: 2000,
maxFailedRequests: 3
}
},
authentication: {
anonymousAccessEnabled: false
}
},
// Notifications config
core_events: {
notificationsPool: 5
},
plugin_data_spreadsheet_new: {
hidden: false
},
plugin_data_export: {
disabled: false
}
}

Let’s get to work!

Now that we have this information, let’s put it into practice using some database pods.

Clone the repository, go to the folder and execute the command bellow

❯ kubectl apply -k .

This command will read the kustomization.yaml file and apply all the specs, configurations, variables, and configMaps that are declared in it.

Commando output:

❯ kubectl apply -k k8s
namespace/cloud-beaver-test created
configmap/dbeaver-product-configmap-kg79td7884 created
configmap/dbeaver-server-configmap-m5fc6m9ff7 created
configmap/dbeaver-sources-global-configmap-9b82g2h9bm created
configmap/dbeaver-sources-user-configmap-5kf2gtc878 created
configmap/mysql-configmap-62g74m555t created
configmap/postgres-configmap-5kt6k78dkc created
secret/dbeaver-secret-b8bmc6h476 created
service/dbeaver created
service/mysql created
service/postgres created
deployment.apps/dbeaver created
deployment.apps/mysql created
deployment.apps/postgres created

Check if everything has been deployed correctly and do a port-forward on the CloudBeaver pod to test it:

❯ kubectl port-forward -n cloud-beaver-test pods/dbeaver-7958f5b776-rk9qh 9090:8978

Log in to CloudBeaver and it should look like this if everything is correct, especially with the data-sources.json file

CloudBeaver Connections

--

--

Dionathan Chrys

DevOps Analyst | AWS Cloud Practitioner Certified | Kubernetes | Docker | Azure Pipelines