Cloud Native 16 min read

Deploy Apache Superset 4.x on Kubernetes Using Official Helm Charts

This guide walks through deploying Apache Superset 4.x on a Kubernetes cluster with the official Helm chart, covering prerequisites, adding the Helm repository, customizing values.yaml, installing required dependencies, configuring security, OAuth, alerts, Celery workers, and loading sample data and dashboards.

Hacker Afternoon Tea
Hacker Afternoon Tea
Hacker Afternoon Tea
Deploy Apache Superset 4.x on Kubernetes Using Official Helm Charts

Preparation

Kubernetes cluster

Helm installed

For a simple single‑node setup, minikube is recommended because it is easy to install on many platforms and works well with the referenced Helm chart.

Minikube installation guide: https://minikube.sigs.k8s.io/docs/start/

Run

Add Superset's Helm repository

helm repo add superset https://apache.github.io/superset
"superset" has been added to your repositories

Search the repository for charts

helm search repo superset
NAME                CHART VERSION   APP VERSION   DESCRIPTION
superset/superset   0.1.1           1.0           Apache Superset is a modern, enterprise‑ready b...

Create a values.yaml file to override defaults. The upstream defaults are at https://github.com/apache/superset/tree/master/helm/superset/values.yaml

Install and run

helm upgrade --install --values my-values.yaml superset superset/superset

After the command runs you should see pods starting, for example:

kubectl get pods
NAME                                    READY   STATUS      RESTARTS   AGE
superset-celerybeat-7cdcc9575f-k6xmc    1/1     Running     0          119s
superset-f5c9c667-dw9lp                 1/1     Running     0          4m7s
superset-f5c9c667-fk8bk                 1/1     Running     0          4m11s
superset-init-db-zlm9z                  0/1     Completed   0          111s
superset-postgresql-0                   1/1     Running     0          6d20h
superset-redis-master-0                 1/1     Running     0          6d20h
superset-worker-75b48bbcc-jmmjr         1/1     Running     0          4m8s
superset-worker-75b48bbcc-qrq49         1/1     Running     0          4m12s

Typical pods (count depends on supersetNode.replicaCount and supersetWorker.replicaCount):

Multiple superset-xxxx-yyyy and superset-worker-xxxx-yyyy pods

One superset-postgresql-0 pod (if PostgreSQL is enabled)

One superset-redis-master-0 pod (if Redis is enabled)

One superset-celerybeat-xxxx-yyyy pod when

supersetCeleryBeat.enabled = true

Access Superset

The Helm chart creates a Service exposing the UI inside the cluster. To reach it externally configure the Service as LoadBalancer or NodePort, set up an Ingress (adjust hostname, TLS, annotations), or use port‑forwarding: kubectl port-forward superset-xxxx-yyyy :8088 Default login credentials for a fresh install:

user: admin password:

admin

Important Settings

Security Settings

Change default passwords for production. Example PostgreSQL password override:

postgresql:
  postgresqlPassword: superset

Generate a strong SECRET_KEY (e.g., openssl rand -base64 42) and set it via configOverrides:

configOverrides:
  secret: |
    SECRET_KEY = 'YOUR_OWN_RANDOM_GENERATED_SECRET_KEY'

To rotate an existing key replace the default thisISaSECRET_1234 with a new value.

Dependencies

Install Python DB‑API drivers and SQLAlchemy dialects for required data sources. Example bootstrap script installing BigQuery and Elasticsearch drivers:

bootstrapScript: |
  #!/bin/bash
  pip install psycopg2==2.9.6 \
    sqlalchemy-bigquery==1.6.1 \
    elasticsearch-dbapi==0.2.5 &&
  if [ ! -f ~/bootstrap ]; then echo "Running Superset with uid {{ .Values.runAsUser }}" > ~/bootstrap; fi

superset_config.py

Extend the minimal default superset_config.py via configOverrides. Example enabling proxy fix and dynamic plugins:

configOverrides:
  my_override: |
    ENABLE_PROXY_FIX = True
    FEATURE_FLAGS = {
        "DYNAMIC_PLUGINS": True
    }

