Packaging & Config

Sealed Secrets

Contrôleur Kubernetes Bitnami pour secrets chiffrés dans Git - CLI kubeseal, chiffrement RSA+AES, scopes strict/namespace-wide/cluster-wide. Apache 2.0.

Sealed Secrets permet de stocker des secrets Kubernetes chiffrés directement dans Git, pour des workflows GitOps 100% déclaratifs. Le contrôleur déployé dans le cluster détient la clé privée RSA. L'outil CLI kubeseal chiffre les secrets avec la clé publique exposée par le contrôleur - le résultat (SealedSecret) est safe à committer dans Git. Seul le contrôleur du cluster concerné peut déchiffrer. La CRD SealedSecret est réconciliée automatiquement en Secret Kubernetes natif.


Informations essentielles

Origine : Bitnami (VMware/Broadcom)  ·  Licence : Apache 2.0  ·  Architectures : x86_64, ARM64

Liens : Documentation  ·  GitHub  ·  Releases

Support : Maintenu activement par Bitnami/Broadcom. Projet mature et stable.

Stack par défaut

ComposantValeur
ContrôleurDéployé dans kube-system
CLIkubeseal
CRDSealedSecret (apiVersion bitnami.com/v1alpha1)
ChiffrementRSA-4096 (clé publique/privée) + AES-256-GCM (données)
Clé privéeStockée en Secret dans kube-system, jamais exposée
RotationAutomatique des clés (30 jours par défaut, configurable)

Prérequis

RessourceValeur
Kubernetes1.16+
kubectlConfiguré avec accès cluster

Installation

Contrôleur via Helm

helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets
helm repo update

helm install sealed-secrets sealed-secrets/sealed-secrets \
  --namespace kube-system

# Vérifier
kubectl get pods -n kube-system -l app.kubernetes.io/name=sealed-secrets

Contrôleur via kubectl

kubectl apply -f \
  https://github.com/bitnami-labs/sealed-secrets/releases/latest/download/controller.yaml

CLI kubeseal

# Homebrew (macOS/Linux)
brew install kubeseal

# Binaire Linux (version dynamique)
KUBESEAL_VERSION=$(curl -s "https://api.github.com/repos/bitnami-labs/sealed-secrets/releases/latest" \
  | grep '"tag_name"' | sed 's/.*"v\([^"]*\)".*/\1/')
curl -Lo kubeseal.tar.gz \
  "https://github.com/bitnami-labs/sealed-secrets/releases/download/v${KUBESEAL_VERSION}/kubeseal-${KUBESEAL_VERSION}-linux-amd64.tar.gz"
tar -xzf kubeseal.tar.gz kubeseal
sudo install -m 755 kubeseal /usr/local/bin/

kubeseal --version

Sceller un secret

# 1. Créer le Secret K8s standard (sans l'appliquer)
kubectl create secret generic my-db-secret \
  --from-literal=username=admin \
  --from-literal=password=SuperSecret123 \
  --namespace production \
  --dry-run=client -o yaml > secret.yaml

# 2. Chiffrer avec kubeseal
kubeseal \
  --controller-name=sealed-secrets \
  --controller-namespace=kube-system \
  -f secret.yaml \
  -w sealed-secret.yaml

# 3. Supprimer le fichier non chiffré
rm secret.yaml

# 4. Committer sealed-secret.yaml dans Git et l'appliquer
kubectl apply -f sealed-secret.yaml

Le SealedSecret résultant

apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  name: my-db-secret
  namespace: production
spec:
  encryptedData:
    password: AgBy3i4OJSWK+PiTySYZZA9rO43cGDEQAx...    # Chiffré, safe dans Git
    username: AgBy3i4OJSWK+PiTySYZZA9rO43cGDEQAx...
  template:
    metadata:
      name: my-db-secret
      namespace: production

Scopes de chiffrement

Par défaut, un SealedSecret est lié à un namespace ET un nom spécifique (strict). Ce comportement est configurable :

# strict (défaut) : lié au namespace + nom exact
kubeseal --scope strict -f secret.yaml -w sealed.yaml

# namespace-wide : utilisable pour tout secret dans ce namespace
kubeseal --scope namespace-wide -f secret.yaml -w sealed.yaml

# cluster-wide : utilisable dans tout le cluster pour tout nom
kubeseal --scope cluster-wide -f secret.yaml -w sealed.yaml

Utilisation sans connexion cluster (CI/CD)

Dans un pipeline CI, le cluster n'est pas toujours accessible. On peut chiffrer hors-ligne avec la clé publique :

# Récupérer la clé publique une fois et la stocker dans le repo
kubeseal --fetch-cert \
  --controller-name=sealed-secrets \
  --controller-namespace=kube-system > public-cert.pem

# Chiffrer hors-ligne (pas besoin d'accès cluster)
kubeseal --cert public-cert.pem -f secret.yaml -w sealed.yaml

# Chiffrer une valeur brute (pour injection dans un YAML existant)
echo -n "SuperSecret123" | kubeseal --raw \
  --name my-db-secret \
  --namespace production \
  --cert public-cert.pem \
  --scope strict

Rotation des clés

Le contrôleur génère automatiquement une nouvelle clé de chiffrement tous les 30 jours (configurable). Les anciennes clés sont conservées pour déchiffrer les anciens SealedSecrets.

# Lister les clés disponibles
kubectl get secrets -n kube-system \
  -l sealedsecrets.bitnami.com/sealed-secrets-key

# Forcer la génération d'une nouvelle clé maintenant
kubectl annotate secret sealed-secrets-key \
  -n kube-system \
  sealedsecrets.bitnami.com/sealed-secrets-key=active

# Exporter les clés (backup critique - à stocker de façon sécurisée)
kubectl get secrets -n kube-system \
  -l sealedsecrets.bitnami.com/sealed-secrets-key \
  -o yaml > sealed-secrets-keys-backup.yaml

Mise à jour

helm repo update
helm upgrade sealed-secrets sealed-secrets/sealed-secrets \
  --namespace kube-system \
  --reuse-values

Troubleshooting

# Logs du contrôleur
kubectl logs -n kube-system \
  -l app.kubernetes.io/name=sealed-secrets --tail=50

# SealedSecret en erreur : vérifier les events
kubectl describe sealedsecret my-db-secret -n production

# Erreur "no key could decrypt secret" : le SealedSecret a été chiffré
# avec une clé d'un autre cluster. Recréer avec la clé du bon cluster.

# Vérifier que le Secret K8s a bien été créé
kubectl get secret my-db-secret -n production

# Vérifier l'état de tous les SealedSecrets
kubectl get sealedsecrets -A

Ressources

Newsletter · 2 000+ abonnés

Reste au courant de ce qui bouge en prod

RudeOps veille devops hebdo, droit au but.

Gratuit · Sans spam · Désinscription en un clic