Skip to main content

Kubernetes

This guide provides instructions for deploying Broadcast Suite on Kubernetes. The assumption is that Kubernetes is already installed and configured.

Overview

The Broadcast Suite Kubernetes deployment consists of the following components:

  • PostgreSQL Database: A non-persistent PostgreSQL database for development/testing purposes
  • Broadcast Suite Core: Handles the business logic and connections
  • Broadcast Suite GUI: The web-based user interface
  • Broadcast Suite API: The REST and gRPC API services
  • Ingress: NGINX ingress controller for external access

Prerequisites

Before deploying, ensure you have the following:

  • A running Kubernetes cluster
  • kubectl configured to communicate with your cluster
  • NGINX Ingress Controller installed in your cluster
  • A valid TLS certificate (referenced as tls-ingress in the example)

Deployment Configuration

The deployment is defined in a single YAML file containing all necessary Kubernetes resources.

PostgreSQL Database

The PostgreSQL database is deployed as a non-persistent deployment for development and testing purposes.

warning

The PostgreSQL deployment uses non-persistent storage. All data will be lost when the pod is restarted. For production use, configure persistent volumes or use an external database.

Key configuration parameters:

  • Database Name: postgres
  • Username: postgres
  • Password: postgres (change for production!)
  • Port: 5432
  • Service Name: db (used for internal cluster communication)

Broadcast Suite

Broadcast Suite is deployed with three containers in a single pod:

Core Container

  • Image: git.broadcastsuite.com/broadcastsuite/broadcastsuite-core:2025.9.2
  • Ports: 8085 (HTTP), 8086 (gRPC), 9000 (Ember+)

GUI Container

  • Image: git.broadcastsuite.com/broadcastsuite/broadcastsuite-gui:2025.9.2
  • Port: 5000 (HTTP)
  • Configuration: Connects to API on ports 8091 (REST), 8092 (gRPC)

API Container

  • Image: git.broadcastsuite.com/broadcastsuite/broadcastsuite-api:2025.9.2
  • Ports: 8091 (REST API), 8092 (gRPC)

The image tags correspond to the version number. The current version used in this documentation is 2025.9.2.

All containers share the following environment variables:

  • ASPNETCORE_ENVIRONMENT: Set to Production
  • ASPNETCORE_FORWARDEDHEADERS_ENABLED: Set to true for proper proxy handling
  • Database__ConnectionString: Connection string to the PostgreSQL database

Ingress Configuration

The Ingress resource provides external access to the GUI through HTTPS.

  • Ingress Class: nginx
  • SSL/TLS: Enabled with automatic redirect from HTTP to HTTPS
  • Upload Size: Maximum request body size set to 50MB
  • Host: Configure your domain (example: helloworld.broadcastsuite.cloud)
note

Update the host and secretName fields in the Ingress configuration to match your domain and TLS certificate.

Deployment Steps

Step 1: Create the Deployment Configuration

Create a file named broadcastsuite.yaml with the following content:

broadcastsuite.yaml
# PostgreSQL Database (Non-Persistent)
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
labels:
app: postgres
spec:
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:16-alpine
env:
- name: POSTGRES_DB
value: "postgres"
- name: POSTGRES_USER
value: "postgres"
- name: POSTGRES_PASSWORD
value: "postgres"
ports:
- containerPort: 5432
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: db
labels:
app: postgres
spec:
type: ClusterIP
selector:
app: postgres
ports:
- name: postgres
port: 5432
targetPort: 5432
protocol: TCP
---
# Broadcast Suite
apiVersion: apps/v1
kind: Deployment
metadata:
name: broadcastsuite
labels:
app: broadcastsuite
spec:
replicas: 1
selector:
matchLabels:
app: broadcastsuite
template:
metadata:
labels:
app: broadcastsuite
spec:
containers:
- name: core
image: git.broadcastsuite.com/broadcastsuite/broadcastsuite-core:2025.9.2
env:
- name: ASPNETCORE_ENVIRONMENT
value: "Production"
- name: ASPNETCORE_FORWARDEDHEADERS_ENABLED
value: "true"
- name: Database__ConnectionString
value: "Host=db;Database=broadcastsuite;Username=postgres;Password=postgres;"
ports:
- containerPort: 8085
protocol: TCP
- containerPort: 8086
protocol: TCP
- containerPort: 9000
protocol: TCP
- name: gui
image: git.broadcastsuite.com/broadcastsuite/broadcastsuite-gui:2025.9.2
env:
- name: ASPNETCORE_ENVIRONMENT
value: "Production"
- name: ASPNETCORE_FORWARDEDHEADERS_ENABLED
value: "true"
- name: Database__ConnectionString
value: "Host=db;Database=broadcastsuite;Username=postgres;Password=postgres;"
- name: Api__BaseUrl
value: "http://localhost"
- name: Kestrel__ListenPort
value: "5000"
- name: Api__Port
value: "8091"
- name: Api__GrpcPort
value: "8092"
ports:
- containerPort: 5000
protocol: TCP
- name: api
image: git.broadcastsuite.com/broadcastsuite/broadcastsuite-api:2025.9.2
env:
- name: ASPNETCORE_ENVIRONMENT
value: "Production"
- name: ASPNETCORE_FORWARDEDHEADERS_ENABLED
value: "true"
- name: Database__ConnectionString
value: "Host=db;Database=broadcastsuite;Username=postgres;Password=postgres;"
- name: Api__Port
value: "8091"
- name: Api__GrpcPort
value: "8092"
ports:
- containerPort: 8091
protocol: TCP
- containerPort: 8092
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: broadcastsuite
labels:
app: broadcastsuite
spec:
type: ClusterIP
selector:
app: broadcastsuite
ports:
- name: core-8085
port: 8085
targetPort: 8085
protocol: TCP
- name: core-8086
port: 8086
targetPort: 8086
protocol: TCP
- name: core-9000
port: 9000
targetPort: 9000
protocol: TCP
- name: gui-5000
port: 5000
targetPort: 5000
protocol: TCP
- name: api-8091
port: 8091
targetPort: 8091
protocol: TCP
- name: api-8092
port: 8092
targetPort: 8092
protocol: TCP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: broadcastsuite-ingress
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
spec:
ingressClassName: nginx
tls:
- hosts:
- helloworld.broadcastsuite.cloud
secretName: tls-ingress
rules:
- host: helloworld.broadcastsuite.cloud
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: broadcastsuite
port:
number: 5000

