Configuration
Synthetic Monitoring works with the defaults from Deployment. This page lists the settings you can change: the Helm values of the KubeSense chart, extra synthetics-api settings, and the settings of agents you run in your own locations.
Settings that users change in the web app (monitor defaults, variables, tag rules) are described in Settings.
Helm Values
All values sit under the top-level synthetics: block of the kubesense (or kubesense-server) chart. Apply changes with helm upgrade and the same values files.
General
| Value | Default | Description |
|---|---|---|
synthetics.enabled | false | Deploys Synthetic Monitoring and shows the Synthetics pages |
synthetics.edition | basic | The installation's edition |
synthetics.existingSecret | "" | A Secret you manage, with SYNTHETICS_API_TOKEN, SYNTHETICS_AGENT_TOKEN and SYNTHETICS_SECRET_KEYS. Nothing is generated when it is set |
synthetics.secret.apiToken | generated | Token the KubeSense API presents to synthetics-api |
synthetics.secret.agentToken | generated | Token agents register with |
synthetics.secret.secretKeys | generated | Key ring that encrypts stored secrets (see Secrets key) |
synthetics-api
| Value | Default | Description |
|---|---|---|
synthetics.api.replicaCount | 1 | API replicas. Replicas elect a leader for scheduling and alerting, so more than one adds availability |
synthetics.api.image.tag | release version | Image tag of synthetics/api |
synthetics.api.port | 8080 | Service port |
synthetics.api.alertingMode | platform | platform: monitor alerts go through KubeSense alert rules and notification channels. Keep it on platform |
synthetics.api.dashboardUrl | https://<global.dashboardHostName> | Base URL that alert notifications link to |
synthetics.api.agentHelmRepo | https://helm.kubesense.ai | Helm repository used in the install commands shown for a location |
synthetics.api.mysql.host | bundled MySQL | host, port, database (synthetics) and username of the control-plane database. Empty uses the bundled MySQL or global.externalMySQL |
synthetics.api.clickhouse.host | bundled ClickHouse | host, port and username of the ClickHouse that holds run results (in kube_synthetics). Empty uses the bundled ClickHouse or the external one. database (synthetics) names the results database of releases before this one, copied once after the upgrade |
synthetics.api.remoteWriteUrl | bundled metrics store | Remote-write URL for the kubesense_synthetics_* series |
synthetics.api.configFile | {} | Extra settings, see synthetics-api settings |
synthetics.api.env | {} | Extra environment variables |
synthetics.api.resources | 250m / 1 CPU, 256 / 512 MiB | Requests and limits |
synthetics.api.nodeSelector, tolerations, affinity, podAnnotations | empty | Pod placement and annotations |
Database passwords come from the release's existing secrets; you do not set them here.
In-cluster location and agents
| Value | Default | Description |
|---|---|---|
synthetics.location.id | in-cluster | Location the in-cluster agents register into. Created on first start if it does not exist |
synthetics.location.name | In-cluster | Display name of that location |
synthetics.location.region | private | Region label of that location |
synthetics.agent.enabled | true | Deploys the in-cluster agents |
synthetics.agent.replicaCount | 2 | Agents in the location. The agents share the location's monitors, so two agents on different nodes keep checks running when one goes down, and more replicas add capacity |
synthetics.agent.workers | 100 | Checks one agent runs at the same time |
synthetics.agent.persistence.enabled | false | A volume per agent for queued results (kept while synthetics-api is unreachable, and across restarts) and its registration. Changing it later needs the StatefulSet recreated: kubectl delete statefulset kubesense-synthetics-agent --cascade=orphan, then helm upgrade |
synthetics.agent.persistence.size / storageClass | 1Gi / default | Volume size and storage class |
synthetics.agent.labels | {} | Agent labels, used to target agents from a monitor |
synthetics.agent.resources | 100m / 500m CPU, 128 / 256 MiB | Requests and limits |
synthetics.agent.env, nodeSelector, tolerations, affinity, podAnnotations | empty | Extra environment and pod placement |
The in-cluster agents have no access to the Kubernetes API. To run Kubernetes resource checks, install a separate agent with the synthetics-agent chart and k8sChecks=true (see Agents in your own locations).
Browser agents
| Value | Default | Description |
|---|---|---|
synthetics.browserAgent.enabled | false | Deploys agents with headless Chromium for browser tests |
synthetics.browserAgent.replicaCount | 1 | Browser agents |
synthetics.browserAgent.concurrency | 2 | Browser tests one agent runs at the same time. Each needs about 800m CPU and 1 GiB |
synthetics.browserAgent.tmpSizeLimit | 1Gi | In-memory /tmp for the browser profiles |
synthetics.browserAgent.persistence.* | disabled | As for synthetics.agent.persistence |
synthetics.browserAgent.resources | 1.7 / 2.5 CPU, 2.25 / 3 GiB | Requests and limits. Raise them together with concurrency |
Agent ingress
Agents outside the cluster reach synthetics-api through this Ingress. It routes only the agent endpoints (/api/v1/probes/* and /healthz); users always go through the KubeSense API.
| Value | Default | Description |
|---|---|---|
synthetics.agentIngress.enabled | false | Creates the Ingress. When enabled, the install commands shown for a location point new agents at it |
synthetics.agentIngress.className | global.ingress.className | Ingress class |
synthetics.agentIngress.host | global.dashboardHostName | Host name. Empty serves the agent paths beside the dashboard |
synthetics.agentIngress.annotations | {} | Ingress annotations |
synthetics.agentIngress.tls.enabled | global.ingress.tls.enabled | TLS |
synthetics.agentIngress.tls.secretName | global.ingress.tls.secretName | TLS Secret. Required with a host of its own |
synthetics:
agentIngress:
enabled: true
host: synthetics-agents.example.com
tls:
enabled: true
secretName: synthetics-agents-tlssynthetics-api Settings
Settings the chart does not expose go in synthetics.api.configFile (Kubernetes) or in synthetics-api.yaml (VM). Keys are snake_case; durations use s, m and h (720h is 30 days). An unknown key or a value of the wrong type stops synthetics-api at startup, and its log says which key.
synthetics:
api:
configFile:
min_interval: 30s
incident_retention: 4320h # 180 days
alert_event_retention: 720h # 30 days# common/config/synthetics/synthetics-api.yaml
listen_port: 8080
# ... mysql, clickhouse and remote_write as in Deployment
min_interval: 30s
incident_retention: 4320h # 180 days
alert_event_retention: 720h # 30 days| Key | Default | Description |
|---|---|---|
min_interval | 10s | Shortest interval a monitor may run at (10s to 7d) |
max_monitors | 0 | Most monitors that can be stored (0 = no limit) |
max_locations_per_monitor | 0 | Most locations one monitor may pick (0 = no limit) |
max_concurrent_on_demand | 20 | On-demand runs (Run now, Test) at the same time; more are refused until one finishes. Scheduled runs are never limited |
max_multistep_steps | 10 | Most steps in a multistep API test (at most 25) |
incident_retention | 8760h (365 days) | How long resolved outages are kept |
alert_event_retention | 2160h (90 days) | How long alert events are kept |
batch_retention | 720h (30 days) | How long CI batches and their runs are kept |
monitor_version_retention | 2160h (90 days) | How long saved monitor versions are kept; the newest 20 of each monitor always are |
remote_write.labels | [service, env, team] | Monitor tags copied onto the kubesense_synthetics_* series as label_<key>, at most 5. Use them to filter dashboards and alerts by tag |
min_agent_version | "" | Agents older than this version are marked outdated on the Locations page |
drain_timeout | 10s | On shutdown, how long running checks get to finish |
evaluation_workers | 8 | Parallel result evaluation. Raise only for very large numbers of monitors |
probe_offline_after | 45s | An agent silent this long is marked offline and its monitors move to the location's other agents. See Handover |
nodata_sweep | 15s | How often offline agents and monitors without results are looked for |
Run history in ClickHouse is kept for 30 days, uptime for 365 days, failure snapshots for 7 days and browser screenshots for 14 days. Change them under Settings → Data Retention (group Synthetics). The retention settings above (outages, alert events, CI batches, monitor versions) are synthetics-api's own clean-up of its MySQL database, once a day; they are set here, not on that page.
Agents in Your Own Locations
Agents in another cluster or on a VM are installed with the command a location shows (see Locations & Agents). The command sets the API address, location and token; add the settings below to it as needed.
Values of the synthetics-agent chart (--set or a values file):
| Value | Default | Description |
|---|---|---|
replicaCount | 1 | Agents in this installation. The agents of a location share its monitors; run two for availability |
imagePullSecrets | [] | Pull access to the KubeSense registry, e.g. [{name: registry-credentials}] |
agent.apiEndpoint | set by the command | synthetics-api address (the agent ingress) |
agent.location | set by the command | Location id the agent registers into |
agent.name / agent.region | pod name / private | Display name and region label |
agent.labels | {} | Agent labels, used to target agents from a monitor |
agent.detectCloud | true | Reads the cloud provider and region from the instance metadata, which places the agent on the map |
agent.workers | 100 | Checks one agent runs at the same time |
agent.syncInterval / agent.heartbeatInterval | 30s / 15s | How often the agent fetches its checks / reports that it is alive. See Handover |
agent.spoolDir / agent.spoolMax | memory / 10000 | Where results wait while synthetics-api is unreachable, and how many |
agent.proxy.bypass | [] | Hosts reached without the proxy (NO_PROXY syntax). The proxy URL itself goes in secrets.proxyUrl |
agent.dns.useHost / agent.dns.servers | true / [] | Use the node's resolver, with servers (ip[:port]) as fallback; useHost: false uses only servers |
agent.egress.allowedDomains / blockedDomains | [] | Only these domains may be checked / never these (blocked wins) |
agent.egress.allowedIpRanges / blockedIpRanges | [] | IP ranges re-allowed / never reached |
agent.enableIpv6 | true | false = IPv4 only |
agent.maxBodySize | 5242880 | Response body bytes read for assertions (at most 50 MiB) |
agent.customCA.secretName / configMapName | "" | Extra root CAs (*.pem, *.crt, *.cer keys) trusted by HTTP, WebSocket, gRPC, TCP-TLS, DNS-over-TLS/HTTPS and SSL checks |
secrets.token / secrets.existingSecret | set by the command | Registration token, or a Secret holding SYNTHETICS_AGENT_TOKEN |
secrets.proxyUrl | "" | Proxy for HTTP, WebSocket and gRPC checks, e.g. http://user:pass@proxy.corp:3128 |
enableICMP | false | Adds CAP_NET_RAW, needed for ICMP ping checks |
networkPath.rawSocket | false | Router identification and UDP/ICMP paths in network path checks (adds CAP_NET_RAW, runs as root with every other capability dropped) |
k8sChecks | false | Kubernetes resource checks: adds a read-only ClusterRole |
k8sCustomResources | [] | Custom resources Kubernetes checks may read, e.g. [{apiGroup: cert-manager.io, resources: [certificates]}] |
browser.enabled | false | Browser agent (headless Chromium) instead of the standard agent |
browser.concurrency | 2 | Browser tests at the same time (about 800m CPU and 1 GiB each) |
resources / browser.resources | 100m / 500m CPU, 128 / 256 MiB | Requests and limits |
configFile | {} | Any other agent setting, as snake_case keys |
Agent flags. Each also works as a snake_case key of a config file passed with -config.
| Flag | Default | Description |
|---|---|---|
-api | — | synthetics-api address (the agent ingress or reverse proxy) |
-location | — | Location id the agent registers into |
-token / SYNTHETICS_AGENT_TOKEN | — | Registration token. Prefer the environment variable |
-token-file | — | Keeps the agent's registration in a file so a restart is back at once. Put it on a volume |
-id / -name / -region / -labels k=v,k=v | generated | Identity and labels |
-workers | 100 | Checks at the same time |
-sync / -heartbeat | 30s / 15s | Check fetch / alive report interval |
-spool-dir / -spool-max | memory / 10000 | Where results wait while synthetics-api is unreachable, and how many |
-proxy-url / -proxy-bypass | — | Proxy for HTTP, WebSocket and gRPC checks / hosts reached without it |
-dns-server / -dns-use-host | — / true | Resolvers for check targets |
-allowed-domains / -blocked-domains | — | Domain rules (blocked wins) |
-allowed-ip-ranges / -blocked-ip-ranges | — | IP range rules |
-enable-ipv6 | true | false = IPv4 only |
-max-body-size | 5 MiB | Response body bytes read for assertions |
-ca-dir | — | Directory of extra root CAs |
-browser / -browser-concurrency / -chrome-no-sandbox | off / 2 / off | Browser agent (use the synthetics/browser-agent image) |
-drain-timeout | 10s | On shutdown, how long running checks get to finish |
-metrics-addr | :9090 | /healthz and Prometheus /metrics |
ICMP ping checks need the NET_RAW capability (--cap-add NET_RAW with Docker).
Handover
When an agent goes offline, its monitors move to the other agents of its location (see Availability). An agent that stops is offline at once, and its monitors move within one check sync, about 30 seconds. An agent that dies is noticed only by its silence: its monitors move within probe_offline_after + nodata_sweep + the agents' check sync, about 30–90 seconds with the defaults. Lower settings shorten the gap at the cost of more requests to synthetics-api:
| Setting | Where | Default | Lower means |
|---|---|---|---|
probe_offline_after | synthetics.handover.offlineAfter (Kubernetes) or synthetics-api settings | 45s | A dead agent is offline sooner. Agents automatically heartbeat at least every third of it, so lowering it never marks live agents offline |
nodata_sweep | synthetics.handover.sweep (Kubernetes) or synthetics-api settings | 15s | Offline agents are found sooner |
| Check sync | synthetics.handover.sync (in-cluster agents), agent.syncInterval (synthetics-agent chart) or -sync (Docker / binary) | 30s | Monitors move sooner after any handover |
For example, probe_offline_after: 15s, nodata_sweep: 5s and agents at a 10s check sync bring the handover after a crash to about 15–30 seconds.
synthetics:
handover:
offlineAfter: 15s
sweep: 5s
sync: 10s # in-cluster agents; set agent.syncInterval on agents of other locationsFor no gap at all, turn on Run every monitor on every agent for the location.
Secrets Key
SYNTHETICS_SECRET_KEYS encrypts secure variables and monitor credentials at rest. Its format is kid:base64key[,kid:base64key] with 32-byte keys (openssl rand -base64 32). The first key encrypts; every key in the list decrypts.
To rotate the key:
-
Put a new key first and keep the old one after it, e.g.
k2:<new>,k1:<old>, and restart synthetics-api. New secrets are encrypted withk2; old ones still decrypt withk1. -
Re-encrypt the stored secrets once. Run the synthetics-api binary with
-rotate-secretsand the same database settings and key list as the running service:# The pod already has the passwords and keys in its environment; # copy the --mysql-* arguments from: kubectl -n kubesense get deploy kubesense-synthetics-api -o yaml kubectl -n kubesense exec deploy/kubesense-synthetics-api -- \ /usr/local/bin/synthetics-api --mysql-host=<host> --mysql-username=<user> -rotate-secretsdocker compose run --rm synthetics-api -config /etc/synthetics/synthetics-api.yaml -rotate-secretsIt logs how many secrets it re-encrypted and exits with code 1 if one could not be decrypted.
-
Remove the old key from the list and restart synthetics-api.
Losing every key in use makes the stored secrets unreadable: re-enter them in the monitors and variables that use them.