The ExternalSecret describes what data should be fetched, how the data should
be transformed and saved as a Kind=Secret:
spec.data to
explicitly sync individual keys or use spec.dataFrom to get all values
from the external API.spec.target.templateWhen the controller reconciles the ExternalSecret it will use the spec.template as a blueprint to construct a new Kind=Secret. You can use golang templates to define the blueprint and use template functions to transform secret values. You can also pull in ConfigMaps that contain golang-template data using templateFrom. See advanced templating for details.
You can control how and when the ExternalSecret is refreshed by setting the spec.refreshPolicy field. If not specified, the default behavior is Periodic.
With refreshPolicy: CreatedOnce, the controller will:
Kind=Secret only if it does not exist yetKind=Secret afterwards if the source data changesKind=Secret if it gets changed/DeletedExample:
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: example
spec:
refreshPolicy: CreatedOnce
# other fields...
With refreshPolicy: Periodic (the default behavior), the controller will:
Kind=Secret if it doesn't existKind=Secret regularly based on the spec.refreshInterval durationspec.refreshInterval is set to zero, it will only create the secret once and not update it afterwardspec.refreshInterval is set to a value greater than zero, the controller will update the Kind=Secret at the specified interval or when the ExternalSecret specification changesExample:
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: example
spec:
refreshPolicy: Periodic
refreshInterval: 1h0m0s # Update every hour
# other fields...
With refreshPolicy: OnChange, the controller will:
Kind=Secret if it doesn't existKind=Secret only when the ExternalSecret's metadata or specification changesrefreshInterval valueExternalSecret resourceExample:
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: example
spec:
refreshPolicy: OnChange
# other fields...
If supported by the configured refreshPolicy, you can manually trigger a refresh of the Kind=Secret by updating the annotations of the ExternalSecret:
kubectl annotate es my-es force-sync=$(date +%s) --overwrite
syncWindows restricts when periodic refreshes may occur. It is evaluated in UTC and applies only to the Periodic refresh policy (or when refreshPolicy is unset). OnChange and CreatedOnce policies are unaffected.
A sync-windows block carries a shared kind and a list of schedule + duration entries:
kind: allow -- periodic syncs are permitted only while at least one window is active; all other times are blocked.kind: deny -- periodic syncs are blocked while any window is active; all other times proceed normally.Each entry in windows uses a standard 5-field cron schedule (UTC) and a duration string (e.g. 8h, 30m). The window stays open for duration after each schedule firing. A window entry with an unparseable schedule is silently ignored and treated as inactive, so a typo does not permanently block syncs.
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: example
spec:
refreshInterval: 1h
syncWindows:
kind: allow
windows:
- schedule: "0 9 * * 1-5" # weekdays at 09:00 UTC
duration: 8h # window open until 17:00 UTC
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: example
spec:
refreshInterval: 30m
syncWindows:
kind: deny
windows:
- schedule: "0 2 * * 6" # Saturdays at 02:00 UTC
duration: 2h # block until 04:00 UTC
You can list several entries under windows. For kind: allow, the sync is permitted when any window is active. For kind: deny, the sync is blocked when any window is active.
syncWindows only suppresses sync operations -- it does not change how often the controller checks. The controller still requeues at refreshInterval regardless of whether a sync was blocked. This means that if refreshInterval is longer than window.duration, a window could open and close entirely between two consecutive checks and the sync would be missed for that occurrence. This is by design: refreshInterval is the primary driver; syncWindows is a gate on top of it. To ensure no window occurrence is missed, set refreshInterval to a value shorter than the smallest window.duration.
Individual features are described in the Guides section:
Take a look at an annotated example to understand the design behind the
ExternalSecret.
{% include 'full-external-secret.yaml' %}