Open source

Access and permissions for Grafana Alloy on Kubernetes

Alloy requires read access to Kubernetes API resources, node and container telemetry, and credentials for observability backends. The Alloy container image runs as root by default and defines a non-root alloy user with UID 473 and GID 473. Set securityContext, RBAC, and network settings to match the components in your configuration.

The Alloy Docker container image defines two users:

  • A root user.
  • A non-root user named alloy with UID 473 and GID 473.

Note

Components like beyla.ebpf and pyroscope.ebpf need root or additional Linux capabilities. Don’t set capabilities.drop: [ALL] when these components are in your configuration. Refer to the component references for required capabilities and Pod settings.

Run as a non-root user

To run Alloy as a non-root user, configure a security context for the Alloy container. If you use the Grafana Helm chart, add this to values.yaml:

YAML
alloy:
  securityContext:
    runAsUser: 473
    runAsGroup: 473

global:
  podSecurityContext:
    fsGroup: 473

configReloader:
  securityContext:
    # this is the UID of the "nobody" user that the configReloader image runs as
    runAsUser: 65534
    runAsGroup: 65534

This configuration runs the Alloy binary with UID 473 and GID 473 instead of as root. It also runs the config reloader sidecar as UID 65534 and GID 65534.

Set container permissions

Set securityContext at the Pod and container level to limit filesystem writes, privilege escalation, and Linux capabilities:

YAML
spec:
  securityContext:
    runAsUser: 473
    runAsGroup: 473
    fsGroup: 473
    runAsNonRoot: true
  containers:
    - name: alloy
      securityContext:
        readOnlyRootFilesystem: true
        allowPrivilegeEscalation: false
        capabilities:
          drop:
            - ALL
  • runAsNonRoot: true causes Kubernetes to reject the Pod if the image tries to run as root.
  • readOnlyRootFilesystem: true blocks writes to the container filesystem except on mounted volumes.
  • allowPrivilegeEscalation: false blocks privilege escalation beyond the parent process, regardless of file capabilities or setuid bits.
  • capabilities.drop: [ALL] removes all Linux capabilities from the container.

When you set readOnlyRootFilesystem: true, mount a writable volume at that path or change alloy.storagePath to a mounted volume.

Note

If you use components that need elevated host access, for example beyla.ebpf or pyroscope.ebpf, add the capabilities those components need. Don’t drop all capabilities when these components are in your configuration. Refer to the component references for required capabilities and volume mounts.

Restrict the HTTP server

The Grafana Helm chart sets alloy.listenAddr to 0.0.0.0 by default so other Pods can reach the container on port 12345. Set alloy.listenAddr to 127.0.0.1 in values.yaml or restrict access with a NetworkPolicy when you don’t need cross-Pod access to the UI or /metrics endpoint. The container image uses the binary default of 127.0.0.1:12345 when you don’t pass --server.http.listen-addr. Refer to the http block for TLS and authentication options.

Kubernetes RBAC

Alloy needs RBAC permissions to interact with Kubernetes APIs. The Helm chart creates a ClusterRole and ClusterRoleBinding when rbac.create is true. The Helm chart sets rbac.rules and rbac.clusterRules in values.yaml. Refer to the Grafana Helm chart values.yaml or README for the default rule blocks and the components each one supports.

To limit permissions, set rbac.rules and rbac.clusterRules to only the rule blocks your configuration uses. Helm replaces each array in full, so copy the defaults and remove the blocks you don’t need. Set rbac.create to false if you manage RBAC outside the chart.

Review the RBAC resources the Helm chart creates:

shell
helm template alloy grafana/alloy --show-only templates/rbac.yaml

Next steps