Values from values.yaml can be referenced, e.g., {{ .Values.ingress.hosts[0] }} resolves to the external hostname.

Environment Variables

Pass key/value pairs through extraEnv and secret values through extraSecretEnv. Access them in superset_config.py with os.getenv("VAR"):

extraEnv:
  SMTP_HOST: smtp.gmail.com
  SMTP_USER: [email protected]
  SMTP_PORT: "587"
  SMTP_MAIL_FROM: [email protected]

extraSecretEnv:
  SMTP_PASSWORD: xxxx

configOverrides:
  smtp: |
    import ast
    SMTP_HOST = os.getenv("SMTP_HOST","localhost")
    SMTP_STARTTLS = ast.literal_eval(os.getenv("SMTP_STARTTLS", "True"))
    SMTP_SSL = ast.literal_eval(os.getenv("SMTP_SSL", "False"))
    SMTP_USER = os.getenv("SMTP_USER","superset")
    SMTP_PORT = os.getenv("SMTP_PORT",25)
    SMTP_PASSWORD = os.getenv("SMTP_PASSWORD","superset")
    SMTP_MAIL_FROM = os.getenv("SMTP_MAIL_FROM","[email protected]")

System Packages

Install additional OS packages by overriding the container command before the application starts:

supersetWorker:
  command:
    - /bin/sh
    - -c
    - |
      apt update
      apt install -y somepackage
      apt autoremove -yqq --purge
      apt clean

      # Run celery worker
      . {{ .Values.configMountPath }}/superset_bootstrap.sh; celery --app=superset.tasks.celery_app:app worker

Data Sources

Declare data sources via extraConfigs in values.yaml:

extraConfigs:
  import_datasources.yaml: |
    databases:
    - allow_file_upload: true
      allow_ctas: true
      allow_cvas: true
      database_name: example-db
      extra: "{
    \"metadata_params\": {},
    \"engine_params\": {},
    \"metadata_cache_timeout\": {}
}"
      sqlalchemy_uri: example://example-db.local
      tables: []

Configuration Examples

Set OAuth

OAuth requires the authlib Python library. Install it via the bootstrapScript using pip .

Authlib documentation: https://authlib.org/

extraEnv:
  AUTH_DOMAIN: example.com

extraSecretEnv:
  GOOGLE_KEY: xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com
  GOOGLE_SECRET: xxxxxxxxxxxxxxxxxxxxxxxx

configOverrides:
  enable_oauth: |
    ENABLE_PROXY_FIX = True
    from flask_appbuilder.security.manager import AUTH_OAUTH
    AUTH_TYPE = AUTH_OAUTH
    OAUTH_PROVIDERS = [
        {
            "name": "google",
            "icon": "fa-google",
            "token_key": "access_token",
            "remote_app": {
                "client_id": os.getenv("GOOGLE_KEY"),
                "client_secret": os.getenv("GOOGLE_SECRET"),
                "api_base_url": "https://www.googleapis.com/oauth2/v2/",
                "client_kwargs": {"scope": "email profile"},
                "request_token_url": None,
                "access_token_url": "https://accounts.google.com/o/oauth2/token",
                "authorize_url": "https://accounts.google.com/o/oauth2/auth",
                "authorize_params": {"hd": os.getenv("AUTH_DOMAIN", "")}
            },
        }
    ]
    AUTH_ROLE_ADMIN = 'Admin'
    AUTH_ROLE_PUBLIC = 'Public'
    AUTH_USER_REGISTRATION = True
    AUTH_USER_REGISTRATION_ROLE = "Admin"

Enable Alerts and Reports

Refer to the official alerts‑reports documentation: https://superset.apache.org/docs/configuration/alerts-reports

Install supported webdriver in Celery worker

Either use a custom image with the webdriver pre‑installed or install it at startup via command:

