When deploying a new component, GitOps can create the Kubernetes resources such as the Deployment, Service, and ServiceAccount. The part I'm unsure about is database access: how should the database, user, permissions, and credentials be created? Should database user provisioning also be declarative and managed through GitOps, or should deployment use a separate provisioning step? I manage credentials through AWS SSM rather than storing them in Git, and I'd like each application module to set up everything across several environments without requiring two separate manual actions.
4 Answers
For small, stable applications, a per-application database and static role managed by an operator or initialization job is often simpler than introducing Vault. For ephemeral workloads such as CI jobs or batch tasks, dynamic credentials are more attractive because old users can be cleaned up automatically. Whichever approach you choose, test the full lifecycle: create the role, deploy the application, rotate the secret, remove the application, and verify that obsolete users and permissions are removed.
Keep the Kubernetes resources and credential storage as separate concerns, but automate both. GitOps can create the application and an operator, Terraform module, migration job, or provisioning pipeline can create the database user and grants. The resulting credentials should come from a secrets manager such as AWS SSM, Vault, or another external secret system, then be exposed to the workload through a Kubernetes Secret. This avoids putting passwords in Git while still allowing one deployment workflow to orchestrate everything.
If your database has an operator, that’s usually the cleanest GitOps approach. Operators such as CloudNativePG or MariaDB Operator can manage databases, users, permissions, and related secrets from Kubernetes manifests or Helm values. You can wrap those resources in an application chart so deploying one module creates the whole database integration. This keeps the workflow declarative without requiring a separate manual provisioning step.
That’s the kind of self-contained setup I’m aiming for. I’ll look more closely at the MariaDB operator since some of our applications use MySQL-compatible databases.
For production, consider identity-based access or short-lived credentials where the database supports it. Workload identity, IAM authentication, Vault database secrets engines, and external secret operators can reduce the need for long-lived passwords. You still need an initial database role and grants, but those can be created by an operator or an automated bootstrap process. Make rotation and revocation part of the design from the beginning rather than treating them as a later task.
I already use IAM authentication in a few places, but the initial database user and grants still need to be created. My main concern is avoiding a separate manual deployment step across all of our environments.

Terraform works well for generating credentials and wiring them into Kubernetes, but it can feel like a second touch if application deployment and infrastructure provisioning are handled separately. A shared module or pipeline can hide that split from the developer.