feat(metabase): add metabase
This commit is contained in:
1
justfile
1
justfile
@@ -12,6 +12,7 @@ mod keycloak
|
|||||||
mod jupyterhub
|
mod jupyterhub
|
||||||
mod k8s
|
mod k8s
|
||||||
mod longhorn
|
mod longhorn
|
||||||
|
mod metabase
|
||||||
mod minio
|
mod minio
|
||||||
mod postgres
|
mod postgres
|
||||||
mod utils
|
mod utils
|
||||||
|
|||||||
2
metabase/.gitignore
vendored
Normal file
2
metabase/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
metabase-values.yaml
|
||||||
|
metabase-config-external-secret.yaml
|
||||||
122
metabase/justfile
Normal file
122
metabase/justfile
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
set fallback := true
|
||||||
|
|
||||||
|
export METABASE_NAMESPACE := env("METABASE_NAMESPACE", "metabase")
|
||||||
|
export METABASE_CHART_VERSION := env("METABASE_CHART_VERSION", "2.22.0")
|
||||||
|
export METABASE_HOST := env("METABASE_HOST", "")
|
||||||
|
export EXTERNAL_SECRETS_NAMESPACE := env("EXTERNAL_SECRETS_NAMESPACE", "external-secrets")
|
||||||
|
export K8S_VAULT_NAMESPACE := env("K8S_VAULT_NAMESPACE", "vault")
|
||||||
|
|
||||||
|
[private]
|
||||||
|
default:
|
||||||
|
@just --list --unsorted --list-submodules
|
||||||
|
|
||||||
|
# Add Helm repository
|
||||||
|
add-helm-repo:
|
||||||
|
helm repo add pmint93 https://pmint93.github.io/helm-charts
|
||||||
|
helm repo update
|
||||||
|
|
||||||
|
# Remove Helm repository
|
||||||
|
remove-helm-repo:
|
||||||
|
helm repo remove pmint93
|
||||||
|
|
||||||
|
# Create Metabase namespace
|
||||||
|
create-namespace:
|
||||||
|
@kubectl get namespace ${METABASE_NAMESPACE} &>/dev/null || \
|
||||||
|
kubectl create namespace ${METABASE_NAMESPACE}
|
||||||
|
|
||||||
|
# Delete Metabase namespace
|
||||||
|
delete-namespace:
|
||||||
|
@kubectl delete namespace ${METABASE_NAMESPACE} --ignore-not-found
|
||||||
|
|
||||||
|
# Create Metabase session secret
|
||||||
|
create-session-secret:
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
session_secret=$(just utils::random-password)
|
||||||
|
|
||||||
|
if helm status external-secrets -n ${EXTERNAL_SECRETS_NAMESPACE} &>/dev/null; then
|
||||||
|
echo "External Secrets Operator detected. Storing session secret in Vault..."
|
||||||
|
just vault::put metabase/config session="${session_secret}"
|
||||||
|
|
||||||
|
kubectl delete secret metabase-config -n ${METABASE_NAMESPACE} --ignore-not-found
|
||||||
|
kubectl delete externalsecret metabase-config -n ${METABASE_NAMESPACE} --ignore-not-found
|
||||||
|
|
||||||
|
# gomplate -f metabase-config-external-secret.gomplate.yaml | kubectl apply -f -
|
||||||
|
gomplate -f metabase-config-external-secret.gomplate.yaml \
|
||||||
|
-o metabase-config-external-secret.yaml
|
||||||
|
kubectl apply -f metabase-config-external-secret.yaml
|
||||||
|
|
||||||
|
echo "Waiting for ExternalSecret to sync..."
|
||||||
|
kubectl wait --for=condition=Ready externalsecret/metabase-config \
|
||||||
|
-n ${METABASE_NAMESPACE} --timeout=60s
|
||||||
|
else
|
||||||
|
echo "External Secrets Operator not found. Creating secret directly..."
|
||||||
|
kubectl delete secret metabase-config -n ${METABASE_NAMESPACE} --ignore-not-found
|
||||||
|
kubectl create secret generic metabase-config -n ${METABASE_NAMESPACE} \
|
||||||
|
--from-literal=session="${session_secret}"
|
||||||
|
|
||||||
|
if helm status vault -n ${K8S_VAULT_NAMESPACE} &>/dev/null; then
|
||||||
|
just vault::put metabase/config session="${session_secret}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create Metabase database secret
|
||||||
|
create-database-secret:
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
if kubectl get secret database-config -n ${METABASE_NAMESPACE} &>/dev/null; then
|
||||||
|
kubectl delete secret database-config -n ${METABASE_NAMESPACE}
|
||||||
|
fi
|
||||||
|
kubectl create secret generic database-config -n ${METABASE_NAMESPACE} \
|
||||||
|
--from-literal=host=postgres-cluster-rw.postgres \
|
||||||
|
--from-literal=port=5432 \
|
||||||
|
--from-literal=user=$(just postgres::admin-username) \
|
||||||
|
--from-literal=password=$(just postgres::admin-password) \
|
||||||
|
--from-literal=database=metabase
|
||||||
|
|
||||||
|
# Delete Metabase database secret
|
||||||
|
delete-database-secret:
|
||||||
|
@kubectl delete secret database-config -n ${METABASE_NAMESPACE} --ignore-not-found
|
||||||
|
|
||||||
|
|
||||||
|
# Install Metabase
|
||||||
|
install:
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
export METABASE_HOST=${METABASE_HOST:-}
|
||||||
|
while [ -z "${METABASE_HOST}" ]; do
|
||||||
|
METABASE_HOST=$(
|
||||||
|
gum input --prompt="Metabase host (FQDN): " --width=100 \
|
||||||
|
--placeholder="e.g., metabase.example.com"
|
||||||
|
)
|
||||||
|
done
|
||||||
|
|
||||||
|
just create-namespace
|
||||||
|
just postgres::create-db metabase
|
||||||
|
just create-database-secret
|
||||||
|
just create-session-secret
|
||||||
|
|
||||||
|
just add-helm-repo
|
||||||
|
gomplate -f metabase-values.gomplate.yaml -o metabase-values.yaml
|
||||||
|
|
||||||
|
helm upgrade --cleanup-on-fail --install metabase pmint93/metabase \
|
||||||
|
--version ${METABASE_CHART_VERSION} -n ${METABASE_NAMESPACE} --wait \
|
||||||
|
-f metabase-values.yaml
|
||||||
|
|
||||||
|
# Uninstall Metabase
|
||||||
|
uninstall delete-db='true':
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
helm uninstall metabase -n ${METABASE_NAMESPACE} --ignore-not-found --wait
|
||||||
|
kubectl delete secret metabase-config -n ${METABASE_NAMESPACE} --ignore-not-found
|
||||||
|
kubectl delete externalsecret metabase-config -n ${METABASE_NAMESPACE} --ignore-not-found
|
||||||
|
just delete-database-secret
|
||||||
|
just delete-namespace
|
||||||
|
if [ "{{ delete-db }}" = "true" ]; then
|
||||||
|
just postgres::delete-db metabase
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean up Vault entries if present
|
||||||
|
if helm status vault -n ${K8S_VAULT_NAMESPACE} &>/dev/null; then
|
||||||
|
just vault::delete metabase/config || true
|
||||||
|
fi
|
||||||
18
metabase/metabase-config-external-secret.gomplate.yaml
Normal file
18
metabase/metabase-config-external-secret.gomplate.yaml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
apiVersion: external-secrets.io/v1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata:
|
||||||
|
name: metabase-config
|
||||||
|
namespace: {{ .Env.METABASE_NAMESPACE }}
|
||||||
|
spec:
|
||||||
|
refreshInterval: 1h
|
||||||
|
secretStoreRef:
|
||||||
|
name: vault-secret-store
|
||||||
|
kind: ClusterSecretStore
|
||||||
|
target:
|
||||||
|
name: metabase-config
|
||||||
|
creationPolicy: Owner
|
||||||
|
data:
|
||||||
|
- secretKey: session
|
||||||
|
remoteRef:
|
||||||
|
key: metabase/config
|
||||||
|
property: session
|
||||||
84
metabase/metabase-values.gomplate.yaml
Normal file
84
metabase/metabase-values.gomplate.yaml
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
# Metabase Helm Chart Values
|
||||||
|
# https://github.com/pmint93/helm-charts/tree/master/charts/metabase
|
||||||
|
|
||||||
|
image:
|
||||||
|
repository: metabase/metabase
|
||||||
|
tag: v0.51.1
|
||||||
|
|
||||||
|
# Use PostgreSQL for production
|
||||||
|
database:
|
||||||
|
type: postgres
|
||||||
|
host: postgres-cluster-rw.postgres
|
||||||
|
port: 5432
|
||||||
|
dbname: metabase
|
||||||
|
existingSecret: database-config
|
||||||
|
existingSecretUsernameKey: user
|
||||||
|
existingSecretPasswordKey: password
|
||||||
|
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
className: traefik
|
||||||
|
annotations:
|
||||||
|
kubernetes.io/ingress.class: traefik
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||||
|
hosts:
|
||||||
|
- {{ .Env.METABASE_HOST }}
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- {{ .Env.METABASE_HOST }}
|
||||||
|
|
||||||
|
# Session configuration
|
||||||
|
session:
|
||||||
|
existingSecret: metabase-config
|
||||||
|
existingSecretKey: session
|
||||||
|
|
||||||
|
# Basic configuration
|
||||||
|
extraEnv:
|
||||||
|
- name: MB_APPLICATION_NAME
|
||||||
|
value: "Metabase Analytics"
|
||||||
|
- name: MB_ENABLE_PUBLIC_SHARING
|
||||||
|
value: "true"
|
||||||
|
- name: MB_ENABLE_EMBEDDING
|
||||||
|
value: "true"
|
||||||
|
|
||||||
|
# Resource limits
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 2Gi
|
||||||
|
cpu: 1000m
|
||||||
|
requests:
|
||||||
|
memory: 1Gi
|
||||||
|
cpu: 500m
|
||||||
|
|
||||||
|
# Security context
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 2000
|
||||||
|
runAsGroup: 2000
|
||||||
|
runAsNonRoot: true
|
||||||
|
|
||||||
|
# Pod security context
|
||||||
|
podSecurityContext:
|
||||||
|
fsGroup: 2000
|
||||||
|
|
||||||
|
# Service account
|
||||||
|
serviceAccount:
|
||||||
|
create: true
|
||||||
|
|
||||||
|
# Log4j2 configuration to reduce verbose logging
|
||||||
|
log4j2XML: |
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Configuration status="WARN" shutdownHook="disable">
|
||||||
|
<Appenders>
|
||||||
|
<Console name="STDOUT" target="SYSTEM_OUT">
|
||||||
|
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %c{1.} :: %m%n"/>
|
||||||
|
</Console>
|
||||||
|
</Appenders>
|
||||||
|
<Loggers>
|
||||||
|
<Logger name="metabase.middleware.log" level="WARN"/>
|
||||||
|
<Logger name="middleware.log" level="WARN"/>
|
||||||
|
<Logger name="metabase" level="WARN"/>
|
||||||
|
<Root level="WARN">
|
||||||
|
<AppenderRef ref="STDOUT"/>
|
||||||
|
</Root>
|
||||||
|
</Loggers>
|
||||||
|
</Configuration>
|
||||||
Reference in New Issue
Block a user