supersetWorker:
  command:
    - /bin/sh
    - -c
    - |
      # Install chrome webdriver
      apt-get update
      apt-get install -y wget
      wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
      apt-get install -y --no-install-recommends ./google-chrome-stable_current_amd64.deb
      wget https://chromedriver.storage.googleapis.com/88.0.4324.96/chromedriver_linux64.zip
      apt-get install -y zip
      unzip chromedriver_linux64.zip
      chmod +x chromedriver
      mv chromedriver /usr/bin
      apt-get autoremove -yqq --purge
      apt-get clean
      rm -f google-chrome-stable_current_amd64.deb chromedriver_linux64.zip

      . {{ .Values.configMountPath }}/superset_bootstrap.sh; celery --app=superset.tasks.celery_app:app worker

Run Celery Beat

Enable the beat pod to trigger scheduled alert/report jobs:

supersetCeleryBeat:
  enabled: true

Configure Celery jobs and SMTP/Slack

extraEnv:
  SMTP_HOST: smtp.gmail.com
  SMTP_USER: [email protected]
  SMTP_PORT: "587"
  SMTP_MAIL_FROM: [email protected]

extraSecretEnv:
  SLACK_API_TOKEN: xoxb-xxxx-yyyy
  SMTP_PASSWORD: xxxx-yyyy

configOverrides:
  feature_flags: |
    import ast
    FEATURE_FLAGS = {"ALERT_REPORTS": True}
    SMTP_HOST = os.getenv("SMTP_HOST","localhost")
    SMTP_STARTTLS = ast.literal_eval(os.getenv("SMTP_STARTTLS", "True"))
    SMTP_SSL = ast.literal_eval(os.getenv("SMTP_SSL", "False"))
    SMTP_USER = os.getenv("SMTP_USER","superset")
    SMTP_PORT = os.getenv("SMTP_PORT",25)
    SMTP_PASSWORD = os.getenv("SMTP_PASSWORD","superset")
    SMTP_MAIL_FROM = os.getenv("SMTP_MAIL_FROM","[email protected]")
    SLACK_API_TOKEN = os.getenv("SLACK_API_TOKEN",None)

  celery_conf: |
    from celery.schedules import crontab
    class CeleryConfig:
      broker_url = f"redis://{env('REDIS_HOST')}:{env('REDIS_PORT')}/0"
      imports = ("superset.sql_lab", "superset.tasks.cache", "superset.tasks.scheduler")
      result_backend = f"redis://{env('REDIS_HOST')}:{env('REDIS_PORT')}/0"
      task_annotations = {"sql_lab.get_sql_results": {"rate_limit": "100/s"}}
      beat_schedule = {
        "reports.scheduler": {"task": "reports.scheduler", "schedule": crontab(minute="*", hour="*")},
        "reports.prune_log": {"task": "reports.prune_log", "schedule": crontab(minute=0, hour=0)},
        "cache-warmup-hourly": {"task": "cache-warmup", "schedule": crontab(minute="*/30", hour="*"), "kwargs": {"strategy_name": "top_n_dashboards", "top_n": 10, "since": "7 days ago"}}
      }
    CELERY_CONFIG = CeleryConfig

  reports: |
    EMAIL_PAGE_RENDER_WAIT = 60
    WEBDRIVER_BASEURL = "http://{{ template \"superset.fullname\" . }}:{{ .Values.service.port }}/"
    WEBDRIVER_BASEURL_USER_FRIENDLY = "https://www.example.com/"
    WEBDRIVER_TYPE = "chrome"
    WEBDRIVER_OPTION_ARGS = [
        "--force-device-scale-factor=2.0",
        "--high-dpi-support=2.0",
        "--headless",
        "--disable-gpu",
        "--disable-dev-shm-usage",
        "--no-sandbox",
        "--disable-setuid-sandbox",
        "--disable-extensions"
    ]

Load Sample Data and Dashboards

To explore Superset with example data, add the following to my-values.yaml and redeploy:

init:
  loadExamples: true

Series

Related article: https://mp.weixin.qq.com/s?__biz=MzA4Mzc4NTE5MQ==∣=2692296804&idx=1&sn=87b7725314598cbbfff6e99d0fa7784d&scene=21

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

kubernetesConfigurationSupersetHelmApache SupersetHelm chartK8s deployment
Hacker Afternoon Tea
Written by

Hacker Afternoon Tea

You might find something interesting here ^_^

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.