Skip to content

Commit e8a43da

Browse files
committed
Create dedicated controller database
1 parent 25cc85e commit e8a43da

File tree

11 files changed

+213
-52
lines changed

11 files changed

+213
-52
lines changed

chart/templates/_helpers.tpl

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,25 @@
22
Reusable snippets shared across Vela Helm templates.
33
*/}}
44

5+
{{/*
6+
Returns the plaintext password for a given DB credential key, preserving it across upgrades
7+
via lookup of the existing vela-controller-secret. On fresh installs the password is derived
8+
deterministically from the release name, namespace, and key so that all templates in the same
9+
render produce the same value.
10+
11+
Usage: {{ include "vela.dbPassword" (list "controller-db-password" .) }}
12+
*/}}
13+
{{- define "vela.dbPassword" -}}
14+
{{- $key := index . 0 -}}
15+
{{- $ctx := index . 1 -}}
16+
{{- $existingSecret := lookup "v1" "Secret" $ctx.Release.Namespace "vela-controller-secret" -}}
17+
{{- if and $existingSecret (index $existingSecret.data $key) -}}
18+
{{- index $existingSecret.data $key | b64dec -}}
19+
{{- else -}}
20+
{{- printf "%s-%s-%s" $ctx.Release.Name $ctx.Release.Namespace $key | sha256sum | trunc 32 -}}
21+
{{- end -}}
22+
{{- end -}}
23+
524
{{/*
625
Renders a Postgres init container that waits for the target database to accept connections.
726
The helper accepts a dictionary with the following optional keys:
@@ -13,6 +32,7 @@ The helper accepts a dictionary with the following optional keys:
1332
- secretName : Kubernetes secret with credentials (default: database)
1433
- usernameKey : Secret key used for DB username (default: superuser-username)
1534
- passwordKey : Secret key used for DB password (default: superuser-password)
35+
- database : database name to verify connectivity (default: controller)
1636
- securityContext : optional security context applied to the init container
1737
*/}}
1838
{{- define "vela.waitForPostgresInitContainer" -}}
@@ -24,6 +44,7 @@ The helper accepts a dictionary with the following optional keys:
2444
{{- $secretName := default "database" .secretName -}}
2545
{{- $usernameKey := default "superuser-username" .usernameKey -}}
2646
{{- $passwordKey := default "superuser-password" .passwordKey -}}
47+
{{- $database := default "controller" .database -}}
2748
- name: {{ $name }}
2849
image: {{ $image }}
2950
imagePullPolicy: {{ $imagePullPolicy }}
@@ -51,9 +72,8 @@ The helper accepts a dictionary with the following optional keys:
5172
done
5273
echo "Database is ready"
5374

54-
# Ensure postgres user can connect
55-
until psql -h "$DB_HOST" -U "$DB_USER" -d postgres -c '\q' 2>/dev/null; do
56-
echo "Waiting for Postgres superuser connection..."
75+
until psql -h "$DB_HOST" -U "$DB_USER" -d {{ $database | quote }} -c '\q' 2>/dev/null; do
76+
echo "Waiting for Postgres connection to {{ $database }}..."
5777
sleep 2
5878
done
5979
{{- with .securityContext }}

