Kubernetes Secrets Operator

Kubernetes Secrets Operator on Thalassa Cloud Kubernetes

Kubernetes Secrets Operator is a Kubernetes operator developed by ContainerInfra, designed to assist in generating secrets for Kubernetes environments, particularly those driven by GitOps methodologies. By deploying Kubernetes Secrets Operator in your Thalassa Cloud Kubernetes cluster, you can automatically generate and manage secrets without manual intervention, making it ideal for GitOps workflows with tools like FluxCD.

This guide walks you through deploying Kubernetes Secrets Operator using FluxCD, configuring it to generate secrets automatically, and using it in your GitOps workflows.

About the Kubernetes Secrets Operator

Kubernetes Secrets Operator provides a middle ground for teams that consider a full Key Management System (KMS) and Secret Management setup to be overly complicated or expensive. It acts as a solution between SealedSecrets (which requires manual work) and cloud-based KMS services (which add process overhead), such as Vault.

The operator works by watching for GeneratedSecret custom resources in your cluster. When you create a GeneratedSecret resource, the operator automatically generates the specified secrets and creates Kubernetes Secret resources based on your configuration. This makes it well-suited for testing purposes, CI/CD operations, and temporary setups.

The operator supports several secret generation methods:

  • Generated values: Automatically generate passwords, tokens, or other random values with configurable requirements
  • Static values: Use predefined values for secrets
  • Templated values: Create secrets that reference other secrets using templates

For GitOps workflows, you can commit GeneratedSecret resources to your Git repository, and the operator will automatically create the corresponding Kubernetes Secrets when the resources are applied to your cluster.

Prerequisites

Before deploying Kubernetes Secrets Operator, ensure you have a few things in place.

  1. First, you need a running Kubernetes cluster in Thalassa Cloud. If you’re new to Thalassa Cloud Kubernetes, see the Getting Started guide for cluster creation and basic setup.

  2. You’ll also need cluster access configured using kubectl. Use tcloud kubernetes connect to configure access, or set up kubeconfig manually. You’ll need cluster administrator permissions to install the operator and create custom resources.

  3. FluxCD must be installed in your cluster. If you haven’t installed it yet, follow the Installing FluxCD guide to set it up. This guide assumes you have FluxCD installed and configured with access to a Git repository where you’ll store your configuration.

  4. Finally, ensure your cluster has sufficient resources. The operator is lightweight, but it needs CPU and memory to run. Most clusters have adequate resources, but verify your nodes have capacity for additional workloads.

Installing Kubernetes Secrets Operator

The recommended way to install Kubernetes Secrets Operator is using FluxCD with Helm charts. The operator consists of two components: CRDs (Custom Resource Definitions) and the operator itself.

Step 1: Install CRDs

First, create an OCIRepository resource for the CRDs:

apiVersion: source.toolkit.fluxcd.io/v1
kind: OCIRepository
metadata:
  name: kube-secrets-operator-crds
  namespace: kube-system
spec:
  interval: 160m
  url: oci://ghcr.io/containerinfra/charts/kube-secrets-operator-crds
  ref:
    semver: ">= 0.0.0"

Apply the OCIRepository:

kubectl apply -f oci-repository-crds.yaml

Or commit it to your Git repository if you’re using FluxCD with Git.

Create a HelmRelease for the CRDs:

apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
  name: kube-secrets-operator-crds
  namespace: kube-system
spec:
  chartRef:
    kind: OCIRepository
    name: kube-secrets-operator-crds
    namespace: kube-system
  interval: 1h
  values: {}

Apply the HelmRelease:

kubectl apply -f helm-release-crds.yaml

Wait for the CRDs to be installed:

kubectl get crd | grep generatedsecret

You should see the generatedsecrets.apps.k8s.containerinfra.com CRD.

Step 2: Install the Operator

Create an OCIRepository resource for the operator:

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"

Apply the OCIRepository:

kubectl apply -f oci-repository-operator.yaml

Create a HelmRelease for the operator:

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:
    enableServiceMonitor: false
    replicaCount: 1
    affinity:
      nodeAffinity:
        preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 1
            preference:
              matchExpressions:
                - key: node-role.kubernetes.io/control-plane
                  operator: Exists
    nodeSelector:
      kubernetes.io/os: linux
    tolerations:
      - key: node-role.kubernetes.io/control-plane
        effect: NoSchedule

The install.crds: Skip setting tells Helm to skip installing CRDs since we installed them separately in Step 1.

Apply the HelmRelease:

kubectl apply -f helm-release-operator.yaml

Step 3: Verify Installation

Verify that the operator is running:

kubectl get pods -n kube-system | grep kube-secrets-operator

You should see the operator pod running. Check the logs if needed:

kubectl logs -n kube-system -l app.kubernetes.io/name=kube-secrets-operator

Verify that the CRD is available:

kubectl get crd generatedsecrets.apps.k8s.containerinfra.com

Generating Secrets

Once the operator is installed, you can create GeneratedSecret resources to automatically generate Kubernetes Secrets. The operator supports several types of secret generation.

Example 1: Simple Generated Password

Create a GeneratedSecret that automatically generates a 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

This example creates a secret named basic-app-secret in the default namespace with:

  • A generated password (16 characters, with up to 4 digits and 2 symbols)
  • A static username value of “admin”

Apply the resource:

kubectl apply -f basic-password.yaml

The operator will automatically create the Kubernetes Secret. Verify it was created:

kubectl get secret basic-app-secret -n default

View the secret (the password will be base64 encoded):

kubectl get secret basic-app-secret -n default -o yaml

Password Generation Options

The generated section supports various options:

  • length: Total length of the generated password
  • maxDigits: Maximum number of digits
  • maxSymbols: Maximum number of symbols
  • noUpperCaseValues: Set to true to exclude uppercase letters
  • noRepeatedValues: Set to true to prevent repeated characters

Example 2: Static Values Only

Create a GeneratedSecret with only static values:

apiVersion: apps.k8s.containerinfra.com/v1
kind: GeneratedSecret
metadata:
  name: static-config
  namespace: default
spec:
  secretType: Opaque
  metadata:
    name: app-config
    namespaces:
      - default
  template:
    data:
      api_endpoint:
        value: https://api.example.com
      api_version:
        value: v1
      environment:
        value: production

This creates a secret with static configuration values. While you could create this secret manually, using GeneratedSecret allows you to manage it declaratively in GitOps workflows.

Apply the resource:

kubectl apply -f static-config.yaml

Verify the secret was created:

kubectl get secret app-config -n default

Example 3: Templated Secrets

Create a GeneratedSecret that uses templates to reference other secrets:

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

This example creates a secret that references values from the app-config secret created in Example 2. The template uses Go template syntax to construct a connection string from the referenced secret values.

Template Syntax

Templates use Go template syntax. Use {{.Ref.key_name}} to reference values from the input secret. The referenced secret must exist before the templated secret can be created.

Apply the resource:

kubectl apply -f generated-config.yaml

Verify the secret was created:

kubectl get secret generated-config -n default

Using Secrets in Applications

Once secrets are generated, you can use them in your applications just like any other Kubernetes Secret. Reference them in your Deployments, StatefulSets, or other resources:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: default
spec:
  template:
    spec:
      containers:
      - name: app
        image: my-app:latest
        env:
        - name: PASSWORD
          valueFrom:
            secretKeyRef:
              name: basic-app-secret
              key: password
        - name: USERNAME
          valueFrom:
            secretKeyRef:
              name: basic-app-secret
              key: username

Or mount them as volumes:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: default
spec:
  template:
    spec:
      containers:
      - name: app
        image: my-app:latest
        volumeMounts:
        - name: config
          mountPath: /etc/config
          readOnly: true
      volumes:
      - name: config
        secret:
          secretName: app-config

Managing Secrets in GitOps

For GitOps workflows, commit your GeneratedSecret resources to your Git repository. FluxCD will automatically apply them to your cluster, and the operator will generate the corresponding secrets. This provides several benefits: all secret configurations are version-controlled in Git, changes are auditable through Git history, secrets are automatically generated when resources are applied, and you maintain consistent secret configurations across environments.

Secret Values in Git

The GeneratedSecret resources contain secret generation instructions, not the actual secret values. The generated secret values are stored only in Kubernetes Secrets, not in Git. This makes it safe to commit GeneratedSecret resources to Git.

Best Practices

Following best practices helps you use Kubernetes Secrets Operator effectively and maintain secure secret management.

  • Use namespaces to organize secrets and control access.
  • Add labels under metadata.labels to help identify and manage secrets.
  • Use templated secrets to combine or reference multiple secret values.
  • Keep GeneratedSecret resources in Git for tracking changes, but never commit the actual secret values.

Summary

Kubernetes Secrets Operator lets you easily generate and manage secrets in Kubernetes without manual steps. Just deploy the operator and create GeneratedSecret resources to have your secrets created automatically. You can use it to generate passwords, set fixed values, or combine values from other secrets with templating, making it useful for both simple and advanced needs.

For more information about Kubernetes Secrets Operator features and advanced configurations, see the official repository.