Skip to main content

Configure BYOC on Kubernetes

This guide installs a reference collector and connects the Speedscale Forwarder to it. Repeat the backend and exporter steps for every independent destination channel.

Prerequisites​

  • A Kubernetes cluster such as EKS, GKE, AKS, k3s, or minikube
  • kubectl configured for the cluster and Helm 3
  • A Speedscale API key with BYOC enabled
  • Credentials and an existing destination for the backend you select

1. Add the Helm repositories​

helm repo add speedscale https://speedscale.github.io/operator-helm/
helm repo add speedscale-byoc https://speedscale.github.io/speedscale-byoc/
helm repo update

2. Create the Speedscale API key Secret​

kubectl create namespace speedscale
kubectl -n speedscale create secret generic speedscale-apikey \
--from-literal=SPEEDSCALE_API_KEY="<YOUR_API_KEY>" \
--from-literal=SPEEDSCALE_APP_URL="app.speedscale.com"

3. Install a backend collector​

Install each collector in its own namespace. The chart README contains its complete IAM policy, credential, and configuration options.

Amazon S3 with static credentials​

kubectl create namespace byoc-s3
kubectl -n byoc-s3 create secret generic s3-creds \
--from-literal=accessKeyId="<AWS_ACCESS_KEY_ID>" \
--from-literal=secretAccessKey="<AWS_SECRET_ACCESS_KEY>"

helm upgrade --install byoc-s3 speedscale-byoc/fluentbit-s3 \
-n byoc-s3 \
--set s3.bucket="<S3_BUCKET>" \
--set s3.region="<AWS_REGION>" \
--set s3.credentialsSecret="s3-creds"

Amazon S3 with EKS IAM Roles for Service Accounts​

helm upgrade --install byoc-s3 speedscale-byoc/fluentbit-s3 \
-n byoc-s3 --create-namespace \
--set s3.bucket="<S3_BUCKET>" \
--set s3.region="<AWS_REGION>" \
--set irsa.enabled=true \
--set irsa.roleArn="arn:aws:iam::<ACCOUNT_ID>:role/<ROLE_NAME>"

Native Google Cloud Storage​

The chart reuses an existing bucket. Its Google service account (GSA) therefore needs storage.objects.create to write objects and storage.buckets.get to check that the bucket exists. roles/storage.objectCreator contains only the first permission, so add a narrowly scoped custom role for the second.

Create the GSA and custom role, then grant both roles on the bucket:

gcloud iam service-accounts create byoc-gcs \
--project=<GCP_PROJECT>

gcloud iam roles create speedscaleByocBucketReader \
--project=<GCP_PROJECT> \
--title="Speedscale BYOC bucket reader" \
--permissions=storage.buckets.get \
--stage=GA

gcloud storage buckets add-iam-policy-binding gs://<GCS_BUCKET> \
--member="serviceAccount:byoc-gcs@<GCP_PROJECT>.iam.gserviceaccount.com" \
--role="roles/storage.objectCreator"

gcloud storage buckets add-iam-policy-binding gs://<GCS_BUCKET> \
--member="serviceAccount:byoc-gcs@<GCP_PROJECT>.iam.gserviceaccount.com" \
--role="projects/<GCP_PROJECT>/roles/speedscaleByocBucketReader"

The GCS exporter documents the extra bucket-read permission required by reuse_if_exists. The predefined Storage Object Creator role does not include it.

With Workload Identity Federation enabled on the cluster and node pool, link the deterministic Kubernetes service account (KSA) byoc-gcs in namespace byoc-gcs to the GSA. Both this IAM binding and the annotation in the Helm values are required by the GKE service-account linking procedure:

gcloud iam service-accounts add-iam-policy-binding \
byoc-gcs@<GCP_PROJECT>.iam.gserviceaccount.com \
--role="roles/iam.workloadIdentityUser" \
--member="serviceAccount:<GCP_PROJECT>.svc.id.goog[byoc-gcs/byoc-gcs]"

Configure the KSA name and GSA annotation in values-gcs.yaml:

gcs:
project: <GCP_PROJECT>
bucket: <GCS_BUCKET>
region: <GCS_REGION>
serviceAccount:
name: byoc-gcs
annotations:
iam.gke.io/gcp-service-account: byoc-gcs@<GCP_PROJECT>.iam.gserviceaccount.com
helm upgrade --install byoc-gcs speedscale-byoc/gcs \
-n byoc-gcs --create-namespace \
-f values-gcs.yaml

Loki and Grafana​

helm upgrade --install byoc-grafana speedscale-byoc/grafana \
-n byoc-grafana --create-namespace

Elasticsearch and Kibana​

helm upgrade --install byoc-elasticsearch speedscale-byoc/elasticsearch \
-n byoc-elasticsearch --create-namespace

For Azure Blob, Datadog, Dynatrace, New Relic, and advanced values, select the chart from the backend guide and follow its README.

4. Configure named Forwarder exporters​

Add one entry under forwarder.exporters for every collector. Keep filters and DLP configuration explicit per destination:

forwarder:
exporters:
byoc_s3:
otel_endpoint: "http://otel-collector.byoc-s3.svc.cluster.local:4317"
filter_rule: standard
dlp_config_id: standard
byoc_gcs:
otel_endpoint: "http://byoc-gcs-gcs.byoc-gcs.svc.cluster.local:4317"
filter_rule: standard
dlp_config_id: standard
byoc_grafana:
otel_endpoint: "http://otel-collector.byoc-grafana.svc.cluster.local:4317"
filter_rule: standard
dlp_config_id: standard

Install or upgrade the operator with that values file:

helm upgrade --install speedscale-operator speedscale/speedscale-operator \
-n speedscale --create-namespace \
--set apiKeySecret=speedscale-apikey \
--set clusterName=<CLUSTER_NAME> \
-f values.yaml
caution

Use the receiver's actual protocol port. A reference collector normally uses OTLP/gRPC on 4317. Including http:// is recommended for compatibility with Forwarder versions older than v2.5.617; newer Forwarders also accept scheme-less gRPC endpoints.

5. Enable capture​

Annotate the workload you want to capture:

kubectl patch deployment my-app -p \
'{"spec":{"template":{"metadata":{"annotations":{"capture.speedscale.com/enabled":"true"}}}}}'

The operator restarts or injects the required capture component according to the selected installation mode. Send a known request through the workload, then verify each BYOC hop.