Stream Host Installation
Overview
On XMPro 5.0, Stream Hosts run as pods in the same AKS or EKS cluster as the platform. There are two ways to deploy them, both driven by the layered Terraform deployment described in the AWS Kubernetes (EKS) and Azure Kubernetes (AKS) guides:
- Default Stream Host - the site application layer (layer 3) can install one Stream Host alongside the platform. Its Collection is created for it during the DS database migration, so it registers with Data Stream Designer on first start.
- Additional Stream Hosts - the Stream Hosts layer (layer 4,
examples/layered/stream-hosts) deploys one standalone Stream Host per Collection. Each is its own Helm release of thestreamhostchart with its own Collection ID and secret.
One Stream Host serves one Collection. To add capacity, add Collections and Stream Hosts rather than pointing several Stream Hosts at the same Collection.
Prerequisites
- Layers 1 to 3 of the AKS or EKS deployment applied, with Data Stream Designer reachable at its public URL
kubectlaccess to the cluster and Terraform installed, as set up in the deployment guide- A Collection in Data Stream Designer for each additional Stream Host. See Manage Collections to create one and copy its ID and Secret.
- The outputs of the site infrastructure and application layers (see the tables below)
Default Stream Host
The application layer's enable_default_stream_host variable controls the default Stream Host. It defaults to true on AKS and false on EKS, where the supported model is independent Stream Hosts through the Stream Hosts layer.
| Application layer variable | Description |
|---|---|
enable_default_stream_host |
Deploy the default in-cluster Stream Host with the platform. |
stream_host_collection_id |
Collection ID for the default Stream Host. Leave empty to generate one. The DS database migration creates the Collection. |
stream_host_collection_secret |
Collection secret for the default Stream Host. Leave empty to generate one. |
stream_host_replica_count |
Replica count for the default Stream Host. Defaults to 1. |
stream_host_image_tag |
Stream Host image tag. Empty falls back to the platform image_tag. |
Set these in the application layer's terraform.tfvars and apply. The default Stream Host appears in Data Stream Designer under Stream Hosts once the pod is running.
Additional Stream Hosts
The Stream Hosts layer lives next to the other layers in the deployment repository and is applied after the application layer. From the application layer directory:
Mac/Linux:
cd ../stream-hosts
cp terraform.tfvars.example terraform.tfvars
Windows (PowerShell):
cd ..\stream-hosts
Copy-Item terraform.tfvars.example terraform.tfvars
Configure the layer
Fill terraform.tfvars with the values from your site. Most come from the outputs of the infrastructure and application layers.
AKS:
| Variable | Value |
|---|---|
subscription_id |
Azure subscription |
cluster_name |
AKS cluster name, from layer 1 |
name_suffix |
Site identifier, the same as the infrastructure and application layers |
aks_resource_group_name |
Resource group of the AKS cluster, from layer 1's resource_group_name output |
resource_group_name |
Site resource group, from the infrastructure layer output |
key_vault_name |
Site Key Vault, from the infrastructure layer output |
namespace |
Site namespace, from the application layer output |
cluster_secret_store_name |
azurekv-<name_suffix> unless you renamed it in the application layer |
image_registry |
{{ACR_URL}} |
image_tag |
{{VERSION}} |
image_pull_secrets |
Required for the XMPro registry. A list holding the application layer's image_pull_secret_name output, ["xmpro-registry"] by default |
ds_server_url |
Data Stream Designer URL, from the application layer's ds_url output |
EKS:
| Variable | Value |
|---|---|
aws_region |
AWS region, the same as the other layers |
name_suffix |
Site identifier, from the infrastructure layer output |
cluster_name |
EKS cluster name, from layer 1 |
namespace |
Site namespace, name_suffix by default |
cluster_secret_store_name |
aws-secrets-<name_suffix> unless you renamed it in the application layer |
secrets_kms_key_arn |
From the infrastructure layer's secrets_kms_key_arn output |
image_registry |
{{ACR_URL}} |
image_tag |
{{VERSION}} |
image_pull_secrets |
Required for the XMPro registry. A list holding the application layer's image_pull_secret_name output, ["xmpro-registry"] by default |
ds_server_url |
Data Stream Designer URL, from the application layer's ds_url output |
Define the Stream Hosts
Each entry in the stream_hosts map is one Stream Host. The key is a short lowercase identifier used in the Kubernetes and secret resource names.
stream_hosts = {
ingest = {
collection_id = "<collection-id-from-DS>"
collection_secret = "<collection-secret-from-DS>"
gateway_name = "SH-AKS-site1-ingest"
}
agg = {
collection_id = "<collection-id-from-DS>"
collection_secret = "<collection-secret-from-DS>"
resources = {
limits = { cpu = "2000m", memory = "8Gi" }
requests = { cpu = "500m", memory = "2Gi" }
}
}
}
| Field | Description |
|---|---|
collection_id |
Required. The Collection ID from Data Stream Designer. |
gateway_name |
Display name in Data Stream Designer. Defaults to SH-<name_suffix>-<key> on AKS and SH-EKS-<name_suffix>-<key> on EKS. |
collection_secret |
Required. The Collection's Secret from Data Stream Designer. The layer stores it in Key Vault (AKS) or Secrets Manager (EKS) and External Secrets Operator delivers it to the pod. If it doesn't match the Collection, Data Stream Designer rejects the Stream Host and the pod restarts. |
image_tag |
Override the layer-wide image_tag for this instance. |
resources |
Container CPU and memory. The chart default is 500m / 1Gi limits and 100m / 256Mi requests. See Sizing. |
enable_app_insights |
Send telemetry to Application Insights. Requires app_insights_secret_name at the layer level. |
The AKS layer also accepts, per entry:
| Field | Description |
|---|---|
replica_count |
Number of pods for this Stream Host. Defaults to 1. |
image_variant |
Image tag suffix for a runtime variant, for example bookworm-slim-python3.12. Appended to the effective tag. |
On EKS each entry runs one pod, and the layer-wide enable_otel and otel_* variables push OTLP telemetry from the Stream Hosts to a collector. See Configure OpenTelemetry.
Apply
terraform init
terraform apply
Confirm each Stream Host shows online in Data Stream Designer under Stream Hosts. To add another, add an entry to stream_hosts and apply again. To remove one, delete its entry and apply.
Sizing
Start at a tier, monitor, then adjust. Actual needs depend on stream count, event rate and aggregation complexity.
| Tier | limits |
requests |
|---|---|---|
| Very Small (chart default) | cpu = "500m", memory = "1Gi" |
cpu = "100m", memory = "256Mi" |
| Small | cpu = "1000m", memory = "4Gi" |
cpu = "250m", memory = "1Gi" |
| Medium | cpu = "2000m", memory = "8Gi" |
cpu = "500m", memory = "2Gi" |
| Large | cpu = "4000m", memory = "16Gi" |
cpu = "1000m", memory = "4Gi" |
Updating
To move Stream Hosts to a new release, change image_tag in terraform.tfvars and apply. The Helm release rolls the pods. Set image_tag on a single entry to move one Stream Host on its own.
Troubleshooting
Stream Host not online in Data Stream Designer
kubectl get pods -n <namespace> -l app=xmpro-sh-<key>-stream-host-sh
kubectl logs -n <namespace> deployment/xmpro-sh-<key>-stream-host-sh -c sh
- Check
ds_server_urlmatches the Data Stream Designer URL and is reachable from the cluster. - Check the Collection ID exists in Data Stream Designer, and that
collection_secretmatches the Collection's Secret.Unauthorizedin the logs means it doesn't. kubectl get externalsecret -n <namespace> xmpro-sh-<key>should showSecretSynced. If not, the ClusterSecretStore name is wrong or External Secrets Operator cannot read the secret.
Stream Host still rejected after you change collection_secret
External Secrets Operator refreshes the pod's secret once an hour, so the pod keeps the old value after an apply. On EKS the layer also doesn't update a secret it has already stored. To push the new value:
# EKS only: replace the stored secret so the new value is written
terraform apply -replace='module.stream_host["<key>"].aws_secretsmanager_secret_version.collection_secret'
# AKS and EKS: refresh the Kubernetes secret, then restart the pod
kubectl annotate externalsecret xmpro-sh-<key> -n <namespace> force-sync=$(date +%s) --overwrite
kubectl rollout restart -n <namespace> deployment/xmpro-sh-<key>-stream-host-sh
Pod stuck in ImagePullBackOff
The registry credential is missing or expired. Confirm image_pull_secrets names the application layer's pull secret and that the secret exists in the namespace.
Pod restarting
The container has a read-only root filesystem and runs as a non-root user. Agents can write only to /tmp, /home/app and /app/Cache.
Related
Last modified: September 28, 2026