Kube Secrets Operator: Secrets Beheren in GitOps Omgevingen

kubernetes gitops secrets fluxcd
2025-11-06
Thomas Kooi

Het Secrets Management Probleem in GitOps

Werken met secrets in Kubernetes is altijd een uitdaging, maar in GitOps workflows wordt dit nog complexer. GitOps methodologieën zoals FluxCD vereisen dat alles version-controlled is en declaratief gedefinieerd wordt - maar hoe beheer je dan secrets zonder ze in plain text in Git te committen?

Over het algemeen heb je een paar opties:

  • SealedSecrets: Werkt, maar vereist handmatige encryptie per secret via kubeseal. Niet ideaal voor dynamische of gegenereerde secrets. Elke wijziging betekent handmatige re-encryptie.
  • SOPS (Secrets OPerationS): Handmatige encryptie/decryptie via CLI tools, vereist key management setup en proces overhead in CI/CD pipelines.
  • External Secrets Operator / Enterprise KMS oplossingen (Vault, AWS Secrets Manager): Krachtig en geschikt voor compliance of enterprise omgevingen, maar vereisen setup van externe secret stores (zoals AWS Secrets Manager of HashiCorp Vault), wat vaak complexe configuratie, cloud provider dependencies, en process overhead introduceert. Dit maakt ze in veel gevallen overkill voor kleinere of tijdelijke omgevingen (zoals testen/CI-workflows).

De meeste van deze alternatieven vereisen significant handmatig werk: per-secret encryptie, key management setup, of complexe configuratie. Voor dynamische secrets die regelmatig gegenereerd moeten worden, wordt dit snel onpraktisch.

Voor veel teams is er behoefte aan iets daartussenin: een oplossing die GitOps-friendly is, automatisch secrets kan genereren, en niet de volledige complexiteit van een enterprise secret management systeem vereist.

Kube Secrets Operator: Een Pragmatische Middle Ground

De Kube Secrets Operator is een Kubernetes operator die we ontwikkeld hebben om precies dit probleem op te lossen. Het is ontworpen voor GitOps workflows zoals FluxCD en biedt een manier om secrets te genereren en beheren via Kubernetes custom resources.

Waarom Deze Oplossing?

De operator zit precies in het sweet spot tussen handmatige encryptie en enterprise secret management:

  • GitOps-native: Alles is een Kubernetes resource die je kunt committen in Git
  • Geen handmatige encryptie: Secrets worden automatisch gegenereerd en bijgewerkt
  • Reusable resources: Perfect voor FluxCD waar je herbruikbare Kubernetes resources nodig hebt
  • Lightweight: Geen complexe infrastructuur of process overhead zoals bij Vault

Dit maakt het uitstekend geschikt voor testing omgevingen, CI/CD pipelines en tijdelijke setups waar je niet meteen een volledig KMS systeem wilt opzetten.

Praktische Voorbeelden

Automatisch Gegenereerde Passwords / Values

Het meest simpele use case: een secret met een automatisch gegenereerd password.

apiVersion: apps.k8s.containerinfra.com/v1
kind: GeneratedSecret
metadata:
  name: basic-password
  namespace: default
spec:
  secretType: Opaque
  deletionPolicy: Delete
  metadata:
    name: basic-app-secret
    namespaces: 
      - default
    labels:
      app: my-app
  template:
    data:
      password:
        generated:
          length: 16
          maxDigits: 4
          maxSymbols: 2
          noUpperCaseValues: false
          noRepeatedValues: true
      username:
        value: admin

De operator genereert automatisch een secure password en combineert dit met statische values zoals de username. Perfect voor applicaties waar je een database connection nodig hebt maar niet handmatig passwords wilt beheren.

Je kan het gegenereerde secret dan gebruiken bij initial boot van de database, waarbij de user & password gezet worden, en vervolgens door de applicatie om hier mee te verbinden.

Templated Secrets

Het meest interessante voorbeeld: secrets die referenties maken naar andere secrets via templates.

apiVersion: apps.k8s.containerinfra.com/v1
kind: GeneratedSecret
metadata:
  name: generated-config
  namespace: default
