README.md
Reloader is a Kubernetes controller that automatically triggers rollouts of workloads (like Deployments, StatefulSets, and more) whenever referenced Secrets, ConfigMaps or optionally CSI-mounted secrets are updated.
In a traditional Kubernetes setup, updating a Secret or ConfigMap does not automatically restart or redeploy your workloads. This can lead to stale configurations running in production, especially when dealing with dynamic values like credentials, feature flags, or environment configs.
Reloader bridges that gap by ensuring your workloads stay in sync with configuration changes β automatically and safely.
flowchart LR
ExternalSecret -->|Creates| Secret
SealedSecret -->|Creates| Secret
Certificate -->|Creates| Secret
Secret -->|Watched by| Reloader
ConfigMap -->|Watched by| Reloader
Reloader -->|Triggers Rollout| Deployment
Reloader -->|Triggers Rollout| DeploymentConfig
Reloader -->|Triggers Rollout| Daemonset
Reloader -->|Triggers Rollout| Statefulset
Reloader -->|Triggers Rollout| ArgoRollout
Reloader -->|Triggers Job| CronJob
Reloader -->|Sends Notification| Slack,Teams,Webhook
ExternalSecret, SealedSecret, or Certificate from cert-manager can create or manage Kubernetes Secrets β but they can also be created manually or delivered through GitOps workflows.Secrets and ConfigMaps are watched by Reloader.Follow any of this installation options.
To enable automatic reload for a Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
annotations:
reloader.stakater.com/auto: "true"
spec:
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: your-image
envFrom:
- configMapRef:
name: my-config
- secretRef:
name: my-secret
This tells Reloader to watch the ConfigMap and Secret referenced in this deployment. When either is updated, it will trigger a rollout.
Stakater offers an enterprise-grade version of Reloader with:
Contact [email protected] for info about Reloader Enterprise.
Reloader supports multiple annotation-based controls to let you customize when and how your Kubernetes workloads are reloaded upon changes in Secrets or ConfigMaps.
Kubernetes does not trigger pod restarts when a referenced Secret or ConfigMap is updated. Reloader bridges this gap by watching for changes and automatically performing rollouts β but it gives you full control via annotations, so you can:
search + match)Use these annotations to automatically restart the workload when referenced Secrets or ConfigMaps change.
| Annotation | Description |
|---|---|
reloader.stakater.com/auto: "true" | Reloads workload when any referenced ConfigMap or Secret changes |
secret.reloader.stakater.com/auto: "true" | Reloads only when referenced Secret(s) change |
configmap.reloader.stakater.com/auto: "true" | Reloads only when referenced ConfigMap(s) change |
These annotations allow you to manually define which ConfigMaps or Secrets should trigger a reload, regardless of whether they're used in the pod spec.
| Annotation | Description |
|---|---|
secret.reloader.stakater.com/reload: "my-secret" | Reloads when specific Secret(s) change, regardless of how they're used |
configmap.reloader.stakater.com/reload: "my-config" | Reloads when specific ConfigMap(s) change, regardless of how they're used |
This pattern allows fine-grained reload control β workloads only restart if the Secret/ConfigMap is both:
match: true| Annotation | Applies To | Description |
|---|---|---|
reloader.stakater.com/search: "true" | Workload | Enables search mode (only reloads if matching secrets/configMaps are found) |
reloader.stakater.com/match: "true" | ConfigMap/Secret | Marks the config/secret as eligible for reload in search mode |
reloader.stakater.com/search: "true"reloader.stakater.com/match: "true"volumeMount, etc.)reloader.stakater.com/match: "true".When you need to prevent specific ConfigMaps or Secrets from triggering any reloads, use the ignore annotation on the resource itself:
apiVersion: v1
kind: ConfigMap # or Secret
metadata:
name: my-config
annotations:
reloader.stakater.com/ignore: "true"
This instructs Reloader to skip all reload logic for that resource across all workloads.
Note: This is only applicable when using Argo Rollouts. It is ignored for standard Kubernetes Deployments, StatefulSets, or DaemonSets. To use this feature, Argo Rollouts support must be enabled in Reloader (for example via --is-argo-rollouts=true).
By default, Reloader triggers the Argo Rollout controller to perform a standard rollout by updating the pod template. This works well in most cases, however, because this modifies the workload spec, GitOps tools like ArgoCD will detect this as "Configuration Drift" and mark your application as OutOfSync.
To avoid that, you can switch to the restart strategy, which simply restarts the pod without changing the pod template.
metadata:
annotations:
reloader.stakater.com/rollout-strategy: "restart"
| Value | Behavior |
|---|---|
rollout (default) | Updates pod template metadata to trigger a rollout |
restart | Deletes the pod to restart it without patching the template |
β
Use restart if:
This setting affects Argo Rollouts behavior, not Argo CD sync settings.
reloader.stakater.com/auto and reloader.stakater.com/search cannot be used together β the auto annotation takes precedence.auto and its typed versions (secret.reloader.stakater.com/auto, configmap.reloader.stakater.com/auto) are used, only one needs to be true to trigger a reload.reloader.stakater.com/auto: "false" explicitly disables reload for that workload.--auto-reload-all is enabled on the controller:
auto: "true" unless they explicitly set it to "false"."false".Reloader can optionally send alerts whenever it triggers a rolling upgrade for a workload (e.g., Deployment, StatefulSet, etc.).
These alerts are sent to a configured webhook endpoint, which can be a generic receiver or services like Slack, Microsoft Teams or Google Chat.
To enable this feature, update the reloader.env.secret section in your values.yaml (when installing via Helm):
reloader:
deployment:
env:
secret:
ALERT_ON_RELOAD: "true" # Enable alerting (default: false)
ALERT_SINK: "slack" # Options: slack, teams, gchat or webhook (default: webhook)
ALERT_WEBHOOK_URL: "<your-webhook-url>" # Required if ALERT_ON_RELOAD is true
ALERT_ADDITIONAL_INFO: "Triggered by Reloader in staging environment"
This feature allows you to pause rollouts for a deployment for a specified duration, helping to prevent multiple restarts when several ConfigMaps or Secrets are updated in quick succession.
| Annotation | Applies To | Description |
|---|---|---|
deployment.reloader.stakater.com/pause-period: "5m" | Deployment | Pauses reloads for the specified period (e.g., 5m, 1h) |
deployment.reloader.stakater.com/pause-period annotation to your Deployment, specifying the pause duration (e.g., "5m" for five minutes).Reloader supports the Secrets Store CSI Driver, which allows mounting secrets from external secret stores (like AWS Secrets Manager, Azure Key Vault, HashiCorp Vault) directly into pods. Unlike Kubernetes Secret objects, CSI-mounted secrets do not always trigger native Kubernetes update events. Reloader solves this by watching CSI status resources and restarting affected workloads when mounted secret versions change.
When secret rotation is enabled, the Secrets Store CSI Driver updates a Kubernetes resource called: SecretProviderClassPodStatus
This resource reflects the currently mounted secret versions for a pod. Reloader watches these updates and triggers a rollout when a change is detected.
--enable-csi-integration=true| Annotation | Description |
|---|---|
reloader.stakater.com/auto: "true" | Global Discovery: Automatically discovers and reloads the workload when any mounted ConfigMap or Secret is updated. |
secretproviderclass.reloader.stakater.com/auto: 'true' | CSI Discovery: Specifically watches for updates to all SecretProviderClasses used by the workload (CSI driver integration). |
secretproviderclass.reloader.stakater.com/reload: "my-secretproviderclass" | Targeted Reload: Only reloads the workload when the specifically named SecretProviderClass(es) are updated. |
Reloader monitors changes at the per-secret level by watching the SecretProviderClassPodStatus. Make sure each secret you want to monitor is properly defined with a secretKey in your SecretProviderClass:
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: vault-reloader-demo
namespace: test
spec:
provider: vault
parameters:
vaultAddress: "http://vault.vault.svc:8200"
vaultSkipTLSVerify: "true"
roleName: "demo-role"
objects: |
- objectName: "password"
secretPath: "secret/data/reloader-demo"
secretKey: "password"
Important: Reloader tracks changes to individual secrets (identified by secretKey). If your SecretProviderClass doesn't specify secretKey for each object, Reloader may not detect updates correctly.
Reloader reacts to CSI status changes, not direct updates to external secret stores
Secret rotation must be enabled in the CSI driver for updates to be detected
CSI limitations (such as subPath mounts) still apply and may require pod restarts
If secrets are synced to Kubernetes Secret objects, standard Reloader behavior applies and CSI support may not be required
Reloader can be installed in multiple ways depending on your Kubernetes setup and preference. Below are the supported methods:
helm repo add stakater https://stakater.github.io/stakater-charts
helm repo update
helm install reloader stakater/reloader
β‘οΈ See full Helm configuration in the chart README.
Apply raw Kubernetes manifests directly:
kubectl apply -f https://raw.githubusercontent.com/stakater/Reloader/master/deployments/kubernetes/reloader.yaml
Use the built-in Kustomize support:
kubectl apply -k https://github.com/stakater/Reloader/deployments/kubernetes
You can create your own kustomization.yaml and use Reloaderβs as a base:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- https://github.com/stakater/Reloader/deployments/kubernetes
namespace: reloader
By default, Reloader is deployed with the following resource requests and limits:
resources:
limits:
cpu: 150m
memory: 512Mi
requests:
cpu: 10m
memory: 128Mi
These flags let you customize Reloader's behavior globally, at the Reloader controller level.
| Flag | Description |
|---|---|
--reload-on-create=true | Reload workloads when a watched ConfigMap or Secret is created |
--reload-on-delete=true | Reload workloads when a watched ConfigMap or Secret is deleted |
--auto-reload-all=true | Automatically reload all workloads unless opted out (auto: "false") |
--reload-strategy=env-vars | Strategy to use for triggering reload (env-vars or annotations) |
--log-format=json | Enable JSON-formatted logs for better machine readability |
Reloader supports multiple strategies for triggering rolling updates when a watched ConfigMap or Secret changes. You can configure the strategy using the --reload-strategy flag.
| Strategy | Description |
|---|---|
env-vars (default) | Adds a dummy environment variable to any container referencing the changed resource (e.g., Deployment, StatefulSet, etc.). This forces Kubernetes to perform a rolling update. |
annotations | Adds a reloader.stakater.com/last-reloaded-from annotation to the pod template metadata. Ideal for GitOps tools like ArgoCD, as it avoids triggering unwanted sync diffs. |
env-vars strategy is the default and works in most setups.annotations strategy is preferred in GitOps environments to prevent config drift in tools like ArgoCD or Flux.annotations mode, a ConfigMap or Secret that is deleted and re-created will still trigger a reload (since previous state is not tracked).| Flag | Description |
|---|---|
--resources-to-ignore=configmaps | Ignore ConfigMaps (only one type can be ignored at a time) |
--resources-to-ignore=secrets | Ignore Secrets (cannot combine with configMaps) |
--ignored-workload-types=jobs,cronjobs | Ignore specific workload types from reload monitoring |
--resource-label-selector=key=value | Only watch ConfigMaps/Secrets with matching labels |
β οΈ Note:
Only one resource type can be ignored at a time. Trying to ignore both
configmapsandsecretswill cause an error in Reloader. β Workaround: Scale the Reloader deployment to0replicas if you want to disable it completely.
π‘ Workload Type Examples:
# Ignore only Jobs
--ignored-workload-types=jobs
# Ignore only CronJobs
--ignored-workload-types=cronjobs
# Ignore both (comma-separated)
--ignored-workload-types=jobs,cronjobs
π§ Use Case: Ignoring workload types is useful when you don't want certain types of workloads to be automatically reloaded.
| Flag | Description |
|---|---|
--namespace-selector='key=value' |
--namespace-selector='key1=value1,key2=value2'
--namespace-selector='key in (value1,value2)'| Watch only namespaces with matching labels. See LIST and WATCH filtering for more details on label selectors |
| --namespaces-to-ignore=ns1,ns2 | Skip specific namespaces from being watched |
These flags allow you to redefine annotation keys used in your workloads or resources:
| Flag | Overrides |
|---|---|
--auto-annotation | Overrides reloader.stakater.com/auto |
--secret-auto-annotation | Overrides secret.reloader.stakater.com/auto |
--configmap-auto-annotation | Overrides configmap.reloader.stakater.com/auto |
--auto-search-annotation | Overrides reloader.stakater.com/search |
--search-match-annotation | Overrides reloader.stakater.com/match |
--secret-annotation | Overrides secret.reloader.stakater.com/reload |
--configmap-annotation | Overrides configmap.reloader.stakater.com/reload |
--pause-deployment-annotation | Overrides deployment.reloader.stakater.com/pause-period |
--pause-deployment-time-annotation | Overrides deployment.reloader.stakater.com/paused-at |
| Flag | Description |
|---|---|
--enable-pprof | Enables pprof for profiling |
--pprof-addr | Address to start pprof server on. Default is :6060 |
Reloader is compatible with Kubernetes >= 1.19
The Reloader documentation can be viewed from the doc site. The doc source is in the docs folder.
File a GitHub issue.
Join and talk to us on Slack for discussing Reloader:
Please use the issue tracker to report any bugs or file feature requests.
okteto up to activate your development containermake build./ReloaderPRs are welcome. In general, we follow the "fork-and-pull" Git workflow:
NOTE: Be sure to merge the latest from "upstream" before making a pull request!
Repository GitHub releases: As requested by the community in issue 685, Reloader is now based on a manual release process. Releases are no longer done on every merged PR to the main branch, but manually on request.
To make a GitHub release:
release-vX.Y.Z from masterTARGET_BRANCH parameter to release branch i.e. release-vX.Y.ZTARGET_VERSION to release version without 'v' i.e. X.Y.ZvX.Y.Z and target branch release-vX.Y.Z, which triggers creation of imagesmaster and bump the helm chart version as well as Reloader image version.
release/helm-chart label, example: PR-846Repository git tagging: Push to the main branch will create a merge-image and merge-tag named merge-${{ github.event.number }}, for example merge-800 when pull request number 800 is merged.
View the releases page to see what has changed in each release.
Apache2 Β© Stakater
Reloader is maintained by Stakater. Like it? Please let us know at [email protected]
See our other projects or contact us in case of professional services and queries on [email protected]