Update the following values in the configuration:

  • Database credentials (replace default postgres/postgres with secure values)
  • Ingress host name (replace helloworld.broadcastsuite.cloud with your domain)
  • TLS secret name (replace tls-ingress with your certificate secret)

Step 2: Deploy to Kubernetes

Apply the configuration to your cluster:

kubectl apply -f broadcastsuite.yaml

Step 3: Verify the Deployment

Check the status of the pods:

kubectl get pods

Check the services:

kubectl get services

Check the ingress:

kubectl get ingress

Wait for all pods to be in Running status. You can monitor the logs:

kubectl logs -f deployment/broadcastsuite -c gui
kubectl logs -f deployment/broadcastsuite -c core
kubectl logs -f deployment/broadcastsuite -c api

Accessing the Application

Once all pods are running, you can access the application:

  • External access: https://your-domain.com (as configured in the Ingress)
  • Internal access (from within the cluster): http://broadcastsuite:5000

Configuration

You can customize the deployment by modifying environment variables or using ConfigMaps and Secrets.

Using ConfigMaps

For non-sensitive configuration, create a ConfigMap:

kubectl create configmap broadcastsuite-config \
--from-literal=Api__BaseUrl=http://localhost \
--from-literal=Api__Port=8091

Using Secrets

For sensitive information like database credentials:

kubectl create secret generic broadcastsuite-db \
--from-literal=connection-string='Host=db;Database=broadcastsuite;Username=postgres;Password=<secure-password>'

Reference these in your deployment:

env:
- name: Database__ConnectionString
valueFrom:
secretKeyRef:
name: broadcastsuite-db
key: connection-string

Persistent Storage

The provided configuration uses non-persistent storage for the database. For production deployments, configure persistent volumes:

Create a PersistentVolumeClaim

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi

Mount the Volume

Add the volume to the PostgreSQL deployment:

spec:
template:
spec:
containers:
- name: postgres
volumeMounts:
- name: postgres-storage
mountPath: /var/lib/postgresql/data
volumes:
- name: postgres-storage
persistentVolumeClaim:
claimName: postgres-pvc
tip

For production environments, consider using an external managed database service instead of running PostgreSQL in the cluster.

Scaling

You can scale the GUI and API components by adjusting the replica count.

warning

Only the GUI and API components support scaling. The Core component should always run as a single instance (replicas=1).

To scale the GUI and API, you need to create separate deployments for each component instead of running all three in a single pod.

Troubleshooting

Pods Not Starting

  • Check pod status: kubectl describe pod <pod-name>
  • Check logs: kubectl logs <pod-name> -c <container-name>
  • Ensure sufficient cluster resources (CPU, memory)

Database Connection Issues

  • Verify the database pod is running: kubectl get pods
  • Check database logs: kubectl logs deployment/postgres
  • Verify the connection string in the application environment variables
  • Test connectivity: kubectl exec -it deployment/broadcastsuite -c api -- ping db

Ingress Not Working

  • Verify NGINX Ingress Controller is installed: kubectl get pods -n ingress-nginx
  • Check ingress status: kubectl describe ingress broadcastsuite-ingress
  • Verify DNS is pointing to the ingress controller's external IP
  • Check TLS certificate: kubectl get secret tls-ingress

Application Errors

  • Check application logs for all containers
  • Verify environment variables are correctly set
  • Ensure database migrations have completed successfully
  • Check for version compatibility between Core, GUI, and API components