spec:
  secretType: Opaque
  metadata:
    name: generated-config
    namespaces:
      - default
  template:
    data:
      connection_string:
        templated:
          template: |
            test: {{.Ref.api_endpoint}}/{{.Ref.api_version}}/{{.Ref.environment}}
          inputSecretRef:
            name: app-config
            namespace: default

Dit laat zien hoe de operator complexere use cases kan oplossen: je kunt secrets genereren die dynamisch refereren naar andere secrets. Handig voor connection strings, URLs of andere samengestelde configuraties.

Veel 3rd party applicaties hebben config files nodig waarin één of meerdere secrets staan. Denk aan object storage access keys/secrets, database passwords, API keys, etc. Dit is een perfecte use case voor de operator omdat je een config file kunt genereren die meerdere secrets combineert.

apiVersion: apps.k8s.containerinfra.com/v1
kind: GeneratedSecret
metadata:
  name: application-config
  namespace: default
spec:
  secretType: Opaque
  metadata:
    name: app-config-file
    namespaces:
      - default
  template:
    data:
      config.yaml:
        templated:
          template: |
            storage:
              endpoint: https://storage.example.com
              access_key: {{.Ref.storage_access_key}}
              secret_key: {{.Ref.storage_secret_key}}
            database:
              host: {{.Ref.db_host}}
              port: {{.Ref.db_port}}
              username: {{.Ref.db_username}}
              password: {{.Ref.db_password}}
            api:
              key: {{.Ref.api_key}}
          inputSecretRef:
            name: app-secrets
            namespace: default

In dit voorbeeld wordt een config.yaml file gegenereerd die meerdere secrets combineert: object storage credentials, database connection details en een API key. De 3rd party applicatie kan deze config file als volume mount gebruiken, zonder dat je handmatig config files hoeft te genereren of te encrypten.

Dit is vooral waardevol omdat:

  • Geen handmatige config file generatie: De operator genereert automatisch de config file met alle secrets
  • Multiple secrets in één file: Je combineert verschillende secrets (storage, database, API) in één bestand
  • Template support: Je kunt de config file structuur volledig customizen via templates
  • GitOps friendly: Alles wordt als Kubernetes resource beheerd zonder handmatige encryptie

Zonder de operator zou je dit handmatig moeten doen: secrets encrypten met SealedSecrets of SOPS, en dan config files genereren die de secrets bevatten - wat snel onpraktisch wordt bij regelmatige wijzigingen.

Deployment via FluxCD

De operator is volledig GitOps-native en deploy je via FluxCD met HelmReleases:

---
apiVersion: source.toolkit.fluxcd.io/v1
kind: OCIRepository
metadata:
  name: kube-secrets-operator
  namespace: kube-system
spec:
  interval: 160m
  url: oci://ghcr.io/containerinfra/charts/kube-secrets-operator
  ref:
    semver: ">= 0.0.0"
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
  name: kube-secrets-operator
  namespace: kube-system
spec:
  chartRef:
    kind: OCIRepository
    name: kube-secrets-operator
    namespace: kube-system
  interval: 1h
  install:
    crds: Skip
  values:
    replicaCount: 1

Wanneer Gebruik Je Kube Secrets Operator?

De operator is niet bedoeld als vervanging voor enterprise secret management in productie omgevingen waar je zeer hoge security eisen hebt. In plaats daarvan is het ideaal voor:

  • Testing & Development: Snel secrets genereren zonder complexe KMS setup
  • CI/CD Pipelines: Geautomatiseerde secret generatie voor deployments
  • Tijdelijke Omgevingen: Staging, demo of temporary clusters
  • GitOps Workflows: Teams die alles declaratief willen via FluxCD
  • Lightweight Secret Management: Omgevingen waar Vault te complex is maar SealedSecrets te handmatig
  • Config Files voor 3rd Party Applicaties: Applicaties die config files nodig hebben met meerdere secrets erin (object storage credentials, database passwords, API keys, etc.)

Open Source

De Kube Secrets Operator is volledig open source en beschikbaar op GitHub. We moedigen feedback en contributions aan van de community.


5 min read
Share this post:

Related posts