Run browser checks on a browser pool
Caution
The browser pool is an experimental feature. Configuration flags and behavior might change in future releases.
By default, the agent starts a Chromium process for each browser check, on the same host and with the same resources as every other check it runs. With a browser pool, the agent instead borrows a browser session from a separate fleet of browser instances. Each instance runs crocochrome, a Chromium supervisor: for each session, it starts a Chromium browser, and it stops the browser and removes its data when the session ends. Each instance runs one session at a time.
Before you begin
The browser pool requires:
crocochromeversionv0.13.0or later, orv0.14.0or later for the unprivileged image.- k6 checks enabled on the agent. They’re enabled by default, so don’t set
-disable-k6. - The agent’s built-in k6 runner. You can’t use the browser pool with a remote k6 runner set with
-k6-uri.
When to use a browser pool
Consider a browser pool when a probe runs many browser checks:
- Resource isolation: Each browser session gets the dedicated CPU and memory of its instance, instead of competing inside the agent with protocol and scripted checks. If Chromium runs out of memory, it affects only that instance, not the agent.
- Independent scaling: You size and scale the browser fleet separately from the agents.
- Smaller agents: The agents no longer run Chromium, so they don’t need the
-browserimage.
If a probe runs only a few browser checks, use the -browser image instead. It’s simpler to operate and needs fewer privileges than the hardened browser pool image. Refer to Browser pool security considerations.
How the browser pool works
For each browser check run, the agent uses a free instance and releases it when the run ends. Several agents, for example the agents in a cluster, can share the same fleet.
If no instance becomes free within a short wait, the check run fails. The agent doesn’t fall back to a local Chromium.
Size the browser pool and the agents
- Browser pool instances: Run at least as many instances as the peak number of browser checks running at the same time. Browser checks with long frequencies, such as hourly checks, tend to run in bursts. Size the fleet for those bursts.
- Agents: With Chromium running on the browser pool, a few agents can run many checks of every type, so keep the number of agents small. If you need the probe to keep running when an agent fails, run a cluster of at least two agents.
To size each instance, use the browser check figures in Calculate resource requirements. Each instance runs one session at a time.
Browser pool security considerations
crocochrome is available as two container images:
- Hardened (default): The supervisor runs Chromium as a separate user, so a compromised browser can’t interfere with the supervisor. To do this, the container needs privilege escalation and a few added Linux capabilities. It meets the Pod Security
baselineprofile, but notrestricted. - Unprivileged: Images tagged
<version>-unprivileged. The container needs no added capabilities or privilege escalation, and can run with an arbitrary user ID. It meets therestrictedprofile. Chromium runs as the same user as the supervisor, so a compromised browser can interfere with the supervisor and with later browser sessions on the same instance.
Use the hardened image unless your platform doesn’t allow it, for example because it enforces the restricted profile, a policy engine such as Kyverno or OPA Gatekeeper blocks added capabilities, or it runs on OpenShift. Only use the unprivileged image when you trust both the check scripts and the content of the pages they load, including third-party scripts.
For the security context that each image requires and the trade-offs in detail, refer to Choosing an image in the crocochrome repository.
Warning
The browser pool instances don’t authenticate requests. Anyone who can reach an instance can start browser sessions in your network. Only allow traffic to the instances from the agents, for example with a Kubernetes NetworkPolicy.
Configure the browser pool on Kubernetes
These steps extend Deployment with Kubernetes and work for both the single agent and the cluster examples. They use the browser pool files from the Kubernetes example in the agent GitHub repository.
Get the browser pool deployment files.
wget https://raw.githubusercontent.com/grafana/synthetic-monitoring-agent/main/examples/kubernetes/crocochrome-service.yaml wget https://raw.githubusercontent.com/grafana/synthetic-monitoring-agent/main/examples/kubernetes/crocochrome-deployment.yamlIn these files:
- The
crocochromeService is headless, so its name resolves to the IP address of every instance. The agent must reach each instance individually. Don’t use a regularClusterIPService. terminationGracePeriodSeconds: 320gives an instance time to finish its active session before it stops. A session can last up to 5 minutes.- The
securityContextallows privilege escalation and adds the capabilities that the hardened image needs to run Chromium as a separate user. Don’t change these settings unless you switch to the unprivileged image. Refer to Browser pool security considerations. - Chromium writes temporary files to an in-memory volume mounted at
/chromium-tmp, which counts toward the memory limit.
- The
Deploy the browser pool.
kubectl apply -f crocochrome-service.yaml kubectl apply -f crocochrome-deployment.yamlIn
deployment.yamlorcluster-deployment.yaml, uncomment the browser pool arguments:- --browser-pool-enabled - --browser-pool-addresses=crocochrome.synthetic-monitoring.svc.cluster.local:8080Then apply the agent manifest again, for example:
kubectl apply -f deployment.yamlVerify that the agent uses the pool. The agent logs a warning that the browser pool is experimental when it starts, and the
sm_agent_browser_pool_instancesmetric reports the instances it found. Refer to Monitor the browser pool.
To change the size of the fleet, scale the crocochrome Deployment. The agents pick up the change within 15 seconds.
Configure the browser pool with Helm
If you deploy the agent with the Helm chart, the chart can deploy the browser pool and point the agents to it. Enable the browser pool in your values file:
browserPool:
enabled: true
crocochrome:
# Each instance runs one browser session at a time.
replicas: 3
# Set to true to use the unprivileged image.
unprivileged: falseThen upgrade the release:
helm upgrade sm-agent oci://ghcr.io/grafana/helm-charts/synthetic-monitoring-agent \
-n synthetic-monitoring -f values.yamlThe chart sets the image and the security context that the selected image requires. Refer to Browser pool security considerations before you set browserPool.crocochrome.unprivileged. With the browser pool, the agents can use the standard image.
Optionally, the chart can also deploy a NetworkPolicy that only allows the agents to reach the instances. If you enable it and want to scrape the instances’ metrics, which use the same port, add your Prometheus Pods to browserPool.crocochrome.networkPolicy.extraIngressFrom. Refer to the chart README.
Configure the browser pool in other environments
You can run the browser pool anywhere the agents can reach it over HTTP, for example as crocochrome containers with Docker. Set -browser-pool-addresses to the address of each instance, or to a DNS name that resolves to all of them.
Browser pool flags reference
The agent doesn’t start if you set only one of these flags. If you disable k6 checks with -disable-k6, the agent logs a warning and ignores the browser pool.
Monitor the browser pool
When the browser pool is enabled, each agent exposes the following metrics. Like the rest of the browser pool, these metrics might change while the feature is experimental.
Each instance also exposes metrics on port 8080 at /metrics, including:
Because each instance runs one session at a time, avg(sm_crocochrome_session_active) across instances is the share of the fleet in use, from 0 to 1. Use it to decide when to add or remove instances, or as the input of an autoscaling policy for the crocochrome Deployment, for example with a HorizontalPodAutoscaler on an external metric or with KEDA.
With the Helm chart, set browserPool.crocochrome.replicas: null, so that helm upgrade doesn’t reset the number of instances, and add the autoscaler with extraObjects.
Keep some headroom: when every instance is busy, new browser check runs wait and can fail.
To estimate how many instances you need, multiply the rate of new sessions across the fleet, sum(rate(sm_crocochrome_sessions_created_total[5m])), by the average session duration from sm_crocochrome_session_duration_seconds. The result is the average number of busy instances. Add headroom for bursts on top of it.
In a healthy pool:
sm_agent_browser_pool_acquires_total{result="exhausted"}doesn’t increase. If it does, browser checks are failing because no instance was free. Add instances.sm_agent_browser_pool_probes_totaldoesn’t grow much faster thansm_agent_browser_pool_acquires_total. A high ratio means agents often try busy instances. Add instances or reduce the number of agents.sm_agent_browser_pool_releases_total{result="error"}doesn’t increase. Sessions that aren’t released stay busy until the instance ends them after 5 minutes.sm_crocochrome_sessions_terminated_total{reason="timeout"}doesn’t increase. If it does, sessions aren’t released, and their instances stay busy until the 5-minute limit.sm_crocochrome_sessions_terminated_total{reason="replaced"}doesn’t increase. Agents never replace sessions, so if it increases, something other than the agents is using the instances.sm_crocochrome_chromium_executions_total{state="failed"}andsm_crocochrome_chromium_oom_kills_totaldon’t increase. Out-of-memory kills mean the memory limit of the instances is too low. Usesm_crocochrome_chromium_resource_usageto see how much memory Chromium uses.


