Skip to content

Init Jobs — Platform Bootstrap

Overview

AKKO uses a set of Kubernetes Jobs to bootstrap the platform on every helm install or helm upgrade. These jobs create PostgreSQL schemas, S3 buckets, Polaris Iceberg catalogs, Keycloak OAuth clients, Superset dashboards, and AI functions. All jobs are idempotent — they can run repeatedly without side effects.

The init jobs are packaged in the akko-init sub-chart and replace the need for manual setup steps after deployment.

Architecture

helm install / upgrade
        |
        v
  +------------------+
  | akko-init chart  |
  +--------+---------+
           |
  +--------+--------+--------+--------+--------+--------+--------+--------+
  |        |        |        |        |        |        |        |        |
  v        v        v        v        v        v        v        v        v
postgres postgres minio   polaris keycloak keycloak superset  ai     bootstrap
 -init   -data    -init   -init  -clients  -sync  -bootstrap func   -admin
         -init

Jobs

Job Purpose Depends On
postgres-init Creates infrastructure databases (keycloak, airflow, superset, polaris, openmetadata, mlflow, jupyterhub) and extensions PostgreSQL (infra)
postgres-data-init Creates functional databases (banking, healthcare, geospatial, rag) with PostGIS + pgvector extensions and seed data PostgreSQL (data)
minio-init Creates S3 buckets (akko-warehouse, akko-production, akko-projects, akko-shared, akko-users) and access policies object storage
polaris-init Creates the akko-warehouse Iceberg catalog and namespaces (banking, healthcare, retail, telecom, manufacturing, raw, staging, analytics) Apache Polaris
keycloak-clients Configures OAuth2 redirect URIs for all services behind oauth2-proxy, using wildcard domain patterns Keycloak
keycloak-sync Synchronizes LDAP users from directory service into Keycloak (when directory service is enabled) Keycloak, directory service
superset-bootstrap Creates datasets, charts, and the demo dashboard in Superset via the API Superset, Trino
ai-functions Installs PL/Python AI functions in PostgreSQL Data (LLM-powered SQL functions) PostgreSQL (data), LiteLLM
bootstrap-admin Creates the initial admin user and assigns RBAC roles Keycloak

Idempotency

Every job uses CREATE ... IF NOT EXISTS, PUT (not POST), or equivalent patterns. This means:

  • First install: everything is created from scratch
  • Subsequent upgrades: existing resources are left untouched, only missing resources are created
  • No data loss: jobs never DROP or DELETE existing data
-- Example: postgres-init ensure.sql
CREATE DATABASE keycloak WITH OWNER = akko_admin;
CREATE EXTENSION IF NOT EXISTS postgis;
CREATE SCHEMA IF NOT EXISTS banking;

Configuration

Enabling / Disabling Jobs

Each job can be individually toggled:

akko-init:
  polaris:
    enabled: true
  minio:
    enabled: true
  ollama:
    enabled: true
  superset:
    enabled: true
  keycloak:
    enabled: true
  aiFunctions:
    enabled: true
  keycloakClients:
    enabled: true

Polaris Namespaces

The Polaris init job creates namespaces for data organization:

akko-init:
  polaris:
    catalog:
      name: akko-warehouse
      namespaces:
        - banking
        - healthcare
        - retail
        - telecom
        - manufacturing
        - raw
        - staging
        - analytics

object storage Buckets

akko-init:
  minio:
    buckets:
      - akko-warehouse
      - akko-production
      - akko-projects
      - akko-shared
      - akko-users

Backup CronJobs

The init chart also includes optional backup CronJobs for PostgreSQL and object storage:

akko-init:
  backup:
    postgres:
      enabled: false        # Enable in production
      schedule: "0 2 * * *" # 2 AM daily
      retention: 7          # Keep 7 backups
    minio:
      enabled: false
      schedule: "0 4 * * *"
      retention: 7

Helm Chart

helm/akko/charts/akko-init/
├── Chart.yaml
├── values.yaml
├── files/                          # SQL scripts, config files
└── templates/
    ├── _helpers.tpl
    ├── postgres-init-job.yaml
    ├── postgres-ensure-configmap.yaml
    ├── postgres-data-init-job.yaml
    ├── postgres-data-ensure-configmap.yaml
    ├── minio-init-job.yaml
    ├── polaris-init-job.yaml
    ├── keycloak-clients-job.yaml
    ├── keycloak-sync-job.yaml
    ├── superset-bootstrap-job.yaml
    ├── ai-functions-job.yaml
    ├── bootstrap-admin-job.yaml
    ├── backup-postgres-cronjob.yaml
    ├── backup-minio-cronjob.yaml
    ├── backup-pvc.yaml
    └── serviceaccount.yaml

Resource Usage

Init jobs are ephemeral and lightweight:

resources:
  requests:
    cpu: 50m
    memory: 64Mi
  limits:
    cpu: 200m
    memory: 128Mi

Jobs run to completion and are cleaned up by Kubernetes after success (ttlSecondsAfterFinished).

Troubleshooting

Job Failed — Pod in Error State

Symptoms: A job pod shows Error or BackoffLimitExceeded. The platform is partially initialized.

Cause: The target service (PostgreSQL, object storage, Keycloak, etc.) was not ready when the job ran. Network policies or secrets may be misconfigured.

Solution:

# Check which jobs failed
kubectl get jobs -n akko -l app.kubernetes.io/instance=akko | grep -v "1/1"

# View logs of the failed job
kubectl logs -n akko job/<job-name> --tail=50

# Re-run a specific job by deleting it (Helm will recreate on next upgrade)
kubectl delete job -n akko <job-name>
helm upgrade akko helm/akko/ -n akko -f helm/examples/values-dev.yaml

PostgreSQL Init: Permission Denied

Symptoms: The postgres-init job fails with permission denied or role does not exist.

Cause: The PostgreSQL superuser credentials in the Helm secret do not match what is configured in the PostgreSQL pod.

Solution:

# Check the init job logs
kubectl logs -n akko job/akko-postgres-init --tail=30

# Verify the secret matches the PostgreSQL config
kubectl get secret -n akko akko-postgresql -o jsonpath='{.data.postgres-password}' | base64 -d

# If credentials changed, the PostgreSQL volume retains the old password
# You may need to ALTER USER inside the running PostgreSQL pod
kubectl exec -n akko deploy/akko-postgresql -- psql -U postgres -c "ALTER USER akko_admin WITH PASSWORD 'newpassword';"

object storage Init: Bucket Already Exists

This is normal and expected. The object storage init job uses mc mb --ignore-existing, so pre-existing buckets are silently skipped.

Polaris Init: Catalog Creation Failed

Symptoms: The polaris-init job fails with HTTP 500 or connection refused.

Cause: Polaris may still be initializing its database schema. The job needs Polaris to be fully ready.

Solution:

# Check Polaris readiness
kubectl get pods -n akko -l app.kubernetes.io/name=akko-polaris

# View polaris-init logs
kubectl logs -n akko job/akko-polaris-init --tail=30

# Re-run the job
kubectl delete job -n akko akko-polaris-init
helm upgrade akko helm/akko/ -n akko -f helm/examples/values-dev.yaml

License

All init job code is part of the AKKO platform: Apache 2.0.