chart/templates/controller/deployment.yaml

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@ spec:
1818
spec:
1919
serviceAccountName: vela-controller
2020
initContainers:
21-
{{ include "vela.waitForPostgresInitContainer" (dict) | nindent 8 }}
21+
{{ include "vela.waitForPostgresInitContainer" (dict
22+
"secretName" "vela-controller-secret"
23+
"usernameKey" "controller-db-username"
24+
"passwordKey" "controller-db-password"
25+
"database" "controller"
26+
) | nindent 8 }}
2227
containers:
2328
- name: vela-controller
2429
image: "{{ .Values.controller.image.repository }}:{{ .Values.controller.image.tag }}"
@@ -41,16 +46,16 @@ spec:
4146
secretKeyRef:
4247
name: vela-grafana-secret
4348
key: VELA_GRAFANA_SECURITY_ADMIN_PASSWORD
44-
- name: DB_USER
49+
- name: CONTROLLER_DB_PASSWORD
4550
valueFrom:
4651
secretKeyRef:
47-
name: database
48-
key: superuser-username
49-
- name: DB_PASSWORD
52+
name: vela-controller-secret
53+
key: controller-db-password
54+
- name: CELERY_DB_PASSWORD
5055
valueFrom:
5156
secretKeyRef:
52-
name: database
53-
key: superuser-password
57+
name: vela-controller-secret
58+
key: celery-db-password
5459
- name: VELA_DEPLOYMENT_PASSWORD_SECRET
5560
valueFrom:
5661
secretKeyRef:
@@ -59,13 +64,13 @@ spec:
5964
- name: DB_HOST
6065
value: database
6166
- name: VELA_POSTGRES_URL
62-
value: 'postgresql+asyncpg://$(DB_USER):$(DB_PASSWORD)@$(DB_HOST):5432/postgres'
63-
- name: VELA_GRAFANA_URL
64-
value: "https://{{ .Values.domain }}:{{ .Values.port }}/grafana"
67+
value: 'postgresql+asyncpg://vela_controller:$(CONTROLLER_DB_PASSWORD)@$(DB_HOST):5432/controller'
6568
- name: VELA_BROKER_URL
66-
value: 'sqla+postgresql+psycopg://$(DB_USER):$(DB_PASSWORD)@$(DB_HOST):5432/postgres'
69+
value: 'sqla+postgresql+psycopg://vela_celery:$(CELERY_DB_PASSWORD)@$(DB_HOST):5432/controller'
6770
- name: VELA_RESULT_BACKEND
68-
value: 'db+postgresql+psycopg://$(DB_USER):$(DB_PASSWORD)@$(DB_HOST):5432/postgres'
71+
value: 'db+postgresql+psycopg://vela_celery:$(CELERY_DB_PASSWORD)@$(DB_HOST):5432/controller'
72+
- name: VELA_GRAFANA_URL
73+
value: "https://{{ .Values.domain }}:{{ .Values.port }}/grafana"
6974
livenessProbe:
7075
httpGet:
7176
path: /health

chart/templates/controller/secret.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ apiVersion: v1
22
kind: Secret
33
metadata:
44
name: vela-controller-secret
5+
namespace: {{ .Release.Namespace }}
56
type: Opaque
67
data:
78
{{- $existingSecret := lookup "v1" "Secret" .Release.Namespace "vela-controller-secret" }}
8-
{{- if $existingSecret }}
9-
deployment-password-secret: {{ index $existingSecret.data "deployment-password-secret" }}
10-
{{- else }}
11-
deployment-password-secret: {{ randAlphaNum 32 | b64enc }}
12-
{{- end }}
9+
deployment-password-secret: {{ if $existingSecret }}{{ index $existingSecret.data "deployment-password-secret" }}{{ else }}{{ randAlphaNum 32 | b64enc }}{{ end }}
10+
controller-db-password: {{ include "vela.dbPassword" (list "controller-db-password" .) | b64enc }}
11+
celery-db-password: {{ include "vela.dbPassword" (list "celery-db-password" .) | b64enc }}
12+
controller-db-username: {{ "vela_controller" | b64enc }}

chart/templates/controller/worker.yaml

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@ spec:
1818
spec:
1919
serviceAccountName: vela-controller
2020
initContainers:
21-
{{ include "vela.waitForPostgresInitContainer" (dict) | nindent 8 }}
21+
{{ include "vela.waitForPostgresInitContainer" (dict
22+
"secretName" "vela-controller-secret"
23+
"usernameKey" "controller-db-username"
24+
"passwordKey" "controller-db-password"
25+
"database" "controller"
26+
) | nindent 8 }}
2227
containers:
2328
- name: vela-controller-worker
2429
image: "{{ .Values.controller.image.repository }}:{{ .Values.controller.image.tag }}"
@@ -38,29 +43,29 @@ spec:
3843
secretKeyRef:
3944
name: vela-grafana-secret
4045
key: VELA_GRAFANA_SECURITY_ADMIN_PASSWORD
41-
- name: DB_USER
46+
- name: CONTROLLER_DB_PASSWORD
4247
valueFrom:
4348
secretKeyRef:
44-
name: database
45-
key: superuser-username
46-
- name: DB_PASSWORD
49+
name: vela-controller-secret
50+
key: controller-db-password
51+
- name: CELERY_DB_PASSWORD
4752
valueFrom:
4853
secretKeyRef:
49-
name: database
50-
key: superuser-password
51-
- name: DB_HOST
52-
value: database
53-
- name: VELA_BROKER_URL
54-
value: 'sqla+postgresql+psycopg://$(DB_USER):$(DB_PASSWORD)@$(DB_HOST):5432/postgres'
55-
- name: VELA_RESULT_BACKEND
56-
value: 'db+postgresql+psycopg://$(DB_USER):$(DB_PASSWORD)@$(DB_HOST):5432/postgres'
54+
name: vela-controller-secret
55+
key: celery-db-password
5756
- name: VELA_DEPLOYMENT_PASSWORD_SECRET
5857
valueFrom:
5958
secretKeyRef:
6059
name: vela-controller-secret
6160
key: deployment-password-secret
61+
- name: DB_HOST
62+
value: database
6263
- name: VELA_POSTGRES_URL
63-
value: 'postgresql+asyncpg://$(DB_USER):$(DB_PASSWORD)@$(DB_HOST):5432/postgres'
64+
value: 'postgresql+asyncpg://vela_controller:$(CONTROLLER_DB_PASSWORD)@$(DB_HOST):5432/controller'
65+
- name: VELA_BROKER_URL
66+
value: 'sqla+postgresql+psycopg://vela_celery:$(CELERY_DB_PASSWORD)@$(DB_HOST):5432/controller'
67+
- name: VELA_RESULT_BACKEND
68+
value: 'db+postgresql+psycopg://vela_celery:$(CELERY_DB_PASSWORD)@$(DB_HOST):5432/controller'
6469
{{- with .Values.containerSecurityContext }}
6570
securityContext:
6671
{{- toYaml . | nindent 12 }}

