Secrets management w Kubernetes — Sealed Secrets vs External Secrets Operator

Jak bezpiecznie trzymać sekrety w repozytorium GitOps? Porównuję dwa podejścia: Sealed Secrets (szyfrowanie w repo) i External Secrets Operator (sekrety w zewnętrznym vault).

Problem: sekrety w GitOps

GitOps zakłada, że wszystko jest w repozytorium Git. Ale sekrety (hasła do baz, klucze API) nie mogą być w repo jako plain text.

Naiwne rozwiązanie — placeholder w repo, ręczny kubectl apply dla sekretów — psuje GitOps: ArgoCD nie zarządza sekretami, trzeba pamiętać o ręcznym tworzeniu.

Opcja 1: Sealed Secrets

Sealed Secrets to operator K8s, który umożliwia zaszyfrowanie sekretu kluczem publicznym klastra. Zaszyfrowany sekret (SealedSecret) można bezpiecznie commitować do repo.

# Instalacja
helm install sealed-secrets sealed-secrets/sealed-secrets -n kube-system

# Szyfrowanie sekretu
kubectl create secret generic db-password 
  --from-literal=password=supersecret 
  --dry-run=client -o yaml | 
  kubeseal --format yaml > k8s/sealed-db-password.yaml

Wynikowy SealedSecret jest bezużyteczny bez klucza prywatnego klastra:

apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  name: db-password
spec:
  encryptedData:
    password: AgBY3mT....(długi zaszyfrowany ciąg)....

Zalety: proste, działa offline, sekrety w repo razem z manifestami Wady: rotacja kluczy klastra wymaga re-szyfrowania wszystkich sekretów, trudniejsze audytowanie

Opcja 2: External Secrets Operator (ESO)

ESO synchronizuje sekrety z zewnętrznego vault (AWS Secrets Manager, HashiCorp Vault, GCP Secret Manager) do Kubernetes Secrets.

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: db-credentials
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault-store
    kind: ClusterSecretStore
  target:
    name: db-credentials
  data:
    - secretKey: password
      remoteRef:
        key: portfolio/db
        property: password

Zalety: centralne zarządzanie sekretami, audyt dostępu, rotacja bez zmian w K8s Wady: zewnętrzna zależność, więcej do konfigurowania

Co wybrałem?

Na środowisku deweloperskim (Minikube) używam plain kubectl create secret — bez GitOps dla sekretów.

Na produkcji planuję Sealed Secrets — prostsze i samodzielne, bez potrzeby zewnętrznego vault. Jeśli projekt wyrośnie i trafi do chmury, migracja do ESO + AWS Secrets Manager będzie naturalnym krokiem.

Secrets w CI/CD

Sekrety używane w GitHub Actions (hasła do GHCR, deploy keys) trzymam w GitHub Secrets — zarządzane przez GitHub, odizolowane od kodu:

- name: Login to GHCR
  uses: docker/login-action@v3
  with:
    registry: ghcr.io
    username: ${{ github.actor }}
    password: ${{ secrets.GITHUB_TOKEN }}  # Automatycznie dostępny

GITHUB_TOKEN jest generowany automatycznie per job — nie trzeba go nigdzie przechowywać.

Comments

No comments yet