Blog

Solving Secret Sprawl in Multi-Account Kubernetes with External Secrets Operator

Picture of Victoria Bisova
Victoria Bisova
DevOps and Cloud Engineer
19.05.2026
Reading time: 4 mins.
Last Updated: 22.05.2026

Table of Contents

Infrastructure automation in Kubernetes is largely a solved problem-until secret management enters the picture. As environments scale, distributing and rotating secrets across multiple isolated clusters quickly becomes a major operational challenge.

Our team recently faced this exact problem while designing a scalable Kubernetes platform for a client running on EKS. The core issue wasn’t specific to one cloud provider or even to cloud infrastructure itself. The same challenges appear in Azure, Google Cloud, multi-cloud setups, on-prem environments, and even local development workflows using tools like KIND or Minikube.

The common denominator is isolation. Each environment-development, staging, and production-lives in its own account, namespace, or cluster. While this separation is essential for security and blast-radius control, it makes shared secret management difficult and error-prone.

This article explains how we solved multi-account Kubernetes secret synchronization using External Secrets Operator (ESO) with Bitwarden Secrets Manager, enabling centralized control with automated distribution.

Our client operates two applications with heavy reliance on third-party integrations. Problems surfaced immediately when automating new environment provisioning:

In development and staging, the applications relied on the same sandbox credentials for external services. Each environment needed identical values, but stored separately.

Each Kubernetes cluster lived in its own account. Using a native secrets service per account meant that rotating a single third-party API key required manual updates everywhere.

The lack of centralized control led to rotation fatigue and increased risk. The requirement was clear:
update a secret once and have it propagate automatically to every cluster.

The key architectural decision was to separate secret storage from secret consumption.

To bridge external secret stores with Kubernetes-native secrets, we selected External Secrets Operator (ESO). ESO synchronizes secrets from an external backend into Kubernetes Secrets using declarative configuration.

For backend storage, we chose Bitwarden Secrets Manager. This decision was pragmatic: the client already used Bitwarden organization-wide, allowing us to reuse existing access controls and governance.

While Bitwarden was the selected provider, this architecture is provider-agnostic. The same pattern works with alternatives such as HashiCorp Vault. The important principle remains the same:

Store secrets centrally, and let ESO synchronize them into every Kubernetes cluster automatically.

Secret Sprawl

The following steps outline the exact configuration used in our Kubernetes environment. While all resources were automated using Terraform, direct commands are shown here for clarity.
(For full automation code, refer to the linked GitHub repository.)

Prerequisites:

  • A Kubernetes cluster (EKS, AKS, GKE, or equivalent)
  • kubectl and helm installed locally
  • A Bitwarden Secrets Manager account

The ESO Bitwarden integration requires secure HTTPS communication. To manage certificates dynamically inside the cluster, we first install Cert Manager.

helm repo add jetstack https://charts.jetstack.io 
helm repo update 

helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --set installCRDs=true

Create a Self-Signed ClusterIssuer

cat <<EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: bitwarden-bootstrap-issuer
spec:
  selfSigned: {}
EOF

Create the External Secrets Namespace and Root CA Certificate

kubectl create namespace external-secrets

cat <<EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: bitwarden-bootstrap-certificate
  namespace: external-secrets
spec:
  commonName: bitwarden-tls-ca
  isCA: true
  secretName: bitwarden-ca-certs
  issuerRef:
    name: bitwarden-bootstrap-issuer
    kind: ClusterIssuer
EOF

Create the Issuer and TLS Certificate for the SDK Server

cat <<EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: bitwarden-certificate-issuer
  namespace: external-secrets
spec:
  ca:
    secretName: bitwarden-ca-certs
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: bitwarden-tls-certs
  namespace: external-secrets
spec:
  secretName: bitwarden-tls-certs
  dnsNames:
    - bitwarden-sdk-server.external-secrets.svc.cluster.local
    - external-secrets-bitwarden-sdk-server.external-secrets.svc.cluster.local
    - localhost
  issuerRef:
    name: bitwarden-certificate-issuer
    kind: Issuer
EOF

ESO must be installed with Bitwarden SDK support enabled, which deploys the internal service used to communicate with the Bitwarden API.

helm repo add external-secrets https://charts.external-secrets.io 

helm install external-secrets external-secrets/external-secrets \
  --namespace external-secrets \
  --set installCRDs=true \
  --set "bitwarden-sdk-server.enabled=true"

Generate a Machine Account Access Token in the Bitwarden portal. This token provides read-only access to the project containing your secrets.

Store the token as a Kubernetes Secret:

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
  name: bitwarden-access-token
  namespace: external-secrets
type: Opaque
stringData:
  token: <YOUR_BITWARDEN_ACCESS_TOKEN>
EOF

Note: The token can also be granted write access if you plan to use ESO’s PushSecret API to create secrets in Bitwarden.

A ClusterSecretStore allows all namespaces to reference a single global backend without duplicating authentication configuration.

cat <<EOF | kubectl apply -f -
apiVersion: external-secrets.io/v1
kind: ClusterSecretStore
metadata:
  name: bitwarden-global-store
spec:
  provider:
    bitwardensecretsmanager:
      apiURL: https://vault.bitwarden.eu./api
      identityURL: https://vault.bitwarden.eu./identity
      auth:
        secretRef:
          credentials:
            key: token
            name: bitwarden-access-token
            namespace: external-secrets
      bitwardenServerSDKURL: https://bitwarden-sdk-server.external-secrets.svc.cluster.local:9998
      caProvider:
        type: Secret
        name: bitwarden-ca-certs
        key: ca.crt
        namespace: external-secrets
      organizationID: <YOUR_ORGANIZATION_ID>
      projectID: <YOUR_PROJECT_ID>
EOF

The ExternalSecret resource defines how secrets are fetched and materialized as Kubernetes Secrets.

cat <<EOF | kubectl apply -f -
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: app-payment-creds
  namespace: app-backend
spec:
  refreshInterval: 15m
  secretStoreRef:
    name: bitwarden-global-store
    kind: ClusterSecretStore
  target:
    name: payment-creds
    creationPolicy: Owner
  data:
  - secretKey: api_key
    remoteRef:
      key: "<YOUR_NAME_OR_ID_SECRET_HERE"
EOF

This approach fully decouples secret lifecycle management from infrastructure provisioning.

When a new environment is created-whether in an existing account or a brand-new one-the only requirement is installing ESO and referencing the existing ClusterSecretStore. Secrets are fetched automatically.

When a secret is rotated, it’s updated once in Bitwarden and propagated to all clusters within minutes.

Whether managing two clusters or two hundred, the outcome is the same: fewer deployment bottlenecks, fewer human errors, and a significantly cleaner operational model. With ESO acting as a universal bridge, secret management becomes invisible infrastructure-secure, centralized, and automatic.

Read more of our blog post here.

More Posts

The ITGix AWS Landing Zone continues to evolve with a clear goal: enabling organizations to build secure, compliant, and scalable AWS environments with less operational overhead. Across recent releases (v1.2.0...
Reading
In earlier articles, we covered migrating repositories from Bitbucket Cloud, securely updating project dependencies, and modernizing CI/CD workflows by translating Jenkins and Bash-based pipelines to GitHub Actions. With those foundations...
Reading
Get In Touch
ITGix provides you with expert consultancy and tailored DevOps services to accelerate your business growth.
Newsletter for
Tech Experts
Join 12,000+ business leaders and engineers who receive blogs, e-Books, and case studies on emerging technology.