chart/templates/database.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,6 @@ spec:
4646
replication:
4747
mode: async
4848
role: ha-read
49+
managedSql:
50+
scripts:
51+
- sgScript: controller-db-init
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
apiVersion: v1
2+
kind: Secret
3+
metadata:
4+
name: vela-db-init-sql
5+
namespace: {{ .Release.Namespace }}
6+
stringData:
7+
init.sql: |
8+
SELECT 'CREATE DATABASE controller' WHERE NOT EXISTS
9+
(SELECT FROM pg_database WHERE datname = 'controller')\gexec
10+
11+
DO $$
12+
BEGIN
13+
IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'vela_controller') THEN
14+
CREATE USER vela_controller WITH PASSWORD '{{ include "vela.dbPassword" (list "controller-db-password" .) }}';
15+
ELSE
16+
ALTER USER vela_controller WITH PASSWORD '{{ include "vela.dbPassword" (list "controller-db-password" .) }}';
17+
END IF;
18+
IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'vela_celery') THEN
19+
CREATE USER vela_celery WITH PASSWORD '{{ include "vela.dbPassword" (list "celery-db-password" .) }}';
20+
ELSE
21+
ALTER USER vela_celery WITH PASSWORD '{{ include "vela.dbPassword" (list "celery-db-password" .) }}';
22+
END IF;
23+
END $$;
24+
25+
GRANT ALL PRIVILEGES ON DATABASE controller TO vela_controller;
26+
ALTER DATABASE controller OWNER TO vela_controller;
27+
GRANT CONNECT ON DATABASE controller TO vela_celery;
28+
29+
init-controller-db.sql: |
30+
CREATE SCHEMA IF NOT EXISTS celery AUTHORIZATION vela_celery;
31+
ALTER ROLE vela_celery IN DATABASE controller SET search_path TO celery;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
apiVersion: stackgres.io/v1
2+
kind: SGScript
3+
metadata:
4+
name: controller-db-init
5+
namespace: {{ .Release.Namespace }}
6+
spec:
7+
scripts:
8+
- name: init-users-and-database
9+
scriptFrom:
10+
secretKeyRef:
11+
name: vela-db-init-sql
12+
key: init.sql
13+
- name: init-controller-db-schemas
14+
database: controller
15+
scriptFrom:
16+
secretKeyRef:
17+
name: vela-db-init-sql
18+
key: init-controller-db.sql
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
apiVersion: batch/v1
2+
kind: Job
3+
metadata:
4+
name: vela-db-migration
5+
namespace: {{ .Release.Namespace }}
6+
annotations:
7+
helm.sh/hook: pre-upgrade
8+
helm.sh/hook-weight: "0"
9+
helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
10+
spec:
11+
template:
12+
spec:
13+
restartPolicy: Never
14+
containers:
15+
- name: db-migration
16+
image: postgres:17-alpine
17+
env:
18+
- name: DB_HOST
19+
value: database
20+
- name: SUPERUSER
21+
valueFrom:
22+
secretKeyRef:
23+
name: database
24+
key: superuser-username
25+
- name: PGPASSWORD
26+
valueFrom:
27+
secretKeyRef:
28+
name: database
29+
key: superuser-password
30+
command: ["/bin/sh", "-c"]
31+
args:
32+
- |
33+
until pg_isready -h "$DB_HOST" -U "$SUPERUSER"; do
34+
echo "Waiting for database..."
35+
sleep 2
36+
done
37+
38+
# Create controller database if it doesn't exist yet.
39+
# The SGScript normally handles this, but it runs asynchronously after
40+
# the upgrade so the migration job must bootstrap the database itself.
41+
psql -h "$DB_HOST" -U "$SUPERUSER" -d postgres -c \
42+
"SELECT 'CREATE DATABASE controller' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'controller')\gexec"
43+
44+
if psql -h "$DB_HOST" -U "$SUPERUSER" -d controller \
45+
-c "SELECT 1 FROM alembic_version LIMIT 1" 2>/dev/null; then
46+
echo "Migration already done, skipping."
47+
exit 0
48+
fi
49+
50+
if ! psql -h "$DB_HOST" -U "$SUPERUSER" -d postgres \
51+
-c "SELECT 1 FROM alembic_version LIMIT 1" 2>/dev/null; then
52+
echo "No source data found, skipping migration."
53+
exit 0
54+
fi
55+
56+
echo "Migrating data from postgres to controller database..."
57+
pg_dump -h "$DB_HOST" -U "$SUPERUSER" -d postgres \
58+
--schema=public --no-owner --no-privileges \
59+
--exclude-table=kombu_message \
60+
--exclude-table=kombu_queue \
61+
--exclude-table=celery_taskmeta \
62+
--exclude-table=celery_tasksetmeta \
63+
| psql -h "$DB_HOST" -U "$SUPERUSER" -d controller
64+
echo "Migration complete."

