Configurando acesso a banco de dados com o CloudBeaver no Kubernetes
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