Sample CRs¶
Working examples of each CRD this operator manages. Apply with:
kubectl apply -n <namespace> -f config/samples/<namespaced-file>.yaml
kubectl apply -f config/samples/tenant_policy_sample.yaml
Namespaced samples intentionally omit metadata.namespace. Apply them to the namespace that should own the CR. TenantPolicy is cluster-scoped and must not carry a namespace.
For invalid-spec fixtures used by webhook tests, see config/samples/invalid/README.md.
Index¶
- Collector:
edge-host-42— Manually-managed Collector CR that overrides remote attributes for one specific collector by ID. - CollectorDiscovery:
prod-linux— CollectorDiscovery that polls Fleet Management every 5 minutes and creates a Collector CR for every Linux production collector. - ExternalAttributeSync:
cmdb-host-attributes— ExternalAttributeSync that pulls host metadata from a CMDB HTTP endpoint every 5 minutes and assigns env / region attributes per collector. - Pipeline:
alloy-pipeline-sample— Alloy Pipeline that scrapes Alloy's own self-metrics and remote-writes them to Grafana Cloud, scoped to Linux collectors in production. - Pipeline:
otel-metrics-pipeline— OpenTelemetry Collector Pipeline that scrapes host metrics and exports OTLP to Grafana Cloud. - PipelineDiscovery:
import-alloy-pipelines— PipelineDiscovery that imports enabled Alloy pipelines from Fleet Management as read-only Pipeline CRs. - RemoteAttributePolicy:
linux-prod-defaults— RemoteAttributePolicy that assigns default region / team attributes to every Linux production collector. Per-Collector CRs override on key collisions. - TenantPolicy:
team-billing— TenantPolicy that requires the billing team's Pipelines, Policies, and Syncs to carry a team=billing matcher (RBAC tenancy guard).
Collector: edge-host-42¶
Manually-managed Collector CR that overrides remote attributes for one specific collector by ID.
Source: config/samples/collector_sample.yaml
apiVersion: fleetmanagement.grafana.com/v1alpha1
kind: Collector
metadata:
name: edge-host-42
spec:
# ID must match a collector that has registered with Fleet Management
# (the collector calls RegisterCollector when it starts up). The operator
# does not create collectors — it only manages their remote attributes.
id: edge-host-42
# remoteAttributes are key/value pairs the operator writes to Fleet
# Management. Keys with the prefix "collector." are reserved by Fleet
# for collector-reported (local) attributes and are rejected by the
# admission webhook.
remoteAttributes:
env: prod
region: us-east-1
team: platform
CollectorDiscovery: prod-linux¶
CollectorDiscovery that polls Fleet Management every 5 minutes and creates a Collector CR for every Linux production collector.
Source: config/samples/collector_discovery_sample.yaml
apiVersion: fleetmanagement.grafana.com/v1alpha1
kind: CollectorDiscovery
metadata:
name: prod-linux
spec:
# How often to call Fleet's ListCollectors. Webhook-enforced minimum
# is 1 minute to protect the shared 3 req/s rate limiter.
pollInterval: 5m
# Server-side filter passed to ListCollectors. Empty selector mirrors
# every collector — accepted but expensive on large fleets.
selector:
matchers:
- "collector.os=linux"
- "env=prod"
# Where to create mirrored Collector CRs. Defaults to this
# CollectorDiscovery's own namespace if omitted.
#
# Setting it to ANOTHER namespace is a privileged, cross-namespace action:
# the operator uses its cluster-wide ServiceAccount to write Collector CRs
# there (a confused-deputy vector). Restrict who can create CollectorDiscovery
# CRs to platform/admin subjects, and consider enabling the manager flag
# --enforce-cross-namespace-discovery-authz. See docs/security.md.
# targetNamespace: fleet-mirror
# Mirror collectors marked inactive in Fleet. Default false.
# includeInactive: false
policy:
# Keep (default): a collector that vanishes from Fleet has its CR
# marked stale via annotation, but the CR remains so user-added
# spec.remoteAttributes survive transient outages.
# Delete: removes the CR; the existing Collector finalizer issues
# REMOVE ops to Fleet (which 404s for a vanished collector — net
# no-op). Use this for clean-mirror semantics where preserving
# user data is not a goal.
onCollectorRemoved: Keep
# v1 only ships Skip — leave conflicting CRs alone.
onConflict: Skip
ExternalAttributeSync: cmdb-host-attributes¶
ExternalAttributeSync that pulls host metadata from a CMDB HTTP endpoint every 5 minutes and assigns env / region attributes per collector.
Source: config/samples/external_sync_sample.yaml
apiVersion: fleetmanagement.grafana.com/v1alpha1
kind: ExternalAttributeSync
metadata:
name: cmdb-host-attributes
spec:
source:
kind: HTTP
http:
url: https://cmdb.example.com/api/hosts
method: GET
# If the response is {"data": {"items": [...]}} use a dotted path:
# recordsPath: data.items
# Optional Secret with auth credentials. Recognized keys:
# bearer-token -> Authorization: Bearer <token> (preferred)
# username + password -> HTTP Basic auth fallback
secretRef:
name: cmdb-credentials
# Either a Go duration ("5m", "30s") or a 5-field cron expression
# ("*/15 * * * *"). Required.
schedule: 5m
# Selector — same shape as RemoteAttributePolicy. Matches AND-ed; OR-ed
# with the explicit collectorIDs list. Empty selector = matches nothing.
selector:
matchers:
- "collector.os=linux"
# Mapping projects each source record into one (collectorID, attributes)
# tuple. The CMDB returns records like:
# {"hostname": "edge-host-42", "env": "prod", "region": "us-east-1"}
mapping:
collectorIDField: hostname
attributeFields:
env: env
region: region
requiredKeys:
- hostname
- env
# Safety guard: when the source returns 0 records but the previous run
# had >0, the controller preserves the prior claim and surfaces a
# Stalled condition. Set true to opt out (e.g. when an empty result is
# legitimate).
allowEmptyResults: false
Pipeline: alloy-pipeline-sample¶
Alloy Pipeline that scrapes Alloy's own self-metrics and remote-writes them to Grafana Cloud, scoped to Linux collectors in production.
Source: config/samples/alloy_pipeline_sample.yaml
apiVersion: fleetmanagement.grafana.com/v1alpha1
kind: Pipeline
metadata:
labels:
app.kubernetes.io/name: fleet-management-operator
app.kubernetes.io/managed-by: kustomize
name: alloy-pipeline-sample
spec:
# Unique pipeline name in Fleet Management. Optional: defaults to
# metadata.name. No whitespace/control characters; max 253 characters.
name: pipeline_sample
# Alloy configuration for Prometheus self-monitoring
contents: |
prometheus.exporter.self "alloy" { }
prometheus.scrape "alloy" {
targets = prometheus.exporter.self.alloy.targets
forward_to = [prometheus.remote_write.grafanacloud.receiver]
scrape_interval = "60s"
}
prometheus.remote_write "grafanacloud" {
external_labels = {"collector_id" = constants.hostname}
endpoint {
url = env("PROMETHEUS_URL")
basic_auth {
username = env("PROMETHEUS_USER")
password_file = "/etc/secrets/prometheus-password"
}
}
}
# Assign to Linux collectors in production
matchers:
- collector.os=linux
- environment=production
# Enable the pipeline
enabled: true
# Configuration type (Alloy or OpenTelemetryCollector)
configType: Alloy
source:
type: Git
namespace: github.com/mbaykara/alloy-configs
Pipeline: otel-metrics-pipeline¶
OpenTelemetry Collector Pipeline that scrapes host metrics and exports OTLP to Grafana Cloud.
Source: config/samples/pipeline_otel_sample.yaml
apiVersion: fleetmanagement.grafana.com/v1alpha1
kind: Pipeline
metadata:
labels:
app.kubernetes.io/name: fleet-management-operator
app.kubernetes.io/managed-by: kustomize
name: otel-metrics-pipeline
spec:
# Unique pipeline name in Fleet Management. Optional: defaults to
# metadata.name. No whitespace/control characters; max 253 characters.
name: otel_metrics_pipeline
# OpenTelemetry Collector configuration
contents: |
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
batch:
timeout: 10s
send_batch_size: 1024
exporters:
prometheusremotewrite:
endpoint: ${env:PROMETHEUS_URL}
auth:
authenticator: basicauth
extensions:
basicauth:
client_auth:
username: ${env:PROMETHEUS_USER}
password: ${env:PROMETHEUS_PASSWORD}
service:
extensions: [basicauth]
pipelines:
metrics:
receivers: [otlp]
processors: [batch]
exporters: [prometheusremotewrite]
# Assign to collectors running OTEL
matchers:
- collector.type=otel
- environment=production
enabled: true
# Must specify OpenTelemetryCollector for OTEL config
configType: OpenTelemetryCollector
# Optional: Source of the pipeline for tracking and grouping
source:
type: Terraform
namespace: production-workspace
PipelineDiscovery: import-alloy-pipelines¶
PipelineDiscovery that imports enabled Alloy pipelines from Fleet Management as read-only Pipeline CRs.
Source: config/samples/pipeline_discovery_sample.yaml
apiVersion: fleetmanagement.grafana.com/v1alpha1
kind: PipelineDiscovery
metadata:
name: import-alloy-pipelines
spec:
pollInterval: 5m
importMode: ReadOnly
selector:
configType: Alloy
enabled: true
# Omit targetNamespace to create Pipeline CRs in this
# PipelineDiscovery's own namespace.
#
# Setting it to ANOTHER namespace is a privileged, cross-namespace action:
# the operator uses its cluster-wide ServiceAccount to write Pipeline CRs
# there (a confused-deputy vector). Restrict who can create PipelineDiscovery
# CRs to platform/admin subjects, and consider enabling the manager flag
# --enforce-cross-namespace-discovery-authz. See docs/security.md.
# targetNamespace: fleet-pipelines
policy:
onPipelineRemoved: Keep
RemoteAttributePolicy: linux-prod-defaults¶
RemoteAttributePolicy that assigns default region / team attributes to every Linux production collector. Per-Collector CRs override on key collisions.
Source: config/samples/policy_sample.yaml
apiVersion: fleetmanagement.grafana.com/v1alpha1
kind: RemoteAttributePolicy
metadata:
name: linux-prod-defaults
spec:
# Selectors. A collector matches if all matchers are true (AND-ed) OR if
# its ID appears in collectorIDs. An empty selector matches NOTHING — both
# selector clauses must be intentional.
selector:
matchers:
- "collector.os=linux"
- "env=prod"
# Optional explicit ID list, OR-ed with the matcher result.
collectorIDs: []
# Attributes applied to every matched collector. Per-Collector CRs win on
# key collisions (Collector spec is the override layer; Policy is the
# default). collector.* prefixed keys are reserved by Fleet Management.
attributes:
region: us-east-1
team: platform
# Higher priority wins among policies that match the same collector and
# set the same key. Equal priority is broken alphabetically by namespaced
# name. Default is 0.
priority: 0
TenantPolicy: team-billing¶
TenantPolicy that requires the billing team's Pipelines, Policies, and Syncs to carry a team=billing matcher (RBAC tenancy guard).
Source: config/samples/tenant_policy_sample.yaml
apiVersion: fleetmanagement.grafana.com/v1alpha1
kind: TenantPolicy
metadata:
name: team-billing
spec:
# Subjects this policy applies to. Use the same forms as a RoleBinding:
# User by username, Group by IDP group name, ServiceAccount by name and
# namespace.
subjects:
- kind: Group
name: team-billing-engineers
- kind: ServiceAccount
name: argocd-billing
namespace: argocd
# Members of any subject above must include at least one of these
# matchers in Pipeline.spec.matchers (or the equivalent
# spec.selector.matchers on RemoteAttributePolicy / ExternalAttributeSync)
# to be allowed by the validating webhook.
requiredMatchers:
- team=billing
- team=billing-shared
# Optional: restrict the policy to specific namespaces by their labels.
# Omit to apply in every namespace.
namespaceSelector:
matchLabels:
tenant: billing