Configurando acesso a banco de dados com o CloudBeaver no Kubernetes

Dionathan Chrys
TOTVS Developers
Published in
7 min readJan 24, 2023
CloudBeaver

Versão em Inglês

Olá pessoal! A intenção principal deste artigo é mostrar e ensinar para vocês como configurar de forma automática e com autenticação o acesso aos seus bancos de dados pelo CloudBeaver.

Caso você tenha caído de paraquedas neste artigo, vou te explicar para o que ele serve. O CloudBeaver é uma ferramenta de gerenciamento de banco de dados que você pode acessar e usar pelo seu navegador, através da porta 8978 exposta do contêiner, mas porquê utilizá-lo? Temos diversas outras opções como PGadmin, MySQL Workbench, HeidiSQL, Beekeeper Studio entre muitos outros. Pois bem, vou te listar algumas vantagens bem interessantes dele.

  • Suporta diversos bancos de dados.
  • Permite manipular os dados como se fossem uma planilha.
  • Estrutura de navegação de banco de dados.
  • Exportação e migração de dados em vários formatos.
  • Túneis SSH para conectividade de bancos de dados remotos.
  • Editor SQL com preenchimento automático inteligente e realce de sintaxe.
  • Ótima interface.
  • Modelo de segurança baseado em usuário/função.

Isso e outros recursos estão na versão community (free), ainda existe as versões Enterprise e AWS. Pode verificar com mais detalhes aqui.

OK! Dada a devida introdução, vamos lá!

Aqui está o repositório com as config do CloudBeaver e as specs do kubernetes.

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

No arquivo kustomization.yaml temos a definição dos ConfigMaps que serão arquivos do repositório, estes ConfigMaps por sua vez serão usados para criar os volumes no deployment.yaml e esses volumes serão montados no nosso pod, substituindo os arquivos padrões e configurando a aplicação.

Calma! Vou explicar melhor logo abaixo.

No configMapGenerator criamos os ConfigMaps apontando para os arquivos .json ou .config com as configurações do CloudBeaver. (Falarei destes arquivos mais a frente)

kustomization.yaml:

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

Exemplo na prática:

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

Após aplicado

❯ 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

Para usar esses configMaps, devemos criar os volumes com eles no deployment, veja a seguir:

deployment.yaml:

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

Exemplo na prática:

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

Com os volumes declarados, podemos agora montar eles:

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

Exemplo na prática:

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

No final o arquivo deployment.yaml (cloudbeaver) deve ficar assim:

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

E o kustomization.yaml (parte do cloudbeaver) assim:

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

Obs: esses secrets gerados no kustomization.yaml são variáveis do CloudBeaver onde:

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

Agora que já sabemos como configurar, vamos entender para que serve esses 3 arquivos: data-sources.json, cloudbeaver.conf, product.conf

data-sources.json

Neste arquivo é onde realizamos as configurações de conexão para as instâncias de banco de dados. No exemplo vamos usar conexões para um banco Postgres e outro MySql.

Ele está localizado da seguinte maneira:

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

Aqui são as configurações do usuário em questão, só ficarão disponíveis as conexões após login no CloudBeaver.

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

Como o nome da pasta já diz, são as configs globais, todas as configurações aqui feitas ficarão disponíveis sem autenticação no CloudBeaver, caso você habilite o acesso anônimo.

Vou explicar os principais parâmetros deste JSON para que você consiga configurar sem problemas:

folders”: Caso você queria configurar várias conexões, pode separar em pastas.

save-password”: Melhor não salvar a senha de acesso ao seu banco de dados né? (deixe em false)

folder”: caso tenha criado pasta, declare ela aqui.

user”: Usuário do banco de dados, caso você declare aqui, ele vai auto completar para você na tela de login.

host”: IP ou endereço DNS da sua instancia de banco de dados.

port”: Porta de acesso ao banco de dados.

database”: Banco de dados que será realizada a comunicação.

url”: A url é composta dos seguintes parâmetros <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

Aqui temos diversas configurações gerais da instância do CloudBeaver

Vou destacar as que acho importante:

anonymousAccessEnabled”: Onde definimos se terá acesso anônimo ou não. (Deixe em false).

publicCredentialsSaveEnabled”: Deixe em false, não preciso dizer porque.

adminCredentialsSaveEnabled”: Deixe em false, não preciso dizer porque.

{
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

Algumas configurações de personalização você encontra aqui, fiz alterações somente nestas abaixo:

defaultTheme”: Definição do tema, sugiro “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
}
}

Mãos à obra

Agora de posse dessas informações vamos colocar em prática usando alguns pods de banco de dados.

Clone o repositório, entre na pasta e execute o comando

❯ kubectl apply -k .

Esse comando irá ler o arquivo kustomization.yaml e aplicar todas as specs, configurações, variáveis e configMaps que estão declaradas nele.

Saída do comando :

❯ 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

Verifique se tudo subiu corretamente e faça um port-forward no pod do CloudBeaver para testar:

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

Faça login no CloudBeaver e deve aparecer assim se tudo estiver correto principalmente com o arquivo data-sources.json

CloudBeaver Connections

--

--

Dionathan Chrys
TOTVS Developers

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