containers/compose-dev.yml

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ services:
77
- ~/.kube/config:/home/vela/.kube/config:ro
88
- ..:/app
99
environment:
10-
VELA_POSTGRES_URL: 'postgresql+asyncpg://postgres:vela@database:5432/vela'
10+
VELA_POSTGRES_URL: 'postgresql+asyncpg://vela_controller:controller@database:5432/controller'
1111
VELA_JWT_SECRET: 'secret'
1212
VELA_CORS_ORIGINS: '["http://localhost:3000"]'
1313
VELA_ENABLE_DB_EXTERNAL_IPV6_LOADBALANCER: 'false'
14-
VELA_BROKER_URL: 'sqla+postgresql+psycopg://postgres:vela@database:5432/vela'
15-
VELA_RESULT_BACKEND: 'db+postgresql+psycopg://postgres:vela@database:5432/vela'
14+
VELA_BROKER_URL: 'sqla+postgresql+psycopg://vela_celery:celery@database:5432/controller'
15+
VELA_RESULT_BACKEND: 'db+postgresql+psycopg://vela_celery:celery@database:5432/controller'
1616
ports:
1717
- 8000:8000
1818
command: 'bash -c "python -m venv /tmp/venv && source /tmp/venv/bin/activate && pip install -e . && uvicorn --host 0.0.0.0 --reload simplyblock.vela.api:app"'
@@ -36,9 +36,9 @@ services:
3636
- ..:/app
3737
command: 'bash -c "python -m venv /tmp/venv && source /tmp/venv/bin/activate && pip install -e . && celery -A simplyblock.vela.worker worker --loglevel=info"'
3838
environment:
39-
VELA_BROKER_URL: 'sqla+postgresql+psycopg://postgres:vela@database:5432/vela'
40-
VELA_RESULT_BACKEND: 'db+postgresql+psycopg://postgres:vela@database:5432/vela'
41-
VELA_POSTGRES_URL: 'postgresql+asyncpg://postgres:vela@database:5432/vela'
39+
VELA_BROKER_URL: 'sqla+postgresql+psycopg://vela_celery:celery@database:5432/controller'
40+
VELA_RESULT_BACKEND: 'db+postgresql+psycopg://vela_celery:celery@database:5432/controller'
41+
VELA_POSTGRES_URL: 'postgresql+asyncpg://vela_controller:controller@database:5432/controller'
4242
VELA_JWT_SECRET: 'secret'
4343
VELA_ENABLE_DB_EXTERNAL_IPV6_LOADBALANCER: 'false'
4444
depends_on:
@@ -50,10 +50,12 @@ services:
5050
database:
5151
image: docker.io/postgres:17
5252
environment:
53-
POSTGRES_PASSWORD: vela
54-
POSTGRES_DB: vela
53+
POSTGRES_PASSWORD: postgres
54+
POSTGRES_DB: postgres
55+
volumes:
56+
- ./init.sql:/docker-entrypoint-initdb.d/90-init.sql:ro
5557
healthcheck:
56-
test: ['CMD-SHELL', 'pg_isready -U postgres -d vela']
58+
test: ['CMD-SHELL', 'pg_isready -U postgres -d postgres']
5759
timeout: 5s
5860
interval: 5s
5961
retries: 3

0 commit comments

Comments
 (0)