Streamer CRD documentation¶
The custom Streamer type is responsible for running a single instance of the video streaming server.
It is needed to:
- ensure correct streamer startup while keeping reliable restart guarantees in case of connectivity issues with license servers
- safely separate access to video content and the API
- update all key parameters without restarting the media server
- fetch API keys from a Kubernetes Secret
Streamer description¶
The Streamer CRD operator manages a single media server instance, assuming one instance per node, but it is not a strict requirement.
The operator supports exactly one Pod per Streamer instance.
All configuration changes that can be applied without restarting the Pod are applied without a restart, which reduces downtime.
The main settings with API keys that must be kept secure are taken from a Kubernetes Secret:
edit_authsetting responsible for API authorizationcluster_keyconfig_externalauth
Quickstart¶
To start, it is enough to follow the minimal steps that allow running in hostPort mode.
You need to prepare:
- a Kubernetes cluster
- a node name, for example
stream-node - the IP address of that node, далее
IP - a license key
LICENSE_KEY
Prepare the following file simple-streamer.yaml:
apiVersion: media.flussonic.com/v1alpha1
kind: Streamer
metadata:
name: simple
spec:
version: "v26.01-5"
licenseKey:
secretKeyRef:
name: flussonic-license
key: license_key
optional: false
nodeName: "stream-node"
adminHostPort: 81
kubectl apply -f https://flussonic.github.io/media-server-operator/latest/operator.yaml
kubectl create secret generic flussonic-license --from-literal=license_key="${LICENSE_KEY}"
kubectl apply -f simple-streamer.yaml
You can get the password from the secret:
kubectl get -o json secret/streamer-sample-license-storage | jq -r .data.edit_auth | base64 -d ; echo
The login and password are separated by a colon.
After that, open http://${IP}:81/ to access the interface.
Using with Ingress¶
As a rule, it is not possible to use ports 80 and 443 on a machine managed by Kubernetes, because they are used by the orchestrator itself.
A streaming traffic balancer can send the client to play video directly on the required node.
In this case, it is very important to ensure traffic locality: when accessing the hostname of the node where the streamer is running, requests must go to the streamer on that node.
This can be achieved in different ways, for example by configuring a separate Ingress route by hostname for each streamer.
Another option is to use local traffic:
apiVersion: v1
kind: Service
metadata:
name: mediaserver
spec:
ports:
- port: 80
targetPort: 80
name: payload
- port: 81
targetPort: 81
name: api
selector:
app.kubernetes.io/component: streamer
internalTrafficPolicy: Local
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: mediaserver
annotations:
traefik.ingress.kubernetes.io/service.nativelb: "true"
nginx.ingress.kubernetes.io/service-upstream: "true"
spec:
rules:
- host: node1-mycluster.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: mediaserver
port:
number: 80
In this configuration, two annotations are specified: one for Traefik and one for NGINX as an ingress controller.
Streamer configuration¶
The operator allows adding additional text to the media server configuration via the configExtra option:
apiVersion: media.flussonic.com/v1alpha1
kind: Streamer
metadata:
name: simple
spec:
version: "26.01-5"
configExtra:
auth.conf: |
auth_backend watcher {
backend http://central/vsaas/api/camera_auth;
}
All sections listed in configExtra will be concatenated into the config and loaded into the streamer.
When this config is updated, there will be no restart: the operator will hot-load the new config.
Video storage¶
Video recording is done to the local disk of each node (the most cost-effective and fast solution).
Failover and replication are provided by an orchestrator at a higher level than the Streamer operator.
The basic approach is as follows:
apiVersion: media.flussonic.com/v1alpha1
kind: Streamer
metadata:
name: simple
spec:
version: "v26.01-5"
configExtra:
dvr.conf: |
dvr watcher {
root /storage;
limits 7d;
}
volumes:
- name: storage
mountPath: /storage
hostPath:
path: /storage
type: DirectoryOrCreate
hostPath is used for local data storage.
Monitoring and statuses¶
The operator tracks the streamer state and sets Conditions in the status of the Streamer resource. These conditions can be used for monitoring and alerting.
StreamerReady condition¶
Shows whether the streamer is ready to work. It can have the following values:
True- the streamer is ready and running (the StatefulSet has a ready replica)False- the streamer is not ready (the StatefulSet was not found or has no ready replicas)Unknown- the state is unknown (error while getting information about the StatefulSet)
You can check the status with:
kubectl get streamer <name> -o jsonpath='{.status.conditions[?(@.type=="StreamerReady")]}'
You can also wait for the streamer to become ready:
kubectl wait --for=condition=StreamerReady=true streamer/<name> --timeout=300s
StreamerConfigSaved condition¶
Shows the result of the latest configuration save attempt via the API. It can have the following values:
True- configuration saved successfully (HTTP status 200)False- configuration saving is forbidden (HTTP status 403)Unknown- error while saving configuration (HTTP status 500+, network errors, or other issues)
You can check the status with:
kubectl get streamer <name> -o jsonpath='{.status.conditions[?(@.type=="StreamerConfigSaved")]}'
Health Checks¶
The operator automatically configures health probes for the streamer Pod:
- Liveness Probe - checks that the streamer is alive. Uses endpoint
/streamer/api/v3/monitoring/liveness. Starts checking 10 seconds after startup, checks every 3 seconds. - Readiness Probe - checks that the streamer is ready to accept traffic. Uses endpoint
/streamer/api/v3/monitoring/readiness. Starts checking 2 seconds after startup, checks every 2 seconds. - Startup Probe - checks that the streamer has started. Uses endpoint
/streamer/api/v3/monitoring/readiness. Starts checking 2 seconds after startup, checks every 2 seconds, allows up to 30 failed attempts.
Pod annotations¶
The operator automatically sets annotations on streamer Pods that can be used by external systems for discovery and routing:
streamer.flussonic.com/api-endpoint- URL to access the streamer API. Format:http://<pod-name>-0.<headless-service>.<namespace>.svc.cluster.local:<port>/streamer/api/v3streamer.flussonic.com/private-payload- URL to access streaming traffic (private endpoint). Usually the same asapi-endpoint.streamer.flussonic.com/public-payload- public URL for streaming traffic. Set only ifpublicUrlis specified in spec.
You can view the annotations with:
kubectl get pod <pod-name> -o jsonpath='{.metadata.annotations}' | jq
Automatic edit_auth generation¶
If editAuth is not specified in spec, the operator automatically generates a login and a random password for API authorization and stores it in the <streamer-name>-license-storage secret under the edit_auth key.
Record format: <login>:<password>.
The generated password is stored in the secret and is not changed later. This guarantees stable API access.
You can get the password with:
kubectl get secret <streamer-name>-license-storage -o jsonpath='{.data.edit_auth}' | base64 -d
If you change this password, the Streamer will go to the StreamerConfigSaved=False state and you will need to delete the Pod with the streamer manually:
kubectl delete pod <streamer-name>-0
Created resources¶
The operator automatically creates and manages the following Kubernetes resources for each Streamer instance:
- StatefulSet (
<streamer-name>-streamer) - manages the streamer Pod - Service (
<streamer-name>-headless) - headless service for accessing the streamer - ConfigMap (
<streamer-name>-config) - contains the generated media server configuration - Secret (
<streamer-name>-license-storage) - stores secret data (edit_auth, license_key, etc.) - ServiceAccount (
<streamer-name>-sa) - service account for the streamer Pod - Role (
<streamer-name>-role) - role with permissions to work with secrets - RoleBinding (
<streamer-name>-rb) - binds the Role to the ServiceAccount
All these resources are automatically deleted when the Streamer resource is deleted.
The list is not stable and may change without notice.
Operator settings list¶
Required settings¶
version: "v26.01-5" - you must explicitly specify the chosen version. latest is strongly discouraged.
nodeName: "stream-node" - the name of the node where the server instance must run.
Optional settings¶
image: "flussonic/flussonic" - you can override the media server image.
env - you can specify environment variables for the Pod in the same way as for a Pod, StatefulSet, etc. When changed, the media server will be restarted.
Example:
env:
- name: MY_ENV_VAR
value: "my-value"
- name: SECRET_VALUE
valueFrom:
secretKeyRef:
name: my-secret
key: secret-key
hostPort: 80 - the port for streaming traffic that will be exposed on the host. Used for direct access to the streamer without Ingress. The value must be in the range 1-65535. By default, port 80 is used inside the container. If you change this value, the container port will also change to the same value.
adminHostPort: 81 - the port for the administrative API that will be exposed on the host. Used for direct access to the streamer administrative interface. The value must be in the range 1-65535. By default, port 81 is used inside the container.
publicUrl: "https://example.com/stream" - public URL for streaming traffic. Set in the Pod annotation under the streamer.flussonic.com/public-payload key for external systems.
licenseKey - reference to a Kubernetes Secret containing the license key. The format is similar to envFrom or env with secretKeyRef:
licenseKey:
secretKeyRef:
name: flussonic-license
key: license_key
editAuth - reference to a Kubernetes Secret containing API authorization data for the streamer. If not specified, the operator automatically generates a random password and saves it in the <streamer-name>-license-storage secret under the edit_auth key. Format:
editAuth:
secretKeyRef:
name: my-edit-auth-secret
key: edit_auth
configExternalUrl: "http://config-server/config" - URL of an external configuration server from which the streamer will load additional settings.
configExternalAuth - reference to a Kubernetes Secret containing authentication data for the external configuration server. Used together with configExternalUrl. Format:
configExternalAuth:
secretKeyRef:
name: config-auth-secret
key: auth_token
logLevel: "info" - media server logging level. Possible values: debug, info, warn, error. By default, the media server standard logging level is used.
configExtra - additional configuration text for the media server. The keys of this map will be used as comments in the config, and the values will be added as-is. For details and examples, see the "Streamer configuration" section.
volumes - list of additional volumes to mount into the Pod. Each volume must contain name, mountPath, and a volume type (for example, hostPath, persistentVolumeClaim, etc.). For details and examples, see the "Video storage" section.