Skip to main content

ScoutInstallation

A ScoutInstallation turns on Scout's standard collection for a whole Kubernetes cluster from one short resource. Every kind of coverage is a preset, and every preset is on by default, so the smallest resource already collects application telemetry, Kubernetes and host metrics, events, container logs, and Kubernetes metadata. Turning a preset off is one line.

From the presets that are on, the operator decides which collectors to run and creates them as ordinary ScoutCollector resources:

CollectorRuns asExists when
nodeDaemonSet on the node's network, one pod per nodeapplicationTelemetry, kubernetesMetrics, logs, or hostMetrics is on
clusterDeployment, always one replicakubernetesMetrics or kubernetesEvents is on
gatewayDeployment with a HorizontalPodAutoscaler and a PodDisruptionBudgetgateway.enabled is true, the default

The node and cluster collectors send to the gateway, and the gateway sends to Scout. Each collector is visible with kubectl get scoutcollectors, and the operator keeps them in step with the ScoutInstallation: an edit to a generated collector is reverted.

Use one ScoutInstallation per cluster. For a collector this page does not cover, such as one that scrapes a specific application, write a ScoutCollector that sends to the gateway.

Presets​

PresetWhat you getRuns onBrings with it
applicationTelemetryTraces, metrics, and logs your applications send over OTLP on ports 4317 (gRPC) and 4318 (HTTP)node and gatewayThe receiving ports
kubernetesMetricsNode, pod, container, and volume metrics from the kubelet, and cluster state such as deployments, replicas, restarts, and pod phaseskubelet metrics on node, cluster state on clusterRead access to nodes and cluster objects
kubernetesEventsKubernetes events as logsclusterRead access to events
logsEvery container's stdout and stderrnodeA read-only mount of the pod log directory, and the collector runs as root
hostMetricsNode CPU, memory, disk, filesystem, network, load, paging, and processesnodeA read-only mount of the node's root filesystem
kubernetesAttributesPod, namespace, workload, node, and container names and IDs, container image, cluster UID, resource.opentelemetry.io/* pod annotations, and app.kubernetes.io/* pod labels on all telemetrynode and clusterRead access to pods, namespaces, and ReplicaSets
selfMonitoringEach collector's own metricsevery collectorNothing

Turning a preset off removes everything it brought: its receivers, its permissions, its mounts, and the root user for logs. Turning off both kubernetesMetrics and kubernetesEvents removes the cluster collector.

kubernetesAttributes and selfMonitoring add to collectors that exist for another reason. On their own they collect nothing, so a resource whose only presets are these two, with the gateway off, is rejected as having nothing to collect.

Before you start​

You need Scout Operator 0.1.16 or later, from chart 0.1.13 or later. See Install.

You need two credentials, each stored in a Secret:

  • your Scout client ID and secret, which the collectors use to send telemetry to Scout and to connect to Scout fleet management;
  • a bootstrap credential, which collectors use to recover their last applied configuration from fleet management when a pod starts.

Create the bootstrap credential in the Scout console:

  1. Open https://console.base14.io/<your-org>/api-keys. You need admin access to your organization.
  2. Select Create API Key and give it a name, such as the cluster name.
  3. Set Credential type to Capo Bootstrap. This credential can only read collector configuration during recovery. Create one per cluster.
  4. Copy the client ID and client secret. The secret is shown only once.

Then create a namespace and both Secrets:

kubectl create namespace scout

kubectl create secret generic scout-credentials \
--namespace scout \
--from-literal=clientId=__YOUR_CLIENT_ID__ \
--from-literal=clientSecret=__YOUR_CLIENT_SECRET__

kubectl create secret generic scout-bootstrap \
--namespace scout \
--from-literal=clientId=__YOUR_BOOTSTRAP_CLIENT_ID__ \
--from-literal=clientSecret=__YOUR_BOOTSTRAP_CLIENT_SECRET__

In Direct mode, collectors do not use fleet management, and you need only scout-credentials. See Credentials for every option.

Full coverage​

This resource turns on every preset and creates all three collectors:

apiVersion: telemetry.scout.base14.io/v1alpha1
kind: ScoutInstallation
metadata:
name: scout-collector
namespace: scout
spec:
clusterName: prod-eu
environment: production
scout:
endpoint: https://otel.play.b14.dev/__YOUR_TENANT__/otlp
tokenURL: https://id.b14.dev/realms/__YOUR_TENANT__/protocol/openid-connect/token
credentialsSecretRef:
name: scout-credentials
management:
opampEndpoint: wss://capo.base14.io/v1/connect
bootstrapEndpoint: https://capo.base14.io
bootstrapCredentialsSecretRef:
name: scout-bootstrap

clusterName identifies the cluster in Scout and cannot change after the resource is created. The connection to fleet management uses scout-credentials unless you give it its own Secret. See Credentials.

To run the generated configuration only, without fleet management, set management.mode: Direct and leave out the rest of management:

spec:
management:
mode: Direct

Apply and check​

kubectl apply -f scoutinstallation.yaml
kubectl get scoutinstallation -n scout
kubectl get scoutcollectors -n scout

The resource reports Ready once every collector it created is ready:

NAME CLUSTER READY PRESETS AGE
scout-collector prod-eu True 7 3m

kubectl describe scoutinstallation scout-collector -n scout lists each collector with its ready replicas, and the addresses applications send to.

Sending application telemetry​

Applications send OTLP to the gateway Service:

ProtocolAddress
gRPCscout-collector-agent-collector.scout.svc.cluster.local:4317
HTTPhttp://scout-collector-agent-collector.scout.svc.cluster.local:4318

The Service is named <name>-agent-collector, the same address the scout-collector Helm chart uses, so applications already sending there need no change. Set gateway.serviceName to use a different name.

The node collector also listens on each node's own address, which keeps traffic on the node:

env:
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: http://$(HOST_IP):4318

With auto-instrumentation, set the ScoutInstrumentation exporter endpoint to the gateway address.

Service names​

Every signal arrives in Scout with a service.name:

Signalservice.name
Traces, metrics, and logs your applications sendThe name the application sets
Container logsThe pod's resource.opentelemetry.io/service.name annotation, or else the container name
Kubernetes and host metricsk8s
Kubernetes eventsk8s-events

To name a workload's container logs, annotate its pods:

spec:
template:
metadata:
annotations:
resource.opentelemetry.io/service.name: checkout

The pod labels app.kubernetes.io/name, instance, version, component, part-of, and managed-by arrive as kube_app_name, kube_app_instance, and so on.

Turning coverage off​

Set enabled: false on any preset. Nothing else in the resource changes:

spec:
presets:
kubernetesEvents:
enabled: false
hostMetrics:
enabled: false

Only the collectors whose configuration changes restart.

Collection intervals​

kubernetesMetrics and hostMetrics collect every 60 seconds by default:

spec:
presets:
kubernetesMetrics:
collectionInterval: 30s
hostMetrics:
collectionInterval: 2m

Logs​

The logs preset reads every container's log from the node. To limit it, list namespaces to include or to exclude, not both:

spec:
presets:
logs:
excludeNamespaces: [kube-system]

The collectors' own logs are always excluded.

The node collector runs as root while logs is on, because the kubelet writes pod logs readable only by root. All Linux capabilities stay dropped and the root filesystem stays read-only.

Custom pod log directory​

Logs are read from /var/log/pods, where the kubelet writes them by default. If your nodes' kubelet sets podLogsDir to another directory, set the same directory on the preset:

spec:
presets:
logs:
podLogsDir: /var/data/kubelet/pods

The path must be absolute, and cannot be / or contain .. or wildcard characters. Inside the collector the directory is always mounted at /var/log/pods, so the log.file.path attribute in Scout shows that path.

Without a gateway​

On small clusters you can leave out the gateway. The node and cluster collectors then send to Scout directly:

spec:
gateway:
enabled: false

Applications then send to the node collector on each node's address, since the gateway Service no longer exists.

Credentials​

Up to three credentials are involved, each in a Secret in the ScoutInstallation namespace. Each one defaults to the one above it:

FieldUsed forDefault
scout.credentialsSecretRefSending telemetry to Scoutrequired
management.credentialsSecretRefEach collector's connection to fleet managementscout.credentialsSecretRef
management.bootstrapCredentialsSecretRefReading a collector's last applied configuration when a pod starts, and refreshing the recovery cachemanagement.credentialsSecretRef

Each Secret holds the client ID under clientId and the secret under clientSecret. To use other keys, set clientIDKey and clientSecretKey next to the Secret name.

The bootstrap credential needs the capo:bootstrap scope, which only a Capo Bootstrap credential from the console carries. Without it, fleet management refuses the recovery read and pods cannot restore their last configuration. Create one per cluster as in Before you start.

The connection to fleet management accepts the same credential the collectors send telemetry with, so scout-credentials works there. To give it a credential of its own, store another collector client ID and secret the same way and reference it:

spec:
management:
credentialsSecretRef:
name: scout-opamp

Every supervised collector mounts the fleet management credentials. Only collectors that send to Scout directly get the Scout client secret: the gateway, or every collector when the gateway is off. When the fleet management connection uses scout-credentials, the default, every collector holds that secret.

Scheduling and sizing​

Each collector role takes the same scheduling fields, under node, cluster, and gateway:

FieldDefault
nodeSelectorkubernetes.io/os: linux. Setting it replaces the default
tolerationsnone
affinitynone
priorityClassNamenone
resourcesnode and cluster: requests 100m CPU and 256Mi memory, limit 512Mi. gateway: requests 200m and 512Mi, limit 1Gi
podLabels, podAnnotationsnone
strategycluster: Recreate. gateway: rolling update with no pod unavailable. Ignored on node

The node collector has no tolerations by default, so it skips tainted nodes such as control planes or dedicated node pools. To collect from every node:

spec:
node:
tolerations:
- operator: Exists

There is no default priority class. Setting system-node-critical on the node collector keeps it from being evicted first when a node runs short of memory, but some providers, GKE among them, allow that class only in kube-system unless a ResourceQuota permits it elsewhere. Set it where your cluster allows it:

spec:
node:
priorityClassName: system-node-critical

The gateway scales between 2 and 6 replicas at 70% CPU, and keeps at least one replica available during disruptions:

spec:
gateway:
autoscaling:
minReplicas: 3
maxReplicas: 10
targetCPUUtilizationPercentage: 60
minAvailable: 2

minReplicas is at least 2, and maxReplicas at least minReplicas.

All fields​

FieldDefaultDescription
clusterNamerequiredCluster name in Scout. Lowercase letters, digits, and -, at most 63 characters. Cannot change
environmentrequiredAdded to all telemetry
scout.endpointrequiredYour Scout OTLP endpoint
scout.tokenURLrequiredYour Scout token endpoint
scout.audienceb14collectorToken audience
scout.credentialsSecretRef.namerequiredSecret with the Scout client ID and secret
scout.credentialsSecretRef.clientIDKey, clientSecretKeyclientId, clientSecretKeys in that Secret. The same two fields exist on every credentials reference
management.modeSupervisedSupervised or Direct
management.opampEndpoint, bootstrapEndpointrequired when SupervisedFleet management endpoints
management.credentialsSecretRefscout.credentialsSecretRefSee Credentials
management.bootstrapCredentialsSecretRefmanagement.credentialsSecretRefSee Credentials
management.bootstrapScopes[capo:bootstrap]Scopes requested for the bootstrap client
presets.<preset>.enabledtrueSee Presets
presets.kubernetesMetrics.collectionInterval60sKubelet and cluster metrics interval
presets.hostMetrics.collectionInterval60sHost metrics interval
presets.kubernetesEvents.namespacesallNamespaces whose events are collected
presets.logs.includeNamespaces, excludeNamespacesnoneSet one or neither
presets.logs.podLogsDir/var/log/podsSee Custom pod log directory
node, cluster, gatewaysee Scheduling and sizing
gateway.enabledtruefalse sends directly to Scout
gateway.serviceName<name>-agent-collectorThe Service applications send to
gateway.autoscaling.minReplicas, maxReplicas, targetCPUUtilizationPercentage2, 6, 70
gateway.minAvailable1PodDisruptionBudget

The resource name is at most 43 characters, so the names of the collectors it creates stay within Kubernetes limits.

What it creates​

For a ScoutInstallation named scout-collector:

CollectorScoutCollectorConfiguration ConfigMapService
nodescout-collector-daemonsupervisor-daemon-configdaemon-collector, when applicationTelemetry is on
clusterscout-collector-agent-clustersupervisor-agent-cluster-confignone
gatewayscout-collector-gatewaysupervisor-gateway-configscout-collector-agent-collector

These are the names the scout-collector Helm chart uses in operator mode. In Scout fleet management the collectors report the roles daemon, agent (with collector.name=cluster), and gateway. See How collectors appear in Scout.

The Collector version is the one the operator pins, 0.161.0 in operator 0.1.16. Upgrading the operator upgrades it.

Moving from the scout-collector chart​

A cluster running the scout-collector chart in operator mode can move without senders changing their address, because a ScoutInstallation named after the chart release uses the chart's names.

  1. In the release namespace, apply a ScoutInstallation named after the release, usually scout-collector, with the same cluster name and environment. Turn off presets the cluster does not collect today if the move should not add coverage.
  2. The operator takes over the chart's ScoutCollector resources and ConfigMaps in place. The gateway Service keeps its address, and each collector restarts once.
  3. Remove the chart straight away, without deleting what was taken over: exclude those objects from Argo CD's pruning, or mark them helm.sh/resource-policy: keep. Until the chart is gone, a sync can write its version of those objects back, so turn off automated sync for the release before step 1. If the objects are deleted anyway, the operator recreates them, at the cost of one more restart.
  4. Once every collector is ready and data arrives in Scout, delete what the chart created that the ScoutInstallation does not use, such as its ServiceAccount and bootstrap Secret.

Named agents the chart runs beyond the cluster agent, and custom configurations in chart values, have no ScoutInstallation equivalent. Keep them as ScoutCollector resources that send to the gateway.

Try the move on one cluster before the rest.

Deleting​

Delete the ScoutInstallation to remove every collector it created, with their permissions:

kubectl delete scoutinstallation scout-collector -n scout
warning

Delete every ScoutInstallation before uninstalling Scout Operator. Collectors that hold cluster permissions keep a finalizer that only the running operator removes, so uninstalling first leaves them, and the CRDs, stuck in deletion.

Troubleshooting​

kubectl describe scoutinstallation <name> shows why the resource is not ready:

ReasonMeaning
CredentialsSecretNotFound, ManagementCredentialsSecretNotFound, BootstrapCredentialsSecretNotFoundThe Secret is missing. Create it and the resource recovers on its own
InvalidCredentialsSecret, InvalidManagementCredentialsSecret, InvalidBootstrapCredentialsSecretThe Secret lacks a client ID or secret under the expected keys
InvalidSpecFor example, nothing left to collect. See Presets
DuplicateScoutInstallationAnother ScoutInstallation in the cluster is older and active. This one creates nothing
CollectorsNotReadyA collector is still starting. Check kubectl get scoutcollectors

The node collector is missing from some nodes​

Those nodes are tainted. Add tolerations to node.

Node collector pods are not created​

If the DaemonSet reports a priority class error, the cluster does not allow the class set in node.priorityClassName in this namespace. Remove it or use a class the cluster allows.

No container logs arrive​

Check where the kubelet writes pod logs on a node. If it is not /var/log/pods, set podLogsDir.

Log volume grows without stopping​

A workload that writes every log record it receives to its own output, such as a Collector with a debug exporter, feeds back into the logs preset. Add its namespace to excludeNamespaces.

FAQ​

How many ScoutInstallations should a cluster have?​

A cluster needs exactly one ScoutInstallation. Two would collect cluster state and events twice, so only the oldest is active and any other reports DuplicateScoutInstallation.

Can I edit the ScoutCollectors a ScoutInstallation creates?​

No, the operator reverts edits to the collectors it creates. Change the ScoutInstallation instead, or write your own ScoutCollector for anything it does not cover.

Can I add my own receivers to the generated collectors?​

Not in this version. Run a separate ScoutCollector with the receiver you need and send its output to the gateway Service.

Does ScoutInstallation collect from Windows nodes?​

No, the node collector runs on Linux nodes only. Windows workloads can still send OTLP to the gateway Service.

Are logs lost when a node collector restarts?​

Lines written while a node collector restarts are not collected. The collector starts reading each log file from its end, so restarts from preset changes or operator upgrades leave a short gap.

Was this page helpful?