OpenMCF logoOpenMCF

Loading...

Kubernetes External Secrets

Deploys the External Secrets Operator (ESO) onto any Kubernetes cluster using its official Helm chart. ESO synchronizes secrets from cloud provider secret stores (Google Cloud Secret Manager, AWS Secrets Manager, Azure Key Vault) into native Kubernetes Secrets, keeping application pods decoupled from provider-specific APIs. The module creates a dedicated ServiceAccount wired to the correct cloud identity mechanism (GKE Workload Identity, EKS IRSA, or AKS Managed Identity), installs CRDs, and configures RBAC automatically.

What Gets Created

When you deploy a KubernetesExternalSecrets resource, OpenMCF provisions:

  • Kubernetes Namespace — created if createNamespace is true
  • ServiceAccount — a Kubernetes ServiceAccount annotated with the appropriate cloud identity binding (iam.gke.io/gcp-service-account for GKE, eks.amazonaws.com/role-arn for EKS, or azure.workload.identity/client-id for AKS)
  • External Secrets Helm Release — the external-secrets chart (v0.9.20) from https://charts.external-secrets.io, which creates:
    • The ESO controller Deployment that watches ExternalSecret custom resources
    • Custom Resource Definitions (ExternalSecret, SecretStore, ClusterSecretStore, and others)
    • ClusterRole and ClusterRoleBinding for RBAC
    • Webhook components for validation and conversion

Prerequisites

  • A Kubernetes cluster with kubectl configured for access
  • A cloud secret store with secrets you want to synchronize (Google Cloud Secret Manager, AWS Secrets Manager, or Azure Key Vault)
  • Cloud identity binding already configured:
    • GKE: A Google Service Account with roles/secretmanager.secretAccessor and Workload Identity binding to the Kubernetes ServiceAccount
    • EKS: An IAM role with secretsmanager:GetSecretValue permission and an IRSA trust policy
    • AKS: A User-Assigned Managed Identity with Key Vault Secrets User role on the target Key Vault

Quick Start

Create a file external-secrets.yaml:

apiVersion: kubernetes.openmcf.org/v1
kind: KubernetesExternalSecrets
metadata:
  name: eso
  labels:
    openmcf.org/provisioner: pulumi
    pulumi.openmcf.org/organization: my-org
    pulumi.openmcf.org/project: my-project
    pulumi.openmcf.org/stack.name: dev.KubernetesExternalSecrets.eso
spec:
  namespace:
    value: external-secrets
  createNamespace: true
  container:
    resources:
      requests:
        cpu: "50m"
        memory: "100Mi"
      limits:
        cpu: "1000m"
        memory: "1Gi"
  gke:
    projectId:
      value: my-gcp-project
    gsaEmail: eso-sa@my-gcp-project.iam.gserviceaccount.com

Deploy:

openmcf apply -f external-secrets.yaml

This installs the External Secrets Operator into the external-secrets namespace with GKE Workload Identity configured. The controller begins polling Google Cloud Secret Manager every 10 seconds by default.

Configuration Reference

Required Fields

FieldTypeDescriptionValidation
namespaceStringValueOrRefKubernetes namespace for the ESO deployment. Use value for a literal string or valueFrom to reference a KubernetesNamespace resource.Required
containerobjectContainer resource configuration for the ESO controller.Required

Optional Fields

FieldTypeDefaultDescription
createNamespaceboolfalseCreate the namespace if it does not exist.
pollIntervalSecondsuint3210How often the controller polls the backing secret store, in seconds. Must be greater than 0. Very small values can incur high cloud API costs.
container.resources.requests.cpustring"50m"CPU request for the ESO controller container.
container.resources.requests.memorystring"100Mi"Memory request for the ESO controller container.
container.resources.limits.cpustring"1000m"CPU limit for the ESO controller container.
container.resources.limits.memorystring"1Gi"Memory limit for the ESO controller container.

Provider Configuration — exactly one of the following blocks must be set:

FieldTypeDescription
gke.projectIdStringValueOrRefGCP project hosting the secrets and the GKE cluster. Use value for a literal string or valueFrom to reference a GcpProject resource. Required when using gke.
gke.gsaEmailstringGoogle Service Account email used via Workload Identity. Required when using gke.
eks.regionstringAWS region containing the secret store. Defaults to the cluster region if empty.
eks.irsaRoleArnOverridestringExisting IAM role ARN for IRSA. If left blank, one is auto-created.
aks.keyVaultResourceIdstringAzure Key Vault resource ID that stores the secrets.
aks.managedIdentityClientIdstringClient ID of an existing User-Assigned Managed Identity to bind to ESO.

Note on StringValueOrRef fields: Fields typed as StringValueOrRef accept either a direct value string or a valueFrom block that references the output of another OpenMCF resource.

Examples

GKE with Google Cloud Secret Manager

Deploy ESO on a GKE cluster with Workload Identity for Google Cloud Secret Manager access:

apiVersion: kubernetes.openmcf.org/v1
kind: KubernetesExternalSecrets
metadata:
  name: eso-gke
  labels:
    openmcf.org/provisioner: pulumi
    pulumi.openmcf.org/organization: my-org
    pulumi.openmcf.org/project: my-project
    pulumi.openmcf.org/stack.name: dev.KubernetesExternalSecrets.eso-gke
spec:
  namespace:
    value: external-secrets
  createNamespace: true
  pollIntervalSeconds: 30
  container:
    resources:
      requests:
        cpu: "100m"
        memory: "128Mi"
      limits:
        cpu: "500m"
        memory: "512Mi"
  gke:
    projectId:
      value: my-gcp-project
    gsaEmail: eso-secrets@my-gcp-project.iam.gserviceaccount.com

EKS with AWS Secrets Manager

Deploy ESO on an EKS cluster with IRSA for AWS Secrets Manager access. The irsaRoleArnOverride field lets you point to a pre-existing IAM role:

apiVersion: kubernetes.openmcf.org/v1
kind: KubernetesExternalSecrets
metadata:
  name: eso-eks
  labels:
    openmcf.org/provisioner: pulumi
    pulumi.openmcf.org/organization: my-org
    pulumi.openmcf.org/project: my-project
    pulumi.openmcf.org/stack.name: staging.KubernetesExternalSecrets.eso-eks
spec:
  namespace:
    value: external-secrets
  createNamespace: true
  pollIntervalSeconds: 15
  container:
    resources:
      requests:
        cpu: "100m"
        memory: "128Mi"
      limits:
        cpu: "1000m"
        memory: "1Gi"
  eks:
    region: us-east-1
    irsaRoleArnOverride: arn:aws:iam::123456789012:role/eso-secrets-role

AKS with Azure Key Vault

Deploy ESO on an AKS cluster with Azure Workload Identity for Key Vault secret synchronization. Increase resource limits for a production workload with many ExternalSecret objects:

apiVersion: kubernetes.openmcf.org/v1
kind: KubernetesExternalSecrets
metadata:
  name: eso-aks
  labels:
    openmcf.org/provisioner: pulumi
    pulumi.openmcf.org/organization: my-org
    pulumi.openmcf.org/project: my-project
    pulumi.openmcf.org/stack.name: prod.KubernetesExternalSecrets.eso-aks
spec:
  namespace:
    value: external-secrets
  createNamespace: true
  pollIntervalSeconds: 60
  container:
    resources:
      requests:
        cpu: "250m"
        memory: "256Mi"
      limits:
        cpu: "2000m"
        memory: "2Gi"
  aks:
    keyVaultResourceId: /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/my-rg/providers/Microsoft.KeyVault/vaults/my-keyvault
    managedIdentityClientId: 11111111-1111-1111-1111-111111111111

Referencing a KubernetesNamespace via valueFrom

Use valueFrom on the namespace field to reference a namespace managed by a separate KubernetesNamespace resource instead of hard-coding the name:

apiVersion: kubernetes.openmcf.org/v1
kind: KubernetesExternalSecrets
metadata:
  name: eso-ref
  labels:
    openmcf.org/provisioner: pulumi
    pulumi.openmcf.org/organization: my-org
    pulumi.openmcf.org/project: my-project
    pulumi.openmcf.org/stack.name: dev.KubernetesExternalSecrets.eso-ref
spec:
  namespace:
    valueFrom:
      kind: KubernetesNamespace
      metadata:
        name: secrets-ns
      fieldPath: spec.name
  container:
    resources:
      requests:
        cpu: "50m"
        memory: "100Mi"
      limits:
        cpu: "1000m"
        memory: "1Gi"
  gke:
    projectId:
      valueFrom:
        kind: GcpProject
        metadata:
          name: my-project
        fieldPath: status.outputs.project_id
    gsaEmail: eso-sa@my-gcp-project.iam.gserviceaccount.com

Stack Outputs

After deployment, the following outputs are available in status.outputs:

OutputTypeDescription
namespacestringKubernetes namespace where the External Secrets Operator is deployed
servicestringName of the Kubernetes Service for the ESO controller
portForwardCommandstringReady-to-run kubectl port-forward command for local access to the operator
kubeEndpointstringCluster-internal endpoint for the ESO service (e.g., eso.external-secrets.svc.cluster.local)
ingressEndpointstringPublic endpoint when ingress is configured

Related Components

  • KubernetesNamespace — pre-create a namespace to reference via valueFrom
  • KubernetesSecret — manage Kubernetes Secrets directly when external secret stores are not needed
  • KubernetesHelmRelease — deploy arbitrary Helm charts if you need to customize the ESO installation beyond what this component offers

Next article

Kubernetes Gateway API CRDs

Kubernetes Gateway API CRDs Installs the Kubernetes Gateway API Custom Resource Definitions (CRDs) on a target Kubernetes cluster. The Gateway API is the next-generation, role-oriented API for managing ingress and service mesh traffic, replacing the legacy Ingress resource with richer routing primitives such as Gateway, HTTPRoute, GRPCRoute, and ReferenceGrant. This component fetches the official CRD manifests from the upstream kubernetes-sigs/gateway-api releases and applies them directly to...
Read next article
Presets
3 ready-to-deploy configurationsView presets →