Reloader
Stakater Reloader is a small Kubernetes controller that watches ConfigMaps and Secrets and starts a rolling update of the Deployments, StatefulSets, DaemonSets and other workloads that use them, so changed config and rotated credentials reach running pods. Workloads opt in with annotations such as reloader.stakater.com/auto; Reloader hashes the data and writes the hash into the pod template, which makes Kubernetes roll the pods. Apache 2.0 and free; a paid Enterprise build adds signed images and support. It fits any cluster where secrets rotate or config changes outside a deploy, for example with External Secrets Operator.
Reloader is a Kubernetes controller from Stakater that restarts workloads when the ConfigMaps or Secrets they use change. Kubernetes does not do this itself: a pod that reads a Secret through environment variables keeps the old value until the pod is replaced, so a rotated password or an edited feature flag can sit unused in the cluster for weeks. Reloader closes that gap with a rolling update that goes through the normal Deployment machinery.
What it is
A single Go controller, usually installed with Helm, that holds watches on ConfigMaps and Secrets and patches the workloads that reference them. It supports Deployments, StatefulSets, DaemonSets, CronJobs (it starts a Job), Argo Rollouts and OpenShift DeploymentConfigs. Optionally it also watches the Secrets Store CSI Driver's SecretProviderClassPodStatus objects, so CSI-mounted secrets can trigger a restart too.
- Licence: Apache 2.0. Stakater sells a Reloader Enterprise build with signed, CVE-scanned images, SBOMs and SLA support; the open-source build is the same controller.
- Release lines: v1 is the stable line, currently v1.4.22 (Helm chart 2.2.18, September 2026). The
masterbranch that carries v1 is feature-frozen and takes only bug and security fixes. v2, rebuilt on the Operator SDK, is in beta (v2.0.0-beta.1, chart3.0.0-beta.x) on thev2branch, and all new features land there. - Compatibility: the project states Kubernetes 1.19 or later.
- Family: a Kubernetes controller in the same small class as Kustomize's hashed ConfigMap names and Helm's checksum-annotation pattern; all three exist to turn a config change into a pod rollout.
How it works
Reloader runs an informer on ConfigMaps and Secrets (cluster-wide by default, or limited to some namespaces). When one of them changes, it computes a SHA-1 hash of the new data, then finds every workload that both references the object and opts in through an annotation. For each match it writes the hash into the workload's pod template. A changed pod template is exactly what the Deployment controller treats as a new revision, so Kubernetes performs a normal rolling update, honouring maxSurge, maxUnavailable and readiness probes.
There are two ways to write the hash, set by --reload-strategy:
env-vars(the default) adds an environment variable such asSTAKATER_MY_SECRET_SECRET=<sha>to each container that uses the changed object.annotationswrites areloader.stakater.com/last-reloaded-fromannotation onto the pod template instead. The project recommends this mode for GitOps tools such as Argo CD and Flux, because it leaves the container spec alone.
The figure below shows the two common sources of a change: a rotated secret that arrives through External Secrets, and a ConfigMap edited in Git and synced by Argo CD.
Step 1 of 5. A credential is rotated in OpenBao. On its next refresh, External Secrets reads the new value.
Two paths: a secret rotated in the vault, and a ConfigMap changed in Git. Both end in an ordinary rolling update.
Reloader acts only on update events by default. Create and delete events are ignored unless --reload-on-create or --reload-on-delete is set. With more than one replica, --enable-ha turns on leader election through a Kubernetes Lease, so only one replica patches workloads at a time.
When to use it
Reach for it when:
- Secrets rotate on a schedule outside the deploy pipeline, for example through External Secrets Operator, cert-manager certificates or a Sealed Secrets update.
- Apps read config through environment variables, which Kubernetes never refreshes in a running container.
- Apps read config from files but do not watch those files for changes.
- A ConfigMap is mounted with
subPath, which the kubelet does not update in place.
Skip it when:
- Every config change already ships with a new image or a new manifest revision, so pods roll anyway.
- Config names are content-hashed (Kustomize
configMapGenerator) or the Helm chart writes achecksum/configannotation; those already roll pods on change. - The app hot-reloads mounted files itself and a restart would only add disruption.
- A workload must never restart without a human decision, such as a single-replica database.
At a glance
Core concepts
- Opt-in annotation:
reloader.stakater.com/auto: "true"on a workload reloads it when any ConfigMap or Secret it references changes.secret.reloader.stakater.com/autoandconfigmap.reloader.stakater.com/autonarrow that to one kind. - Named reload:
secret.reloader.stakater.com/reload: "db-creds"reloads on a named object even when the pod spec does not reference it. - Search and match:
reloader.stakater.com/search: "true"on the workload plusreloader.stakater.com/match: "true"on the ConfigMap or Secret. Only tagged objects trigger reloads. - Ignore:
reloader.stakater.com/ignore: "true"on a ConfigMap or Secret stops it from triggering any reload. - Pause period:
deployment.reloader.stakater.com/pause-period: "5m"holds back further rollouts after a reload, so a burst of related changes causes one restart. - Global opt-in:
--auto-reload-alltreats every workload asauto: "true"unless it sets"false".
Key facts
| Aspect | Value |
|---|---|
| Stable release | v1.4.22 (chart 2.2.18) |
| Next major | v2 beta, Operator SDK based |
| Licence | Apache 2.0 |
| Image | ghcr.io/stakater/reloader |
| Default resources | requests 10m CPU / 128Mi; limits 150m / 512Mi |
| Default scope | all namespaces (watchGlobally: true) |
| Default strategy | env-vars |
| Kubernetes | 1.19 or later |
Reloader compared with the built-in patterns
| Aspect | Reloader | Helm checksum annotation | Kustomize configMapGenerator |
|---|---|---|---|
| Catches changes made outside the deploy (ESO, cert-manager) | Yes | No | No |
| Needs a running controller | Yes | No | No |
| Works with any manifest source | Yes | Helm charts only | Kustomize only |
| Restarts on Secret rotation | Yes | Only on the next helm upgrade |
Only on the next build and apply |
| Extra RBAC in the cluster | Read Secrets cluster-wide by default | None | None |
How to integrate
Install from the Stakater chart repository:
helm repo add stakater https://stakater.github.io/stakater-charts
helm repo update
helm install reloader stakater/reloader \
--namespace reloader --create-namespace \
--version 2.2.18 \
-f reloader-values.yaml
A small values file for a GitOps cluster:
reloader:
reloadStrategy: annotations # leave container env alone; friendlier to Argo CD / Flux diffs
watchGlobally: true
ignoreNamespaces: "kube-system"
logFormat: json
enableHA: false # set true and raise replicas for leader election
readOnlyRootFileSystem: true
Opt a workload in:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
annotations:
secret.reloader.stakater.com/auto: "true"
spec:
template:
spec:
containers:
- name: api
image: example/api:1.0.0
envFrom:
- secretRef:
name: api-env # written by an ExternalSecret
To test, change a key in the Secret and watch kubectl rollout status deploy/api. The Reloader log records which object triggered which workload.
In the GL stack
Reloader v1.4.22 runs on the beta and prod clusters, the two clusters that host the product workloads behind paiddaily.io, sagedaily.io and the other sites.
- Why it is there. Application secrets live in OpenBao. On each workload cluster, External Secrets Operator pulls them into Kubernetes Secrets through ExternalSecret objects. Without Reloader, a secret rotated in OpenBao would reach the Kubernetes Secret but not the running pods. Reloader closes that last step, so a rotation takes effect without a manual restart.
- How it is wired. Reloading is annotation-driven: only Deployments that carry a Reloader annotation are rolled, and every other workload is left alone. It watches both ConfigMaps and Secrets.
- Where it sits in delivery. Argo CD applies the manifests, including the Deployment annotations; External Secrets supplies the Secret data; Reloader turns a change in that data into a rollout.
Gotchas
- The env-vars strategy shows up as drift. The default writes a
STAKATER_*env var into the container spec, so the live object no longer matches Git. With Argo CD or Flux, usereloadStrategy: annotationsor expect diffs. - Argo Rollouts needs its own flag. Rollouts support is off until
isArgoRollouts: true. Thereloader.stakater.com/rollout-strategy: "restart"annotation deletes pods instead of patching the template, which avoids drift for Rollouts only. autoandsearchdo not combine. If both are set on one workload,autowins.- Changes during downtime. Reloader reacts to watch events.
syncAfterRestarthandles add events after a Reloader restart, and only whenreloadOnCreateis also true. After an outage of Reloader, check that recent rotations were applied. - One ignored type only.
--resources-to-ignoreacceptsconfigmapsorsecrets, not both. To disable Reloader, scale it to zero. - Rollout rules still apply. A StatefulSet with
updateStrategy: OnDeletewill not roll when its template changes, and a Deployment with one replica andmaxUnavailable: 1will have a short outage. - CSI secrets need
secretKey. For Secrets Store CSI integration, rotation must be on in the driver, Reloader needs--enable-csi-integration=true, and each object in theSecretProviderClassneeds asecretKeyor updates may be missed. - A burst of changes means a burst of rollouts. Several Secrets updated together can roll a workload several times. Use the
pause-periodannotation on Deployments that read many objects.
Risks
- RBAC reach. In global mode Reloader can list and watch every Secret in the cluster and patch workloads in every namespace. Scope it with
watchGlobally: false,reloader.namespacesornamespaceSelectorwhere that matters, and keep the image pinned. - Release-line transition. v1 is feature-frozen and v2 is still in beta. v1 will receive fixes, but new features go to v2 only, and a v1-to-v2 move will need a chart major bump (2.x to 3.x) and a values review.
- Single-vendor project. Stakater maintains it and also sells the Enterprise build. The project is widely used (the README cites more than 24 billion image pulls), but its roadmap follows one company.
- Lock-in is low. The annotations are the only coupling. Removing Reloader leaves workloads intact; they simply stop rolling on config change.
Alternatives
- Helm
checksum/configannotation: a hash of the rendered ConfigMap in the pod template; pick it when all config comes from the chart and rotations always go throughhelm upgrade. - Kustomize
configMapGenerator/secretGenerator: content-hashed object names; pick it when Kustomize builds every config change. - App-side file watching: mount config as a volume and reload in-process; pick it when restarts are costly and the app or framework supports hot reload.
- Manual
kubectl rollout restart: pick it when rotations are rare and a human already runs them.
Related
- External Secrets and OpenBao: where the Secrets that Reloader watches come from.
- Argo CD: applies the Deployments and their Reloader annotations.
- cert-manager: another writer of Secrets that can trigger a reload.
- K3s and Rancher: the clusters Reloader runs on and the plane that manages them.
- Operations layer and Security layer.
- Official: Reloader docs, stakater/Reloader on GitHub, Reloader releases, Helm chart README.
