From 5479acfc14edba4a2426bb2bf21e4c0aae21849c Mon Sep 17 00:00:00 2001 From: Doug Goldstein Date: Fri, 16 Oct 2026 16:41:24 -0500 Subject: [PATCH 1/4] feat(neutron): let the MariaDB operator render the database connection Have the neutron chart declare the Database, User, Grant and Connection resources and project the operator-written neutron-db-conn secret into every workload that talks to the database, instead of generating a [database] connection from the NEUTRON_DB_PASSWORD Helm value. The password is read from the existing neutron-db-password secret (mariadb_db.password_secret.create: false) and the resources attach to the MariaDB named mariadb (mariadb_ref) while clients keep connecting through the mariadb-primary service. This needs a neutron chart carrying the mariadb_db.password_secret and mariadb_db.mariadb_ref values; the chart pin must be bumped before this syncs. components/neutron/neutron-mariadb-db.yaml is no longer needed and NEUTRON_DB_PASSWORD is dropped from openstack-secrets.tpl.yaml. --- ...doug.goldstein_mariadb_operator_db_conn.md | 28 ++++++++++ charts/argocd-understack/values.yaml | 2 +- components/neutron/kustomization.yaml | 1 - components/neutron/neutron-mariadb-db.yaml | 52 ------------------- components/neutron/values.yaml | 30 +++++++++++ components/openstack-secrets.tpl.yaml | 3 -- 6 files changed, 59 insertions(+), 57 deletions(-) create mode 100644 changelog.d/20261016_120000_doug.goldstein_mariadb_operator_db_conn.md delete mode 100644 components/neutron/neutron-mariadb-db.yaml diff --git a/changelog.d/20261016_120000_doug.goldstein_mariadb_operator_db_conn.md b/changelog.d/20261016_120000_doug.goldstein_mariadb_operator_db_conn.md new file mode 100644 index 000000000..abcebbb24 --- /dev/null +++ b/changelog.d/20261016_120000_doug.goldstein_mariadb_operator_db_conn.md @@ -0,0 +1,28 @@ +### Deploy repo changes + +Services are moving to get their `[database] connection` from the MariaDB operator instead of from a `_DB_PASSWORD` Helm value. For each converted service the chart renders the `Database`, `User`, `Grant` and `Connection` resources, and the operator writes the connection string into the `-db-conn` Secret, which is projected into every workload of that service that talks to the database. The service's `components//-mariadb-db.yaml` is removed. + +Converted so far: Neutron. + +The `-db-password` Secret (`username` and `password` keys) is still read from your deploy repo, and the chart no longer renders it, so it must exist before this change syncs. Pods wait for `-db-conn`, so a missing Secret shows up as pods stuck in `ContainerCreating`. + +Argo CD prunes the old `Grant` named `-grant`; the chart's is named ``. Check that both are Ready after the sync: + +```bash +SERVICE=neutron +kubectl -n openstack get database,user,grant,connection -l application=$SERVICE +``` + +The old `-grant` can get stuck terminating. With `privileges: [ALL]` and `grantOption: true`, the operator's finalizer fails on delete with `Error 1064 ... near 'ON ``.* FROM ''@'%''` (seen on mariadb-operator 25.8.4). If `-grant` is still present with a `deletionTimestamp`, revoke the privileges by hand and then remove the finalizer so the object can go away: + +```bash +SERVICE=neutron +kubectl mariadb -n openstack mariadb -e "REVOKE ALL PRIVILEGES, GRANT OPTION FROM '$SERVICE'@'%';" +kubectl -n openstack patch grant $SERVICE-grant --type=merge -p '{"metadata":{"finalizers":null}}' +``` + +Set `SERVICE` to each converted service in turn. + +Patching the finalizer alone leaves the old grant in the database. The new `` Grant re-applies the privileges for the same account. + +`_DB_PASSWORD` in `secret-openstack.yaml` is no longer used by a converted service and can be removed from your deploy repo once every cluster is on this version. diff --git a/charts/argocd-understack/values.yaml b/charts/argocd-understack/values.yaml index e839335f2..bc58fa8c5 100644 --- a/charts/argocd-understack/values.yaml +++ b/charts/argocd-understack/values.yaml @@ -404,7 +404,7 @@ site: wave: 2 # -- Chart version for Neutron # renovate: datasource=helm depName=neutron registryUrl=https://tarballs.opendev.org/openstack/openstack-helm - chartVersion: 2026.1.107+a39ebbeb1 + chartVersion: 2026.2.1+b90c3a6ab # -- Placement (Placement Service) placement: diff --git a/components/neutron/kustomization.yaml b/components/neutron/kustomization.yaml index e2622ca96..c0a01bf67 100644 --- a/components/neutron/kustomization.yaml +++ b/components/neutron/kustomization.yaml @@ -3,6 +3,5 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - - neutron-mariadb-db.yaml - neutron-rabbitmq-queue.yaml - job-neutron-post-deploy.yaml diff --git a/components/neutron/neutron-mariadb-db.yaml b/components/neutron/neutron-mariadb-db.yaml deleted file mode 100644 index ac07b24fc..000000000 --- a/components/neutron/neutron-mariadb-db.yaml +++ /dev/null @@ -1,52 +0,0 @@ ---- -apiVersion: k8s.mariadb.com/v1alpha1 -kind: Database -metadata: - name: neutron - namespace: openstack -spec: - # If you want the database to be created with a different name than the resource name - # name: data-custom - mariaDbRef: - name: mariadb # name of the MariaDB kind - waitForIt: true - characterSet: utf8 - collate: utf8_general_ci - retryInterval: 5s ---- -apiVersion: k8s.mariadb.com/v1alpha1 -kind: User -metadata: - name: neutron - namespace: openstack -spec: - # If you want the user to be created with a different name than the resource name - # name: user-custom - mariaDbRef: - name: mariadb # name of the MariaDB kind - waitForIt: true - passwordSecretKeyRef: - name: neutron-db-password - key: password - # This field is immutable and defaults to 10, 0 means unlimited. - maxUserConnections: 0 - host: "%" - retryInterval: 5s ---- -apiVersion: k8s.mariadb.com/v1alpha1 -kind: Grant -metadata: - name: neutron-grant - namespace: openstack -spec: - mariaDbRef: - name: mariadb # name of the MariaDB kind - waitForIt: true - privileges: - - "ALL" - database: "neutron" - table: "*" - username: neutron - grantOption: true - host: "%" - retryInterval: 5s diff --git a/components/neutron/values.yaml b/components/neutron/values.yaml index cee6dbf39..50e518057 100644 --- a/components/neutron/values.yaml +++ b/components/neutron/values.yaml @@ -69,6 +69,11 @@ conf: #ovn_nb_connection: "tcp:ovn-ovsdb-nb.openstack.svc:6641" #ovn_sb_connection: "tcp:ovn-ovsdb-sb.openstack.svc:6642" neutron: + database: + # The MariaDB operator writes the connection string into the + # neutron-db-conn secret, which is projected into the config directory + # below, so the chart must not generate one from the DB password. + connection: null DEFAULT: # https://docs.openstack.org/neutron/latest/admin/config-wsgi.html # the api_workers set the number of uWSGI processes as well @@ -157,21 +162,34 @@ pod: neutron_db_sync: - secret: name: neutron-ks-etc + - secret: + name: neutron-db-conn neutron_ironic_agent: - secret: name: neutron-ks-etc neutron_server: - secret: name: neutron-ks-etc + - secret: + name: neutron-db-conn neutron_ovn_maintenance_worker: - secret: name: neutron-ks-etc + - secret: + name: neutron-db-conn neutron_rpc_server: - secret: name: neutron-ks-etc + - secret: + name: neutron-db-conn neutron_periodic_worker: - secret: name: neutron-ks-etc + - secret: + name: neutron-db-conn + neutron_ovn_db_sync: + - secret: + name: neutron-db-conn use_fqdn: neutron_agent: false @@ -310,8 +328,20 @@ dependencies: services: [] +# The chart declares the Database, User, Grant and Connection resources instead +# of the db-init job. The password is read from the neutron-db-password secret +# in the deploy repo rather than rendered from Helm values. +mariadb_db: + api_group: k8s.mariadb.com + # the MariaDB resource is named mariadb, while clients connect through the + # mariadb-primary service set in endpoints.oslo_db.hosts + mariadb_ref: mariadb + password_secret: + create: false + manifests: job_db_init: false + mariadb_db: true job_rabbit_init: false pod_rally_test: false secret_db: false diff --git a/components/openstack-secrets.tpl.yaml b/components/openstack-secrets.tpl.yaml index 680397ed6..1e69d1da0 100644 --- a/components/openstack-secrets.tpl.yaml +++ b/components/openstack-secrets.tpl.yaml @@ -30,9 +30,6 @@ endpoints: # this is what the ironic service uses to connect to MariaDB ironic: password: "${IRONIC_DB_PASSWORD}" - # this is what the neutron service uses to connect to MariaDB - neutron: - password: "${NEUTRON_DB_PASSWORD}" # this is what the nova service uses to connect to MariaDB nova: password: "${NOVA_DB_PASSWORD}" From ef8b857feed7b71c10e2c6cd436d9a781c07a41e Mon Sep 17 00:00:00 2001 From: Doug Goldstein Date: Thu, 22 Oct 2026 15:40:07 -0500 Subject: [PATCH 2/4] feat(placement): let the MariaDB operator render the database connection Convert placement the same way as neutron: the chart declares the Database, User, Grant and Connection resources and the operator-written placement-db-conn secret is projected into the db-sync job and the API instead of generating a [database] connection from PLACEMENT_DB_PASSWORD. Bump the placement chart to 2026.2.3, which carries the mariadb_db values. components/placement/placement-mariadb-db.yaml is removed and PLACEMENT_DB_PASSWORD is dropped from openstack-secrets.tpl.yaml. The kustomization is left with an empty resources list because the Argo application always adds components/placement/ as a source. --- ...doug.goldstein_mariadb_operator_db_conn.md | 6 +-- charts/argocd-understack/values.yaml | 2 +- components/openstack-secrets.tpl.yaml | 3 -- components/placement/kustomization.yaml | 3 +- .../placement/placement-mariadb-db.yaml | 52 ------------------- components/placement/values.yaml | 22 ++++++++ 6 files changed, 27 insertions(+), 61 deletions(-) delete mode 100644 components/placement/placement-mariadb-db.yaml diff --git a/changelog.d/20261016_120000_doug.goldstein_mariadb_operator_db_conn.md b/changelog.d/20261016_120000_doug.goldstein_mariadb_operator_db_conn.md index abcebbb24..7c7671b22 100644 --- a/changelog.d/20261016_120000_doug.goldstein_mariadb_operator_db_conn.md +++ b/changelog.d/20261016_120000_doug.goldstein_mariadb_operator_db_conn.md @@ -2,21 +2,21 @@ Services are moving to get their `[database] connection` from the MariaDB operator instead of from a `_DB_PASSWORD` Helm value. For each converted service the chart renders the `Database`, `User`, `Grant` and `Connection` resources, and the operator writes the connection string into the `-db-conn` Secret, which is projected into every workload of that service that talks to the database. The service's `components//-mariadb-db.yaml` is removed. -Converted so far: Neutron. +Converted so far: Neutron, Placement. The `-db-password` Secret (`username` and `password` keys) is still read from your deploy repo, and the chart no longer renders it, so it must exist before this change syncs. Pods wait for `-db-conn`, so a missing Secret shows up as pods stuck in `ContainerCreating`. Argo CD prunes the old `Grant` named `-grant`; the chart's is named ``. Check that both are Ready after the sync: ```bash -SERVICE=neutron +SERVICE=neutron # or placement kubectl -n openstack get database,user,grant,connection -l application=$SERVICE ``` The old `-grant` can get stuck terminating. With `privileges: [ALL]` and `grantOption: true`, the operator's finalizer fails on delete with `Error 1064 ... near 'ON ``.* FROM ''@'%''` (seen on mariadb-operator 25.8.4). If `-grant` is still present with a `deletionTimestamp`, revoke the privileges by hand and then remove the finalizer so the object can go away: ```bash -SERVICE=neutron +SERVICE=neutron # or placement kubectl mariadb -n openstack mariadb -e "REVOKE ALL PRIVILEGES, GRANT OPTION FROM '$SERVICE'@'%';" kubectl -n openstack patch grant $SERVICE-grant --type=merge -p '{"metadata":{"finalizers":null}}' ``` diff --git a/charts/argocd-understack/values.yaml b/charts/argocd-understack/values.yaml index bc58fa8c5..9ced88d18 100644 --- a/charts/argocd-understack/values.yaml +++ b/charts/argocd-understack/values.yaml @@ -416,7 +416,7 @@ site: wave: 2 # -- Chart version for Placement # renovate: datasource=helm depName=placement registryUrl=https://tarballs.opendev.org/openstack/openstack-helm - chartVersion: 2026.1.58+a39ebbeb1 + chartVersion: 2026.2.3+b5078da51 # -- Nova (Compute Service) nova: diff --git a/components/openstack-secrets.tpl.yaml b/components/openstack-secrets.tpl.yaml index 1e69d1da0..6ceb2e4ef 100644 --- a/components/openstack-secrets.tpl.yaml +++ b/components/openstack-secrets.tpl.yaml @@ -33,9 +33,6 @@ endpoints: # this is what the nova service uses to connect to MariaDB nova: password: "${NOVA_DB_PASSWORD}" - # this is what the placement service uses to connect to MariaDB - placement: - password: "${PLACEMENT_DB_PASSWORD}" # this is what the horizon dashboard service uses to connect to MariaDB horizon: password: "${HORIZON_DB_PASSWORD}" diff --git a/components/placement/kustomization.yaml b/components/placement/kustomization.yaml index 13e194d36..9efcfde31 100644 --- a/components/placement/kustomization.yaml +++ b/components/placement/kustomization.yaml @@ -2,5 +2,4 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization -resources: - - placement-mariadb-db.yaml +resources: [] diff --git a/components/placement/placement-mariadb-db.yaml b/components/placement/placement-mariadb-db.yaml deleted file mode 100644 index 4a5020bb7..000000000 --- a/components/placement/placement-mariadb-db.yaml +++ /dev/null @@ -1,52 +0,0 @@ ---- -apiVersion: k8s.mariadb.com/v1alpha1 -kind: Database -metadata: - name: placement - namespace: openstack -spec: - # If you want the database to be created with a different name than the resource name - # name: data-custom - mariaDbRef: - name: mariadb # name of the MariaDB kind - waitForIt: true - characterSet: utf8 - collate: utf8_general_ci - retryInterval: 5s ---- -apiVersion: k8s.mariadb.com/v1alpha1 -kind: User -metadata: - name: placement - namespace: openstack -spec: - # If you want the user to be created with a different name than the resource name - # name: user-custom - mariaDbRef: - name: mariadb # name of the MariaDB kind - waitForIt: true - passwordSecretKeyRef: - name: placement-db-password - key: password - # This field is immutable and defaults to 10, 0 means unlimited. - maxUserConnections: 0 - host: "%" - retryInterval: 5s ---- -apiVersion: k8s.mariadb.com/v1alpha1 -kind: Grant -metadata: - name: placement-grant - namespace: openstack -spec: - mariaDbRef: - name: mariadb # name of the MariaDB kind - waitForIt: true - privileges: - - "ALL" - database: "placement" - table: "*" - username: placement - grantOption: true - host: "%" - retryInterval: 5s diff --git a/components/placement/values.yaml b/components/placement/values.yaml index ad7e56c18..22cfb5b3b 100644 --- a/components/placement/values.yaml +++ b/components/placement/values.yaml @@ -2,6 +2,12 @@ release_group: null conf: + placement: + database: + # The MariaDB operator writes the connection string into the + # placement-db-conn secret, which is projected into the config directory + # below, so the chart must not generate one from the DB password. + connection: null placement_api_uwsgi: uwsgi: start-time: "%t" @@ -42,9 +48,13 @@ pod: placement_db_sync: - secret: name: placement-ks-etc + - secret: + name: placement-db-conn placement: - secret: name: placement-ks-etc + - secret: + name: placement-db-conn lifecycle: disruption_budget: api: @@ -72,8 +82,20 @@ endpoints: name: understack-cluster-issuer kind: ClusterIssuer +# The chart declares the Database, User, Grant and Connection resources instead +# of the db-init job. The password is read from the placement-db-password secret +# in the deploy repo rather than rendered from Helm values. +mariadb_db: + api_group: k8s.mariadb.com + # the MariaDB resource is named mariadb, while clients connect through the + # mariadb-primary service set in endpoints.oslo_db.hosts + mariadb_ref: mariadb + password_secret: + create: false + manifests: job_db_init: false + mariadb_db: true secret_db: false service_ingress: false # We set the `secret_keystone` and `secret_ks_etc` to false in order to disable From 98145d057cbe9a834c8a8e99bc020c2bc469a722 Mon Sep 17 00:00:00 2001 From: Doug Goldstein Date: Thu, 22 Oct 2026 15:40:33 -0500 Subject: [PATCH 3/4] feat(glance): let the MariaDB operator render the database connection Convert glance the same way as neutron and placement: the chart declares the Database, User, Grant and Connection resources and the operator-written glance-db-conn secret is projected into the API, the db-sync job and the metadefs-load job (which runs glance-manage against the database) instead of generating a [database] connection from GLANCE_DB_PASSWORD. Bump the glance chart to 2026.2.3, which carries the mariadb_db values. components/glance/glance-mariadb-db.yaml is removed and GLANCE_DB_PASSWORD is dropped from openstack-secrets.tpl.yaml. --- ...doug.goldstein_mariadb_operator_db_conn.md | 6 +-- charts/argocd-understack/values.yaml | 2 +- components/glance/glance-mariadb-db.yaml | 52 ------------------- components/glance/kustomization.yaml | 1 - components/glance/values.yaml | 25 ++++++++- components/openstack-secrets.tpl.yaml | 3 -- 6 files changed, 28 insertions(+), 61 deletions(-) delete mode 100644 components/glance/glance-mariadb-db.yaml diff --git a/changelog.d/20261016_120000_doug.goldstein_mariadb_operator_db_conn.md b/changelog.d/20261016_120000_doug.goldstein_mariadb_operator_db_conn.md index 7c7671b22..28425dd22 100644 --- a/changelog.d/20261016_120000_doug.goldstein_mariadb_operator_db_conn.md +++ b/changelog.d/20261016_120000_doug.goldstein_mariadb_operator_db_conn.md @@ -2,21 +2,21 @@ Services are moving to get their `[database] connection` from the MariaDB operator instead of from a `_DB_PASSWORD` Helm value. For each converted service the chart renders the `Database`, `User`, `Grant` and `Connection` resources, and the operator writes the connection string into the `-db-conn` Secret, which is projected into every workload of that service that talks to the database. The service's `components//-mariadb-db.yaml` is removed. -Converted so far: Neutron, Placement. +Converted so far: Neutron, Placement, Glance. The `-db-password` Secret (`username` and `password` keys) is still read from your deploy repo, and the chart no longer renders it, so it must exist before this change syncs. Pods wait for `-db-conn`, so a missing Secret shows up as pods stuck in `ContainerCreating`. Argo CD prunes the old `Grant` named `-grant`; the chart's is named ``. Check that both are Ready after the sync: ```bash -SERVICE=neutron # or placement +SERVICE=neutron # or placement, glance kubectl -n openstack get database,user,grant,connection -l application=$SERVICE ``` The old `-grant` can get stuck terminating. With `privileges: [ALL]` and `grantOption: true`, the operator's finalizer fails on delete with `Error 1064 ... near 'ON ``.* FROM ''@'%''` (seen on mariadb-operator 25.8.4). If `-grant` is still present with a `deletionTimestamp`, revoke the privileges by hand and then remove the finalizer so the object can go away: ```bash -SERVICE=neutron # or placement +SERVICE=neutron # or placement, glance kubectl mariadb -n openstack mariadb -e "REVOKE ALL PRIVILEGES, GRANT OPTION FROM '$SERVICE'@'%';" kubectl -n openstack patch grant $SERVICE-grant --type=merge -p '{"metadata":{"finalizers":null}}' ``` diff --git a/charts/argocd-understack/values.yaml b/charts/argocd-understack/values.yaml index 9ced88d18..4f7b4209b 100644 --- a/charts/argocd-understack/values.yaml +++ b/charts/argocd-understack/values.yaml @@ -368,7 +368,7 @@ site: wave: 2 # -- Chart version for Glance # renovate: datasource=helm depName=glance registryUrl=https://tarballs.opendev.org/openstack/openstack-helm - chartVersion: 2026.1.67+a39ebbeb1 + chartVersion: 2026.2.3+b5078da51 # -- Cinder (Block Storage Service) cinder: diff --git a/components/glance/glance-mariadb-db.yaml b/components/glance/glance-mariadb-db.yaml deleted file mode 100644 index 81ec18d06..000000000 --- a/components/glance/glance-mariadb-db.yaml +++ /dev/null @@ -1,52 +0,0 @@ ---- -apiVersion: k8s.mariadb.com/v1alpha1 -kind: Database -metadata: - name: glance - namespace: openstack -spec: - # If you want the database to be created with a different name than the resource name - # name: data-custom - mariaDbRef: - name: mariadb # name of the MariaDB kind - waitForIt: true - characterSet: utf8 - collate: utf8_general_ci - retryInterval: 5s ---- -apiVersion: k8s.mariadb.com/v1alpha1 -kind: User -metadata: - name: glance - namespace: openstack -spec: - # If you want the user to be created with a different name than the resource name - # name: user-custom - mariaDbRef: - name: mariadb # name of the MariaDB kind - waitForIt: true - passwordSecretKeyRef: - name: glance-db-password - key: password - # This field is immutable and defaults to 10, 0 means unlimited. - maxUserConnections: 0 - host: "%" - retryInterval: 5s ---- -apiVersion: k8s.mariadb.com/v1alpha1 -kind: Grant -metadata: - name: glance-grant - namespace: openstack -spec: - mariaDbRef: - name: mariadb # name of the MariaDB kind - waitForIt: true - privileges: - - "ALL" - database: "glance" - table: "*" - username: glance - grantOption: true - host: "%" - retryInterval: 5s diff --git a/components/glance/kustomization.yaml b/components/glance/kustomization.yaml index abf06dc78..a768699b0 100644 --- a/components/glance/kustomization.yaml +++ b/components/glance/kustomization.yaml @@ -3,5 +3,4 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - - glance-mariadb-db.yaml - glance-rabbitmq-queue.yaml diff --git a/components/glance/values.yaml b/components/glance/values.yaml index 93faa89d4..c2b175f95 100644 --- a/components/glance/values.yaml +++ b/components/glance/values.yaml @@ -92,10 +92,16 @@ pod: glance_api: - secret: name: glance-ks-etc + - secret: + name: glance-db-conn glance_db_sync: - secret: name: glance-ks-etc - glance_metadefs_load: [] + - secret: + name: glance-db-conn + glance_metadefs_load: + - secret: + name: glance-db-conn replicas: api: 2 lifecycle: @@ -128,6 +134,11 @@ pod: conf: glance: + database: + # The MariaDB operator writes the connection string into the + # glance-db-conn secret, which is projected into the config directory + # above, so the chart must not generate one from the DB password. + connection: null oslo_messaging_notifications: driver: messagingv2 oslo_messaging_rabbit: @@ -140,7 +151,19 @@ conf: # Kubernetes environment. processes: 2 +# The chart declares the Database, User, Grant and Connection resources instead +# of the db-init job. The password is read from the glance-db-password secret +# in the deploy repo rather than rendered from Helm values. +mariadb_db: + api_group: k8s.mariadb.com + # the MariaDB resource is named mariadb, while clients connect through the + # mariadb-primary service set in endpoints.oslo_db.hosts + mariadb_ref: mariadb + password_secret: + create: false + manifests: + mariadb_db: true # its pre-delete hook makes ArgoCD add pre-delete finalizers to the # Application, which the app-of-apps then fights. no-op for us anyway. job_clean: false diff --git a/components/openstack-secrets.tpl.yaml b/components/openstack-secrets.tpl.yaml index 6ceb2e4ef..caba63dd6 100644 --- a/components/openstack-secrets.tpl.yaml +++ b/components/openstack-secrets.tpl.yaml @@ -24,9 +24,6 @@ endpoints: # this is what the keystone service uses to connect to MariaDB keystone: password: "${KEYSTONE_DB_PASSWORD}" - # this is what the glance service uses to connect to MariaDB - glance: - password: "${GLANCE_DB_PASSWORD}" # this is what the ironic service uses to connect to MariaDB ironic: password: "${IRONIC_DB_PASSWORD}" From 17474cdcbfab8888df962860506626edefbb4935 Mon Sep 17 00:00:00 2001 From: Doug Goldstein Date: Thu, 22 Oct 2026 15:41:09 -0500 Subject: [PATCH 4/4] feat(keystone): let the MariaDB operator render the database connection Convert keystone the same way as neutron, placement and glance: the chart declares the Database, User, Grant and Connection resources and the operator-written keystone-db-conn secret is projected into the API, the db-sync job and the credential-rotate cronjob (credential_migrate touches the database) instead of generating a [database] connection from KEYSTONE_DB_PASSWORD. Bump the keystone chart to 2026.2.3, which carries the mariadb_db values. components/keystone/keystone-mariadb-db.yaml is removed and KEYSTONE_DB_PASSWORD is dropped from openstack-secrets.tpl.yaml. --- ...doug.goldstein_mariadb_operator_db_conn.md | 6 +-- charts/argocd-understack/values.yaml | 2 +- components/keystone/keystone-mariadb-db.yaml | 52 ------------------- components/keystone/kustomization.yaml | 1 - components/keystone/values.yaml | 29 +++++++++++ components/openstack-secrets.tpl.yaml | 3 -- 6 files changed, 33 insertions(+), 60 deletions(-) delete mode 100644 components/keystone/keystone-mariadb-db.yaml diff --git a/changelog.d/20261016_120000_doug.goldstein_mariadb_operator_db_conn.md b/changelog.d/20261016_120000_doug.goldstein_mariadb_operator_db_conn.md index 28425dd22..130abb2b9 100644 --- a/changelog.d/20261016_120000_doug.goldstein_mariadb_operator_db_conn.md +++ b/changelog.d/20261016_120000_doug.goldstein_mariadb_operator_db_conn.md @@ -2,21 +2,21 @@ Services are moving to get their `[database] connection` from the MariaDB operator instead of from a `_DB_PASSWORD` Helm value. For each converted service the chart renders the `Database`, `User`, `Grant` and `Connection` resources, and the operator writes the connection string into the `-db-conn` Secret, which is projected into every workload of that service that talks to the database. The service's `components//-mariadb-db.yaml` is removed. -Converted so far: Neutron, Placement, Glance. +Converted so far: Neutron, Placement, Glance, Keystone. The `-db-password` Secret (`username` and `password` keys) is still read from your deploy repo, and the chart no longer renders it, so it must exist before this change syncs. Pods wait for `-db-conn`, so a missing Secret shows up as pods stuck in `ContainerCreating`. Argo CD prunes the old `Grant` named `-grant`; the chart's is named ``. Check that both are Ready after the sync: ```bash -SERVICE=neutron # or placement, glance +SERVICE=neutron # or placement, glance, keystone kubectl -n openstack get database,user,grant,connection -l application=$SERVICE ``` The old `-grant` can get stuck terminating. With `privileges: [ALL]` and `grantOption: true`, the operator's finalizer fails on delete with `Error 1064 ... near 'ON ``.* FROM ''@'%''` (seen on mariadb-operator 25.8.4). If `-grant` is still present with a `deletionTimestamp`, revoke the privileges by hand and then remove the finalizer so the object can go away: ```bash -SERVICE=neutron # or placement, glance +SERVICE=neutron # or placement, glance, keystone kubectl mariadb -n openstack mariadb -e "REVOKE ALL PRIVILEGES, GRANT OPTION FROM '$SERVICE'@'%';" kubectl -n openstack patch grant $SERVICE-grant --type=merge -p '{"metadata":{"finalizers":null}}' ``` diff --git a/charts/argocd-understack/values.yaml b/charts/argocd-understack/values.yaml index 4f7b4209b..a96f4eb1d 100644 --- a/charts/argocd-understack/values.yaml +++ b/charts/argocd-understack/values.yaml @@ -356,7 +356,7 @@ site: wave: 1 # -- Chart version for Keystone # renovate: datasource=helm depName=keystone registryUrl=https://tarballs.opendev.org/openstack/openstack-helm - chartVersion: 2026.1.61+a39ebbeb1 + chartVersion: 2026.2.3+b5078da51 # -- Glance (Image Service) glance: diff --git a/components/keystone/keystone-mariadb-db.yaml b/components/keystone/keystone-mariadb-db.yaml deleted file mode 100644 index f044959c1..000000000 --- a/components/keystone/keystone-mariadb-db.yaml +++ /dev/null @@ -1,52 +0,0 @@ ---- -apiVersion: k8s.mariadb.com/v1alpha1 -kind: Database -metadata: - name: keystone - namespace: openstack -spec: - # If you want the database to be created with a different name than the resource name - # name: data-custom - mariaDbRef: - name: mariadb # name of the MariaDB kind - waitForIt: true - characterSet: utf8 - collate: utf8_general_ci - retryInterval: 5s ---- -apiVersion: k8s.mariadb.com/v1alpha1 -kind: User -metadata: - name: keystone - namespace: openstack -spec: - # If you want the user to be created with a different name than the resource name - # name: user-custom - mariaDbRef: - name: mariadb # name of the MariaDB kind - waitForIt: true - passwordSecretKeyRef: - name: keystone-db-password - key: password - # This field is immutable and defaults to 10, 0 means unlimited. - maxUserConnections: 0 - host: "%" - retryInterval: 5s ---- -apiVersion: k8s.mariadb.com/v1alpha1 -kind: Grant -metadata: - name: keystone-grant - namespace: openstack -spec: - mariaDbRef: - name: mariadb # name of the MariaDB kind - waitForIt: true - privileges: - - "ALL" - database: "keystone" - table: "*" - username: keystone - grantOption: true - host: "%" - retryInterval: 5s diff --git a/components/keystone/kustomization.yaml b/components/keystone/kustomization.yaml index d66eedff3..00c52306d 100644 --- a/components/keystone/kustomization.yaml +++ b/components/keystone/kustomization.yaml @@ -3,5 +3,4 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - - keystone-mariadb-db.yaml - keystone-rabbitmq-queue.yaml diff --git a/components/keystone/values.yaml b/components/keystone/values.yaml index 0f4fb1cdb..d7d4afdf1 100644 --- a/components/keystone/values.yaml +++ b/components/keystone/values.yaml @@ -31,6 +31,18 @@ dependencies: - keystone-fernet-setup pod: + etcSources: + keystone_api: + - secret: + name: keystone-db-conn + keystone_db_sync: + - secret: + name: keystone-db-conn + # credential_rotate runs credential_migrate, which re-encrypts rows in the + # database + keystone_credential_rotate: + - secret: + name: keystone-db-conn resources: enabled: true api: @@ -174,6 +186,11 @@ pod: conf: keystone: + database: + # The MariaDB operator writes the connection string into the + # keystone-db-conn secret, which is projected into the config directory + # above, so the chart must not generate one from the DB password. + connection: null auth: methods: password,token,openid,mapped,application_credential openid: @@ -339,7 +356,19 @@ endpoints: default: 5556 path: '' +# The chart declares the Database, User, Grant and Connection resources instead +# of the db-init job. The password is read from the keystone-db-password secret +# in the deploy repo rather than rendered from Helm values. +mariadb_db: + api_group: k8s.mariadb.com + # the MariaDB resource is named mariadb, while clients connect through the + # mariadb-primary service set in endpoints.oslo_db.hosts + mariadb_ref: mariadb + password_secret: + create: false + manifests: + mariadb_db: true job_credential_cleanup: false job_db_init: false job_rabbit_init: false diff --git a/components/openstack-secrets.tpl.yaml b/components/openstack-secrets.tpl.yaml index caba63dd6..b9d9eb5fe 100644 --- a/components/openstack-secrets.tpl.yaml +++ b/components/openstack-secrets.tpl.yaml @@ -21,9 +21,6 @@ endpoints: # 'oslo_db' is for MariaDB oslo_db: auth: - # this is what the keystone service uses to connect to MariaDB - keystone: - password: "${KEYSTONE_DB_PASSWORD}" # this is what the ironic service uses to connect to MariaDB ironic: password: "${IRONIC_DB_PASSWORD}"