Skip to main content

Deploy on Single-Node OpenShift

This path puts the Expanso Edge agent on a Single-Node OpenShift (SNO) node and deploys the telemetry job to it through Expanso Cloud. The agent runs under the default restricted-v2 SecurityContextConstraint: non-root, no privilege escalation, no hostPath, no hostNetwork. Everything it writes lands on PersistentVolumeClaims.

The manifests live in examples/integrations/oran-telco-pipeline/openshift. This page applies them; it does not report a verified run on a specific cluster.

What lands on the cluster​

ResourcePurpose
Namespace oran-telemetryRestricted pod security, default SCC
PVC oran-telemetry-data (50Gi) at /dataParquet output and dead-letter files
PVC expanso-edge-state (1Gi) at /var/lib/expansoNode identity, so restarts do not re-register the node
Kafka oran-kafka + KafkaNodePool (AMQ Streams)One KRaft broker, TLS listener on 9093 only, SCRAM-SHA-512
KafkaTopic x2, KafkaUser x2Topics and producer/consumer identities with separate ACLs
OpenTelemetryCollector oranOTLP in (4317/4318), Prometheus exporter out (8889)
ServiceMonitor oran-collectorHands the exporter to OpenShift user-workload monitoring
Deployment + Service expanso-edgeThe agent, plus an in-cluster endpoint for DU exporters to POST telemetry
ConfigMaps oran-site, expanso-edge-configSite identity env vars; agent config with the labels the job selects on

Prerequisites​

  • An SNO cluster and oc logged in as a user who can create a namespace. One step needs cluster-admin.
  • The AMQ Streams and Red Hat build of OpenTelemetry operators installed from OperatorHub.
  • A default StorageClass (on SNO this is usually the LVM Storage operator's class).
  • An Expanso Cloud account, a bootstrap token for a new node, and expanso-cli logged in.
  • A DU exporter that can POST JSON to an in-cluster Service, or leave the built-in simulator on.

Run the deployment​

  1. From the repository root, validate the job offline. This checks the config schema, every Bloblang mapping, and the component types.

    expanso-edge validate static/pipelines/oran-telco-pipeline.yaml
  2. Enable user-workload monitoring. Cluster-admin, once per cluster. If cluster-monitoring-config already exists, merge enableUserWorkload: true into it instead.

    cd examples/integrations/oran-telco-pipeline/openshift
    oc apply -f cluster/user-workload-monitoring.yaml
  3. Apply the namespace, storage, Kafka, collector, and agent manifests.

    oc apply -k .
  4. Create the two Secrets the Deployment reads. The third, expanso-oran, is written by the AMQ Streams User Operator.

    oc -n oran-telemetry create secret generic expanso-bootstrap \
    --from-literal=token="$EXPANSO_BOOTSTRAP_TOKEN"
    oc -n oran-telemetry create secret generic oran-du-api \
    --from-literal=token="$DU_API_KEY"
  5. Wait for Kafka, then confirm the CA and the user password exist. The agent pod stays in CreateContainerConfigError until they do.

    oc -n oran-telemetry wait kafka/oran-kafka \
    --for=condition=Ready --timeout=10m
    oc -n oran-telemetry get secret \
    oran-kafka-cluster-ca-cert expanso-oran
    oc -n oran-telemetry get pods
  6. From the OpenShift manifest directory, deploy the job through Expanso Cloud. The selector in the job spec matches the labels in expanso-edge-config.

    expanso-cli job deploy \
    ../../../../static/pipelines/oran-telco-pipeline.yaml

Before connecting a real DU, remove the du_simulator input from the job and redeploy it through Expanso Cloud. SIMULATION_INTERVAL=0s removes pacing; it does not disable the simulator.

The ingress NetworkPolicy permits TCP 8080 only from pods labelled app.kubernetes.io/name: oran-du in namespace oran-du. Set both selectors in 62-telemetry-networkpolicy.yaml to match your exporter before applying the manifests. This restricts access to the /telemetry listener by network source, not by HTTP path or claimed DU identity.

Expected output​

  • oc -n oran-telemetry get pods lists expanso-edge, oran-kafka-dual-role-0, the entity operator, and oran-collector as Running.

  • expanso-cli node list shows sno-oran-edge with labels platform=openshift-sno and role=oran-du-telemetry.

  • Within five minutes the first Parquet file exists on the claim:

    oc -n oran-telemetry exec deploy/expanso-edge -- \
    find /data/oran-telemetry -name '*.parquet'
  • In the OpenShift console, Observe, Metrics, the query oran_ptp_review_score returns one series per du_id.

  • oc -n oran-telemetry get kafkatopic shows both topics Ready.

Cleanup​

From the OpenShift manifest directory, oc delete -k . removes the namespace, its Secrets, and the PersistentVolumeClaims. Volume data deletion follows the StorageClass reclaim policy. Copy anything you want to keep first.

expanso-cli job delete oran-edge-telemetry
oc delete -k .

Common failures​

  • Pod Pending, PVC Pending. No default StorageClass. Set storageClassName on both claims.
  • CreateContainerConfigError. A referenced Secret is missing: expanso-bootstrap, oran-du-api, or expanso-oran (not yet created by the User Operator).
  • Agent restarts with a bootstrap error. The token expired or was revoked. Create a new one, update the Secret, and restart the Deployment.
  • Kafka output logs client has run out of available brokers. The CA is not mounted, the KafkaUser is not ready, or the listener name or port changed. The broker only speaks TLS on 9093.
  • No oran_* series. User-workload monitoring is off, or the ServiceMonitor label selector no longer matches the collector Service. Check oc -n openshift-user-workload-monitoring get pods.
  • Job never schedules. The agent's labels do not match the selector. Compare expanso-cli node describe with the selector block in the job.

Next: Inspect the source boundary.