diff --git a/helm-videocall-deployment/.gitignore b/helm-videocall-deployment/.gitignore new file mode 100644 index 000000000..2c096649a --- /dev/null +++ b/helm-videocall-deployment/.gitignore @@ -0,0 +1 @@ +digital-ocean-secret diff --git a/helm-videocall-deployment/README.md b/helm-videocall-deployment/README.md new file mode 100644 index 000000000..7f3d76163 --- /dev/null +++ b/helm-videocall-deployment/README.md @@ -0,0 +1,38 @@ +# Videocall Deployment Configurations + +This directory contains deployment-specific configurations and infrastructure charts for Videocall.rs. + +## Structure + +``` +helm-videocall-deployment/ +├── infrastructure/ # Infrastructure charts (NATS, Prometheus, Postgres, etc.) +├── apps/ # Other applications (engineering-vlog, website) +├── us-east/ # US East region deployment values +└── singapore/ # Singapore region deployment values +``` + +## Infrastructure Charts + +Shared infrastructure components: +- **nats/** - NATS messaging server +- **postgres/** - PostgreSQL database +- **prometheus/** - Metrics collection +- **grafana/** - Metrics visualization +- **cert-manager/** - TLS certificate management +- **ingress-nginx/** - Ingress controller +- **external-dns/** - DNS automation +- And more... + +## Region-Specific Deployments + +Each region directory contains Helm value overrides for deploying the videocall chart and infrastructure to that region. + +## Usage + +The public Videocall application chart is at `../helm/videocall/` + +This directory is for: +1. Infrastructure dependencies +2. Region-specific configuration values +3. Other applications deployed alongside Videocall diff --git a/helm/engineering-vlog/Chart.yaml b/helm-videocall-deployment/apps/engineering-vlog/Chart.yaml similarity index 100% rename from helm/engineering-vlog/Chart.yaml rename to helm-videocall-deployment/apps/engineering-vlog/Chart.yaml diff --git a/helm/engineering-vlog/templates/_helpers.tpl b/helm-videocall-deployment/apps/engineering-vlog/templates/_helpers.tpl similarity index 100% rename from helm/engineering-vlog/templates/_helpers.tpl rename to helm-videocall-deployment/apps/engineering-vlog/templates/_helpers.tpl diff --git a/helm/engineering-vlog/templates/deployment.yaml b/helm-videocall-deployment/apps/engineering-vlog/templates/deployment.yaml similarity index 100% rename from helm/engineering-vlog/templates/deployment.yaml rename to helm-videocall-deployment/apps/engineering-vlog/templates/deployment.yaml diff --git a/helm/engineering-vlog/templates/ingress.yaml b/helm-videocall-deployment/apps/engineering-vlog/templates/ingress.yaml similarity index 100% rename from helm/engineering-vlog/templates/ingress.yaml rename to helm-videocall-deployment/apps/engineering-vlog/templates/ingress.yaml diff --git a/helm/engineering-vlog/templates/service.yaml b/helm-videocall-deployment/apps/engineering-vlog/templates/service.yaml similarity index 100% rename from helm/engineering-vlog/templates/service.yaml rename to helm-videocall-deployment/apps/engineering-vlog/templates/service.yaml diff --git a/helm/engineering-vlog/values.yaml b/helm-videocall-deployment/apps/engineering-vlog/values.yaml similarity index 100% rename from helm/engineering-vlog/values.yaml rename to helm-videocall-deployment/apps/engineering-vlog/values.yaml diff --git a/helm-videocall-deployment/infrastructure/cert-manager-issuer/cloudflare-issuer.yaml b/helm-videocall-deployment/infrastructure/cert-manager-issuer/cloudflare-issuer.yaml new file mode 100644 index 000000000..088ce2834 --- /dev/null +++ b/helm-videocall-deployment/infrastructure/cert-manager-issuer/cloudflare-issuer.yaml @@ -0,0 +1,18 @@ +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: letsencrypt-prod + namespace: videocall +spec: + acme: + server: https://acme-v02.api.letsencrypt.org/directory + email: your-email@yourdomain.com + privateKeySecretRef: + name: letsencrypt-prod + solvers: + - dns01: + cloudflare: + email: your-email@yourdomain.com + apiTokenSecretRef: + name: cloudflare-api-token-secret + key: api-token \ No newline at end of file diff --git a/helm/cert-manager-issuer/cert-manager-issuer.yaml b/helm-videocall-deployment/infrastructure/cert-manager-issuer/digital-ocean.yaml similarity index 93% rename from helm/cert-manager-issuer/cert-manager-issuer.yaml rename to helm-videocall-deployment/infrastructure/cert-manager-issuer/digital-ocean.yaml index 5835d4f97..839e9ceb4 100644 --- a/helm/cert-manager-issuer/cert-manager-issuer.yaml +++ b/helm-videocall-deployment/infrastructure/cert-manager-issuer/digital-ocean.yaml @@ -7,7 +7,7 @@ spec: # The ACME server URL server: https://acme-v02.api.letsencrypt.org/directory # Email address used for ACME registration - email: social@securityunion.dev + email: your-email@yourdomain.com # Name of a secret used to store the ACME account private key privateKeySecretRef: name: letsencrypt-prod diff --git a/helm-videocall-deployment/infrastructure/cert-manager-issuer/route53-issuer.yaml b/helm-videocall-deployment/infrastructure/cert-manager-issuer/route53-issuer.yaml new file mode 100644 index 000000000..14f92afe0 --- /dev/null +++ b/helm-videocall-deployment/infrastructure/cert-manager-issuer/route53-issuer.yaml @@ -0,0 +1,21 @@ +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: letsencrypt-prod + namespace: videocall +spec: + acme: + server: https://acme-v02.api.letsencrypt.org/directory + email: your-email@yourdomain.com + privateKeySecretRef: + name: letsencrypt-prod + solvers: + - dns01: + route53: + region: us-east-1 + accessKeyIDSecretRef: + name: route53-creds + key: aws_access_key_id + secretAccessKeySecretRef: + name: route53-creds + key: aws_secret_access_key diff --git a/helm/cert-manager/Chart.lock b/helm-videocall-deployment/infrastructure/cert-manager/Chart.lock similarity index 100% rename from helm/cert-manager/Chart.lock rename to helm-videocall-deployment/infrastructure/cert-manager/Chart.lock diff --git a/helm/cert-manager/Chart.yaml b/helm-videocall-deployment/infrastructure/cert-manager/Chart.yaml similarity index 100% rename from helm/cert-manager/Chart.yaml rename to helm-videocall-deployment/infrastructure/cert-manager/Chart.yaml diff --git a/helm-videocall-deployment/infrastructure/cert-manager/charts/cert-manager-v1.12.2.tgz b/helm-videocall-deployment/infrastructure/cert-manager/charts/cert-manager-v1.12.2.tgz new file mode 100644 index 000000000..13d233c26 Binary files /dev/null and b/helm-videocall-deployment/infrastructure/cert-manager/charts/cert-manager-v1.12.2.tgz differ diff --git a/helm/cert-manager/values.yaml b/helm-videocall-deployment/infrastructure/cert-manager/values.yaml similarity index 100% rename from helm/cert-manager/values.yaml rename to helm-videocall-deployment/infrastructure/cert-manager/values.yaml diff --git a/helm/digital-ocean-service-account/README.md b/helm-videocall-deployment/infrastructure/digital-ocean-service-account/README.md similarity index 100% rename from helm/digital-ocean-service-account/README.md rename to helm-videocall-deployment/infrastructure/digital-ocean-service-account/README.md diff --git a/helm/digital-ocean-service-account/cluster-role-binding.yaml b/helm-videocall-deployment/infrastructure/digital-ocean-service-account/cluster-role-binding.yaml similarity index 100% rename from helm/digital-ocean-service-account/cluster-role-binding.yaml rename to helm-videocall-deployment/infrastructure/digital-ocean-service-account/cluster-role-binding.yaml diff --git a/helm/digital-ocean-service-account/service-account.yaml b/helm-videocall-deployment/infrastructure/digital-ocean-service-account/service-account.yaml similarity index 100% rename from helm/digital-ocean-service-account/service-account.yaml rename to helm-videocall-deployment/infrastructure/digital-ocean-service-account/service-account.yaml diff --git a/helm/external-dns/README.md b/helm-videocall-deployment/infrastructure/external-dns/README.md similarity index 100% rename from helm/external-dns/README.md rename to helm-videocall-deployment/infrastructure/external-dns/README.md diff --git a/helm/external-dns/external-dns-values.yaml b/helm-videocall-deployment/infrastructure/external-dns/digital-ocean.yaml similarity index 100% rename from helm/external-dns/external-dns-values.yaml rename to helm-videocall-deployment/infrastructure/external-dns/digital-ocean.yaml diff --git a/helm/external-dns/install.sh b/helm-videocall-deployment/infrastructure/external-dns/install.sh similarity index 100% rename from helm/external-dns/install.sh rename to helm-videocall-deployment/infrastructure/external-dns/install.sh diff --git a/helm-videocall-deployment/infrastructure/external-dns/route53.yaml b/helm-videocall-deployment/infrastructure/external-dns/route53.yaml new file mode 100644 index 000000000..3c5c9bcd8 --- /dev/null +++ b/helm-videocall-deployment/infrastructure/external-dns/route53.yaml @@ -0,0 +1,20 @@ +# AWS Route53 Provider Configuration +provider: + name: aws + +# AWS Credentials Configuration +env: + - name: AWS_SHARED_CREDENTIALS_FILE + value: /etc/aws/credentials/dns-creds + - name: AWS_DEFAULT_REGION + value: us-east-1 + +# Mount AWS credentials from secret +extraVolumeMounts: + - mountPath: /etc/aws/credentials + name: aws-credentials + readOnly: true +extraVolumes: + - name: aws-credentials + secret: + secretName: external-dns \ No newline at end of file diff --git a/helm/global/us-east/grafana/Chart.lock b/helm-videocall-deployment/infrastructure/grafana/Chart.lock similarity index 100% rename from helm/global/us-east/grafana/Chart.lock rename to helm-videocall-deployment/infrastructure/grafana/Chart.lock diff --git a/helm/global/us-east/grafana/Chart.yaml b/helm-videocall-deployment/infrastructure/grafana/Chart.yaml similarity index 100% rename from helm/global/us-east/grafana/Chart.yaml rename to helm-videocall-deployment/infrastructure/grafana/Chart.yaml diff --git a/helm-videocall-deployment/infrastructure/grafana/certificate.yaml b/helm-videocall-deployment/infrastructure/grafana/certificate.yaml new file mode 100644 index 000000000..2102dd92a --- /dev/null +++ b/helm-videocall-deployment/infrastructure/grafana/certificate.yaml @@ -0,0 +1,12 @@ +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: grafana-tls + namespace: videocall +spec: + secretName: grafana-tls + issuerRef: + name: letsencrypt-prod + kind: Issuer + dnsNames: + - grafana.YOUR_DOMAIN_NAME \ No newline at end of file diff --git a/helm/global/us-east/grafana/dashboards/server-connections-analytics.json b/helm-videocall-deployment/infrastructure/grafana/dashboards/server-connections-analytics.json similarity index 100% rename from helm/global/us-east/grafana/dashboards/server-connections-analytics.json rename to helm-videocall-deployment/infrastructure/grafana/dashboards/server-connections-analytics.json diff --git a/helm-videocall-deployment/infrastructure/grafana/dashboards/server-connections-analytics.json:Zone.Identifier b/helm-videocall-deployment/infrastructure/grafana/dashboards/server-connections-analytics.json:Zone.Identifier new file mode 100644 index 000000000..d6c1ec682 Binary files /dev/null and b/helm-videocall-deployment/infrastructure/grafana/dashboards/server-connections-analytics.json:Zone.Identifier differ diff --git a/helm/global/us-east/grafana/dashboards/videocall-health.json b/helm-videocall-deployment/infrastructure/grafana/dashboards/videocall-health.json similarity index 100% rename from helm/global/us-east/grafana/dashboards/videocall-health.json rename to helm-videocall-deployment/infrastructure/grafana/dashboards/videocall-health.json diff --git a/helm-videocall-deployment/infrastructure/grafana/dashboards/videocall-health.json:Zone.Identifier b/helm-videocall-deployment/infrastructure/grafana/dashboards/videocall-health.json:Zone.Identifier new file mode 100644 index 000000000..d6c1ec682 Binary files /dev/null and b/helm-videocall-deployment/infrastructure/grafana/dashboards/videocall-health.json:Zone.Identifier differ diff --git a/helm-videocall-deployment/infrastructure/grafana/deploy.sh b/helm-videocall-deployment/infrastructure/grafana/deploy.sh new file mode 100755 index 000000000..4b9999e58 --- /dev/null +++ b/helm-videocall-deployment/infrastructure/grafana/deploy.sh @@ -0,0 +1,35 @@ + +#!/bin/bash + + +# Save current working directory and ensure we return to it on script exit +ORIG_CWD="$(pwd)" +trap 'cd "$ORIG_CWD"' EXIT + +# Change to the directory where the script resides +cd "$(dirname "$0")" + +# Set Grafana credentials from environment variables +export GRAFANA_ADMIN_USER=${GRAFANA_ADMIN_USER:-admin} +export GRAFANA_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD:-videocall-monitoring-2024} + +# Update Helm dependencies +echo "Updating Helm dependencies..." +helm dependency update . + +# Deploy Grafana with credentials from environment +echo "Deploying Grafana..." +helm upgrade --install grafana . \ + --namespace videocall \ + --debug \ + --set grafana.adminUser=$GRAFANA_ADMIN_USER \ + --set grafana.adminPassword=$GRAFANA_ADMIN_PASSWORD \ + --set grafana.grafana.ini.security.admin_user=$GRAFANA_ADMIN_USER \ + --set grafana.grafana.ini.security.admin_password=$GRAFANA_ADMIN_PASSWORD + +# Apply the certificate resource +echo "Applying certificate..." +kubectl apply -f certificate.yaml + +echo "Deployment complete!" +echo "Check status with: kubectl get pods,ingress,certificate -n videocall" diff --git a/helm/global/us-east/grafana/external-secret.yaml b/helm-videocall-deployment/infrastructure/grafana/external-secret.yaml similarity index 100% rename from helm/global/us-east/grafana/external-secret.yaml rename to helm-videocall-deployment/infrastructure/grafana/external-secret.yaml diff --git a/helm-videocall-deployment/infrastructure/grafana/values.yaml b/helm-videocall-deployment/infrastructure/grafana/values.yaml new file mode 100644 index 000000000..d21cd98cf --- /dev/null +++ b/helm-videocall-deployment/infrastructure/grafana/values.yaml @@ -0,0 +1,90 @@ +# Grafana values for videocall monitoring (minimal resources) +grafana: + # Image configuration + image: + tag: "10.0.0" + + # Minimal resources for cost optimization + resources: + limits: + cpu: 50m + memory: 128Mi + requests: + cpu: 50m + memory: 64Mi + + # Single replica + replicas: 1 + + # Persistence (minimal) + persistence: + enabled: true + size: 1Gi + storageClassName: "local-path" + + # Admin credentials from secret + adminUser: admin + adminPassword: password + + # Service configuration + service: + type: ClusterIP + port: 80 + + # Ingress configuration + ingress: + enabled: true + annotations: + kubernetes.io/ingress.class: "nginx" + cert-manager.io/issuer: "letsencrypt-prod" + nginx.ingress.kubernetes.io/ssl-redirect: "true" + nginx.ingress.kubernetes.io/proxy-buffer-size: "16k" + nginx.ingress.kubernetes.io/proxy-busy-buffers-size: "16k" + hosts: + - grafana.YOUR_DOMAIN_NAME + tls: + - secretName: grafana-tls + hosts: + - grafana.YOUR_DOMAIN_NAME + + # Grafana configuration + grafana.ini: + server: + domain: grafana.YOUR_DOMAIN_NAME + root_url: https://grafana.YOUR_DOMAIN_NAME + security: + admin_user: admin + admin_password: password + users: + allow_sign_up: false + auth.anonymous: + enabled: false + + # Datasources + datasources: + datasources.yaml: + apiVersion: 1 + datasources: + - name: Prometheus + type: prometheus + url: http://prometheus-server:80 + access: proxy + isDefault: true + + # Dashboard provisioning + dashboards: + default: + videocall-health: + file: dashboards/videocall-health.json + + # Security context + securityContext: + runAsUser: 472 + runAsGroup: 472 + fsGroup: 472 + + # Pod security context + podSecurityContext: + runAsUser: 472 + runAsGroup: 472 + fsGroup: 472 \ No newline at end of file diff --git a/helm/ingress-nginx/Chart.lock b/helm-videocall-deployment/infrastructure/ingress-nginx/Chart.lock similarity index 100% rename from helm/ingress-nginx/Chart.lock rename to helm-videocall-deployment/infrastructure/ingress-nginx/Chart.lock diff --git a/helm/ingress-nginx/Chart.yaml b/helm-videocall-deployment/infrastructure/ingress-nginx/Chart.yaml similarity index 100% rename from helm/ingress-nginx/Chart.yaml rename to helm-videocall-deployment/infrastructure/ingress-nginx/Chart.yaml diff --git a/helm-videocall-deployment/infrastructure/ingress-nginx/charts/ingress-nginx-4.7.0.tgz b/helm-videocall-deployment/infrastructure/ingress-nginx/charts/ingress-nginx-4.7.0.tgz new file mode 100644 index 000000000..5372ca877 Binary files /dev/null and b/helm-videocall-deployment/infrastructure/ingress-nginx/charts/ingress-nginx-4.7.0.tgz differ diff --git a/helm/global/us-east/nats/Chart.lock b/helm-videocall-deployment/infrastructure/nats/Chart.lock similarity index 100% rename from helm/global/us-east/nats/Chart.lock rename to helm-videocall-deployment/infrastructure/nats/Chart.lock diff --git a/helm/global/us-east/nats/Chart.yaml b/helm-videocall-deployment/infrastructure/nats/Chart.yaml similarity index 100% rename from helm/global/us-east/nats/Chart.yaml rename to helm-videocall-deployment/infrastructure/nats/Chart.yaml diff --git a/helm-videocall-deployment/infrastructure/nats/values.yaml b/helm-videocall-deployment/infrastructure/nats/values.yaml new file mode 100644 index 000000000..ca4a77c83 --- /dev/null +++ b/helm-videocall-deployment/infrastructure/nats/values.yaml @@ -0,0 +1,34 @@ +nats: + nats: + natsbox: + enabled: true + # Basic cluster configuration (simplified for single region) + cluster: + enabled: true + replicas: 1 # Single instance for minimal deployment + noAdvertise: true + # Gateway configuration disabled for simple deployment + gateway: + enabled: false # No cross-region needed + # JetStream (persistence) disabled for simplicity (can enable if needed) + jetstream: + enabled: false + # Simplified monitoring config + exporter: + enabled: true + serviceMonitor: + enabled: false # Set to true if you have Prometheus operator + # Simplified auth configuration + auth: + enabled: false # Simplified for basic deployment + # Adjusted resource limits for smaller deployments + resources: + limits: + cpu: 300m + memory: 256Mi + requests: + cpu: 100m + memory: 128Mi + # Service configuration for simple deployment + service: + type: ClusterIP # Use ingress instead of LoadBalancer diff --git a/helm/global/us-east/postgres/Chart.lock b/helm-videocall-deployment/infrastructure/postgres/Chart.lock similarity index 100% rename from helm/global/us-east/postgres/Chart.lock rename to helm-videocall-deployment/infrastructure/postgres/Chart.lock diff --git a/helm/postgres/Chart.yaml b/helm-videocall-deployment/infrastructure/postgres/Chart.yaml similarity index 52% rename from helm/postgres/Chart.yaml rename to helm-videocall-deployment/infrastructure/postgres/Chart.yaml index d2d508669..20ea4cc3e 100644 --- a/helm/postgres/Chart.yaml +++ b/helm-videocall-deployment/infrastructure/postgres/Chart.yaml @@ -1,8 +1,10 @@ apiVersion: v2 -name: rustlemania-postgres -version: 1.0.0 +name: postgres-us-east +version: 0.1.0 +description: PostgreSQL database dependencies: - name: postgresql - version: 12.5.7 + version: 18.1.3 repository: https://charts.bitnami.com/bitnami + diff --git a/helm/global/us-east/postgres/README.md b/helm-videocall-deployment/infrastructure/postgres/README.md similarity index 100% rename from helm/global/us-east/postgres/README.md rename to helm-videocall-deployment/infrastructure/postgres/README.md diff --git a/helm/global/us-east/prometheus/Chart.lock b/helm-videocall-deployment/infrastructure/prometheus/Chart.lock similarity index 100% rename from helm/global/us-east/prometheus/Chart.lock rename to helm-videocall-deployment/infrastructure/prometheus/Chart.lock diff --git a/helm/global/us-east/prometheus/Chart.yaml b/helm-videocall-deployment/infrastructure/prometheus/Chart.yaml similarity index 100% rename from helm/global/us-east/prometheus/Chart.yaml rename to helm-videocall-deployment/infrastructure/prometheus/Chart.yaml diff --git a/helm-videocall-deployment/infrastructure/prometheus/values.yaml b/helm-videocall-deployment/infrastructure/prometheus/values.yaml new file mode 100644 index 000000000..11dee0251 --- /dev/null +++ b/helm-videocall-deployment/infrastructure/prometheus/values.yaml @@ -0,0 +1,280 @@ +# Prometheus values for videocall monitoring (minimal resources) +prometheus: + # Prometheus server configuration + server: + # Resources (adjusted to avoid OOM errors) + resources: + limits: + cpu: 200m + memory: 800Mi + requests: + cpu: 100m + memory: 256Mi + + # Single replica + replicaCount: 1 + + # Persistence (minimal) + persistentVolume: + enabled: true + size: 8Gi + storageClass: "local-path" + + # Retention + retention: "7d" + + # Service configuration + service: + type: ClusterIP + servicePort: 80 + + # Security context + securityContext: + runAsUser: 65534 + runAsGroup: 65534 + fsGroup: 65534 + + # Global scrape configuration + global: + scrape_interval: 15s + evaluation_interval: 15s + + # Alertmanager (disabled for minimal setup) + alertmanager: + enabled: false + + # Node exporter (disabled for minimal setup) + nodeExporter: + enabled: false + + # Pushgateway (disabled for minimal setup) + pushgateway: + enabled: false + + # Kube-state-metrics (minimal) + kubeStateMetrics: + enabled: true + resources: + limits: + cpu: 25m + memory: 32Mi + requests: + cpu: 10m + memory: 16Mi + + # Server configuration files + serverFiles: + prometheus.yml: + rule_files: + - "alert_rules.yml" + + scrape_configs: + - job_name: 'prometheus' + static_configs: + - targets: ['localhost:9090'] + + # Client health metrics (sessions, NetEQ, video quality, etc.) + - job_name: 'videocall-client-metrics' + static_configs: + - targets: ['client-metrics-api:9091'] + metrics_path: '/metrics' + scrape_interval: 5s + scrape_timeout: 4s + + # Server connection tracking (with session_id, stale cleanup, etc.) + - job_name: 'videocall-server-stats' + static_configs: + - targets: ['server-metrics-api:9092'] + metrics_path: '/metrics' + scrape_interval: 5s + scrape_timeout: 4s + + # Kubernetes API server + - job_name: 'kubernetes-apiservers' + kubernetes_sd_configs: + - role: endpoints + scheme: https + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + relabel_configs: + - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: default;kubernetes;https + + # Kubernetes nodes + - job_name: 'kubernetes-nodes' + kubernetes_sd_configs: + - role: node + scheme: https + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + relabel_configs: + - action: labelmap + regex: __meta_kubernetes_node_label_(.+) + - target_label: __address__ + replacement: kubernetes.default.svc:443 + - source_labels: [__meta_kubernetes_node_name] + regex: (.+) + target_label: __metrics_path__ + replacement: /api/v1/nodes/${1}/proxy/metrics + + # Kubernetes service endpoints + - job_name: 'kubernetes-service-endpoints' + honor_labels: true + kubernetes_sd_configs: + - role: endpoints + relabel_configs: + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape] + action: keep + regex: "true" + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape_slow] + action: drop + regex: "true" + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme] + action: replace + regex: (https?) + target_label: __scheme__ + replacement: $1 + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path] + action: replace + regex: (.+) + target_label: __metrics_path__ + replacement: $1 + - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port] + action: replace + regex: (.+?)(?::\d+)?;(\d+) + target_label: __address__ + replacement: $1:$2 + - action: labelmap + regex: __meta_kubernetes_service_annotation_prometheus_io_param_(.+) + replacement: __param_$1 + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: namespace + - source_labels: [__meta_kubernetes_service_name] + action: replace + target_label: service + - source_labels: [__meta_kubernetes_pod_node_name] + action: replace + target_label: node + + # Kubernetes pods + - job_name: 'kubernetes-pods' + honor_labels: true + kubernetes_sd_configs: + - role: pod + relabel_configs: + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] + action: keep + regex: "true" + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape_slow] + action: drop + regex: "true" + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scheme] + action: replace + regex: (https?) + target_label: __scheme__ + replacement: $1 + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] + action: replace + regex: (.+) + target_label: __metrics_path__ + replacement: $1 + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_port, __meta_kubernetes_pod_ip] + action: replace + regex: (\d+);(([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}) + target_label: __address__ + replacement: '[$2]:$1' + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_port, __meta_kubernetes_pod_ip] + action: replace + regex: (\d+);((([0-9]+?)(\.|$)){4}) + target_label: __address__ + replacement: $2:$1 + - action: labelmap + regex: __meta_kubernetes_pod_annotation_prometheus_io_param_(.+) + replacement: __param_$1 + - action: labelmap + regex: __meta_kubernetes_pod_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: namespace + - source_labels: [__meta_kubernetes_pod_name] + action: replace + target_label: pod + - source_labels: [__meta_kubernetes_pod_phase] + action: drop + regex: Pending|Succeeded|Failed|Completed + - source_labels: [__meta_kubernetes_pod_node_name] + action: replace + target_label: node + + alert_rules.yml: + groups: + - name: videocall_alerts + rules: + - alert: HighAudioReceptionFailures + expr: rate(videocall_audio_reception_failures_total[5m]) > 0.1 + for: 2m + labels: + severity: warning + annotations: + summary: "High audio reception failures detected" + description: "Audio reception failure rate is {{ $value }} failures/sec" + + - alert: HighVideoReceptionFailures + expr: rate(videocall_video_reception_failures_total[5m]) > 0.1 + for: 2m + labels: + severity: warning + annotations: + summary: "High video reception failures detected" + description: "Video reception failure rate is {{ $value }} failures/sec" + + - alert: LowAudioConnectivity + expr: videocall_peer_can_listen < 0.5 + for: 1m + labels: + severity: critical + annotations: + summary: "Low audio connectivity detected" + description: "Audio connectivity is {{ $value }}%" + + - alert: LowVideoConnectivity + expr: videocall_peer_can_see < 0.5 + for: 1m + labels: + severity: critical + annotations: + summary: "Low video connectivity detected" + description: "Video connectivity is {{ $value }}%" + + - alert: HighNetEQBuffer + expr: videocall_neteq_audio_buffer_ms > 200 + for: 2m + labels: + severity: warning + annotations: + summary: "High NetEQ audio buffer detected" + description: "NetEQ audio buffer is {{ $value }}ms" + + - alert: HighPacketDecodeQueue + expr: videocall_neteq_packets_awaiting_decode > 20 + for: 2m + labels: + severity: warning + annotations: + summary: "High packet decode queue detected" + description: "{{ $value }} packets awaiting decode" + + - alert: HighDecodeOperations + expr: rate(videocall_neteq_normal_ops_per_sec[5m]) + rate(videocall_neteq_expand_ops_per_sec[5m]) + rate(videocall_neteq_accelerate_ops_per_sec[5m]) > 50 + for: 2m + labels: + severity: warning + annotations: + summary: "High decode operations detected" + description: "{{ $value }} decode operations per second" \ No newline at end of file diff --git a/helm/global/singapore/ingress-nginx/Chart.lock b/helm-videocall-deployment/singapore/ingress-nginx/Chart.lock similarity index 100% rename from helm/global/singapore/ingress-nginx/Chart.lock rename to helm-videocall-deployment/singapore/ingress-nginx/Chart.lock diff --git a/helm/global/singapore/ingress-nginx/Chart.yaml b/helm-videocall-deployment/singapore/ingress-nginx/Chart.yaml similarity index 100% rename from helm/global/singapore/ingress-nginx/Chart.yaml rename to helm-videocall-deployment/singapore/ingress-nginx/Chart.yaml diff --git a/helm-videocall-deployment/singapore/ingress-nginx/charts/ingress-nginx-4.7.0.tgz b/helm-videocall-deployment/singapore/ingress-nginx/charts/ingress-nginx-4.7.0.tgz new file mode 100644 index 000000000..5372ca877 Binary files /dev/null and b/helm-videocall-deployment/singapore/ingress-nginx/charts/ingress-nginx-4.7.0.tgz differ diff --git a/helm/global/singapore/ingress-nginx/values.yaml b/helm-videocall-deployment/singapore/ingress-nginx/values.yaml similarity index 100% rename from helm/global/singapore/ingress-nginx/values.yaml rename to helm-videocall-deployment/singapore/ingress-nginx/values.yaml diff --git a/helm/global/singapore/nats/Chart.lock b/helm-videocall-deployment/singapore/nats/Chart.lock similarity index 100% rename from helm/global/singapore/nats/Chart.lock rename to helm-videocall-deployment/singapore/nats/Chart.lock diff --git a/helm/global/singapore/nats/Chart.yaml b/helm-videocall-deployment/singapore/nats/Chart.yaml similarity index 100% rename from helm/global/singapore/nats/Chart.yaml rename to helm-videocall-deployment/singapore/nats/Chart.yaml diff --git a/helm-videocall-deployment/singapore/nats/charts/nats-0.19.15.tgz b/helm-videocall-deployment/singapore/nats/charts/nats-0.19.15.tgz new file mode 100644 index 000000000..4d2b0c2d6 Binary files /dev/null and b/helm-videocall-deployment/singapore/nats/charts/nats-0.19.15.tgz differ diff --git a/helm/global/singapore/nats/values.yaml b/helm-videocall-deployment/singapore/nats/values.yaml similarity index 100% rename from helm/global/singapore/nats/values.yaml rename to helm-videocall-deployment/singapore/nats/values.yaml diff --git a/helm/global/singapore/websocket/Chart.lock b/helm-videocall-deployment/singapore/websocket/Chart.lock similarity index 100% rename from helm/global/singapore/websocket/Chart.lock rename to helm-videocall-deployment/singapore/websocket/Chart.lock diff --git a/helm/global/singapore/websocket/Chart.yaml b/helm-videocall-deployment/singapore/websocket/Chart.yaml similarity index 100% rename from helm/global/singapore/websocket/Chart.yaml rename to helm-videocall-deployment/singapore/websocket/Chart.yaml diff --git a/helm/global/singapore/websocket/certificate.yaml b/helm-videocall-deployment/singapore/websocket/certificate.yaml similarity index 100% rename from helm/global/singapore/websocket/certificate.yaml rename to helm-videocall-deployment/singapore/websocket/certificate.yaml diff --git a/helm-videocall-deployment/singapore/websocket/charts/rustlemania-websocket-0.1.0.tgz b/helm-videocall-deployment/singapore/websocket/charts/rustlemania-websocket-0.1.0.tgz new file mode 100644 index 000000000..431d949f5 Binary files /dev/null and b/helm-videocall-deployment/singapore/websocket/charts/rustlemania-websocket-0.1.0.tgz differ diff --git a/helm/global/singapore/websocket/values.yaml b/helm-videocall-deployment/singapore/websocket/values.yaml similarity index 100% rename from helm/global/singapore/websocket/values.yaml rename to helm-videocall-deployment/singapore/websocket/values.yaml diff --git a/helm/global/singapore/webtransport/Chart.lock b/helm-videocall-deployment/singapore/webtransport/Chart.lock similarity index 100% rename from helm/global/singapore/webtransport/Chart.lock rename to helm-videocall-deployment/singapore/webtransport/Chart.lock diff --git a/helm/global/singapore/webtransport/Chart.yaml b/helm-videocall-deployment/singapore/webtransport/Chart.yaml similarity index 100% rename from helm/global/singapore/webtransport/Chart.yaml rename to helm-videocall-deployment/singapore/webtransport/Chart.yaml diff --git a/helm/global/singapore/webtransport/certificate.yaml b/helm-videocall-deployment/singapore/webtransport/certificate.yaml similarity index 100% rename from helm/global/singapore/webtransport/certificate.yaml rename to helm-videocall-deployment/singapore/webtransport/certificate.yaml diff --git a/helm-videocall-deployment/singapore/webtransport/charts/rustlemania-webtransport-0.1.0.tgz b/helm-videocall-deployment/singapore/webtransport/charts/rustlemania-webtransport-0.1.0.tgz new file mode 100644 index 000000000..429fc6c30 Binary files /dev/null and b/helm-videocall-deployment/singapore/webtransport/charts/rustlemania-webtransport-0.1.0.tgz differ diff --git a/helm/global/singapore/webtransport/values.yaml b/helm-videocall-deployment/singapore/webtransport/values.yaml similarity index 99% rename from helm/global/singapore/webtransport/values.yaml rename to helm-videocall-deployment/singapore/webtransport/values.yaml index b91ef1170..5f81ef852 100644 --- a/helm/global/singapore/webtransport/values.yaml +++ b/helm-videocall-deployment/singapore/webtransport/values.yaml @@ -57,7 +57,8 @@ rustlemania-webtransport: type: LoadBalancer # LoadBalancer for UDP traffic port: 443 healthPort: 444 - annotations: + + loadBalancerAnnotations: service.beta.kubernetes.io/do-loadbalancer-name: "webtransport-singapore" service.beta.kubernetes.io/do-loadbalancer-size-unit: "1" service.beta.kubernetes.io/do-loadbalancer-healthcheck-protocol: "http" diff --git a/helm/global/us-east/engineering-vlog/Chart.lock b/helm-videocall-deployment/us-east/engineering-vlog/Chart.lock similarity index 100% rename from helm/global/us-east/engineering-vlog/Chart.lock rename to helm-videocall-deployment/us-east/engineering-vlog/Chart.lock diff --git a/helm/global/us-east/engineering-vlog/Chart.yaml b/helm-videocall-deployment/us-east/engineering-vlog/Chart.yaml similarity index 100% rename from helm/global/us-east/engineering-vlog/Chart.yaml rename to helm-videocall-deployment/us-east/engineering-vlog/Chart.yaml diff --git a/helm/global/us-east/engineering-vlog/certificate.yaml b/helm-videocall-deployment/us-east/engineering-vlog/certificate.yaml similarity index 100% rename from helm/global/us-east/engineering-vlog/certificate.yaml rename to helm-videocall-deployment/us-east/engineering-vlog/certificate.yaml diff --git a/helm-videocall-deployment/us-east/engineering-vlog/charts/engineering-vlog-0.1.0.tgz b/helm-videocall-deployment/us-east/engineering-vlog/charts/engineering-vlog-0.1.0.tgz new file mode 100644 index 000000000..78bfcc976 Binary files /dev/null and b/helm-videocall-deployment/us-east/engineering-vlog/charts/engineering-vlog-0.1.0.tgz differ diff --git a/helm/global/us-east/engineering-vlog/values.yaml b/helm-videocall-deployment/us-east/engineering-vlog/values.yaml similarity index 100% rename from helm/global/us-east/engineering-vlog/values.yaml rename to helm-videocall-deployment/us-east/engineering-vlog/values.yaml diff --git a/helm-videocall-deployment/us-east/grafana/Chart.lock b/helm-videocall-deployment/us-east/grafana/Chart.lock new file mode 100644 index 000000000..c32b5877d --- /dev/null +++ b/helm-videocall-deployment/us-east/grafana/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: grafana + repository: https://grafana.github.io/helm-charts + version: 7.0.0 +digest: sha256:9fb57a692b37aae8415581f943defc5a76f4f189ed89744d69b020166a0a1185 +generated: "2025-08-05T23:33:20.996318-04:00" diff --git a/helm-videocall-deployment/us-east/grafana/Chart.yaml b/helm-videocall-deployment/us-east/grafana/Chart.yaml new file mode 100644 index 000000000..bd4a394f0 --- /dev/null +++ b/helm-videocall-deployment/us-east/grafana/Chart.yaml @@ -0,0 +1,11 @@ +apiVersion: v2 +name: grafana +description: Grafana monitoring for videocall infrastructure +type: application +version: 0.1.0 +appVersion: "10.0.0" + +dependencies: + - name: grafana + version: "7.0.0" + repository: "https://grafana.github.io/helm-charts" \ No newline at end of file diff --git a/helm/global/us-east/grafana/certificate.yaml b/helm-videocall-deployment/us-east/grafana/certificate.yaml similarity index 100% rename from helm/global/us-east/grafana/certificate.yaml rename to helm-videocall-deployment/us-east/grafana/certificate.yaml diff --git a/helm-videocall-deployment/us-east/grafana/charts/grafana-7.0.0.tgz b/helm-videocall-deployment/us-east/grafana/charts/grafana-7.0.0.tgz new file mode 100644 index 000000000..1ec95bb75 Binary files /dev/null and b/helm-videocall-deployment/us-east/grafana/charts/grafana-7.0.0.tgz differ diff --git a/helm/global/us-east/grafana/deploy.sh b/helm-videocall-deployment/us-east/grafana/deploy.sh similarity index 100% rename from helm/global/us-east/grafana/deploy.sh rename to helm-videocall-deployment/us-east/grafana/deploy.sh diff --git a/helm-videocall-deployment/us-east/grafana/external-secret.yaml b/helm-videocall-deployment/us-east/grafana/external-secret.yaml new file mode 100644 index 000000000..1999b8337 --- /dev/null +++ b/helm-videocall-deployment/us-east/grafana/external-secret.yaml @@ -0,0 +1,20 @@ +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: grafana-admin-credentials + namespace: default +spec: + refreshInterval: 1h + secretStoreRef: + name: cluster-store + kind: SecretStore + target: + name: grafana-admin-credentials + type: Opaque + data: + - secretKey: admin-user + remoteRef: + key: grafana/admin-user + - secretKey: admin-password + remoteRef: + key: grafana/admin-password \ No newline at end of file diff --git a/helm-videocall-deployment/us-east/grafana/secret.yaml b/helm-videocall-deployment/us-east/grafana/secret.yaml new file mode 100644 index 000000000..5ccec10c2 --- /dev/null +++ b/helm-videocall-deployment/us-east/grafana/secret.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Secret +metadata: + name: grafana-admin-credentials + namespace: default +type: Opaque +data: + admin-user: YWRtaW4= # admin in base64 + admin-password: dmlkZW9jYWxsLW1vbml0b3JpbmctMjAyNA== # videocall-monitoring-2024 in base64 \ No newline at end of file diff --git a/helm/global/us-east/grafana/values.yaml b/helm-videocall-deployment/us-east/grafana/values.yaml similarity index 96% rename from helm/global/us-east/grafana/values.yaml rename to helm-videocall-deployment/us-east/grafana/values.yaml index 1d4bbeb4a..eef43f71a 100644 --- a/helm/global/us-east/grafana/values.yaml +++ b/helm-videocall-deployment/us-east/grafana/values.yaml @@ -36,7 +36,7 @@ grafana: enabled: true ingressClassName: nginx annotations: - cert-manager.io/cluster-issuer: "letsencrypt-prod" + cert-manager.io/issuer: "letsencrypt-prod" nginx.ingress.kubernetes.io/ssl-redirect: "true" hosts: - grafana.videocall.rs diff --git a/helm/global/us-east/ingress-nginx/Chart.lock b/helm-videocall-deployment/us-east/ingress-nginx/Chart.lock similarity index 100% rename from helm/global/us-east/ingress-nginx/Chart.lock rename to helm-videocall-deployment/us-east/ingress-nginx/Chart.lock diff --git a/helm/global/us-east/ingress-nginx/Chart.yaml b/helm-videocall-deployment/us-east/ingress-nginx/Chart.yaml similarity index 100% rename from helm/global/us-east/ingress-nginx/Chart.yaml rename to helm-videocall-deployment/us-east/ingress-nginx/Chart.yaml diff --git a/helm-videocall-deployment/us-east/ingress-nginx/charts/ingress-nginx-4.7.0.tgz b/helm-videocall-deployment/us-east/ingress-nginx/charts/ingress-nginx-4.7.0.tgz new file mode 100644 index 000000000..5372ca877 Binary files /dev/null and b/helm-videocall-deployment/us-east/ingress-nginx/charts/ingress-nginx-4.7.0.tgz differ diff --git a/helm/global/us-east/ingress-nginx/values.yaml b/helm-videocall-deployment/us-east/ingress-nginx/values.yaml similarity index 100% rename from helm/global/us-east/ingress-nginx/values.yaml rename to helm-videocall-deployment/us-east/ingress-nginx/values.yaml diff --git a/helm/global/us-east/matomo/Chart.lock b/helm-videocall-deployment/us-east/matomo/Chart.lock similarity index 100% rename from helm/global/us-east/matomo/Chart.lock rename to helm-videocall-deployment/us-east/matomo/Chart.lock diff --git a/helm/global/us-east/matomo/Chart.yaml b/helm-videocall-deployment/us-east/matomo/Chart.yaml similarity index 100% rename from helm/global/us-east/matomo/Chart.yaml rename to helm-videocall-deployment/us-east/matomo/Chart.yaml diff --git a/helm/global/us-east/matomo/certificate.yaml b/helm-videocall-deployment/us-east/matomo/certificate.yaml similarity index 100% rename from helm/global/us-east/matomo/certificate.yaml rename to helm-videocall-deployment/us-east/matomo/certificate.yaml diff --git a/helm-videocall-deployment/us-east/matomo/charts/matomo-10.0.25.tgz b/helm-videocall-deployment/us-east/matomo/charts/matomo-10.0.25.tgz new file mode 100644 index 000000000..120abfa57 Binary files /dev/null and b/helm-videocall-deployment/us-east/matomo/charts/matomo-10.0.25.tgz differ diff --git a/helm/global/us-east/matomo/values.yaml b/helm-videocall-deployment/us-east/matomo/values.yaml similarity index 100% rename from helm/global/us-east/matomo/values.yaml rename to helm-videocall-deployment/us-east/matomo/values.yaml diff --git a/helm-videocall-deployment/us-east/metrics-api/Chart.lock b/helm-videocall-deployment/us-east/metrics-api/Chart.lock new file mode 100644 index 000000000..b4d621e20 --- /dev/null +++ b/helm-videocall-deployment/us-east/metrics-api/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: metrics-api + repository: file://../../../metrics-api + version: 0.1.0 +digest: sha256:29e0657f2530c414e018c5f70b0c02458361919d548095e92b74d24b04731858 +generated: "2025-11-14T11:37:27.808905037-05:00" diff --git a/helm/global/us-east/metrics-api/Chart.yaml b/helm-videocall-deployment/us-east/metrics-api/Chart.yaml similarity index 71% rename from helm/global/us-east/metrics-api/Chart.yaml rename to helm-videocall-deployment/us-east/metrics-api/Chart.yaml index 5e30075bf..78dea445e 100644 --- a/helm/global/us-east/metrics-api/Chart.yaml +++ b/helm-videocall-deployment/us-east/metrics-api/Chart.yaml @@ -14,4 +14,9 @@ sources: - https://github.com/your-org/videocall-rs maintainers: - name: Your Name - email: your-email@example.com \ No newline at end of file + email: your-email@example.com + +dependencies: + - name: metrics-api + version: 0.1.0 + repository: file://../../../metrics-api \ No newline at end of file diff --git a/helm-videocall-deployment/us-east/metrics-api/values.yaml b/helm-videocall-deployment/us-east/metrics-api/values.yaml new file mode 100644 index 000000000..55f315fb1 --- /dev/null +++ b/helm-videocall-deployment/us-east/metrics-api/values.yaml @@ -0,0 +1,133 @@ +# Metrics API values for videocall monitoring (minimal resources) +metrics-api: + metricsApi: + # Image configuration + image: + repository: securityunion/rustlemania-api + pullPolicy: Always + tag: latest + + # Minimal resources for cost optimization + resources: + limits: + cpu: 50m + memory: 128Mi + requests: + cpu: 25m + memory: 64Mi + + # Single replica + replicas: 1 + + # Service configuration + service: + type: ClusterIP + port: 9091 + targetPort: 9091 + + # Environment variables + env: + METRICS_PORT: "9091" + NATS_URL: "nats://nats-us-east:4222" + REGION: "us-east" + SERVICE_TYPE: "metrics" + RUST_LOG: "warn,async_nats=warn" + TOKIO_WORKER_THREADS: "1" # Optimal for 50m CPU (metrics collection is I/O bound) + + # Health check configuration + livenessProbe: + httpGet: + path: /health + port: 9091 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + + readinessProbe: + httpGet: + path: /health + port: 9091 + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 3 + + # Security context + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + + # Pod security context + podSecurityContext: + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + + # Separate Server Stats pod for connection tracking (stateless snapshot approach) + serverStats: + # Image configuration (same as metrics-api but different binary) + image: + repository: securityunion/rustlemania-api + pullPolicy: Always + tag: latest + + # Minimal resources for server connection tracking + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 50m + memory: 64Mi + + # Single replica + replicas: 1 + + # Service configuration - different port from client metrics + service: + type: ClusterIP + port: 9092 + targetPort: 9092 + + # Environment variables for server stats + env: + METRICS_PORT: "9092" + NATS_URL: "nats://nats-us-east:4222" + REGION: "us-east" + SERVICE_TYPE: "server-stats" + RUST_LOG: "debug,async_nats=info" + TOKIO_WORKER_THREADS: "1" # Optimal for 100m CPU (server stats aggregation is I/O bound) + + # Binary to run + command: ["/usr/bin/metrics_server_snapshot"] + + # Health check configuration + livenessProbe: + httpGet: + path: /health + port: 9092 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + + readinessProbe: + httpGet: + path: /health + port: 9092 + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 3 + + # Security context + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + + # Pod security context + podSecurityContext: + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 \ No newline at end of file diff --git a/helm-videocall-deployment/us-east/nats/Chart.lock b/helm-videocall-deployment/us-east/nats/Chart.lock new file mode 100644 index 000000000..431e886ee --- /dev/null +++ b/helm-videocall-deployment/us-east/nats/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: nats + repository: https://nats-io.github.io/k8s/helm/charts/ + version: 0.19.15 +digest: sha256:068e4c9258b50decadb4bc245b16a7036613591d64f1138fa7715c2af09aec1b +generated: "2025-07-16T06:00:32.684518-04:00" diff --git a/helm-videocall-deployment/us-east/nats/Chart.yaml b/helm-videocall-deployment/us-east/nats/Chart.yaml new file mode 100644 index 000000000..e9272660e --- /dev/null +++ b/helm-videocall-deployment/us-east/nats/Chart.yaml @@ -0,0 +1,9 @@ +apiVersion: v2 +name: nats-us-east +version: 0.1.0 +description: NATS cluster for US East region with cross-region gateway + +dependencies: + - name: nats + version: 0.19.15 + repository: https://nats-io.github.io/k8s/helm/charts/ diff --git a/helm-videocall-deployment/us-east/nats/charts/nats-0.19.15.tgz b/helm-videocall-deployment/us-east/nats/charts/nats-0.19.15.tgz new file mode 100644 index 000000000..4d2b0c2d6 Binary files /dev/null and b/helm-videocall-deployment/us-east/nats/charts/nats-0.19.15.tgz differ diff --git a/helm/global/us-east/nats/values.yaml b/helm-videocall-deployment/us-east/nats/values.yaml similarity index 100% rename from helm/global/us-east/nats/values.yaml rename to helm-videocall-deployment/us-east/nats/values.yaml diff --git a/helm-videocall-deployment/us-east/postgres/Chart.lock b/helm-videocall-deployment/us-east/postgres/Chart.lock new file mode 100644 index 000000000..332cbfbf8 --- /dev/null +++ b/helm-videocall-deployment/us-east/postgres/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: postgresql + repository: https://charts.bitnami.com/bitnami + version: 18.1.3 +digest: sha256:0c6b3a36ce405f3f0bb6fe005781859a04e5d7b5e275b7abeb169a1d6d99a518 +generated: "2025-10-30T22:44:18.167122-04:00" diff --git a/helm/global/us-east/postgres/Chart.yaml b/helm-videocall-deployment/us-east/postgres/Chart.yaml similarity index 100% rename from helm/global/us-east/postgres/Chart.yaml rename to helm-videocall-deployment/us-east/postgres/Chart.yaml diff --git a/helm-videocall-deployment/us-east/postgres/README.md b/helm-videocall-deployment/us-east/postgres/README.md new file mode 100644 index 000000000..35f3a8aed --- /dev/null +++ b/helm-videocall-deployment/us-east/postgres/README.md @@ -0,0 +1,142 @@ +# PostgreSQL for US East Region + +This Helm chart deploys PostgreSQL with persistent storage for the videocall-rs application. + +## Installation + +### 1. Update Helm dependencies + +```bash +cd helm/global/us-east/postgres +helm dependency update +``` + +### 2. Install PostgreSQL + +```bash +helm install postgres . -n default +``` + +Or with custom values: + +```bash +helm install postgres . -n default -f values.yaml +``` + +## Database Configuration + +- **Database Name**: `actix-api-db` +- **Username**: `postgres` +- **Password**: Set in `values.yaml` (change for production!) +- **Port**: 5432 +- **Service Name**: `postgres-us-east-postgresql` + +## Connecting to PostgreSQL + +### From within the cluster: + +``` +Host: postgres-us-east-postgresql +Port: 5432 +Database: actix-api-db +Username: postgres +Password: +``` + +### Connection string for actix-api: + +``` +DATABASE_URL=postgres://postgres:@postgres-us-east-postgresql:5432/actix-api-db?sslmode=disable +``` + +## Persistent Volume + +- **Storage Class**: `do-block-storage` (DigitalOcean Block Storage) +- **Size**: 10Gi +- **Retention**: Volume persists after `helm uninstall` due to `helm.sh/resource-policy: keep` annotation + +## Managing the Database + +### Access PostgreSQL shell: + +```bash +kubectl exec -it postgres-us-east-postgresql-0 -- psql -U postgres -d actix-api-db +``` + +### View logs: + +```bash +kubectl logs postgres-us-east-postgresql-0 +``` + +### Check PVC status: + +```bash +kubectl get pvc | grep postgres +``` + +## Backup and Restore + +### Manual backup: + +```bash +kubectl exec postgres-us-east-postgresql-0 -- pg_dump -U postgres actix-api-db > backup.sql +``` + +### Restore from backup: + +```bash +kubectl exec -i postgres-us-east-postgresql-0 -- psql -U postgres actix-api-db < backup.sql +``` + +## Uninstalling + +```bash +helm uninstall postgres -n default +``` + +**Note**: The Persistent Volume Claim (PVC) will **NOT** be deleted and your data will be preserved. To completely remove everything including data: + +```bash +kubectl delete pvc data-postgres-us-east-postgresql-0 +``` + +## Monitoring + +PostgreSQL metrics are enabled and can be scraped by Prometheus. The metrics endpoint is available at: + +``` +http://postgres-us-east-postgresql-metrics:9187/metrics +``` + +## Security Recommendations + +1. **Change default passwords** in production +2. Use **Kubernetes Secrets** instead of plain text passwords in values.yaml +3. Enable **SSL/TLS** for database connections +4. Set up **regular backups** +5. Consider enabling **read replicas** for high availability + +## Troubleshooting + +### Pod not starting: + +```bash +kubectl describe pod postgres-us-east-postgresql-0 +kubectl logs postgres-us-east-postgresql-0 +``` + +### Storage issues: + +```bash +kubectl get pvc +kubectl describe pvc data-postgres-us-east-postgresql-0 +``` + +### Connection issues: + +```bash +kubectl get svc postgres-us-east-postgresql +kubectl exec -it postgres-us-east-postgresql-0 -- psql -U postgres -c "SELECT version();" +``` + diff --git a/helm-videocall-deployment/us-east/postgres/charts/postgresql-18.1.3.tgz b/helm-videocall-deployment/us-east/postgres/charts/postgresql-18.1.3.tgz new file mode 100644 index 000000000..34ad0badc Binary files /dev/null and b/helm-videocall-deployment/us-east/postgres/charts/postgresql-18.1.3.tgz differ diff --git a/helm/global/us-east/postgres/values.yaml b/helm-videocall-deployment/us-east/postgres/values.yaml similarity index 100% rename from helm/global/us-east/postgres/values.yaml rename to helm-videocall-deployment/us-east/postgres/values.yaml diff --git a/helm-videocall-deployment/us-east/prometheus/Chart.lock b/helm-videocall-deployment/us-east/prometheus/Chart.lock new file mode 100644 index 000000000..b03aa621d --- /dev/null +++ b/helm-videocall-deployment/us-east/prometheus/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: prometheus + repository: https://prometheus-community.github.io/helm-charts + version: 25.0.0 +digest: sha256:c36fca4c53a92945499bff5961e2fbf19c1b29c13bde6666a8c57c1ae3bc3b02 +generated: "2025-08-05T23:33:13.937811-04:00" diff --git a/helm-videocall-deployment/us-east/prometheus/Chart.yaml b/helm-videocall-deployment/us-east/prometheus/Chart.yaml new file mode 100644 index 000000000..ee25f7953 --- /dev/null +++ b/helm-videocall-deployment/us-east/prometheus/Chart.yaml @@ -0,0 +1,11 @@ +apiVersion: v2 +name: prometheus +description: Prometheus monitoring for videocall infrastructure +type: application +version: 0.1.0 +appVersion: "2.45.0" + +dependencies: + - name: prometheus + version: "25.0.0" + repository: "https://prometheus-community.github.io/helm-charts" \ No newline at end of file diff --git a/helm-videocall-deployment/us-east/prometheus/charts/prometheus-25.0.0.tgz b/helm-videocall-deployment/us-east/prometheus/charts/prometheus-25.0.0.tgz new file mode 100644 index 000000000..e82764bcc Binary files /dev/null and b/helm-videocall-deployment/us-east/prometheus/charts/prometheus-25.0.0.tgz differ diff --git a/helm/global/us-east/prometheus/values.yaml b/helm-videocall-deployment/us-east/prometheus/values.yaml similarity index 100% rename from helm/global/us-east/prometheus/values.yaml rename to helm-videocall-deployment/us-east/prometheus/values.yaml diff --git a/helm/global/us-east/rustlemania-ui-staging/Chart.lock b/helm-videocall-deployment/us-east/rustlemania-ui-staging/Chart.lock similarity index 100% rename from helm/global/us-east/rustlemania-ui-staging/Chart.lock rename to helm-videocall-deployment/us-east/rustlemania-ui-staging/Chart.lock diff --git a/helm/global/us-east/rustlemania-ui-staging/Chart.yaml b/helm-videocall-deployment/us-east/rustlemania-ui-staging/Chart.yaml similarity index 100% rename from helm/global/us-east/rustlemania-ui-staging/Chart.yaml rename to helm-videocall-deployment/us-east/rustlemania-ui-staging/Chart.yaml diff --git a/helm/global/us-east/rustlemania-ui-staging/certificate.yaml b/helm-videocall-deployment/us-east/rustlemania-ui-staging/certificate.yaml similarity index 100% rename from helm/global/us-east/rustlemania-ui-staging/certificate.yaml rename to helm-videocall-deployment/us-east/rustlemania-ui-staging/certificate.yaml diff --git a/helm-videocall-deployment/us-east/rustlemania-ui-staging/charts/rustlemania-ui-0.1.0.tgz b/helm-videocall-deployment/us-east/rustlemania-ui-staging/charts/rustlemania-ui-0.1.0.tgz new file mode 100644 index 000000000..c8d61ed18 Binary files /dev/null and b/helm-videocall-deployment/us-east/rustlemania-ui-staging/charts/rustlemania-ui-0.1.0.tgz differ diff --git a/helm/global/us-east/rustlemania-ui-staging/values.yaml b/helm-videocall-deployment/us-east/rustlemania-ui-staging/values.yaml similarity index 100% rename from helm/global/us-east/rustlemania-ui-staging/values.yaml rename to helm-videocall-deployment/us-east/rustlemania-ui-staging/values.yaml diff --git a/helm/global/us-east/rustlemania-ui/Chart.lock b/helm-videocall-deployment/us-east/rustlemania-ui/Chart.lock similarity index 100% rename from helm/global/us-east/rustlemania-ui/Chart.lock rename to helm-videocall-deployment/us-east/rustlemania-ui/Chart.lock diff --git a/helm/global/us-east/rustlemania-ui/Chart.yaml b/helm-videocall-deployment/us-east/rustlemania-ui/Chart.yaml similarity index 100% rename from helm/global/us-east/rustlemania-ui/Chart.yaml rename to helm-videocall-deployment/us-east/rustlemania-ui/Chart.yaml diff --git a/helm/global/us-east/rustlemania-ui/certificate.yaml b/helm-videocall-deployment/us-east/rustlemania-ui/certificate.yaml similarity index 100% rename from helm/global/us-east/rustlemania-ui/certificate.yaml rename to helm-videocall-deployment/us-east/rustlemania-ui/certificate.yaml diff --git a/helm-videocall-deployment/us-east/rustlemania-ui/charts/rustlemania-ui-0.1.0.tgz b/helm-videocall-deployment/us-east/rustlemania-ui/charts/rustlemania-ui-0.1.0.tgz new file mode 100644 index 000000000..49161960d Binary files /dev/null and b/helm-videocall-deployment/us-east/rustlemania-ui/charts/rustlemania-ui-0.1.0.tgz differ diff --git a/helm/global/us-east/rustlemania-ui/values.yaml b/helm-videocall-deployment/us-east/rustlemania-ui/values.yaml similarity index 100% rename from helm/global/us-east/rustlemania-ui/values.yaml rename to helm-videocall-deployment/us-east/rustlemania-ui/values.yaml diff --git a/helm/global/us-east/videocall-website/Chart.lock b/helm-videocall-deployment/us-east/videocall-website/Chart.lock similarity index 100% rename from helm/global/us-east/videocall-website/Chart.lock rename to helm-videocall-deployment/us-east/videocall-website/Chart.lock diff --git a/helm/global/us-east/videocall-website/Chart.yaml b/helm-videocall-deployment/us-east/videocall-website/Chart.yaml similarity index 100% rename from helm/global/us-east/videocall-website/Chart.yaml rename to helm-videocall-deployment/us-east/videocall-website/Chart.yaml diff --git a/helm/global/us-east/videocall-website/certificate.yaml b/helm-videocall-deployment/us-east/videocall-website/certificate.yaml similarity index 100% rename from helm/global/us-east/videocall-website/certificate.yaml rename to helm-videocall-deployment/us-east/videocall-website/certificate.yaml diff --git a/helm-videocall-deployment/us-east/videocall-website/charts/videocall-website-0.1.0.tgz b/helm-videocall-deployment/us-east/videocall-website/charts/videocall-website-0.1.0.tgz new file mode 100644 index 000000000..ccff6f94d Binary files /dev/null and b/helm-videocall-deployment/us-east/videocall-website/charts/videocall-website-0.1.0.tgz differ diff --git a/helm/global/us-east/videocall-website/values.yaml b/helm-videocall-deployment/us-east/videocall-website/values.yaml similarity index 100% rename from helm/global/us-east/videocall-website/values.yaml rename to helm-videocall-deployment/us-east/videocall-website/values.yaml diff --git a/helm/global/us-east/websocket/Chart.lock b/helm-videocall-deployment/us-east/websocket/Chart.lock similarity index 100% rename from helm/global/us-east/websocket/Chart.lock rename to helm-videocall-deployment/us-east/websocket/Chart.lock diff --git a/helm/global/us-east/websocket/Chart.yaml b/helm-videocall-deployment/us-east/websocket/Chart.yaml similarity index 100% rename from helm/global/us-east/websocket/Chart.yaml rename to helm-videocall-deployment/us-east/websocket/Chart.yaml diff --git a/helm/global/us-east/websocket/certificate.yaml b/helm-videocall-deployment/us-east/websocket/certificate.yaml similarity index 100% rename from helm/global/us-east/websocket/certificate.yaml rename to helm-videocall-deployment/us-east/websocket/certificate.yaml diff --git a/helm-videocall-deployment/us-east/websocket/charts/rustlemania-websocket-0.1.0.tgz b/helm-videocall-deployment/us-east/websocket/charts/rustlemania-websocket-0.1.0.tgz new file mode 100644 index 000000000..cc74ece83 Binary files /dev/null and b/helm-videocall-deployment/us-east/websocket/charts/rustlemania-websocket-0.1.0.tgz differ diff --git a/helm/global/us-east/websocket/values.yaml b/helm-videocall-deployment/us-east/websocket/values.yaml similarity index 87% rename from helm/global/us-east/websocket/values.yaml rename to helm-videocall-deployment/us-east/websocket/values.yaml index a2e018276..a7afb6f4f 100644 --- a/helm/global/us-east/websocket/values.yaml +++ b/helm-videocall-deployment/us-east/websocket/values.yaml @@ -19,11 +19,6 @@ rustlemania-websocket: value: nats-us-east:4222 # Connect to US East NATS cluster - name: DATABASE_ENABLED value: "true" - - name: PG_PASSWORD - valueFrom: - secretKeyRef: - name: postgres-credentials - key: password - name: DATABASE_URL value: postgres://postgres:$(PG_PASSWORD)@postgres-postgresql:5432/actix-api-db?sslmode=disable - name: REGION @@ -42,17 +37,6 @@ rustlemania-websocket: value: "5" - name: TOKIO_WORKER_THREADS value: "2" # Optimal for 2400m CPU (I/O bound WebSocket operations) - # OAuth Configuration (from secret) - - name: OAUTH_CLIENT_ID - valueFrom: - secretKeyRef: - name: google-oauth-credentials - key: client-id - - name: OAUTH_CLIENT_SECRET - valueFrom: - secretKeyRef: - name: google-oauth-credentials - key: client-secret - name: OAUTH_AUTH_URL value: "https://accounts.google.com/o/oauth2/v2/auth" - name: OAUTH_TOKEN_URL diff --git a/helm/global/us-east/webtransport/Chart.lock b/helm-videocall-deployment/us-east/webtransport/Chart.lock similarity index 100% rename from helm/global/us-east/webtransport/Chart.lock rename to helm-videocall-deployment/us-east/webtransport/Chart.lock diff --git a/helm/global/us-east/webtransport/Chart.yaml b/helm-videocall-deployment/us-east/webtransport/Chart.yaml similarity index 100% rename from helm/global/us-east/webtransport/Chart.yaml rename to helm-videocall-deployment/us-east/webtransport/Chart.yaml diff --git a/helm/global/us-east/webtransport/certificate.yaml b/helm-videocall-deployment/us-east/webtransport/certificate.yaml similarity index 100% rename from helm/global/us-east/webtransport/certificate.yaml rename to helm-videocall-deployment/us-east/webtransport/certificate.yaml diff --git a/helm-videocall-deployment/us-east/webtransport/charts/rustlemania-webtransport-0.1.0.tgz b/helm-videocall-deployment/us-east/webtransport/charts/rustlemania-webtransport-0.1.0.tgz new file mode 100644 index 000000000..c31f05c21 Binary files /dev/null and b/helm-videocall-deployment/us-east/webtransport/charts/rustlemania-webtransport-0.1.0.tgz differ diff --git a/helm/global/us-east/webtransport/values.yaml b/helm-videocall-deployment/us-east/webtransport/values.yaml similarity index 70% rename from helm/global/us-east/webtransport/values.yaml rename to helm-videocall-deployment/us-east/webtransport/values.yaml index e60d88078..d52512bf7 100644 --- a/helm/global/us-east/webtransport/values.yaml +++ b/helm-videocall-deployment/us-east/webtransport/values.yaml @@ -45,6 +45,8 @@ rustlemania-webtransport: - name: TOKIO_BLOCKING_THREADS value: "2" # Small pool for blocking crypto operations + certificateDomain: "webtransport-us-east.webtransport.video" + resources: limits: cpu: "3500m" @@ -57,17 +59,18 @@ rustlemania-webtransport: type: LoadBalancer # LoadBalancer for UDP traffic port: 443 healthPort: 444 - annotations: - service.beta.kubernetes.io/do-loadbalancer-name: "webtransport-us-east" - service.beta.kubernetes.io/do-loadbalancer-size-unit: "1" - service.beta.kubernetes.io/do-loadbalancer-healthcheck-protocol: "http" - service.beta.kubernetes.io/do-loadbalancer-healthcheck-check-interval-seconds: "10" - service.beta.kubernetes.io/do-loadbalancer-healthcheck-response-timeout-seconds: "5" - service.beta.kubernetes.io/do-loadbalancer-healthcheck-unhealthy-threshold: "3" - service.beta.kubernetes.io/do-loadbalancer-healthcheck-healthy-threshold: "2" - service.beta.kubernetes.io/do-loadbalancer-healthcheck-port: "444" - service.beta.kubernetes.io/do-loadbalancer-healthcheck-path: "/healthz" - external-dns.alpha.kubernetes.io/hostname: "webtransport-us-east.webtransport.video" + + loadBalancerAnnotations: + external-dns.alpha.kubernetes.io/hostname: "webtransport-us-east.webtransport.video" + service.beta.kubernetes.io/do-loadbalancer-name: "webtransport-us-east" + service.beta.kubernetes.io/do-loadbalancer-size-unit: "1" + service.beta.kubernetes.io/do-loadbalancer-healthcheck-protocol: "http" + service.beta.kubernetes.io/do-loadbalancer-healthcheck-check-interval-seconds: "10" + service.beta.kubernetes.io/do-loadbalancer-healthcheck-response-timeout-seconds: "5" + service.beta.kubernetes.io/do-loadbalancer-healthcheck-unhealthy-threshold: "3" + service.beta.kubernetes.io/do-loadbalancer-healthcheck-healthy-threshold: "2" + service.beta.kubernetes.io/do-loadbalancer-healthcheck-port: "444" + service.beta.kubernetes.io/do-loadbalancer-healthcheck-path: "/healthz" autoscaling: enabled: false diff --git a/helm/K3S_DEPLOYMENT_GUIDE.md b/helm/K3S_DEPLOYMENT_GUIDE.md new file mode 100644 index 000000000..3a1ec9ffe --- /dev/null +++ b/helm/K3S_DEPLOYMENT_GUIDE.md @@ -0,0 +1,543 @@ +# K3s Deployment Guide for VideoCall-RS + +This guide outlines how to deploy a simple Kubernetes cluster with VideoCall-RS application on a bare K3s cluster. It includes both the infrastructure components and application-specific services with a simplified configuration. + +**Updated for Unified Chart**: This guide now uses the unified `videocall` Helm chart which deploys all application components (UI, WebSocket, WebTransport, Website, Metrics) in a single install. Infrastructure components (NATS, Prometheus, etc.) are installed separately from `helm-videocall-deployment/infrastructure/`. + +We encourage you to read through this doc in its entirety first, ensure you understand what values need to be customized (and customize them!) before you go crazy deploying with cut and paste! + +## Prerequisites + +- A server with sufficient resources (recommended: 4+ CPU cores, 8GB+ RAM). This guide was done on an AWS EC2 instance using t3a.xlarge instance type. +- A domain name that you can modify DNS A records. This guide assumes you can establish programmatic interaction with DNS so that Cert Manager can obtain SSL certs via ACME & Lets Encrypt. You will also need to add A records, either dynamically with External DNS or manually prior to your install. +- Ability to open necessary ports (80, 443, 443/UDP for WebTransport) +- Clone the github repo https://github.com/security-union/videocall-rs locally and ensure you do your work from the root of the cloned repo (within the `videocall-rs` directory) + +**Before proceeding, you'll need to create a values file for your domain.** You must have a valid domain name - the procedure below requires cert-manager and optionally external-dns to set DNS entries for use with obtaining valid SSL certificates and resolving DNS names. + +Create a custom values file for your deployment: +```bash +cat > my-values.yaml <> ~/.bashrc +# Set it for this interactive shell sessions +export KUBECONFIG=~/.kube/config +``` + +We're going to install the application components into the `videocall` namespace. Let's create that now and set it as the default context: +```bash +kubectl create namespace videocall +kubectl config set-context --current --namespace=videocall +``` + +## 2. Core Infrastructure Components + +### 2.1 NGINX Ingress Controller + +Install the NGINX Ingress Controller. + +Setup the required Helm repository: +```bash +helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx +helm repo update +``` +You need to specify the Ingress external IP address: +```bash +IPADDR=`hostname -i` +echo "Ingress IP Address: $IPADDR" +``` +Ensure you validate this IP address before proceeding, reset the environment variable if necessary. Then install NGINX: +```bash +# Install NGINX Ingress Controller +helm install ingress-nginx helm-videocall-deployment/infrastructure/ingress-nginx \ + --create-namespace \ + --namespace ingress-nginx \ + --version 4.13.0 \ + --set controller.service.type=NodePort \ + --set controller.service.externalIPs={$IPADDR} +``` + +This configuration exposes the NGINX Ingress Controller on the specified IP address, making it accessible from outside the cluster. The NodePort service type allows the controller to be reached on specific ports on all nodes in the cluster (in our example here, single node). + +### 2.2 Cert Manager + +Install cert-manager for TLS certificate management. + +Add the necessary Helm repo: +```bash +helm repo add jetstack https://charts.jetstack.io +helm repo update +``` +Install Cert Manager: +```bash +helm install cert-manager helm-videocall-deployment/infrastructure/cert-manager \ + --namespace cert-manager \ + --create-namespace +``` + +You only need to install one Issuer. Below are examples of a AWS Route 53 Issuer and a CloudFlare Issuer. If you are using different DNS management, consult the Cert Manager documentation: https://cert-manager.io/docs/configuration/acme/dns01 + +#### 2.2.1 AWS Route 53 +##### AWS IAM Permissions for Route 53 DNS01 Challenge + +The AWS identity (user or role) whose credentials are used for DNS01 challenge must have permissions to manage Route 53 records for your domain. At minimum, the following IAM policy should be attached: + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "route53:ListHostedZones", + "route53:GetChange", + "route53:ChangeResourceRecordSets" + ], + "Resource": "*" + } + ] +} +``` + +This allows cert-manager to list hosted zones, submit DNS record changes, and check their status. For production, you may wish to restrict the `Resource` to only the hosted zone(s) you use. + +For more details, see the cert-manager documentation: https://cert-manager.io/docs/configuration/acme/dns01/route53/ + +Configure the LetsEncrypt Issuer in the videocall namespace using AWS Route 53 for DNS01 challenge. We'll create a namespaced Issuer (vs a cluster issuer). + +Refer to [Configuring DNS01 Challenge Provider](https://cert-manager.io/docs/configuration/acme/dns01/). + + +In the steps below, you must use your own AWS Access Key details. Additionally, locate and edit `helm-videocall-deployment/infrastructure/cert-manager-issuer/route53-issuer.yaml` and update the `email` attribute with your own email. Do that now before continuing. +```bash +# Create a secret for AWS Route53 API credentials +kubectl create secret generic route53-creds -n videocall \ + --from-literal=aws_access_key_id=YOUR_AWS_ACCESS_KEY_ID \ + --from-literal=aws_secret_access_key=YOUR_AWS_SECRET_ACCESS_KEY + +# Create the namespace-scoped Issuer with DNS01 challenge using Route53 +kubectl apply -f helm-videocall-deployment/infrastructure/cert-manager-issuer/route53-issuer.yaml +``` + +> **Note**: This configuration uses DNS01 challenge with AWS Route53, which is required for validating wildcard certificates and is generally more reliable than HTTP01 validation. This deployment will use this method for certificate validation. You can use other DNS providers supported by cert-manager, or switch to HTTP01 validation (which doesn't work for wildcard certificates) if your deployment is available on the internet. + +#### 2.2.2 Cloudflare + +Alternatively, you can use Cloudflare for DNS01 challenge. The process is similar, but uses Cloudflare API credentials. See [cert-manager Cloudflare DNS01 documentation](https://cert-manager.io/docs/configuration/acme/dns01/cloudflare/). + +1. Create a Cloudflare API token with permissions for "Zone:DNS:Edit" and "Zone:Read" for your domain. +2. Store the token in a Kubernetes secret: + +```bash +kubectl create secret generic cloudflare-api-token-secret -n videocall \ + --from-literal=api-token=YOUR_CLOUDFLARE_API_TOKEN +``` + +3. Edit `helm-videocall-deployment/infrastructure/cert-manager-issuer/cloudflare-issuer.yaml` and update the two `email` attributes with your own email. Do that now before continuing. + +4. Create the Issuer: +```bash +kubectl apply -f helm-videocall-deployment/infrastructure/cert-manager-issuer/cloudflare-issuer.yaml +``` +> **Note**: This configuration uses DNS01 challenge with Cloudflare. You must use an API token (not your global API key) with the correct permissions. For more details, see [cert-manager Cloudflare DNS01 documentation](https://cert-manager.io/docs/configuration/acme/dns01/cloudflare/). + +### 2.3 DNS A Records + +A DNS A record, or Address record, maps a domain name (like www.example.com) to a specific IPv4 address (e.g., 192.0.2.1). You can manually create these or you can use External DNS to do it for you. Follow one of these steps below. + +#### 2.3.1 External DNS +The Videocall charts are setup to utilize External DNS (https://github.com/kubernetes-sigs/external-dns) to automatically create the necessary DNS records. The procedure below installs and configured External DNS. + +Add the necessary Helm repo: +```bash +helm repo add external-dns https://kubernetes-sigs.github.io/external-dns/ +helm repo update +``` + +Create a new namespace for External DNS: +```bash +# Create a secret for AWS Route53 API credentials +kubectl create namespace externaldns +``` + +In this example we're using AWS Route 53 for DNS management. You could use Digital Ocean, Cloudflare, or any other supported DNS provider. + +Setup your AWS Credentials. **Use your own values for the access key and secret access key.** Create your aws credentials file (~/.aws/credentials): +```bash +[default] +aws_access_key_id = AKIAEXAMPLEKEY123456 +aws_secret_access_key = AbCdEfGhIjKlMnOpQrStUvWxYz1234567890+EXAMPLE +``` +Create a secret from these credentials: +```bash +kubectl create secret generic external-dns -n externaldns \ + --from-file=dns-creds=~/.aws/credentials +``` + +Install External DNS with AWS Route53 configuration +```bash +helm install external-dns external-dns/external-dns \ + --namespace externaldns \ + --values ./helm-videocall-deployment/infrastructure/external-dns/route53.yaml +``` + + +#### 2.3.2 Manual DNS Configuration + +External DNS can be skipped if you prefer to manage DNS records manually. In this case, you would need to create the following A/CNAME records pointing to your cluster's public IP address: + +| DNS Name | Purpose | Service Type | +|---------|---------|-------------| +| webtransport.yourdomain.com | WebTransport server | LoadBalancer | +| app.yourdomain.com | UI application | Ingress | +| api.yourdomain.com | API application | Ingress | +| websocket.yourdomain.com | WebSocket server | Ingress | +| grafana.yourdomain.com | Grafana dashboard | Ingress | + +In this simple K3s configuration, use the IP address of the K3s node which can usually be reviewed with the command `hostname -i`. If you are using a cloud based VM, there may be multiple IPs that point to this host, often times one internal (private) and one external. If your audience is coming from the internet, ensure you are using the correct IP address here. + +For each DNS name in the table above, create an A record in your DNS provider for the appropriate hostname pointing to this IP. + +Manual DNS configuration requires updating records whenever your service IPs change (such as after cluster redeployment), whereas External DNS handles this automatically. + +## 3. Monitoring Stack (Optional) + +### 3.1 Prometheus + +Install Prometheus for metrics collection: + +```bash +helm repo add prometheus-community https://prometheus-community.github.io/helm-charts +helm dependency build helm-videocall-deployment/infrastructure/prometheus +helm install prometheus helm-videocall-deployment/infrastructure/prometheus --namespace videocall +``` + +Key configurations to review: +- Retention period +- Storage size and class +- Scrape configurations (especially for service endpoints) + +revise `./helm-videocall-deployment/infrastructure/prometheus/values.yaml` as necessary prior to install. + + +### 3.2 Grafana + +Install Grafana for metrics visualization. + +Setup the required Helm repository: + +```bash +helm repo add grafana https://grafana.github.io/helm-charts +helm dependency build helm-videocall-deployment/infrastructure/grafana +``` +Use a custom value for the Grafana Admin Password: +```bash +export GRAFANA_ADMIN_USER=admin +export GRAFANA_ADMIN_PASSWORD=videocall-monitoring-2024 +``` +Install: +```bash +helm upgrade --install grafana helm-videocall-deployment/infrastructure/grafana \ + --namespace videocall \ + --set grafana.adminUser=$GRAFANA_ADMIN_USER \ + --set grafana.adminPassword=$GRAFANA_ADMIN_PASSWORD \ + --set grafana.grafana.ini.security.admin_user=$GRAFANA_ADMIN_USER \ + --set grafana.grafana.ini.security.admin_password=$GRAFANA_ADMIN_PASSWORD +``` + + + +## 4. Video Call Application + +### 4.1 NATS Message Broker + +Before installing NATS, add the NATS Helm repository and build chart dependencies: + +```bash +helm repo add nats https://nats-io.github.io/k8s/helm/charts/ +helm dependency build helm-videocall-deployment/infrastructure/nats +``` + +Install NATS for application messaging: + +```bash +helm install nats helm-videocall-deployment/infrastructure/nats --namespace videocall +``` + +This uses a very simple, non-persisted NATS configuration. + +### 4.2 Videocall Application (Unified Chart) + +Install the complete Videocall application using the unified chart and your custom values file: + +```bash +helm install videocall ./helm/videocall \ + --namespace videocall \ + -f my-values.yaml +``` + +This single command deploys all six application components: +- **UI** - Web application frontend (port 80) +- **WebSocket** - Real-time signaling server (port 8080) +- **WebTransport** - High-performance media transport (port 443 UDP) +- **Website** - Marketing site (port 80, optional) +- **Metrics Client** - Client metrics collection (port 9091) +- **Metrics Server** - Server stats tracking (port 9092) + +> **Important**: The WebTransport server does not use the NGINX Ingress Controller. Instead, it's exposed directly using a Kubernetes LoadBalancer Service that handles UDP traffic required for HTTP3/WebTransport protocol. The WebTransport server handles its own TLS termination using mounted certificates, and clients connect directly to this service rather than through NGINX. This is necessary because WebTransport requires direct UDP connectivity for the QUIC protocol. + +> **Note**: The WebTransport pod may restart several times before success, typically because it tries to start before cert-manager has obtained the SSL certificate. You can view the pod logs to confirm: +```bash +kubectl logs -l app.kubernetes.io/component=webtransport +``` + +To verify all components are deployed: +```bash +kubectl get pods -l app.kubernetes.io/instance=videocall +``` + +You should see pods for each enabled component with unique `app.kubernetes.io/component` labels. + + +## 5. Post-Installation Verification + +### 5.1 Verify Services + +Check that all services are running: + +```bash +$ kubectl get pods,services,ingress +NAME READY STATUS RESTARTS AGE +pod/grafana-c44db467f-xkztd 1/1 Running 0 5h25m +pod/nats-0 3/3 Running 0 5d1h +pod/nats-box-69b79775f4-5fxgn 1/1 Running 0 5d1h +pod/prometheus-kube-state-metrics-686d9fd46c-jx6b9 1/1 Running 0 4h18m +pod/prometheus-prometheus-node-exporter-4zrz4 1/1 Running 0 4h18m +pod/prometheus-prometheus-pushgateway-6bf748ccc9-zlhb6 1/1 Running 0 4h18m +pod/prometheus-server-58cc4bc869-m6pnk 2/2 Running 0 4h18m +pod/videocall-metrics-client-68889cbdb6-k7sh4 1/1 Running 0 149m +pod/videocall-metrics-server-75447fcc86-nc4pq 1/1 Running 0 4h44m +pod/videocall-ui-cb7f7f5b-j8s5j 1/1 Running 0 29h +pod/videocall-websocket-7d5685bf44-vs7sf 1/1 Running 0 29h +pod/videocall-webtransport-6db5b5678f-pthjk 1/1 Running 0 29h + +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +service/grafana ClusterIP 10.43.157.225 80/TCP 5h25m +service/nats ClusterIP None 4222/TCP,6222/TCP,8222/TCP,7777/TCP,7422/TCP,7522/TCP 5d1h +service/prometheus-kube-state-metrics ClusterIP 10.43.243.0 8080/TCP 5h31m +service/prometheus-prometheus-node-exporter ClusterIP 10.43.143.191 9100/TCP 5h31m +service/prometheus-prometheus-pushgateway ClusterIP 10.43.20.225 9091/TCP 5h31m +service/prometheus-server ClusterIP 10.43.32.88 80/TCP 5h31m +service/videocall-metrics-client ClusterIP 10.43.112.83 9091/TCP 4h45m +service/videocall-metrics-server ClusterIP 10.43.18.91 9092/TCP 4h45m +service/videocall-ui ClusterIP 10.43.115.124 80/TCP 47h +service/videocall-websocket ClusterIP 10.43.136.127 8080/TCP 29h +service/videocall-webtransport-lb LoadBalancer 10.43.74.88 10.190.252.181 444:32767/TCP,443:32463/UDP 47h + +NAME CLASS HOSTS ADDRESS PORTS AGE +ingress.networking.k8s.io/grafana grafana.yourdomain.com 10.190.252.181 80, 443 5h25m +ingress.networking.k8s.io/prometheus-server prometheus.yourdomain.com 10.190.252.181 80, 443 4h18m +ingress.networking.k8s.io/videocall-ui nginx app.yourdomain.com 10.190.252.181 80, 443 47h +ingress.networking.k8s.io/videocall-websocket nginx websocket.yourdomain.com 10.190.252.181 80, 443 29h + api.yourdomain.com +``` + +Note the naming: All videocall components now have the `videocall-` prefix and use the `app.kubernetes.io/component` label for differentiation. + +### 5.2 Verify TLS Certificates + +Ensure certificates are properly issued, they should be ready: + +```bash +$ kubectl get certificates -n videocall +NAME READY SECRET AGE +grafana-tls True grafana-tls 5h18m +prometheus-tls True prometheus-tls 4h16m +videocall-ui-tls True videocall-ui-tls 47h +videocall-webtransport-cert True webtransport-tls 47h +websocket-tls True websocket-tls 29h +api-tls True api-tls 29h +``` + + +### 5.3 Test Connectivity + +Test connectivity to the various services: +- UI: https://app.yourdomain.com **<-- this is the main url, open it in your browser!!** +- WebSocket: wss://websocket.yourdomain.com +- WebTransport: https://webtransport.yourdomain.com +- Grafana: https://grafana.yourdomain.com + +## 6. Configuration Files to Review + +The following configuration files should be reviewed and customized for your deployment: + +### 6.1 Videocall Application + +**Your custom values file** (`my-values.yaml`): +- Domain settings in `global.domain` +- Component enablement flags (`ui.enabled`, `websocket.enabled`, etc.) +- Resource limits for each component +- Ingress hostnames +- Image tags and repositories + +**Reference template**: `./helm/videocall/values.yaml` (967 lines, fully documented) +- Contains all available configuration options +- Every parameter is explained with comments +- Use this as a reference when creating your `my-values.yaml` + +### 6.2 Infrastructure Components + +1. **NATS**: `./helm-videocall-deployment/infrastructure/nats/values.yaml` + - Configure authentication if needed + - Adjust resource limits + +2. **Prometheus**: `./helm-videocall-deployment/infrastructure/prometheus/values.yaml` + - Adjust retention and storage + +3. **Grafana**: `./helm-videocall-deployment/infrastructure/grafana/values.yaml` + - Configure admin credentials + - Set up dashboards and data sources + +### Quick Configuration Example + +To customize component resources in your `my-values.yaml`: + +```yaml +websocket: + replicaCount: 2 + resources: + limits: + cpu: "2000m" + memory: "4Gi" + requests: + cpu: "1000m" + memory: "2Gi" +``` + + +## 7. Monitoring + +Grafana is used for monitoring and visualizing metrics in this deployment. + +### Accessing Grafana + +1. Log in to your Grafana instance (https://grafana.yourdomain.com). The admin username and password were specified when you installed Grafana (see the `$GRAFANA_ADMIN_USER` and `$GRAFANA_ADMIN_PASSWORD` environment variables). +2. Configure Prometheus as a data source if not already configured +3. Access metrics from the Videocall components: + - Client metrics: `videocall-metrics-client:9091/metrics` + - Server stats: `videocall-metrics-server:9092/metrics` + +Create dashboards to visualize: +- Active connections per server +- Client engagement metrics +- Media quality statistics +- Server health and resource usage + +--- +## 8. Troubleshooting + +### 7.1 Pod Status Issues + +If pods are not reaching the Running state: + +```bash +kubectl describe pod -n videocall +kubectl logs -n videocall +``` + +### 7.2 Certificate Issues + +If certificates are not being issued: + +```bash +kubectl describe certificate -n videocall +kubectl describe challenges -n cert-manager +``` + +### 7.3 Ingress Problems + +For ingress troubleshooting: + +```bash +kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx +``` + + +### 7.5 Common OOM Issues + +If services are experiencing OOM errors: +- Check the resource limits in the values.yaml files +- Ensure you've applied the changes with helm upgrade +- Verify the actual resource settings: + ```bash + kubectl get deployment -n videocall -o yaml | grep -A10 resources + ``` diff --git a/helm/README.md b/helm/README.md index 15fa53719..98d27d436 100644 --- a/helm/README.md +++ b/helm/README.md @@ -1,29 +1,43 @@ -# Deploying with helm to kubernetes - -1. Create a cluster -1. Label the nodes in the node pool - ``` - kubectl label nodes node-role=worker - ``` -1. Deploy ingress-nginx -1. Install external-DNS - ``` - helm repo add bitnami https://charts.bitnami.com/bitnami - helm install external-dns bitnami/external-dns \ - --set provider=digitalocean \ - --set digitalocean.apiToken=YOUR_DIGITALOCEAN_API_TOKEN - ``` -1. Deploy internal nats -1. Create an opaque secret named "rusltemania" with the key postgres-password filled in with a random password -1. Deploy rustlemania without SSL -1. Deploy cert-manager -1. Create a cert-manager issuer -1. Upgrade rustlemania to include SSL -1. Install kubernetes dashboard through the digital ocean marketplace -1. Start the kubernetes dashboard locally -```kubectl -n kubernetes-dashboard port-forward svc/kubernetes-dashboard-kong-proxy 8443:443``` - -## Updating the website - -1. Update the tag in the videocall-website/values.yaml file -1. Run ```helm dependency update && helm upgrade videocall-website . -f values.yaml``` +# Videocall Helm Charts + +This directory contains public Helm charts for Videocall.rs. + +## Charts + +### videocall/ + +The unified Helm chart for deploying the complete Videocall.rs application stack. + +Includes 6 components: +- UI +- WebSocket API +- WebTransport +- Website +- Metrics Client +- Metrics Server + +See [videocall/README.md](videocall/README.md) for installation and configuration. + +## Deployment-Specific Charts + +Infrastructure and deployment-specific charts are in `helm-videocall-deployment/`: + +- **infrastructure/** - NATS, PostgreSQL, Prometheus, Grafana, cert-manager, ingress, etc. +- **apps/** - Other applications (engineering-vlog, etc.) +- **us-east/** - US East region deployment values +- **singapore/** - Singapore region deployment values + +## Quick Start + +```bash +# Install Videocall application +cd videocall +helm install videocall . -f my-values.yaml +``` + +## Documentation + +- **K3S_DEPLOYMENT_GUIDE.md** - Guide for deploying to K3s clusters +- **videocall/README.md** - Videocall chart documentation +- **videocall/QUICKSTART.md** - 5-minute getting started +- **videocall/MIGRATION.md** - Migrating from separate charts diff --git a/helm/global/us-east/metrics-api/templates/_helpers.tpl b/helm/global/us-east/metrics-api/templates/_helpers.tpl deleted file mode 100644 index 087686c1c..000000000 --- a/helm/global/us-east/metrics-api/templates/_helpers.tpl +++ /dev/null @@ -1,62 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define "metrics-api.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "metrics-api.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "metrics-api.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "metrics-api.labels" -}} -helm.sh/chart: {{ include "metrics-api.chart" . }} -{{ include "metrics-api.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "metrics-api.selectorLabels" -}} -app.kubernetes.io/name: {{ include "metrics-api.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "metrics-api.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "metrics-api.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/helm/global/us-east/metrics-api/templates/deployment.yaml b/helm/global/us-east/metrics-api/templates/deployment.yaml deleted file mode 100644 index e42994d57..000000000 --- a/helm/global/us-east/metrics-api/templates/deployment.yaml +++ /dev/null @@ -1,55 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: client-{{ include "metrics-api.fullname" . }} - labels: - {{- include "metrics-api.labels" . | nindent 4 }} -spec: - replicas: {{ .Values.metricsApi.replicas }} - selector: - matchLabels: - {{- include "metrics-api.selectorLabels" . | nindent 6 }} - template: - metadata: - labels: - {{- include "metrics-api.selectorLabels" . | nindent 8 }} - spec: - securityContext: - {{- toYaml .Values.metricsApi.podSecurityContext | nindent 8 }} - containers: - - name: {{ .Chart.Name }} - image: "{{ .Values.metricsApi.image.repository }}:{{ .Values.metricsApi.image.tag }}" - imagePullPolicy: {{ .Values.metricsApi.image.pullPolicy }} - command: ["/usr/bin/metrics_server"] - workingDir: /app/actix-api - ports: - - name: http - containerPort: {{ .Values.metricsApi.service.targetPort }} - protocol: TCP - env: - - name: METRICS_PORT - value: {{ .Values.metricsApi.env.METRICS_PORT | quote }} - - name: NATS_URL - value: {{ .Values.metricsApi.env.NATS_URL | quote }} - - name: REGION - value: {{ .Values.metricsApi.env.REGION | quote }} - - name: HOSTNAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: SERVER_ID - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: SERVICE_TYPE - value: {{ .Values.metricsApi.env.SERVICE_TYPE | quote }} - - name: RUST_LOG - value: {{ .Values.metricsApi.env.RUST_LOG | quote }} - resources: - {{- toYaml .Values.metricsApi.resources | nindent 12 }} - livenessProbe: - {{- toYaml .Values.metricsApi.livenessProbe | nindent 12 }} - readinessProbe: - {{- toYaml .Values.metricsApi.readinessProbe | nindent 12 }} - securityContext: - {{- toYaml .Values.metricsApi.securityContext | nindent 12 }} \ No newline at end of file diff --git a/helm/global/us-east/metrics-api/templates/server-stats-deployment.yaml b/helm/global/us-east/metrics-api/templates/server-stats-deployment.yaml deleted file mode 100644 index 3d1dd5c71..000000000 --- a/helm/global/us-east/metrics-api/templates/server-stats-deployment.yaml +++ /dev/null @@ -1,62 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: server-{{ include "metrics-api.fullname" . }} - labels: - {{- include "metrics-api.labels" . | nindent 4 }} - app.kubernetes.io/component: server-stats -spec: - replicas: {{ .Values.serverStats.replicas }} - selector: - matchLabels: - {{- include "metrics-api.selectorLabels" . | nindent 6 }} - app.kubernetes.io/component: server-stats - template: - metadata: - labels: - {{- include "metrics-api.selectorLabels" . | nindent 8 }} - app.kubernetes.io/component: server-stats - spec: - securityContext: - {{- toYaml .Values.serverStats.podSecurityContext | nindent 8 }} - containers: - - name: {{ .Chart.Name }}-server-stats - image: "{{ .Values.serverStats.image.repository }}:{{ .Values.serverStats.image.tag }}" - imagePullPolicy: {{ .Values.serverStats.image.pullPolicy }} - command: {{ .Values.serverStats.command }} - workingDir: /app/actix-api - ports: - - name: http - containerPort: {{ .Values.serverStats.service.targetPort }} - protocol: TCP - env: - - name: METRICS_PORT - value: "{{ .Values.serverStats.env.METRICS_PORT }}" - - name: NATS_URL - value: "{{ .Values.serverStats.env.NATS_URL }}" - - name: REGION - value: "{{ .Values.serverStats.env.REGION }}" - - name: SERVICE_TYPE - value: "{{ .Values.serverStats.env.SERVICE_TYPE }}" - - name: RUST_LOG - value: "{{ .Values.serverStats.env.RUST_LOG }}" - livenessProbe: - httpGet: - path: {{ .Values.serverStats.livenessProbe.httpGet.path }} - port: {{ .Values.serverStats.livenessProbe.httpGet.port }} - initialDelaySeconds: {{ .Values.serverStats.livenessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.serverStats.livenessProbe.periodSeconds }} - timeoutSeconds: {{ .Values.serverStats.livenessProbe.timeoutSeconds }} - failureThreshold: {{ .Values.serverStats.livenessProbe.failureThreshold }} - readinessProbe: - httpGet: - path: {{ .Values.serverStats.readinessProbe.httpGet.path }} - port: {{ .Values.serverStats.readinessProbe.httpGet.port }} - initialDelaySeconds: {{ .Values.serverStats.readinessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.serverStats.readinessProbe.periodSeconds }} - timeoutSeconds: {{ .Values.serverStats.readinessProbe.timeoutSeconds }} - failureThreshold: {{ .Values.serverStats.readinessProbe.failureThreshold }} - resources: - {{- toYaml .Values.serverStats.resources | nindent 12 }} - securityContext: - {{- toYaml .Values.serverStats.securityContext | nindent 12 }} diff --git a/helm/global/us-east/metrics-api/templates/server-stats-service.yaml b/helm/global/us-east/metrics-api/templates/server-stats-service.yaml deleted file mode 100644 index 3dd256a45..000000000 --- a/helm/global/us-east/metrics-api/templates/server-stats-service.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: server-{{ include "metrics-api.fullname" . }} - labels: - {{- include "metrics-api.labels" . | nindent 4 }} - app.kubernetes.io/component: server-stats -spec: - type: {{ .Values.serverStats.service.type }} - ports: - - port: {{ .Values.serverStats.service.port }} - targetPort: {{ .Values.serverStats.service.targetPort }} - protocol: TCP - name: http - selector: - {{- include "metrics-api.selectorLabels" . | nindent 4 }} - app.kubernetes.io/component: server-stats diff --git a/helm/global/us-east/metrics-api/templates/service.yaml b/helm/global/us-east/metrics-api/templates/service.yaml deleted file mode 100644 index 41680f912..000000000 --- a/helm/global/us-east/metrics-api/templates/service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: client-{{ include "metrics-api.fullname" . }} - labels: - {{- include "metrics-api.labels" . | nindent 4 }} -spec: - type: {{ .Values.metricsApi.service.type }} - ports: - - port: {{ .Values.metricsApi.service.port }} - targetPort: {{ .Values.metricsApi.service.targetPort }} - protocol: TCP - name: http - selector: - {{- include "metrics-api.selectorLabels" . | nindent 4 }} \ No newline at end of file diff --git a/helm/global/us-east/metrics-api/values.yaml b/helm/global/us-east/metrics-api/values.yaml deleted file mode 100644 index 7b887e581..000000000 --- a/helm/global/us-east/metrics-api/values.yaml +++ /dev/null @@ -1,134 +0,0 @@ -# Metrics API values for videocall monitoring (minimal resources) -metricsApi: - # Image configuration - image: - repository: securityunion/rustlemania-api - pullPolicy: Always - tag: latest - - # Minimal resources for cost optimization - resources: - limits: - cpu: 50m - memory: 128Mi - requests: - cpu: 25m - memory: 64Mi - - # Single replica - replicas: 1 - - # Service configuration - service: - type: ClusterIP - port: 9091 - targetPort: 9091 - - # Environment variables - env: - METRICS_PORT: "9091" - NATS_URL: "nats://nats-us-east:4222" - REGION: "us-east" - SERVICE_TYPE: "metrics" - RUST_LOG: "warn,async_nats=warn" - TOKIO_WORKER_THREADS: "1" # Optimal for 50m CPU (metrics collection is I/O bound) - - # Health check configuration - livenessProbe: - httpGet: - path: /health - port: 9091 - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 3 - - readinessProbe: - httpGet: - path: /health - port: 9091 - initialDelaySeconds: 5 - periodSeconds: 5 - timeoutSeconds: 3 - failureThreshold: 3 - - # Security context - securityContext: - runAsUser: 1000 - runAsGroup: 1000 - fsGroup: 1000 - - # Pod security context - podSecurityContext: - runAsUser: 1000 - runAsGroup: 1000 - fsGroup: 1000 - -# Separate Server Stats pod for connection tracking (stateless snapshot approach) -serverStats: - # Image configuration (same as metrics-api but different binary) - image: - repository: securityunion/rustlemania-api - pullPolicy: Always - tag: latest - - # Minimal resources for server connection tracking - resources: - limits: - cpu: 100m - memory: 128Mi - requests: - cpu: 50m - memory: 64Mi - - # Single replica - replicas: 1 - - # Service configuration - different port from client metrics - service: - type: ClusterIP - port: 9092 - targetPort: 9092 - - # Environment variables for server stats - env: - METRICS_PORT: "9092" - NATS_URL: "nats://nats-us-east:4222" - REGION: "us-east" - SERVICE_TYPE: "server-stats" - RUST_LOG: "debug,async_nats=info" - TOKIO_WORKER_THREADS: "1" # Optimal for 100m CPU (server stats aggregation is I/O bound) - - # Binary to run - command: ["/usr/bin/metrics_server_snapshot"] - - # Health check configuration - livenessProbe: - httpGet: - path: /health - port: 9092 - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 3 - - readinessProbe: - httpGet: - path: /health - port: 9092 - initialDelaySeconds: 5 - periodSeconds: 5 - timeoutSeconds: 3 - failureThreshold: 3 - - # Security context - securityContext: - runAsUser: 1000 - runAsGroup: 1000 - fsGroup: 1000 - - # Pod security context - podSecurityContext: - runAsUser: 1000 - runAsGroup: 1000 - fsGroup: 1000 \ No newline at end of file diff --git a/helm/postgres/Chart.lock b/helm/postgres/Chart.lock deleted file mode 100644 index 185a42ce6..000000000 --- a/helm/postgres/Chart.lock +++ /dev/null @@ -1,6 +0,0 @@ -dependencies: -- name: postgresql - repository: https://charts.bitnami.com/bitnami - version: 12.5.7 -digest: sha256:b81e4b8537abfe5f8a5fbbd93ee3eb9b7396eb145d52bf717e1c81f286260993 -generated: "2023-06-16T15:46:17.792158524-04:00" diff --git a/helm/postgres/values.yaml b/helm/postgres/values.yaml deleted file mode 100644 index 92c1bd217..000000000 --- a/helm/postgres/values.yaml +++ /dev/null @@ -1,3 +0,0 @@ -postgresql: - auth: - existingSecret: rustlemania diff --git a/helm/rustlemania-ui/Chart.yaml b/helm/rustlemania-ui/Chart.yaml deleted file mode 100644 index 516575f1b..000000000 --- a/helm/rustlemania-ui/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v2 -name: rustlemania-ui -description: A Helm chart for rustlemania-ui -type: application -version: 0.1.0 diff --git a/helm/rustlemania-ui/templates/NOTES.txt b/helm/rustlemania-ui/templates/NOTES.txt deleted file mode 100644 index 63317124b..000000000 --- a/helm/rustlemania-ui/templates/NOTES.txt +++ /dev/null @@ -1,22 +0,0 @@ -1. Get the application URL by running these commands: -{{- if .Values.ingress.enabled }} -{{- range $host := .Values.ingress.hosts }} - {{- range .paths }} - http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} - {{- end }} -{{- end }} -{{- else if contains "NodePort" .Values.service.type }} - export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "rustlemania.fullname" . }}) - export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") - echo http://$NODE_IP:$NODE_PORT -{{- else if contains "LoadBalancer" .Values.service.type }} - NOTE: It may take a few minutes for the LoadBalancer IP to be available. - You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "rustlemania.fullname" . }}' - export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "rustlemania.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") - echo http://$SERVICE_IP:{{ .Values.service.port }} -{{- else if contains "ClusterIP" .Values.service.type }} - export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "rustlemania.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") - export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") - echo "Visit http://127.0.0.1:8080 to use your application" - kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT -{{- end }} diff --git a/helm/rustlemania-ui/templates/_helpers.tpl b/helm/rustlemania-ui/templates/_helpers.tpl deleted file mode 100644 index ed4b53c15..000000000 --- a/helm/rustlemania-ui/templates/_helpers.tpl +++ /dev/null @@ -1,62 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define "rustlemania.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "rustlemania.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "rustlemania.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "rustlemania.labels" -}} -helm.sh/chart: {{ include "rustlemania.chart" . }} -{{ include "rustlemania.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "rustlemania.selectorLabels" -}} -app.kubernetes.io/name: {{ include "rustlemania.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "rustlemania.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "rustlemania.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} diff --git a/helm/rustlemania-ui/templates/configmap-configjs.yaml b/helm/rustlemania-ui/templates/configmap-configjs.yaml deleted file mode 100644 index b314a8315..000000000 --- a/helm/rustlemania-ui/templates/configmap-configjs.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "rustlemania.fullname" . }}-config - labels: - {{- include "rustlemania.labels" . | nindent 4 }} -data: - config.js: |- - {{ $cfg := default dict .Values.runtimeConfig }} - window.__APP_CONFIG = Object.freeze({{ $cfg | toJson }}); - diff --git a/helm/rustlemania-ui/templates/deployment.yaml b/helm/rustlemania-ui/templates/deployment.yaml deleted file mode 100644 index e2e2e2443..000000000 --- a/helm/rustlemania-ui/templates/deployment.yaml +++ /dev/null @@ -1,64 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "rustlemania.fullname" . }} - labels: - {{- include "rustlemania.labels" . | nindent 4 }} -spec: - {{- if not .Values.autoscaling.enabled }} - replicas: {{ .Values.replicaCount }} - {{- end }} - selector: - matchLabels: - {{- include "rustlemania.selectorLabels" . | nindent 6 }} - template: - metadata: - annotations: - checksum/config: {{ include (print $.Template.BasePath "/configmap-configjs.yaml") . | sha256sum }} - {{- with .Values.podAnnotations }} - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - {{- include "rustlemania.selectorLabels" . | nindent 8 }} - spec: - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} - containers: - - name: {{ include "rustlemania.fullname" . }} - securityContext: - {{- toYaml .Values.securityContext | nindent 12 }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - {{- toYaml .Values.env | nindent 12 }} - ports: - - name: http - containerPort: {{ .Values.service.port }} - protocol: TCP - resources: - {{- toYaml .Values.resources | nindent 12 }} - volumeMounts: - - name: app-config - mountPath: /usr/share/nginx/html/config.js - subPath: config.js - readOnly: true - volumes: - - name: app-config - configMap: - name: {{ include "rustlemania.fullname" . }}-config - {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} - {{- end }} diff --git a/helm/rustlemania-ui/templates/hpa.yaml b/helm/rustlemania-ui/templates/hpa.yaml deleted file mode 100644 index 8e45acf14..000000000 --- a/helm/rustlemania-ui/templates/hpa.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if .Values.autoscaling.enabled }} -uiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: {{ include "rustlemania.fullname" . }} - labels: - {{- include "rustlemania.labels" . | nindent 4 }} -spec: - scaleTargetRef: - uiVersion: apps/v1 - kind: Deployment - name: {{ include "rustlemania.fullname" . }} - minReplicas: {{ .Values.autoscaling.minReplicas }} - maxReplicas: {{ .Values.autoscaling.maxReplicas }} - metrics: - {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} - {{- end }} - {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} - {{- end }} -{{- end }} diff --git a/helm/rustlemania-ui/templates/ingress.yaml b/helm/rustlemania-ui/templates/ingress.yaml deleted file mode 100644 index dbe4a1e64..000000000 --- a/helm/rustlemania-ui/templates/ingress.yaml +++ /dev/null @@ -1,60 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $fullName := include "rustlemania.fullname" . -}} -{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} - {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} - {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} - {{- end }} -{{- end }} -{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1 -{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1beta1 -{{- else -}} -apiVersion: extensions/v1beta1 -{{- end }} -kind: Ingress -metadata: - name: {{ $fullName }} - labels: - {{- include "rustlemania.labels" . | nindent 4 }} - {{- with .Values.ingress.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} - ingressClassName: {{ .Values.ingress.className }} - {{- end }} - {{- if .Values.ingress.tls }} - tls: - {{- range .Values.ingress.tls }} - - hosts: - {{- range .hosts }} - - {{ . | quote }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} - {{- end }} - rules: - {{- range .Values.ingress.hosts }} - - host: {{ .host | quote }} - http: - paths: - {{- range .paths }} - - path: {{ .path }} - {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} - pathType: {{ .pathType }} - {{- end }} - backend: - {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} - service: - name: {{ .service.name }} - port: - number: {{ .service.port.number }} - {{- else }} - serviceName: {{ .service.name }} - servicePort: {{ .service.port.number }} - {{- end }} - {{- end }} - {{- end }} -{{- end }} diff --git a/helm/rustlemania-ui/templates/redirect-ingress.yaml b/helm/rustlemania-ui/templates/redirect-ingress.yaml deleted file mode 100644 index 71ed16656..000000000 --- a/helm/rustlemania-ui/templates/redirect-ingress.yaml +++ /dev/null @@ -1,48 +0,0 @@ -{{- if .Values.ingress.enabled }} -{{- if and .Values.ingress.enabled .Values.ingress.redirect }} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: {{ include "rustlemania.fullname" . }}-redirect - annotations: - cert-manager.io/issuer: letsencrypt-prod - nginx.ingress.kubernetes.io/ssl-redirect: "true" - kubernetes.io/tls-acme: "true" - # Some ingress-nginx versions reject the `$` character in this annotation (see - # https://github.com/kubernetes/ingress-nginx/issues/11175). Dropping `$request_uri` - # prevents the webhook from denying the ingress and fixes the 404 you were seeing - # on rustlemania.com. - nginx.ingress.kubernetes.io/permanent-redirect: "https://videocall.rs" - nginx.ingress.kubernetes.io/permanent-redirect-code: "308" -spec: - ingressClassName: {{ .Values.ingress.className }} - tls: - - secretName: rustlemania-ui-tls - hosts: - - rustlemania.com - - www.rustlemania.com - rules: - - host: rustlemania.com - http: - paths: - - path: / - pathType: Prefix - backend: - service: - # A backend must be specified, but will never be reached because of the redirect. - name: {{ include "rustlemania.fullname" . }} - port: - number: 80 - - host: www.rustlemania.com - http: - paths: - - path: / - pathType: Prefix - backend: - service: - # Same dummy backend; request will never reach it thanks to the redirect. - name: {{ include "rustlemania.fullname" . }} - port: - number: 80 -{{- end }} -{{- end }} \ No newline at end of file diff --git a/helm/rustlemania-ui/templates/service.yaml b/helm/rustlemania-ui/templates/service.yaml deleted file mode 100644 index ef779dc6f..000000000 --- a/helm/rustlemania-ui/templates/service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ include "rustlemania.fullname" . }} - labels: - {{- include "rustlemania.labels" . | nindent 4 }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - {{- include "rustlemania.selectorLabels" . | nindent 4 }} diff --git a/helm/rustlemania-ui/values.yaml b/helm/rustlemania-ui/values.yaml deleted file mode 100644 index 24e84d39f..000000000 --- a/helm/rustlemania-ui/values.yaml +++ /dev/null @@ -1,73 +0,0 @@ -# Default values for rustlemania. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. -nameOverride: "" -fullnameOverride: "" - -replicaCount: 1 -image: - repository: securityunion/rustlemania-ui - pullPolicy: Always - tag: latest -resources: - limits: - cpu: "50m" # 50% of a single CPU - memory: "10Mi" # 512 MiB of memory - requests: - cpu: "20m" # 25% of a single CPU - memory: "10Mi" # 256 MiB of memory -podAnnotations: {} -podSecurityContext: {} -securityContext: {} -service: - type: ClusterIP - port: 80 -autoscaling: - enabled: false - minReplicas: 1 - maxReplicas: 100 - targetCPUUtilizationPercentage: 80 - targetMemoryUtilizationPercentage: 80 -nodeSelector: {} -tolerations: [] -affinity: {} - -runtimeConfig: - # Using values aligned with docker/Dockerfile.yew - apiBaseUrl: "https://app.videocall.rs" - wsUrl: "wss://websocket-singapore.webtransport.video,wss://websocket-us-east.webtransport.video" - webTransportHost: "https://webtransport-singapore.webtransport.video,https://webtransport-us-east.webtransport.video" - oauthEnabled: "false" - e2eeEnabled: "false" - webTransportEnabled: "true" - usersAllowedToStream: "" - serverElectionPeriodMs: 2000 - audioBitrateKbps: 65 - videoBitrateKbps: 1000 - screenBitrateKbps: 1000 - -ingress: - enabled: true - redirect: true - className: nginx - annotations: - cert-manager.io/issuer: letsencrypt-prod - nginx.ingress.kubernetes.io/ssl-redirect: "true" - kubernetes.io/tls-acme: "true" - hosts: - - host: app.videocall.rs - paths: - - path: / - pathType: Prefix - service: - name: rustlemania-ui - port: - number: 80 - # setup redirect from rustlemania.com to app.videocall.rs - # NOTE: rustlemania.com is now handled by a separate redirect Ingress defined in templates/redirect-ingress.yaml - tls: - - secretName: rustlemania-ui-tls - hosts: - - app.videocall.rs - - transport.rustlemania.com - # rustlemania.com cert is still referenced by redirect Ingress diff --git a/helm/rustlemania-websocket/.helmignore b/helm/rustlemania-websocket/.helmignore deleted file mode 100644 index 0e8a0eb36..000000000 --- a/helm/rustlemania-websocket/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/helm/rustlemania-websocket/Chart.yaml b/helm/rustlemania-websocket/Chart.yaml deleted file mode 100644 index f0ecd6273..000000000 --- a/helm/rustlemania-websocket/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v2 -name: rustlemania-websocket -description: A Helm chart for rustlemania -type: application -version: 0.1.0 diff --git a/helm/rustlemania-websocket/templates/NOTES.txt b/helm/rustlemania-websocket/templates/NOTES.txt deleted file mode 100644 index 63317124b..000000000 --- a/helm/rustlemania-websocket/templates/NOTES.txt +++ /dev/null @@ -1,22 +0,0 @@ -1. Get the application URL by running these commands: -{{- if .Values.ingress.enabled }} -{{- range $host := .Values.ingress.hosts }} - {{- range .paths }} - http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} - {{- end }} -{{- end }} -{{- else if contains "NodePort" .Values.service.type }} - export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "rustlemania.fullname" . }}) - export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") - echo http://$NODE_IP:$NODE_PORT -{{- else if contains "LoadBalancer" .Values.service.type }} - NOTE: It may take a few minutes for the LoadBalancer IP to be available. - You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "rustlemania.fullname" . }}' - export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "rustlemania.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") - echo http://$SERVICE_IP:{{ .Values.service.port }} -{{- else if contains "ClusterIP" .Values.service.type }} - export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "rustlemania.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") - export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") - echo "Visit http://127.0.0.1:8080 to use your application" - kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT -{{- end }} diff --git a/helm/rustlemania-websocket/templates/_helpers.tpl b/helm/rustlemania-websocket/templates/_helpers.tpl deleted file mode 100644 index ed4b53c15..000000000 --- a/helm/rustlemania-websocket/templates/_helpers.tpl +++ /dev/null @@ -1,62 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define "rustlemania.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "rustlemania.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "rustlemania.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "rustlemania.labels" -}} -helm.sh/chart: {{ include "rustlemania.chart" . }} -{{ include "rustlemania.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "rustlemania.selectorLabels" -}} -app.kubernetes.io/name: {{ include "rustlemania.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "rustlemania.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "rustlemania.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} diff --git a/helm/rustlemania-websocket/templates/deployment.yaml b/helm/rustlemania-websocket/templates/deployment.yaml deleted file mode 100644 index c4b7fba9f..000000000 --- a/helm/rustlemania-websocket/templates/deployment.yaml +++ /dev/null @@ -1,54 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "rustlemania.fullname" . }} - labels: - {{- include "rustlemania.labels" . | nindent 4 }} -spec: - {{- if not .Values.autoscaling.enabled }} - replicas: {{ .Values.replicaCount }} - {{- end }} - selector: - matchLabels: - {{- include "rustlemania.selectorLabels" . | nindent 6 }} - template: - metadata: - {{- with .Values.podAnnotations }} - annotations: - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - {{- include "rustlemania.selectorLabels" . | nindent 8 }} - spec: - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} - containers: - - name: {{ include "rustlemania.fullname" . }} - securityContext: - {{- toYaml .Values.securityContext | nindent 12 }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - {{- toYaml .Values.env | nindent 12 }} - ports: - - name: ws-api - containerPort: {{ .Values.service.port }} - protocol: TCP - resources: - {{- toYaml .Values.resources | nindent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} - {{- end }} diff --git a/helm/rustlemania-websocket/templates/hpa.yaml b/helm/rustlemania-websocket/templates/hpa.yaml deleted file mode 100644 index 80379e564..000000000 --- a/helm/rustlemania-websocket/templates/hpa.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if .Values.autoscaling.enabled }} -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: {{ include "rustlemania.fullname" . }} - labels: - {{- include "rustlemania.labels" . | nindent 4 }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: {{ include "rustlemania.fullname" . }} - minReplicas: {{ .Values.autoscaling.minReplicas }} - maxReplicas: {{ .Values.autoscaling.maxReplicas }} - metrics: - {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} - {{- end }} - {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} - {{- end }} -{{- end }} diff --git a/helm/rustlemania-websocket/templates/ingress.yaml b/helm/rustlemania-websocket/templates/ingress.yaml deleted file mode 100644 index dbe4a1e64..000000000 --- a/helm/rustlemania-websocket/templates/ingress.yaml +++ /dev/null @@ -1,60 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $fullName := include "rustlemania.fullname" . -}} -{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} - {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} - {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} - {{- end }} -{{- end }} -{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1 -{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1beta1 -{{- else -}} -apiVersion: extensions/v1beta1 -{{- end }} -kind: Ingress -metadata: - name: {{ $fullName }} - labels: - {{- include "rustlemania.labels" . | nindent 4 }} - {{- with .Values.ingress.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} - ingressClassName: {{ .Values.ingress.className }} - {{- end }} - {{- if .Values.ingress.tls }} - tls: - {{- range .Values.ingress.tls }} - - hosts: - {{- range .hosts }} - - {{ . | quote }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} - {{- end }} - rules: - {{- range .Values.ingress.hosts }} - - host: {{ .host | quote }} - http: - paths: - {{- range .paths }} - - path: {{ .path }} - {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} - pathType: {{ .pathType }} - {{- end }} - backend: - {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} - service: - name: {{ .service.name }} - port: - number: {{ .service.port.number }} - {{- else }} - serviceName: {{ .service.name }} - servicePort: {{ .service.port.number }} - {{- end }} - {{- end }} - {{- end }} -{{- end }} diff --git a/helm/rustlemania-websocket/templates/service.yaml b/helm/rustlemania-websocket/templates/service.yaml deleted file mode 100644 index 0672e4e8e..000000000 --- a/helm/rustlemania-websocket/templates/service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ include "rustlemania.fullname" . }} - labels: - {{- include "rustlemania.labels" . | nindent 4 }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: 8080 - protocol: TCP - name: ws-api - selector: - {{- include "rustlemania.selectorLabels" . | nindent 4 }} diff --git a/helm/rustlemania-websocket/values.yaml b/helm/rustlemania-websocket/values.yaml deleted file mode 100644 index d16040107..000000000 --- a/helm/rustlemania-websocket/values.yaml +++ /dev/null @@ -1,70 +0,0 @@ -# Default values for rustlemania. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. -nameOverride: "" -fullnameOverride: "" - - -replicaCount: 1 -image: - repository: securityunion/rustlemania-api - pullPolicy: Always - tag: high-availability-cf63fcce -env: - - name: RUST_LOG - value: info - - name: ACTIX_PORT - value: "8080" - - name: UI_ENDPOINT - value: https://rustlemania.com - - name: NATS_URL - value: nats:4222 - - name: DATABASE_ENABLED - value: "false" - - name: DATABASE_URL - value: abc - - name: TOKIO_WORKER_THREADS - value: "1" # Default for WebSocket services - adjust per region as needed -resources: - limits: - cpu: "50m" - memory: "10Mi" - requests: - cpu: "20m" - memory: "10Mi" -podAnnotations: {} -podSecurityContext: {} -securityContext: {} -service: - type: ClusterIP - port: 8080 -autoscaling: - enabled: false - minReplicas: 1 - maxReplicas: 100 - targetCPUUtilizationPercentage: 80 - targetMemoryUtilizationPercentage: 80 -nodeSelector: {} -tolerations: [] -affinity: {} - -ingress: - enabled: true - className: nginx - annotations: - cert-manager.io/issuer: letsencrypt-prod - nginx.ingress.kubernetes.io/ssl-redirect: "true" - kubernetes.io/tls-acme: "true" - hosts: - - host: api.rustlemania.com - paths: - - path: / - pathType: Prefix - service: - name: rustlemania-websocket - port: - number: 8080 - tls: - - secretName: rustlemania-websocket-tls - hosts: - - api.rustlemania.com diff --git a/helm/rustlemania-webtransport/.helmignore b/helm/rustlemania-webtransport/.helmignore deleted file mode 100644 index 0e8a0eb36..000000000 --- a/helm/rustlemania-webtransport/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/helm/rustlemania-webtransport/Chart.yaml b/helm/rustlemania-webtransport/Chart.yaml deleted file mode 100644 index eec44911e..000000000 --- a/helm/rustlemania-webtransport/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v2 -name: rustlemania-webtransport -description: A Helm chart for rustlemania -type: application -version: 0.1.0 diff --git a/helm/rustlemania-webtransport/templates/_helpers.tpl b/helm/rustlemania-webtransport/templates/_helpers.tpl deleted file mode 100644 index ed4b53c15..000000000 --- a/helm/rustlemania-webtransport/templates/_helpers.tpl +++ /dev/null @@ -1,62 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define "rustlemania.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "rustlemania.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "rustlemania.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "rustlemania.labels" -}} -helm.sh/chart: {{ include "rustlemania.chart" . }} -{{ include "rustlemania.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "rustlemania.selectorLabels" -}} -app.kubernetes.io/name: {{ include "rustlemania.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "rustlemania.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "rustlemania.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} diff --git a/helm/rustlemania-webtransport/templates/deployment.yaml b/helm/rustlemania-webtransport/templates/deployment.yaml deleted file mode 100644 index cf445a688..000000000 --- a/helm/rustlemania-webtransport/templates/deployment.yaml +++ /dev/null @@ -1,68 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "rustlemania.fullname" . }} - labels: - {{- include "rustlemania.labels" . | nindent 4 }} -spec: - {{- if not .Values.autoscaling.enabled }} - replicas: {{ .Values.replicaCount }} - {{- end }} - selector: - matchLabels: - {{- include "rustlemania.selectorLabels" . | nindent 6 }} - template: - metadata: - {{- with .Values.podAnnotations }} - annotations: - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - {{- include "rustlemania.selectorLabels" . | nindent 8 }} - spec: - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} - containers: - - name: {{ include "rustlemania.fullname" . }} - securityContext: - {{- toYaml .Values.securityContext | nindent 12 }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" - command: {{ .Values.command }} - args: {{ .Values.args }} - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - {{- toYaml .Values.env | nindent 12 }} - ports: - - name: wt-api - containerPort: {{ .Values.service.port }} - protocol: UDP - - name: wt-api-health - containerPort: {{ .Values.service.healthPort }} - protocol: TCP - resources: - {{- toYaml .Values.resources | nindent 12 }} - volumeMounts: - - name: tls - mountPath: "/certs" - readOnly: true - volumes: - - name: tls - secret: - secretName: {{ .Values.tlsSecret }} - optional: true - {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} - {{- end }} diff --git a/helm/rustlemania-webtransport/templates/hpa.yaml b/helm/rustlemania-webtransport/templates/hpa.yaml deleted file mode 100644 index 80379e564..000000000 --- a/helm/rustlemania-webtransport/templates/hpa.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if .Values.autoscaling.enabled }} -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: {{ include "rustlemania.fullname" . }} - labels: - {{- include "rustlemania.labels" . | nindent 4 }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: {{ include "rustlemania.fullname" . }} - minReplicas: {{ .Values.autoscaling.minReplicas }} - maxReplicas: {{ .Values.autoscaling.maxReplicas }} - metrics: - {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} - {{- end }} - {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} - {{- end }} -{{- end }} diff --git a/helm/rustlemania-webtransport/templates/loadbalancer.yaml b/helm/rustlemania-webtransport/templates/loadbalancer.yaml deleted file mode 100644 index 01f381389..000000000 --- a/helm/rustlemania-webtransport/templates/loadbalancer.yaml +++ /dev/null @@ -1,25 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ include "rustlemania.fullname" . }}-lb - labels: - {{- include "rustlemania.labels" . | nindent 4 }} - {{- if .Values.loadBalancerAnnotations}} - annotations: - {{- range $key, $value := .Values.loadBalancerAnnotations }} - {{ $key }}: {{ $value | quote }} - {{- end }} - {{- end }} -spec: - type: LoadBalancer - selector: - {{- include "rustlemania.selectorLabels" . | nindent 4 }} - ports: - - protocol: TCP - port: {{ .Values.service.healthPort }} - targetPort: {{ .Values.service.healthPort }} - name: wt-api-health - - protocol: UDP - port: {{ .Values.service.port }} - targetPort: {{ .Values.service.port }} - name: wt-api diff --git a/helm/rustlemania-webtransport/values.yaml b/helm/rustlemania-webtransport/values.yaml deleted file mode 100644 index 48d80073e..000000000 --- a/helm/rustlemania-webtransport/values.yaml +++ /dev/null @@ -1,65 +0,0 @@ -# Default values for rustlemania. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. -nameOverride: "" -fullnameOverride: "" - -replicaCount: 1 -image: - repository: securityunion/rustlemania-api - pullPolicy: Always - tag: high-availability-cf63fcce -command: ['webtransport_server'] -args: [] -tlsSecret: rustlemania-ui-tls -env: - - name: RUST_LOG - value: debug,quinn=warn - - name: NATS_URL - value: nats:4222 - - name: LISTEN_URL - value: 0.0.0.0:443 - - name: HEALTH_LISTEN_URL - value: 0.0.0.0:444 - - name: CERT_PATH - value: /certs/tls.crt - - name: KEY_PATH - value: /certs/tls.key - - name: TOKIO_WORKER_THREADS - value: "1" # Default for WebTransport services - adjust per region as needed - - name: TOKIO_BLOCKING_THREADS - value: "2" # Small pool for blocking crypto operations -resources: - limits: - cpu: "300m" - memory: "300Mi" - requests: - cpu: "300m" - memory: "300Mi" -podAnnotations: {} -podSecurityContext: {} -securityContext: {} -service: - type: NodePort - port: 443 - healthPort: 444 -autoscaling: - enabled: false - minReplicas: 1 - maxReplicas: 100 - targetCPUUtilizationPercentage: 80 - targetMemoryUtilizationPercentage: 80 -nodeSelector: {} -tolerations: [] -affinity: {} -# Used to configure cloud provider specific LB service type -loadBalancerAnnotations: - external-dns.alpha.kubernetes.io/hostname: "transport.rustlemania.com" - service.beta.kubernetes.io/do-loadbalancer-healthcheck-protocol: "http" - service.beta.kubernetes.io/do-loadbalancer-healthcheck-check-interval-seconds: "3" - service.beta.kubernetes.io/do-loadbalancer-healthcheck-response-timeout-seconds: "4" - service.beta.kubernetes.io/do-loadbalancer-healthcheck-unhealthy-threshold: "3" - service.beta.kubernetes.io/do-loadbalancer-healthcheck-healthy-threshold: "5" - service.beta.kubernetes.io/do-loadbalancer-healthcheck-port: "444" - service.beta.kubernetes.io/do-loadbalancer-size-unit: "1" - service.beta.kubernetes.io/do-loadbalancer-healthcheck-path: "/healthz" diff --git a/helm/videocall-website/.helmignore b/helm/videocall-website/.helmignore deleted file mode 100644 index 0e8a0eb36..000000000 --- a/helm/videocall-website/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/helm/videocall-website/Chart.yaml b/helm/videocall-website/Chart.yaml deleted file mode 100644 index e0a11b63c..000000000 --- a/helm/videocall-website/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v2 -name: videocall-website -description: A Helm chart for videocall-website -type: application -version: 0.1.0 diff --git a/helm/videocall-website/templates/NOTES.txt b/helm/videocall-website/templates/NOTES.txt deleted file mode 100644 index 67c60bffd..000000000 --- a/helm/videocall-website/templates/NOTES.txt +++ /dev/null @@ -1,22 +0,0 @@ -1. Get the application URL by running these commands: -{{- if .Values.ingress.enabled }} -{{- range $host := .Values.ingress.hosts }} - {{- range .paths }} - http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} - {{- end }} -{{- end }} -{{- else if contains "NodePort" .Values.service.type }} - export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "videocall-website.fullname" . }}) - export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") - echo http://$NODE_IP:$NODE_PORT -{{- else if contains "LoadBalancer" .Values.service.type }} - NOTE: It may take a few minutes for the LoadBalancer IP to be available. - You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "videocall-website.fullname" . }}' - export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "videocall-website.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") - echo http://$SERVICE_IP:{{ .Values.service.port }} -{{- else if contains "ClusterIP" .Values.service.type }} - export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "videocall-website.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") - export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") - echo "Visit http://127.0.0.1:8080 to use your application" - kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT -{{- end }} diff --git a/helm/videocall-website/templates/_helpers.tpl b/helm/videocall-website/templates/_helpers.tpl deleted file mode 100644 index 2c720034d..000000000 --- a/helm/videocall-website/templates/_helpers.tpl +++ /dev/null @@ -1,62 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define "videocall-website.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "videocall-website.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "videocall-website.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "videocall-website.labels" -}} -helm.sh/chart: {{ include "videocall-website.chart" . }} -{{ include "videocall-website.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "videocall-website.selectorLabels" -}} -app.kubernetes.io/name: {{ include "videocall-website.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "videocall-website.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "videocall-website.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} diff --git a/helm/videocall-website/templates/deployment.yaml b/helm/videocall-website/templates/deployment.yaml deleted file mode 100644 index c86dd986c..000000000 --- a/helm/videocall-website/templates/deployment.yaml +++ /dev/null @@ -1,55 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "videocall-website.fullname" . }} - labels: - {{- include "videocall-website.labels" . | nindent 4 }} -spec: - {{- if not .Values.autoscaling.enabled }} - replicas: {{ .Values.replicaCount }} - {{- end }} - selector: - matchLabels: - {{- include "videocall-website.selectorLabels" . | nindent 6 }} - template: - metadata: - {{- with .Values.podAnnotations }} - annotations: - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - app: videocall-website - {{- include "videocall-website.selectorLabels" . | nindent 8 }} - spec: - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} - containers: - - name: {{ include "videocall-website.fullname" . }} - securityContext: - {{- toYaml .Values.securityContext | nindent 12 }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - {{- toYaml .Values.env | nindent 12 }} - ports: - - name: website - containerPort: {{ .Values.service.port }} - protocol: TCP - resources: - {{- toYaml .Values.resources | nindent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} - {{- end }} diff --git a/helm/videocall-website/templates/ingress.yaml b/helm/videocall-website/templates/ingress.yaml deleted file mode 100644 index 7287693d6..000000000 --- a/helm/videocall-website/templates/ingress.yaml +++ /dev/null @@ -1,60 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $fullName := include "videocall-website.fullname" . -}} -{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} - {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} - {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} - {{- end }} -{{- end }} -{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1 -{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1beta1 -{{- else -}} -apiVersion: extensions/v1beta1 -{{- end }} -kind: Ingress -metadata: - name: {{ $fullName }} - labels: - {{- include "videocall-website.labels" . | nindent 4 }} - {{- with .Values.ingress.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} - ingressClassName: {{ .Values.ingress.className }} - {{- end }} - {{- if .Values.ingress.tls }} - tls: - {{- range .Values.ingress.tls }} - - hosts: - {{- range .hosts }} - - {{ . | quote }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} - {{- end }} - rules: - {{- range .Values.ingress.hosts }} - - host: {{ .host | quote }} - http: - paths: - {{- range .paths }} - - path: {{ .path }} - {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} - pathType: {{ .pathType }} - {{- end }} - backend: - {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} - service: - name: {{ .service.name }} - port: - number: {{ .service.port.number }} - {{- else }} - serviceName: {{ .service.name }} - servicePort: {{ .service.port.number }} - {{- end }} - {{- end }} - {{- end }} -{{- end }} diff --git a/helm/videocall-website/templates/service.yaml b/helm/videocall-website/templates/service.yaml deleted file mode 100644 index bf83124a7..000000000 --- a/helm/videocall-website/templates/service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.service.name }} - labels: - {{- include "videocall-website.labels" . | nindent 4 }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: 80 - protocol: TCP - name: website - selector: - app: videocall-website \ No newline at end of file diff --git a/helm/videocall-website/values.yaml b/helm/videocall-website/values.yaml deleted file mode 100644 index ca1702663..000000000 --- a/helm/videocall-website/values.yaml +++ /dev/null @@ -1,71 +0,0 @@ -# Default values for videocall-website. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. -nameOverride: "" -fullnameOverride: "" - -replicaCount: 1 -image: - repository: securityunion/video-call-rs-website - pullPolicy: Always - tag: latest -env: - - name: RUST_LOG - value: info - - name: LISTEN_URL - value: "0.0.0.0:80" - - name: LEPTOS_SITE_ADDR - value: "0.0.0.0:80" -resources: - limits: - cpu: "50m" - memory: "10Mi" - requests: - cpu: "20m" - memory: "10Mi" -podAnnotations: {} -podSecurityContext: {} -securityContext: {} -service: - name: videocall-website - type: ClusterIP - port: 80 -autoscaling: - enabled: false - minReplicas: 1 - maxReplicas: 100 - targetCPUUtilizationPercentage: 80 - targetMemoryUtilizationPercentage: 80 -nodeSelector: {} -tolerations: [] -affinity: {} - -ingress: - enabled: true - className: nginx - annotations: - cert-manager.io/issuer: letsencrypt-prod - nginx.ingress.kubernetes.io/ssl-redirect: "true" - kubernetes.io/tls-acme: "true" - hosts: - - host: www.videocall.rs - paths: - - path: / - pathType: Prefix - service: - name: videocall-website - port: - number: 80 - - host: videocall.rs - paths: - - path: / - pathType: Prefix - service: - name: videocall-website - port: - number: 80 - tls: - - secretName: videocall-website-tls - hosts: - - videocall.rs - - www.videocall.rs diff --git a/helm/rustlemania-ui/.helmignore b/helm/videocall/.helmignore similarity index 99% rename from helm/rustlemania-ui/.helmignore rename to helm/videocall/.helmignore index 0e8a0eb36..898df4886 100644 --- a/helm/rustlemania-ui/.helmignore +++ b/helm/videocall/.helmignore @@ -21,3 +21,4 @@ .idea/ *.tmproj .vscode/ + diff --git a/helm/videocall/CHART_SUMMARY.md b/helm/videocall/CHART_SUMMARY.md new file mode 100644 index 000000000..f631cabdb --- /dev/null +++ b/helm/videocall/CHART_SUMMARY.md @@ -0,0 +1,388 @@ +# Videocall Unified Helm Chart - Summary + +## What Was Created + +A unified, production-ready Helm chart that combines all six videocall components into a single, well-architected deployment. + +### Chart Structure + +``` +helm/videocall/ +├── Chart.yaml # Chart metadata +├── values.yaml # Beautifully commented default values +├── .helmignore # Files to exclude from packaging +├── README.md # Comprehensive documentation +├── QUICKSTART.md # 5-minute getting started guide +├── MIGRATION.md # Migration guide from separate charts +├── CHART_SUMMARY.md # This file +└── templates/ + ├── _helpers.tpl # Component-aware helper functions + ├── NOTES.txt # Post-install instructions + ├── ui-deployment.yaml # UI component deployment + ├── ui-service.yaml # UI service with component selector + ├── ui-configmap.yaml # UI runtime configuration + ├── ui-ingress.yaml # UI ingress for HTTPS + ├── ui-hpa.yaml # UI horizontal pod autoscaler + ├── websocket-deployment.yaml # WebSocket deployment + ├── websocket-service.yaml # WebSocket service with component selector + ├── websocket-ingress.yaml # WebSocket ingress (supports multiple hosts) + ├── websocket-hpa.yaml # WebSocket autoscaler + ├── webtransport-deployment.yaml # WebTransport deployment + ├── webtransport-service.yaml # WebTransport LoadBalancer with component selector + ├── webtransport-certificate.yaml # WebTransport TLS certificate + ├── webtransport-hpa.yaml # WebTransport autoscaler + ├── website-deployment.yaml # Website deployment + ├── website-service.yaml # Website service with component selector + ├── website-ingress.yaml # Website ingress (apex + www) + ├── website-hpa.yaml # Website autoscaler + ├── metrics-client-deployment.yaml # Metrics client deployment (port 9091) + ├── metrics-client-service.yaml # Metrics client service with component selector + ├── metrics-server-deployment.yaml # Metrics server deployment (port 9092) + └── metrics-server-service.yaml # Metrics server service with component selector +``` + +## The Critical Fix: Component-Based Label Strategy + +### The Problem You Experienced + +When deploying all four charts with the same release pattern, services shared these labels: + +```yaml +# All components had the same labels +app.kubernetes.io/name: rustlemania (or videocall) +app.kubernetes.io/instance: my-release +``` + +This caused **selector collisions**: +- ❌ UI service would route to WebSocket pods +- ❌ WebSocket service would route to WebTransport pods +- ❌ WebTransport load balancer would route to Website pods +- ❌ Complete routing chaos! + +### The Solution: Component Differentiation + +Every resource now includes a **component label**: + +```yaml +app.kubernetes.io/component: ui|websocket|webtransport|website +``` + +#### Example: UI Component + +**Service Selector (templates/ui-service.yaml):** +```yaml +selector: + app.kubernetes.io/name: videocall + app.kubernetes.io/instance: my-release + app.kubernetes.io/component: ui # ← Only matches UI pods +``` + +**Pod Labels (templates/ui-deployment.yaml):** +```yaml +labels: + app.kubernetes.io/name: videocall + app.kubernetes.io/instance: my-release + app.kubernetes.io/component: ui # ← Matches service selector +``` + +#### Verification + +Run `helm template` and check selectors: + +```bash +$ helm template test . | grep -A 3 "selector:" + +# UI Service +selector: + app.kubernetes.io/component: ui + +# WebSocket Service +selector: + app.kubernetes.io/component: websocket + +# WebTransport LoadBalancer +selector: + app.kubernetes.io/component: webtransport + +# Website Service +selector: + app.kubernetes.io/component: website + +# Metrics Client Service +selector: + app.kubernetes.io/component: metrics-client + +# Metrics Server Service +selector: + app.kubernetes.io/component: metrics-server +``` + +✅ **Each service now routes ONLY to its own component's pods!** + +## Key Features + +### 1. Beautiful, Comprehensive Documentation + +Every value in `values.yaml` has detailed comments: + +```yaml +# Audio bitrate in kilobits per second +# Typical range: 8-32 kbps for voice +audioBitrateKbps: 16 +``` + +**Total documentation:** +- 700+ lines of commented values.yaml +- Comprehensive README.md with architecture details +- QUICKSTART.md for new users +- MIGRATION.md for existing deployments +- CHART_SUMMARY.md (this file) + +### 2. Component Enable/Disable Flags + +Deploy any combination of components: + +```yaml +ui: + enabled: true # ✓ Deploy UI +websocket: + enabled: true # ✓ Deploy WebSocket +webtransport: + enabled: false # ✗ Skip WebTransport (dev mode) +website: + enabled: false # ✗ Skip Website +metricsClient: + enabled: true # ✓ Deploy metrics client +metricsServer: + enabled: true # ✓ Deploy metrics server +``` + +### 3. Global Configuration + +Share common settings across components: + +```yaml +global: + domain: "videocall.rs" # Used by all ingress/cert configs + region: "us-east" # Injected into env vars + natsUrl: "nats:4222" # Shared NATS connection +``` + +### 4. Per-Component Customization + +Each component has full configuration: + +```yaml +websocket: + replicaCount: 5 + resources: + limits: + cpu: "2000m" + memory: "4Gi" + autoscaling: + enabled: true + minReplicas: 3 + maxReplicas: 20 + nodeSelector: + topology.kubernetes.io/region: "us-east-1" +``` + +### 5. Multi-Region Support + +UI supports comma-separated server lists: + +```yaml +ui: + runtimeConfig: + wsUrl: "wss://ws-us.videocall.rs,wss://ws-eu.videocall.rs" + webTransportHost: "https://wt-us.videocall.rs:443,https://wt-eu.videocall.rs:443" +``` + +Client automatically selects best server based on latency. + +### 6. Secret Integration + +Automatically uses secrets if available: + +```yaml +# In deployment template +{{- if (lookup "v1" "Secret" .Release.Namespace "postgres-credentials") }} +- name: PG_PASSWORD + valueFrom: + secretKeyRef: + name: postgres-credentials + key: password +{{- end }} +``` + +### 7. Production-Ready Defaults + +- ✅ Resource limits and requests defined +- ✅ Health check ports configured (WebTransport) +- ✅ TLS/SSL enabled by default +- ✅ cert-manager integration +- ✅ Horizontal Pod Autoscaler templates +- ✅ Pod anti-affinity options +- ✅ Node selector support + +## Usage Patterns + +### Pattern 1: Public Template (This Chart) + +Located at `helm/videocall/` - this is what users download and use: + +```bash +git clone https://github.com/security-union/videocall-rs +cd videocall-rs/helm/videocall +helm install my-app . -f my-values.yaml +``` + +### Pattern 2: Production Deployment (Your Use Case) + +In `helm-videocall-deployment/us-east/`, wrap the public chart: + +**Chart.yaml:** +```yaml +apiVersion: v2 +name: videocall-us-east +version: 0.1.0 +dependencies: + - name: videocall + version: 0.1.0 + repository: "file://../../../../helm/videocall" +``` + +**values.yaml:** +```yaml +videocall: # Namespace all values under chart name + global: + domain: "videocall.rs" + region: "us-east" + + ui: + fullnameOverride: "videocall-ui-us-east" + replicaCount: 3 + # ... production config + + websocket: + fullnameOverride: "websocket-us-east" + replicaCount: 5 + # ... production config +``` + +This pattern: +- ✅ Separates public template from production config +- ✅ Makes updates easy: `helm dependency update` +- ✅ Keeps your deployment values clean and focused +- ✅ Follows Helm best practices + +## Validation Results + +### Helm Lint + +```bash +$ helm lint . +==> Linting . +[INFO] Chart.yaml: icon is recommended +1 chart(s) linted, 0 chart(s) failed +``` + +✅ **Passes all validations** + +### Selector Verification + +```bash +$ helm template test . | grep -A 3 "selector:" + +# Results show each service has unique component label ✓ +``` + +### Template Rendering + +```bash +$ helm template test . --debug +# Successfully renders all 20 templates ✓ +``` + +## Installation Commands + +### Quick Install (All Components) + +```bash +helm install videocall ./helm/videocall \ + --set global.domain=yourdomain.com +``` + +### Custom Install (Select Components) + +```bash +helm install videocall ./helm/videocall \ + --set ui.enabled=true \ + --set websocket.enabled=true \ + --set webtransport.enabled=false \ + --set website.enabled=false \ + -f my-values.yaml +``` + +### Production Install (From Wrapper Chart) + +```bash +cd helm-videocall-deployment/us-east/videocall +helm dependency update +helm install videocall-us-east . -f values.yaml +``` + +## Benefits Over Separate Charts + +| Aspect | Before (4 Charts) | After (Unified) | +|--------|------------------|-----------------| +| **Selector Collision** | ❌ Services route to wrong pods | ✅ Component labels prevent collisions | +| **Deployment Complexity** | ❌ 4 helm install commands | ✅ 1 helm install command | +| **Configuration** | ❌ Duplicated across 4 files | ✅ Shared global config | +| **Maintenance** | ❌ Update 4 charts separately | ✅ Update 1 chart | +| **Documentation** | ❌ Scattered across charts | ✅ Centralized, comprehensive | +| **Version Control** | ❌ 4 chart versions to track | ✅ 1 unified version | +| **Partial Deployment** | ❌ Install/uninstall individual charts | ✅ Enable/disable flags | + +## Next Steps + +1. **Test the Chart:** + ```bash + cd helm/videocall + helm template test . > /tmp/test-output.yaml + kubectl apply --dry-run=client -f /tmp/test-output.yaml + ``` + +2. **Create Production Values:** + ```bash + cp values.yaml my-production-values.yaml + # Edit with your production settings + ``` + +3. **Deploy to Staging:** + ```bash + helm install videocall-staging . -f my-production-values.yaml -n staging + ``` + +4. **Verify Selectors:** + ```bash + kubectl get svc -n staging + kubectl get endpoints -n staging + # Ensure each service has correct endpoints + ``` + +5. **Update Deployment Repos:** + - Update `helm-videocall-deployment/us-east/` to use wrapper pattern + - Update `helm-videocall-deployment/singapore/` to use wrapper pattern + +## Support + +- **Chart Location**: `helm/videocall/` +- **Documentation**: See README.md, QUICKSTART.md, MIGRATION.md +- **Issues**: https://github.com/security-union/videocall-rs/issues +- **Discussions**: https://github.com/security-union/videocall-rs/discussions + +--- + +**Chart created with ❤️ to solve the selector collision problem!** + diff --git a/helm/videocall/Chart.yaml b/helm/videocall/Chart.yaml new file mode 100644 index 000000000..47b684b19 --- /dev/null +++ b/helm/videocall/Chart.yaml @@ -0,0 +1,18 @@ +apiVersion: v2 +name: videocall +description: A unified Helm chart for deploying the complete Videocall.rs application stack +type: application +version: 0.1.0 +appVersion: "1.0.0" +keywords: + - videocall + - webrtc + - rust + - real-time-communication +maintainers: + - name: Security Union + url: https://github.com/security-union +home: https://videocall.rs +sources: + - https://github.com/security-union/videocall-rs + diff --git a/helm/videocall/METRICS_COMPONENTS.md b/helm/videocall/METRICS_COMPONENTS.md new file mode 100644 index 000000000..9fc307e6a --- /dev/null +++ b/helm/videocall/METRICS_COMPONENTS.md @@ -0,0 +1,262 @@ +# Metrics Components + +The unified Videocall chart includes two dedicated metrics collection pods: + +## Component Overview + +### 1. Metrics Client (`metricsClient`) +- **Purpose**: Collects client-side metrics from NATS events +- **Port**: 9091 +- **Binary**: `/usr/bin/metrics_server` +- **Service Type**: ClusterIP +- **Resources**: Minimal (50m CPU, 128Mi memory) +- **Component Label**: `app.kubernetes.io/component: metrics-client` + +**What it collects**: +- Client connection events +- Media quality metrics +- User engagement statistics +- Client-side performance data + +### 2. Metrics Server (`metricsServer`) +- **Purpose**: Tracks server connection statistics and aggregates server stats +- **Port**: 9092 +- **Binary**: `/usr/bin/metrics_server_snapshot` +- **Service Type**: ClusterIP +- **Resources**: Minimal (100m CPU, 128Mi memory) +- **Component Label**: `app.kubernetes.io/component: metrics-server` + +**What it collects**: +- Active server connections per WebSocket/WebTransport server +- Server load distribution +- Connection state snapshots +- Server health metrics + +## Configuration + +### Enable/Disable Metrics + +```yaml +# Both metrics components enabled by default +metricsClient: + enabled: true + +metricsServer: + enabled: true +``` + +### Prometheus Annotations + +Both components include automatic Prometheus scraping annotations: + +```yaml +metricsClient: + podAnnotations: + prometheus.io/scrape: "true" + prometheus.io/port: "9091" + prometheus.io/path: "/metrics" + +metricsServer: + podAnnotations: + prometheus.io/scrape: "true" + prometheus.io/port: "9092" + prometheus.io/path: "/metrics" +``` + +### Resource Optimization + +Both components use minimal resources for cost optimization: + +```yaml +metricsClient: + resources: + limits: + cpu: "50m" # 0.05 CPU cores + memory: "128Mi" + requests: + cpu: "25m" + memory: "64Mi" + +metricsServer: + resources: + limits: + cpu: "100m" # Slightly higher for aggregation + memory: "128Mi" + requests: + cpu: "50m" + memory: "64Mi" +``` + +## Accessing Metrics + +### Via Port-Forward + +```bash +# Client metrics +kubectl port-forward svc/videocall-metrics-client 9091:9091 +curl http://localhost:9091/metrics + +# Server stats +kubectl port-forward svc/videocall-metrics-server 9092:9092 +curl http://localhost:9092/metrics +``` + +### Via Service Discovery + +```yaml +# Prometheus scrape config +scrape_configs: + - job_name: 'videocall-metrics' + kubernetes_sd_configs: + - role: service + relabel_configs: + - source_labels: [__meta_kubernetes_service_label_app_kubernetes_io_component] + regex: metrics-(client|server) + action: keep +``` + +## Health Checks + +Both components include health endpoints: + +- **Liveness Probe**: `/health` (checks if pod is alive) +- **Readiness Probe**: `/health` (checks if ready to serve traffic) + +## Security Context + +Both run as non-root user 1000 for security: + +```yaml +podSecurityContext: + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + +securityContext: + runAsUser: 1000 + runAsGroup: 1000 +``` + +## Service Selectors + +Each component has unique selectors to prevent routing collisions: + +```yaml +# Metrics Client Service +selector: + app.kubernetes.io/name: videocall + app.kubernetes.io/instance: my-release + app.kubernetes.io/component: metrics-client + +# Metrics Server Service +selector: + app.kubernetes.io/name: videocall + app.kubernetes.io/instance: my-release + app.kubernetes.io/component: metrics-server +``` + +## Deployment Example + +```yaml +# values.yaml +global: + domain: "videocall.rs" + region: "us-east" + natsUrl: "nats:4222" + +metricsClient: + enabled: true + replicaCount: 1 + env: + - name: METRICS_PORT + value: "9091" + - name: NATS_URL + value: nats:4222 + - name: REGION + value: "us-east" + +metricsServer: + enabled: true + replicaCount: 1 + env: + - name: METRICS_PORT + value: "9092" + - name: NATS_URL + value: nats:4222 + - name: REGION + value: "us-east" +``` + +## Verification + +After deployment, verify both metrics pods are running: + +```bash +# Check pods +kubectl get pods -l app.kubernetes.io/component=metrics-client +kubectl get pods -l app.kubernetes.io/component=metrics-server + +# Check services +kubectl get svc -l app.kubernetes.io/component=metrics-client +kubectl get svc -l app.kubernetes.io/component=metrics-server + +# Check endpoints +kubectl get endpoints | grep metrics +``` + +## Integration with Grafana + +Create a Grafana dashboard to visualize metrics from both endpoints: + +```yaml +# datasource.yaml +apiVersion: 1 +datasources: + - name: Videocall Metrics + type: prometheus + url: http://prometheus:9090 + access: proxy + isDefault: true +``` + +Query examples: +- Client metrics: `{job="videocall-metrics", component="metrics-client"}` +- Server stats: `{job="videocall-metrics", component="metrics-server"}` + +## Troubleshooting + +### Metrics not appearing in Prometheus + +1. Check pod annotations: + ```bash + kubectl get pods -l app.kubernetes.io/component=metrics-client -o jsonpath='{.items[0].metadata.annotations}' + ``` + +2. Verify service is exposing the right port: + ```bash + kubectl get svc videocall-metrics-client -o yaml + ``` + +3. Check Prometheus target status at `/targets` + +### Pod not starting + +1. Check logs: + ```bash + kubectl logs -l app.kubernetes.io/component=metrics-client + kubectl logs -l app.kubernetes.io/component=metrics-server + ``` + +2. Verify NATS connectivity: + ```bash + kubectl exec -it deployment/videocall-metrics-client -- sh + nc -zv nats 4222 + ``` + +### Health check failures + +Check health endpoint directly: +```bash +kubectl port-forward svc/videocall-metrics-client 9091:9091 +curl http://localhost:9091/health +``` diff --git a/helm/videocall/MIGRATION.md b/helm/videocall/MIGRATION.md new file mode 100644 index 000000000..5ae7ada28 --- /dev/null +++ b/helm/videocall/MIGRATION.md @@ -0,0 +1,305 @@ +# Migration Guide: From Separate Charts to Unified Videocall Chart + +This guide helps you migrate from the four separate Helm charts to the unified `videocall` chart. + +## The Problem We Solved + +Previously, deploying all four components from separate charts with similar naming could cause **selector label collisions**, where: + +- ❌ UI service might route to WebSocket pods +- ❌ WebSocket service might route to WebTransport pods +- ❌ WebTransport load balancer might route to Website pods +- ❌ All services shared the same `app.kubernetes.io/name` label + +## The Solution: Component-Based Labeling + +The unified chart uses a **component-specific label** to ensure each service only routes to its own pods: + +```yaml +# Each component gets a unique label +app.kubernetes.io/component: ui|websocket|webtransport|website +``` + +### Label Structure Example + +**UI Component:** +```yaml +# Pod labels (from Deployment) +labels: + app.kubernetes.io/name: videocall + app.kubernetes.io/instance: my-release + app.kubernetes.io/component: ui # <-- Unique identifier + +# Service selector (from Service) +selector: + app.kubernetes.io/name: videocall + app.kubernetes.io/instance: my-release + app.kubernetes.io/component: ui # <-- Matches only UI pods +``` + +**WebSocket Component:** +```yaml +# Pod labels +labels: + app.kubernetes.io/name: videocall + app.kubernetes.io/instance: my-release + app.kubernetes.io/component: websocket # <-- Different from UI + +# Service selector +selector: + app.kubernetes.io/name: videocall + app.kubernetes.io/instance: my-release + app.kubernetes.io/component: websocket # <-- Matches only WebSocket pods +``` + +This pattern is repeated for all four components, preventing any cross-component routing. + +## Migration Steps + +### Option 1: Clean Deployment (Recommended for Non-Production) + +1. **Uninstall old charts:** + ```bash + helm uninstall rustlemania-ui + helm uninstall rustlemania-websocket + helm uninstall rustlemania-webtransport + helm uninstall videocall-website + ``` + +2. **Create unified values file:** + ```bash + cat > my-values.yaml < my-values.yaml <<'EOF' +global: + domain: "example.com" # Replace with your domain + region: "us-east" + natsUrl: "nats:4222" + +ui: + enabled: true + ingress: + hosts: + - host: app.example.com + paths: + - path: / + pathType: Prefix + service: + name: videocall-ui + port: + number: 80 + runtimeConfig: + apiBaseUrl: "https://api.example.com" + wsUrl: "wss://websocket.example.com" + webTransportHost: "https://webtransport.example.com:443" + +websocket: + enabled: true + ingress: + hosts: + - host: websocket.example.com + paths: + - path: / + pathType: Prefix + service: + port: + number: 8080 + - host: api.example.com + paths: + - path: / + pathType: Prefix + service: + port: + number: 8080 + +webtransport: + enabled: true + certificateDomain: "webtransport.example.com" + loadBalancerAnnotations: + external-dns.alpha.kubernetes.io/hostname: "webtransport.example.com" + +website: + enabled: true + ingress: + hosts: + - host: example.com + paths: + - path: / + pathType: Prefix + service: + name: videocall-website + port: + number: 80 + - host: www.example.com + paths: + - path: / + pathType: Prefix + service: + name: videocall-website + port: + number: 80 +EOF +``` + +### 3. Install the Chart + +```bash +# Install with default namespace +helm install videocall . -f my-values.yaml + +# Or install in a specific namespace +kubectl create namespace videocall +helm install videocall . -f my-values.yaml -n videocall +``` + +### 4. Watch Deployment Progress + +```bash +# Watch pods come up +kubectl get pods -l app.kubernetes.io/instance=videocall -w + +# Check all resources +kubectl get all -l app.kubernetes.io/instance=videocall +``` + +## Verification + +### Check Services and Selectors + +```bash +# List all services +kubectl get svc -l app.kubernetes.io/instance=videocall + +# Verify each service has correct endpoints +kubectl get endpoints | grep videocall + +# Check that UI service only routes to UI pods +kubectl get endpoints videocall-ui -o yaml +``` + +You should see **each service routing only to its component's pods** thanks to the `app.kubernetes.io/component` label! + +### Check Ingress + +```bash +# Wait for ingress to be ready +kubectl get ingress -l app.kubernetes.io/instance=videocall + +# Check certificate status +kubectl get certificates +``` + +### Test the Application + +```bash +# Get the UI URL +echo "https://$(kubectl get ingress videocall-ui -o jsonpath='{.spec.rules[0].host}')" + +# Visit the URL in your browser +``` + +## Common Scenarios + +### Development: Run Only UI and WebSocket + +```bash +cat > dev-values.yaml < prod-values.yaml < us-east-values.yaml < +``` + +### Service Not Routing Correctly + +```bash +# Verify service selectors match pod labels +kubectl get svc videocall-ui -o yaml | grep -A 5 selector +kubectl get pods -l app.kubernetes.io/component=ui --show-labels + +# Check endpoints +kubectl get endpoints videocall-ui +``` + +**Expected:** Service selector should include `app.kubernetes.io/component: ui` and match pod labels. + +### Ingress 404 Errors + +```bash +# Check ingress configuration +kubectl describe ingress videocall-ui + +# Verify backend service exists +kubectl get svc videocall-ui + +# Check ingress controller logs +kubectl logs -n ingress-nginx -l app.kubernetes.io/component=controller +``` + +### Certificate Not Issued + +```bash +# Check certificate status +kubectl get certificate +kubectl describe certificate videocall-ui-tls + +# Check cert-manager logs +kubectl logs -n cert-manager deploy/cert-manager + +# Verify issuer exists +kubectl get clusterissuer letsencrypt-prod +``` + +## Upgrading + +```bash +# Upgrade with new values +helm upgrade videocall . -f my-values.yaml + +# Upgrade specific component (disable others) +helm upgrade videocall . \ + --set ui.enabled=true \ + --set ui.replicaCount=5 + +# Rollback if needed +helm rollback videocall +``` + +## Uninstallation + +```bash +# Uninstall the release +helm uninstall videocall + +# Optional: Clean up PVCs and secrets +kubectl delete pvc -l app.kubernetes.io/instance=videocall +kubectl delete secret videocall-ui-tls websocket-tls api-tls webtransport-tls videocall-website-tls +``` + +## Next Steps + +- Read the full [README.md](README.md) for detailed configuration options +- Check [MIGRATION.md](MIGRATION.md) if migrating from separate charts +- Review [values.yaml](values.yaml) for all available configuration parameters +- Visit [videocall.rs](https://videocall.rs) for documentation + +## Getting Help + +- **GitHub Issues**: https://github.com/security-union/videocall-rs/issues +- **Discussions**: https://github.com/security-union/videocall-rs/discussions +- **Documentation**: https://videocall.rs + +--- + +**Happy Video Calling! 🎥** + diff --git a/helm/videocall/README.md b/helm/videocall/README.md new file mode 100644 index 000000000..868d4390a --- /dev/null +++ b/helm/videocall/README.md @@ -0,0 +1,128 @@ +# Videocall Helm Chart + +Unified chart for deploying the complete Videocall.rs stack. + +## Components + +- **UI** (port 80) - Web application +- **WebSocket** (port 8080) - Real-time signaling +- **WebTransport** (port 443 UDP) - High-performance media transport +- **Website** (port 80) - Marketing site +- **Metrics Client** (port 9091) - Client metrics collection +- **Metrics Server** (port 9092) - Server stats tracking + +All components can be independently enabled/disabled. + +## Quick Start + +```bash +# Clone repo +git clone https://github.com/security-union/videocall-rs.git +cd videocall-rs/helm/videocall + +# Install with defaults +helm install videocall . + +# Or with custom values +helm install videocall . -f my-values.yaml +``` + +## Configuration + +See [values.yaml](values.yaml) - every option is documented with comments. + +**Key settings:** + +```yaml +global: + domain: "yourdomain.com" + region: "us-east" + natsUrl: "nats:4222" + +ui: + enabled: true + replicaCount: 1 + +websocket: + enabled: true + +webtransport: + enabled: true + certificateDomain: "webtransport.yourdomain.com" + +website: + enabled: true + +metricsClient: + enabled: true + +metricsServer: + enabled: true +``` + +## Prerequisites + +- Kubernetes 1.19+ +- Helm 3.2.0+ +- NATS server +- cert-manager (for TLS) +- Ingress controller (nginx recommended) + +## Component Labels + +Each component uses unique labels to prevent selector collisions: + +```yaml +app.kubernetes.io/component: ui|websocket|webtransport|website|metrics-client|metrics-server +``` + +Services only route to their own component's pods. + +## Secrets + +**PostgreSQL** (if websocket database enabled): +```bash +kubectl create secret generic postgres-credentials --from-literal=password=YOUR_PASSWORD +``` + +**OAuth** (if enabled): +```bash +kubectl create secret generic google-oauth-credentials \ + --from-literal=client-id=YOUR_CLIENT_ID \ + --from-literal=client-secret=YOUR_CLIENT_SECRET +``` + +## Monitoring + +Metrics exposed on ports 9091 (client) and 9092 (server) with Prometheus annotations. + +```bash +# Access metrics +kubectl port-forward svc/videocall-metrics-client 9091:9091 +curl http://localhost:9091/metrics +``` + +## Troubleshooting + +```bash +# Check pods +kubectl get pods -l app.kubernetes.io/instance=videocall + +# Check logs by component +kubectl logs -l app.kubernetes.io/component=ui +kubectl logs -l app.kubernetes.io/component=websocket + +# Verify service endpoints +kubectl get endpoints +``` + +## More Info + +- **QUICKSTART.md** - 5-minute getting started guide +- **MIGRATION.md** - Migrating from separate charts +- **CHART_SUMMARY.md** - Technical deep-dive +- **METRICS_COMPONENTS.md** - Metrics setup guide + +## License + +Dual-licensed under Apache 2.0 and MIT. diff --git a/helm/videocall/templates/NOTES.txt b/helm/videocall/templates/NOTES.txt new file mode 100644 index 000000000..98a8a43c6 --- /dev/null +++ b/helm/videocall/templates/NOTES.txt @@ -0,0 +1,101 @@ +========================================================================= + ____ ____ _ _ _ _ + | _ \ / ___|| | ___ | |__ ___ _ __ ___ __ _| || |_ _ + | | | | | | |/ _ \| '_ \ / _ \ | '__| / _ \/ _` | || | | | | + | |_| | |___ | | (_) | |_) || __/ | | | __/ (_| | || | |_| | + |____/ \____||_|\___/|_.__/ \___| |_| \___|\__,_|_||_|\__, | + |___/ +========================================================================= + +Thank you for installing {{ .Chart.Name }} version {{ .Chart.Version }}! + +Your videocall application has been deployed with the following components: + +{{- if .Values.ui.enabled }} +✓ UI Application + - Accessible at: {{ range .Values.ui.ingress.hosts }}{{ .host }}{{ end }} + - Service: {{ include "videocall.componentFullname" (dict "root" . "component" "ui") }} + - Replicas: {{ .Values.ui.replicaCount }} +{{- end }} + +{{- if .Values.websocket.enabled }} +✓ WebSocket API Server + - Accessible at: {{ range .Values.websocket.ingress.hosts }}{{ .host }} {{ end }} + - Service: {{ include "videocall.componentFullname" (dict "root" . "component" "websocket") }} + - Replicas: {{ .Values.websocket.replicaCount }} +{{- end }} + +{{- if .Values.webtransport.enabled }} +✓ WebTransport Server + - Domain: {{ .Values.webtransport.certificateDomain }} + - Service: {{ include "videocall.componentFullname" (dict "root" . "component" "webtransport") }}-lb + - Replicas: {{ .Values.webtransport.replicaCount }} +{{- end }} + +{{- if .Values.website.enabled }} +✓ Marketing Website + - Accessible at: {{ range .Values.website.ingress.hosts }}{{ .host }} {{ end }} + - Service: {{ include "videocall.componentFullname" (dict "root" . "component" "website") }} + - Replicas: {{ .Values.website.replicaCount }} +{{- end }} + +{{- if .Values.metricsClient.enabled }} +✓ Metrics Client (Client Metrics Collection) + - Metrics endpoint: http://{{ include "videocall.componentFullname" (dict "root" . "component" "metrics-client") }}:{{ .Values.metricsClient.service.port }}/metrics + - Service: {{ include "videocall.componentFullname" (dict "root" . "component" "metrics-client") }} + - Replicas: {{ .Values.metricsClient.replicaCount }} +{{- end }} + +{{- if .Values.metricsServer.enabled }} +✓ Metrics Server (Server Stats Tracking) + - Metrics endpoint: http://{{ include "videocall.componentFullname" (dict "root" . "component" "metrics-server") }}:{{ .Values.metricsServer.service.port }}/metrics + - Service: {{ include "videocall.componentFullname" (dict "root" . "component" "metrics-server") }} + - Replicas: {{ .Values.metricsServer.replicaCount }} +{{- end }} + +========================================================================= + +To get the status of your deployment: + + kubectl get pods -l app.kubernetes.io/instance={{ .Release.Name }} + +To view logs for a specific component: + +{{- if .Values.ui.enabled }} + kubectl logs -l app.kubernetes.io/component=ui +{{- end }} +{{- if .Values.websocket.enabled }} + kubectl logs -l app.kubernetes.io/component=websocket +{{- end }} +{{- if .Values.webtransport.enabled }} + kubectl logs -l app.kubernetes.io/component=webtransport +{{- end }} +{{- if .Values.website.enabled }} + kubectl logs -l app.kubernetes.io/component=website +{{- end }} +{{- if .Values.metricsClient.enabled }} + kubectl logs -l app.kubernetes.io/component=metrics-client +{{- end }} +{{- if .Values.metricsServer.enabled }} + kubectl logs -l app.kubernetes.io/component=metrics-server +{{- end }} + +To access the application: +{{- if .Values.ui.enabled }} + + 1. Wait for the UI ingress to be ready: + kubectl wait --for=condition=ready ingress/{{ include "videocall.componentFullname" (dict "root" . "component" "ui") }} + + 2. Visit the application: + {{- range .Values.ui.ingress.hosts }} + https://{{ .host }} + {{- end }} +{{- end }} + +For more information about Videocall.rs: + - Documentation: https://videocall.rs + - GitHub: https://github.com/security-union/videocall-rs + - Issues: https://github.com/security-union/videocall-rs/issues + +========================================================================= + diff --git a/helm/videocall/templates/_helpers.tpl b/helm/videocall/templates/_helpers.tpl new file mode 100644 index 000000000..240579310 --- /dev/null +++ b/helm/videocall/templates/_helpers.tpl @@ -0,0 +1,108 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "videocall.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "videocall.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "videocall.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a component-specific fullname. +Usage: include "videocall.componentFullname" (dict "root" $ "component" "ui") +This creates names like: videocall-ui, videocall-websocket, etc. +*/}} +{{- define "videocall.componentFullname" -}} +{{- $componentConfig := index .root.Values .component }} +{{- if $componentConfig.fullnameOverride }} +{{- $componentConfig.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else if $componentConfig.nameOverride }} +{{- $componentConfig.nameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" (include "videocall.fullname" .root) .component | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} + +{{/* +Common labels - includes component label for proper resource grouping. +Usage: include "videocall.labels" (dict "root" $ "component" "ui") +*/}} +{{- define "videocall.labels" -}} +helm.sh/chart: {{ include "videocall.chart" .root }} +{{ include "videocall.selectorLabels" . }} +{{- if .root.Chart.AppVersion }} +app.kubernetes.io/version: {{ .root.Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .root.Release.Service }} +{{- end }} + +{{/* +Selector labels - CRITICAL: includes component label to prevent selector collisions. +This ensures each service only routes to its own component's pods. +Usage: include "videocall.selectorLabels" (dict "root" $ "component" "ui") + +Example output: + app.kubernetes.io/name: videocall + app.kubernetes.io/instance: my-release + app.kubernetes.io/component: ui +*/}} +{{- define "videocall.selectorLabels" -}} +app.kubernetes.io/name: {{ include "videocall.name" .root }} +app.kubernetes.io/instance: {{ .root.Release.Name }} +app.kubernetes.io/component: {{ .component }} +{{- end }} + +{{/* +Create the name of the service account to use. +*/}} +{{- define "videocall.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "videocall.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Generate the config.js content for the UI component. +This is injected as a ConfigMap and mounted into the UI container. +*/}} +{{- define "videocall.ui.configjs" -}} +window.__APP_CONFIG = { + apiBaseUrl: {{ .Values.ui.runtimeConfig.apiBaseUrl | quote }}, + wsUrl: {{ .Values.ui.runtimeConfig.wsUrl | quote }}, + webTransportHost: {{ .Values.ui.runtimeConfig.webTransportHost | quote }}, + oauthEnabled: {{ .Values.ui.runtimeConfig.oauthEnabled | quote }}, + e2eeEnabled: {{ .Values.ui.runtimeConfig.e2eeEnabled | quote }}, + webTransportEnabled: {{ .Values.ui.runtimeConfig.webTransportEnabled | quote }}, + usersAllowedToStream: {{ .Values.ui.runtimeConfig.usersAllowedToStream | quote }}, + serverElectionPeriodMs: {{ .Values.ui.runtimeConfig.serverElectionPeriodMs }}, + audioBitrateKbps: {{ .Values.ui.runtimeConfig.audioBitrateKbps }}, + videoBitrateKbps: {{ .Values.ui.runtimeConfig.videoBitrateKbps }}, + screenBitrateKbps: {{ .Values.ui.runtimeConfig.screenBitrateKbps }} +}; +{{- end }} + diff --git a/helm/videocall/templates/metrics-client-deployment.yaml b/helm/videocall/templates/metrics-client-deployment.yaml new file mode 100644 index 000000000..7f2572ff2 --- /dev/null +++ b/helm/videocall/templates/metrics-client-deployment.yaml @@ -0,0 +1,57 @@ +{{- if .Values.metricsClient.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "videocall.componentFullname" (dict "root" . "component" "metrics-client") }} + labels: + {{- include "videocall.labels" (dict "root" . "component" "metrics-client") | nindent 4 }} +spec: + replicas: {{ .Values.metricsClient.replicaCount }} + selector: + matchLabels: + {{- include "videocall.selectorLabels" (dict "root" . "component" "metrics-client") | nindent 6 }} + template: + metadata: + {{- with .Values.metricsClient.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "videocall.selectorLabels" (dict "root" . "component" "metrics-client") | nindent 8 }} + spec: + securityContext: + {{- toYaml .Values.metricsClient.podSecurityContext | nindent 8 }} + containers: + - name: metrics-client + securityContext: + {{- toYaml .Values.metricsClient.securityContext | nindent 12 }} + image: "{{ .Values.metricsClient.image.repository }}:{{ .Values.metricsClient.image.tag }}" + imagePullPolicy: {{ .Values.metricsClient.image.pullPolicy }} + command: {{ .Values.metricsClient.command }} + workingDir: {{ .Values.metricsClient.workingDir }} + env: + {{- toYaml .Values.metricsClient.env | nindent 12 }} + ports: + - name: http + containerPort: {{ .Values.metricsClient.service.targetPort }} + protocol: TCP + livenessProbe: + {{- toYaml .Values.metricsClient.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.metricsClient.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.metricsClient.resources | nindent 12 }} + {{- with .Values.metricsClient.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.metricsClient.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.metricsClient.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} + diff --git a/helm/videocall/templates/metrics-client-service.yaml b/helm/videocall/templates/metrics-client-service.yaml new file mode 100644 index 000000000..d33245a1b --- /dev/null +++ b/helm/videocall/templates/metrics-client-service.yaml @@ -0,0 +1,18 @@ +{{- if .Values.metricsClient.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "videocall.componentFullname" (dict "root" . "component" "metrics-client") }} + labels: + {{- include "videocall.labels" (dict "root" . "component" "metrics-client") | nindent 4 }} +spec: + type: {{ .Values.metricsClient.service.type }} + ports: + - port: {{ .Values.metricsClient.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "videocall.selectorLabels" (dict "root" . "component" "metrics-client") | nindent 4 }} +{{- end }} + diff --git a/helm/videocall/templates/metrics-server-deployment.yaml b/helm/videocall/templates/metrics-server-deployment.yaml new file mode 100644 index 000000000..03f5ff072 --- /dev/null +++ b/helm/videocall/templates/metrics-server-deployment.yaml @@ -0,0 +1,57 @@ +{{- if .Values.metricsServer.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "videocall.componentFullname" (dict "root" . "component" "metrics-server") }} + labels: + {{- include "videocall.labels" (dict "root" . "component" "metrics-server") | nindent 4 }} +spec: + replicas: {{ .Values.metricsServer.replicaCount }} + selector: + matchLabels: + {{- include "videocall.selectorLabels" (dict "root" . "component" "metrics-server") | nindent 6 }} + template: + metadata: + {{- with .Values.metricsServer.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "videocall.selectorLabels" (dict "root" . "component" "metrics-server") | nindent 8 }} + spec: + securityContext: + {{- toYaml .Values.metricsServer.podSecurityContext | nindent 8 }} + containers: + - name: metrics-server + securityContext: + {{- toYaml .Values.metricsServer.securityContext | nindent 12 }} + image: "{{ .Values.metricsServer.image.repository }}:{{ .Values.metricsServer.image.tag }}" + imagePullPolicy: {{ .Values.metricsServer.image.pullPolicy }} + command: {{ .Values.metricsServer.command }} + workingDir: {{ .Values.metricsServer.workingDir }} + env: + {{- toYaml .Values.metricsServer.env | nindent 12 }} + ports: + - name: http + containerPort: {{ .Values.metricsServer.service.targetPort }} + protocol: TCP + livenessProbe: + {{- toYaml .Values.metricsServer.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.metricsServer.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.metricsServer.resources | nindent 12 }} + {{- with .Values.metricsServer.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.metricsServer.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.metricsServer.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} + diff --git a/helm/videocall/templates/metrics-server-service.yaml b/helm/videocall/templates/metrics-server-service.yaml new file mode 100644 index 000000000..e7eac9f46 --- /dev/null +++ b/helm/videocall/templates/metrics-server-service.yaml @@ -0,0 +1,18 @@ +{{- if .Values.metricsServer.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "videocall.componentFullname" (dict "root" . "component" "metrics-server") }} + labels: + {{- include "videocall.labels" (dict "root" . "component" "metrics-server") | nindent 4 }} +spec: + type: {{ .Values.metricsServer.service.type }} + ports: + - port: {{ .Values.metricsServer.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "videocall.selectorLabels" (dict "root" . "component" "metrics-server") | nindent 4 }} +{{- end }} + diff --git a/helm/videocall/templates/ui-configmap.yaml b/helm/videocall/templates/ui-configmap.yaml new file mode 100644 index 000000000..d6965bd5f --- /dev/null +++ b/helm/videocall/templates/ui-configmap.yaml @@ -0,0 +1,12 @@ +{{- if .Values.ui.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "videocall.componentFullname" (dict "root" . "component" "ui") }}-config + labels: + {{- include "videocall.labels" (dict "root" . "component" "ui") | nindent 4 }} +data: + config.js: | + {{- include "videocall.ui.configjs" . | nindent 4 }} +{{- end }} + diff --git a/helm/videocall/templates/ui-deployment.yaml b/helm/videocall/templates/ui-deployment.yaml new file mode 100644 index 000000000..8a49b4aac --- /dev/null +++ b/helm/videocall/templates/ui-deployment.yaml @@ -0,0 +1,65 @@ +{{- if .Values.ui.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "videocall.componentFullname" (dict "root" . "component" "ui") }} + labels: + {{- include "videocall.labels" (dict "root" . "component" "ui") | nindent 4 }} +spec: + {{- if not .Values.ui.autoscaling.enabled }} + replicas: {{ .Values.ui.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "videocall.selectorLabels" (dict "root" . "component" "ui") | nindent 6 }} + template: + metadata: + annotations: + checksum/config: {{ include (print $.Template.BasePath "/ui-configmap.yaml") . | sha256sum }} + {{- with .Values.ui.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "videocall.selectorLabels" (dict "root" . "component" "ui") | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .Values.ui.podSecurityContext | nindent 8 }} + containers: + - name: ui + securityContext: + {{- toYaml .Values.ui.securityContext | nindent 12 }} + image: "{{ .Values.ui.image.repository }}:{{ .Values.ui.image.tag }}" + imagePullPolicy: {{ .Values.ui.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.ui.service.port }} + protocol: TCP + resources: + {{- toYaml .Values.ui.resources | nindent 12 }} + volumeMounts: + - name: app-config + mountPath: /usr/share/nginx/html/config.js + subPath: config.js + readOnly: true + volumes: + - name: app-config + configMap: + name: {{ include "videocall.componentFullname" (dict "root" . "component" "ui") }}-config + {{- with .Values.ui.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ui.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ui.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} + diff --git a/helm/videocall/templates/ui-hpa.yaml b/helm/videocall/templates/ui-hpa.yaml new file mode 100644 index 000000000..4acfbcec2 --- /dev/null +++ b/helm/videocall/templates/ui-hpa.yaml @@ -0,0 +1,33 @@ +{{- if and .Values.ui.enabled .Values.ui.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "videocall.componentFullname" (dict "root" . "component" "ui") }} + labels: + {{- include "videocall.labels" (dict "root" . "component" "ui") | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "videocall.componentFullname" (dict "root" . "component" "ui") }} + minReplicas: {{ .Values.ui.autoscaling.minReplicas }} + maxReplicas: {{ .Values.ui.autoscaling.maxReplicas }} + metrics: + {{- if .Values.ui.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.ui.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.ui.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.ui.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} + diff --git a/helm/videocall/templates/ui-ingress.yaml b/helm/videocall/templates/ui-ingress.yaml new file mode 100644 index 000000000..8d53bde01 --- /dev/null +++ b/helm/videocall/templates/ui-ingress.yaml @@ -0,0 +1,42 @@ +{{- if and .Values.ui.enabled .Values.ui.ingress.enabled }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "videocall.componentFullname" (dict "root" . "component" "ui") }} + labels: + {{- include "videocall.labels" (dict "root" . "component" "ui") | nindent 4 }} + {{- with .Values.ui.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.ui.ingress.className }} + ingressClassName: {{ .Values.ui.ingress.className }} + {{- end }} + {{- if .Values.ui.ingress.tls }} + tls: + {{- range .Values.ui.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ui.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + pathType: {{ .pathType }} + backend: + service: + name: {{ .service.name | default (include "videocall.componentFullname" (dict "root" $ "component" "ui")) }} + port: + number: {{ .service.port.number }} + {{- end }} + {{- end }} +{{- end }} + diff --git a/helm/videocall/templates/ui-service.yaml b/helm/videocall/templates/ui-service.yaml new file mode 100644 index 000000000..c47aecd70 --- /dev/null +++ b/helm/videocall/templates/ui-service.yaml @@ -0,0 +1,18 @@ +{{- if .Values.ui.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "videocall.componentFullname" (dict "root" . "component" "ui") }} + labels: + {{- include "videocall.labels" (dict "root" . "component" "ui") | nindent 4 }} +spec: + type: {{ .Values.ui.service.type }} + ports: + - port: {{ .Values.ui.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "videocall.selectorLabels" (dict "root" . "component" "ui") | nindent 4 }} +{{- end }} + diff --git a/helm/videocall/templates/website-deployment.yaml b/helm/videocall/templates/website-deployment.yaml new file mode 100644 index 000000000..52408d712 --- /dev/null +++ b/helm/videocall/templates/website-deployment.yaml @@ -0,0 +1,57 @@ +{{- if .Values.website.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "videocall.componentFullname" (dict "root" . "component" "website") }} + labels: + {{- include "videocall.labels" (dict "root" . "component" "website") | nindent 4 }} +spec: + {{- if not .Values.website.autoscaling.enabled }} + replicas: {{ .Values.website.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "videocall.selectorLabels" (dict "root" . "component" "website") | nindent 6 }} + template: + metadata: + {{- with .Values.website.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "videocall.selectorLabels" (dict "root" . "component" "website") | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .Values.website.podSecurityContext | nindent 8 }} + containers: + - name: website + securityContext: + {{- toYaml .Values.website.securityContext | nindent 12 }} + image: "{{ .Values.website.image.repository }}:{{ .Values.website.image.tag }}" + imagePullPolicy: {{ .Values.website.image.pullPolicy }} + env: + {{- toYaml .Values.website.env | nindent 12 }} + ports: + - name: http + containerPort: {{ .Values.website.service.port }} + protocol: TCP + resources: + {{- toYaml .Values.website.resources | nindent 12 }} + {{- with .Values.website.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.website.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.website.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} + diff --git a/helm/videocall/templates/website-hpa.yaml b/helm/videocall/templates/website-hpa.yaml new file mode 100644 index 000000000..fe389e097 --- /dev/null +++ b/helm/videocall/templates/website-hpa.yaml @@ -0,0 +1,33 @@ +{{- if and .Values.website.enabled .Values.website.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "videocall.componentFullname" (dict "root" . "component" "website") }} + labels: + {{- include "videocall.labels" (dict "root" . "component" "website") | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "videocall.componentFullname" (dict "root" . "component" "website") }} + minReplicas: {{ .Values.website.autoscaling.minReplicas }} + maxReplicas: {{ .Values.website.autoscaling.maxReplicas }} + metrics: + {{- if .Values.website.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.website.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.website.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.website.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} + diff --git a/helm/videocall/templates/website-ingress.yaml b/helm/videocall/templates/website-ingress.yaml new file mode 100644 index 000000000..b538a5936 --- /dev/null +++ b/helm/videocall/templates/website-ingress.yaml @@ -0,0 +1,42 @@ +{{- if and .Values.website.enabled .Values.website.ingress.enabled }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "videocall.componentFullname" (dict "root" . "component" "website") }} + labels: + {{- include "videocall.labels" (dict "root" . "component" "website") | nindent 4 }} + {{- with .Values.website.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.website.ingress.className }} + ingressClassName: {{ .Values.website.ingress.className }} + {{- end }} + {{- if .Values.website.ingress.tls }} + tls: + {{- range .Values.website.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.website.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + pathType: {{ .pathType }} + backend: + service: + name: {{ .service.name }} + port: + number: {{ .service.port.number }} + {{- end }} + {{- end }} +{{- end }} + diff --git a/helm/videocall/templates/website-service.yaml b/helm/videocall/templates/website-service.yaml new file mode 100644 index 000000000..a19c1c7c0 --- /dev/null +++ b/helm/videocall/templates/website-service.yaml @@ -0,0 +1,18 @@ +{{- if .Values.website.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.website.service.name | default (include "videocall.componentFullname" (dict "root" . "component" "website")) }} + labels: + {{- include "videocall.labels" (dict "root" . "component" "website") | nindent 4 }} +spec: + type: {{ .Values.website.service.type }} + ports: + - port: {{ .Values.website.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "videocall.selectorLabels" (dict "root" . "component" "website") | nindent 4 }} +{{- end }} + diff --git a/helm/videocall/templates/websocket-deployment.yaml b/helm/videocall/templates/websocket-deployment.yaml new file mode 100644 index 000000000..47168e9d7 --- /dev/null +++ b/helm/videocall/templates/websocket-deployment.yaml @@ -0,0 +1,76 @@ +{{- if .Values.websocket.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "videocall.componentFullname" (dict "root" . "component" "websocket") }} + labels: + {{- include "videocall.labels" (dict "root" . "component" "websocket") | nindent 4 }} +spec: + {{- if not .Values.websocket.autoscaling.enabled }} + replicas: {{ .Values.websocket.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "videocall.selectorLabels" (dict "root" . "component" "websocket") | nindent 6 }} + template: + metadata: + {{- with .Values.websocket.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "videocall.selectorLabels" (dict "root" . "component" "websocket") | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .Values.websocket.podSecurityContext | nindent 8 }} + containers: + - name: websocket + securityContext: + {{- toYaml .Values.websocket.securityContext | nindent 12 }} + image: "{{ .Values.websocket.image.repository }}:{{ .Values.websocket.image.tag }}" + imagePullPolicy: {{ .Values.websocket.image.pullPolicy }} + env: + {{- toYaml .Values.websocket.env | nindent 12 }} + {{- if (lookup "v1" "Secret" .Release.Namespace "postgres-credentials") }} + - name: PG_PASSWORD + valueFrom: + secretKeyRef: + name: postgres-credentials + key: password + {{- end }} + {{- if (lookup "v1" "Secret" .Release.Namespace "google-oauth-credentials") }} + - name: OAUTH_CLIENT_ID + valueFrom: + secretKeyRef: + name: google-oauth-credentials + key: client-id + - name: OAUTH_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: google-oauth-credentials + key: client-secret + {{- end }} + ports: + - name: ws-api + containerPort: {{ .Values.websocket.service.port }} + protocol: TCP + resources: + {{- toYaml .Values.websocket.resources | nindent 12 }} + {{- with .Values.websocket.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.websocket.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.websocket.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} + diff --git a/helm/videocall/templates/websocket-hpa.yaml b/helm/videocall/templates/websocket-hpa.yaml new file mode 100644 index 000000000..a32eacaa8 --- /dev/null +++ b/helm/videocall/templates/websocket-hpa.yaml @@ -0,0 +1,33 @@ +{{- if and .Values.websocket.enabled .Values.websocket.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "videocall.componentFullname" (dict "root" . "component" "websocket") }} + labels: + {{- include "videocall.labels" (dict "root" . "component" "websocket") | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "videocall.componentFullname" (dict "root" . "component" "websocket") }} + minReplicas: {{ .Values.websocket.autoscaling.minReplicas }} + maxReplicas: {{ .Values.websocket.autoscaling.maxReplicas }} + metrics: + {{- if .Values.websocket.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.websocket.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.websocket.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.websocket.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} + diff --git a/helm/videocall/templates/websocket-ingress.yaml b/helm/videocall/templates/websocket-ingress.yaml new file mode 100644 index 000000000..ef5ecebac --- /dev/null +++ b/helm/videocall/templates/websocket-ingress.yaml @@ -0,0 +1,42 @@ +{{- if and .Values.websocket.enabled .Values.websocket.ingress.enabled }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "videocall.componentFullname" (dict "root" . "component" "websocket") }} + labels: + {{- include "videocall.labels" (dict "root" . "component" "websocket") | nindent 4 }} + {{- with .Values.websocket.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.websocket.ingress.className }} + ingressClassName: {{ .Values.websocket.ingress.className }} + {{- end }} + {{- if .Values.websocket.ingress.tls }} + tls: + {{- range .Values.websocket.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.websocket.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + pathType: {{ .pathType }} + backend: + service: + name: {{ default (include "videocall.componentFullname" (dict "root" $ "component" "websocket")) .service.name }} + port: + number: {{ .service.port.number }} + {{- end }} + {{- end }} +{{- end }} + diff --git a/helm/videocall/templates/websocket-service.yaml b/helm/videocall/templates/websocket-service.yaml new file mode 100644 index 000000000..d53c13e5e --- /dev/null +++ b/helm/videocall/templates/websocket-service.yaml @@ -0,0 +1,18 @@ +{{- if .Values.websocket.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "videocall.componentFullname" (dict "root" . "component" "websocket") }} + labels: + {{- include "videocall.labels" (dict "root" . "component" "websocket") | nindent 4 }} +spec: + type: {{ .Values.websocket.service.type }} + ports: + - port: {{ .Values.websocket.service.port }} + targetPort: ws-api + protocol: TCP + name: ws-api + selector: + {{- include "videocall.selectorLabels" (dict "root" . "component" "websocket") | nindent 4 }} +{{- end }} + diff --git a/helm/videocall/templates/webtransport-certificate.yaml b/helm/videocall/templates/webtransport-certificate.yaml new file mode 100644 index 000000000..19a4e5fc3 --- /dev/null +++ b/helm/videocall/templates/webtransport-certificate.yaml @@ -0,0 +1,16 @@ +{{- if .Values.webtransport.enabled }} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ include "videocall.componentFullname" (dict "root" . "component" "webtransport") }}-cert + labels: + {{- include "videocall.labels" (dict "root" . "component" "webtransport") | nindent 4 }} +spec: + secretName: {{ .Values.webtransport.tlsSecret }} + issuerRef: + name: {{ .Values.webtransport.certificate.issuerName }} + kind: Issuer + dnsNames: + - {{ .Values.webtransport.certificateDomain }} +{{- end }} + diff --git a/helm/videocall/templates/webtransport-deployment.yaml b/helm/videocall/templates/webtransport-deployment.yaml new file mode 100644 index 000000000..5a17489ec --- /dev/null +++ b/helm/videocall/templates/webtransport-deployment.yaml @@ -0,0 +1,71 @@ +{{- if .Values.webtransport.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "videocall.componentFullname" (dict "root" . "component" "webtransport") }} + labels: + {{- include "videocall.labels" (dict "root" . "component" "webtransport") | nindent 4 }} +spec: + {{- if not .Values.webtransport.autoscaling.enabled }} + replicas: {{ .Values.webtransport.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "videocall.selectorLabels" (dict "root" . "component" "webtransport") | nindent 6 }} + template: + metadata: + {{- with .Values.webtransport.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "videocall.selectorLabels" (dict "root" . "component" "webtransport") | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .Values.webtransport.podSecurityContext | nindent 8 }} + containers: + - name: webtransport + securityContext: + {{- toYaml .Values.webtransport.securityContext | nindent 12 }} + image: "{{ .Values.webtransport.image.repository }}:{{ .Values.webtransport.image.tag }}" + command: {{ .Values.webtransport.command }} + args: {{ .Values.webtransport.args }} + imagePullPolicy: {{ .Values.webtransport.image.pullPolicy }} + env: + {{- toYaml .Values.webtransport.env | nindent 12 }} + ports: + - name: wt-api + containerPort: {{ .Values.webtransport.service.port }} + protocol: UDP + - name: wt-api-health + containerPort: {{ .Values.webtransport.service.healthPort }} + protocol: TCP + resources: + {{- toYaml .Values.webtransport.resources | nindent 12 }} + volumeMounts: + - name: tls + mountPath: "/certs" + readOnly: true + volumes: + - name: tls + secret: + secretName: {{ .Values.webtransport.tlsSecret }} + optional: true + {{- with .Values.webtransport.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.webtransport.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.webtransport.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} + diff --git a/helm/videocall/templates/webtransport-hpa.yaml b/helm/videocall/templates/webtransport-hpa.yaml new file mode 100644 index 000000000..8f609823b --- /dev/null +++ b/helm/videocall/templates/webtransport-hpa.yaml @@ -0,0 +1,33 @@ +{{- if and .Values.webtransport.enabled .Values.webtransport.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "videocall.componentFullname" (dict "root" . "component" "webtransport") }} + labels: + {{- include "videocall.labels" (dict "root" . "component" "webtransport") | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "videocall.componentFullname" (dict "root" . "component" "webtransport") }} + minReplicas: {{ .Values.webtransport.autoscaling.minReplicas }} + maxReplicas: {{ .Values.webtransport.autoscaling.maxReplicas }} + metrics: + {{- if .Values.webtransport.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.webtransport.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.webtransport.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.webtransport.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} + diff --git a/helm/videocall/templates/webtransport-service.yaml b/helm/videocall/templates/webtransport-service.yaml new file mode 100644 index 000000000..55f1cb399 --- /dev/null +++ b/helm/videocall/templates/webtransport-service.yaml @@ -0,0 +1,28 @@ +{{- if .Values.webtransport.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "videocall.componentFullname" (dict "root" . "component" "webtransport") }}-lb + labels: + {{- include "videocall.labels" (dict "root" . "component" "webtransport") | nindent 4 }} + {{- if .Values.webtransport.loadBalancerAnnotations }} + annotations: + {{- range $key, $value := .Values.webtransport.loadBalancerAnnotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- end }} +spec: + type: {{ .Values.webtransport.service.type }} + selector: + {{- include "videocall.selectorLabels" (dict "root" . "component" "webtransport") | nindent 4 }} + ports: + - protocol: TCP + port: {{ .Values.webtransport.service.healthPort }} + targetPort: wt-api-health + name: wt-api-health + - protocol: UDP + port: {{ .Values.webtransport.service.port }} + targetPort: wt-api + name: wt-api +{{- end }} + diff --git a/helm/videocall/values.yaml b/helm/videocall/values.yaml new file mode 100644 index 000000000..5fd0690e7 --- /dev/null +++ b/helm/videocall/values.yaml @@ -0,0 +1,966 @@ +# ============================================================================ +# Videocall.rs Helm Chart Values +# ============================================================================ +# This is the default values file for the Videocall.rs unified Helm chart. +# It deploys all four components of the video calling application: +# - UI (Web Application) +# - WebSocket API (Real-time signaling server) +# - WebTransport API (High-performance media transport) +# - Website (Marketing/landing pages) +# +# Each component can be independently enabled/disabled and configured. +# Override these values in your deployment-specific values.yaml file. +# ============================================================================ + +# ---------------------------------------------------------------------------- +# Global Configuration +# ---------------------------------------------------------------------------- +# Settings shared across all components + +global: + # Domain name for your videocall deployment + # This is used to construct default hostnames for all services + # Example: "videocall.rs" or "yourdomain.com" + domain: "YOUR_DOMAIN_NAME" + + # Deployment region identifier + # Used for multi-region deployments and service discovery + # Example: "us-east", "eu-west", "ap-south" + region: "us-east" + + # NATS server connection URL + # NATS is used for pub/sub messaging between components + # Format: "host:port" or comma-separated for cluster: "nats-1:4222,nats-2:4222" + natsUrl: "nats:4222" + + # Docker image pull policy + # Options: "Always", "IfNotPresent", "Never" + imagePullPolicy: Always + +# ---------------------------------------------------------------------------- +# UI Component Configuration +# ---------------------------------------------------------------------------- +# The frontend web application that users interact with +# Serves the React/Yew-based video calling interface + +ui: + # Enable or disable the UI component deployment + enabled: true + + # Override the component name (leave empty to use default: videocall-ui) + nameOverride: "" + + # Override the full resource name (leave empty to use chart-generated name) + fullnameOverride: "" + + # Number of UI pod replicas to run + # Increase for high availability and load distribution + replicaCount: 1 + + # Container image configuration + image: + # Docker image repository for the UI + repository: securityunion/rustlemania-ui + + # Image pull policy (overrides global if set) + pullPolicy: Always + + # Image tag (defaults to chart appVersion if not specified) + # Use "latest" for development, specific versions for production + tag: latest + + # Runtime configuration injected into the UI + # These values are written to config.js and loaded by the frontend + runtimeConfig: + # Base URL for the REST API + # Example: "https://api.videocall.rs" + apiBaseUrl: "https://api.YOUR_DOMAIN_NAME" + + # WebSocket server URL(s) for real-time signaling + # Supports comma-separated list for multi-region fallback + # Example: "wss://websocket.YOUR_DOMAIN_NAME" or "wss://ws-us.domain.com,wss://ws-eu.domain.com" + wsUrl: "wss://websocket.YOUR_DOMAIN_NAME" + + # WebTransport server URL(s) for high-performance media transport + # Supports comma-separated list for multi-region fallback + # Must include port (typically 443) + # Example: "https://webtransport.YOUR_DOMAIN_NAME:443" + webTransportHost: "https://webtransport.YOUR_DOMAIN_NAME:443" + + # Enable OAuth authentication (Google OAuth) + # Set to "true" to require users to sign in, "false" for anonymous access + oauthEnabled: "false" + + # Enable end-to-end encryption for media streams + # Requires client-side key exchange implementation + e2eeEnabled: "false" + + # Enable WebTransport protocol (recommended for best performance) + # Falls back to WebSocket if disabled or unavailable + webTransportEnabled: "true" + + # Comma-separated list of user IDs allowed to stream + # Empty string allows all users (default) + # Example: "user1@example.com,user2@example.com" + usersAllowedToStream: "" + + # Server election period in milliseconds + # How often clients re-evaluate which media server to connect to + # Lower values = faster failover, higher control plane load + serverElectionPeriodMs: 2000 + + # Audio bitrate in kilobits per second + # Typical range: 8-32 kbps for voice + audioBitrateKbps: 16 + + # Video bitrate in kilobits per second + # Typical range: 100-500 kbps for video calls + videoBitrateKbps: 160 + + # Screen sharing bitrate in kilobits per second + # Typical range: 200-1000 kbps depending on content + screenBitrateKbps: 160 + + # Resource limits and requests + resources: + # Maximum resources the container can use (enforced) + limits: + cpu: "100m" # 0.1 CPU cores + memory: "128Mi" # 128 mebibytes + + # Minimum resources guaranteed to the container + requests: + cpu: "50m" # 0.05 CPU cores + memory: "64Mi" # 64 mebibytes + + # Kubernetes service configuration + service: + # Service type: ClusterIP (internal), NodePort, LoadBalancer + type: ClusterIP + + # Port the service listens on + port: 80 + + # Ingress configuration for external access + ingress: + # Enable ingress resource creation + enabled: true + + # Ingress class name (e.g., "nginx", "traefik") + className: nginx + + # Ingress annotations for SSL, redirects, etc. + annotations: + cert-manager.io/issuer: letsencrypt-prod + nginx.ingress.kubernetes.io/ssl-redirect: "true" + kubernetes.io/tls-acme: "true" + + # Hostname and path configuration + hosts: + - host: app.YOUR_DOMAIN_NAME + paths: + - path: / + pathType: Prefix + service: + name: videocall-ui + port: + number: 80 + + # TLS/SSL certificate configuration + tls: + - secretName: videocall-ui-tls + hosts: + - app.YOUR_DOMAIN_NAME + + # Horizontal Pod Autoscaler configuration + autoscaling: + # Enable automatic scaling based on metrics + enabled: false + + # Minimum number of replicas + minReplicas: 1 + + # Maximum number of replicas + maxReplicas: 10 + + # Target CPU utilization percentage to trigger scaling + targetCPUUtilizationPercentage: 80 + + # Target memory utilization percentage to trigger scaling + targetMemoryUtilizationPercentage: 80 + + # Pod annotations (e.g., for Prometheus scraping) + podAnnotations: {} + + # Pod security context (run as non-root, etc.) + podSecurityContext: {} + + # Container security context + securityContext: {} + + # Node selector for pod placement + # Example: {topology.kubernetes.io/region: "us-east"} + nodeSelector: {} + + # Tolerations for node taints + tolerations: [] + + # Pod affinity/anti-affinity rules + affinity: {} + +# ---------------------------------------------------------------------------- +# WebSocket Component Configuration +# ---------------------------------------------------------------------------- +# Real-time signaling server using WebSocket protocol +# Handles user connections, room management, and message routing + +websocket: + # Enable or disable the WebSocket component deployment + enabled: true + + # Override the component name (leave empty to use default: videocall-websocket) + nameOverride: "" + + # Override the full resource name + fullnameOverride: "" + + # Number of WebSocket server pod replicas + # Scale horizontally for high concurrency + replicaCount: 1 + + # Container image configuration + image: + # Docker image repository (same as webtransport, different command) + repository: securityunion/rustlemania-api + + # Image pull policy + pullPolicy: Always + + # Image tag + tag: latest + + # Environment variables for the WebSocket server + env: + - name: RUST_LOG + # Rust logging level: trace, debug, info, warn, error + value: warn + + - name: ACTIX_PORT + # Port the Actix web server binds to inside the container + value: "8080" + + - name: NATS_URL + # NATS server connection (uses global.natsUrl by default in deployment) + value: nats:4222 + + - name: DATABASE_ENABLED + # Enable PostgreSQL database for persistence + value: "false" + + - name: DATABASE_URL + # PostgreSQL connection string (uses secret if DATABASE_ENABLED=true) + value: "postgres://postgres:$(PG_PASSWORD)@postgres-postgresql:5432/actix-api-db?sslmode=disable" + + - name: TOKIO_WORKER_THREADS + # Number of Tokio async runtime worker threads + # Recommended: 1-2 per CPU core for I/O-bound workloads + value: "1" + + - name: REGION + # Deployment region (uses global.region in deployment) + value: "us-east" + + - name: HOSTNAME + # Automatically populated with pod name via downward API + valueFrom: + fieldRef: + fieldPath: metadata.name + + - name: SERVER_ID + # Unique server identifier (uses pod name) + valueFrom: + fieldRef: + fieldPath: metadata.name + + - name: SERVICE_TYPE + # Service type identifier for metrics and logging + value: websocket + + - name: SERVER_STATS_INTERVAL_SECS + # How often to publish server statistics to NATS (seconds) + value: "5" + + - name: OAUTH_AUTH_URL + # Google OAuth authorization endpoint + value: "https://accounts.google.com/o/oauth2/v2/auth" + + - name: OAUTH_TOKEN_URL + # Google OAuth token endpoint + value: "https://oauth2.googleapis.com/token" + + - name: OAUTH_REDIRECT_URL + # OAuth callback URL (must match Google Cloud Console configuration) + value: "https://api.YOUR_DOMAIN_NAME/login/callback" + + - name: UI_ENDPOINT + # Frontend URL for OAuth redirects after login + value: "https://app.YOUR_DOMAIN_NAME" + + - name: COOKIE_DOMAIN + # Domain for session cookies (must include leading dot for subdomains) + value: ".YOUR_DOMAIN_NAME" + + # Resource limits and requests + # WebSocket servers are I/O-bound, tune based on concurrent connections + resources: + limits: + cpu: "500m" # 0.5 CPU cores + memory: "384Mi" # 384 mebibytes + requests: + cpu: "200m" # 0.2 CPU cores + memory: "192Mi" # 192 mebibytes + + # Kubernetes service configuration + service: + # Service type (ClusterIP for ingress-based routing) + type: ClusterIP + + # Service port + port: 8080 + + # Ingress configuration + ingress: + # Enable ingress + enabled: true + + # Ingress class + className: nginx + + # Annotations + annotations: + cert-manager.io/issuer: letsencrypt-prod + nginx.ingress.kubernetes.io/ssl-redirect: "true" + kubernetes.io/tls-acme: "true" + + # Multiple hostnames (WebSocket + API endpoints) + hosts: + - host: websocket.YOUR_DOMAIN_NAME + paths: + - path: / + pathType: Prefix + service: + port: + number: 8080 + - host: api.YOUR_DOMAIN_NAME + paths: + - path: / + pathType: Prefix + service: + port: + number: 8080 + + # TLS configuration for both hostnames + tls: + - secretName: websocket-tls + hosts: + - websocket.YOUR_DOMAIN_NAME + - secretName: api-tls + hosts: + - api.YOUR_DOMAIN_NAME + + # Horizontal Pod Autoscaler + autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 10 + targetCPUUtilizationPercentage: 80 + targetMemoryUtilizationPercentage: 80 + + # Pod configuration + podAnnotations: {} + podSecurityContext: {} + securityContext: {} + nodeSelector: {} + tolerations: [] + affinity: {} + +# ---------------------------------------------------------------------------- +# WebTransport Component Configuration +# ---------------------------------------------------------------------------- +# High-performance media transport server using QUIC/WebTransport +# Handles audio/video streams with lower latency than WebSocket + +webtransport: + # Enable or disable the WebTransport component deployment + enabled: true + + # Override the component name + nameOverride: "" + + # Override the full resource name + fullnameOverride: "" + + # Number of WebTransport server replicas + # Scale based on concurrent media streams + replicaCount: 1 + + # Container image configuration + image: + # Same image as websocket, different entrypoint + repository: securityunion/rustlemania-api + + # Image pull policy + pullPolicy: Always + + # Image tag + tag: latest + + # Container command override (runs webtransport_server binary) + command: ['webtransport_server'] + + # Container command arguments + args: [] + + # TLS certificate secret name + # Must contain tls.crt and tls.key + tlsSecret: webtransport-tls + + # Domain name for TLS certificate + # Used by cert-manager to issue certificates + certificateDomain: "webtransport.YOUR_DOMAIN_NAME" + + # Certificate issuer configuration + certificate: + # Name of the cert-manager Issuer or ClusterIssuer + issuerName: "letsencrypt-prod" + + # Environment variables for WebTransport server + env: + - name: RUST_LOG + # Reduce logging for noisy QUIC libraries + value: warn,quinn=warn,web-transport-quinn=warn,async_nats=warn + + - name: NATS_URL + # NATS connection + value: nats:4222 + + - name: LISTEN_URL + # WebTransport listen address (UDP on port 443) + value: 0.0.0.0:443 + + - name: HEALTH_LISTEN_URL + # Health check HTTP server (TCP) + value: 0.0.0.0:444 + + - name: CERT_PATH + # Path to TLS certificate (mounted from secret) + value: /certs/tls.crt + + - name: KEY_PATH + # Path to TLS private key (mounted from secret) + value: /certs/tls.key + + - name: TOKIO_WORKER_THREADS + # Worker threads (WebTransport is compute-intensive due to crypto) + value: "1" + + - name: TOKIO_BLOCKING_THREADS + # Blocking thread pool for synchronous crypto operations + value: "2" + + - name: REGION + # Deployment region + value: "us-east" + + - name: HOSTNAME + # Pod name via downward API + valueFrom: + fieldRef: + fieldPath: metadata.name + + - name: SERVER_ID + # Unique server ID + valueFrom: + fieldRef: + fieldPath: metadata.name + + - name: SERVICE_TYPE + # Service type identifier + value: webtransport + + - name: SERVER_STATS_INTERVAL_SECS + # Statistics publishing interval + value: "5" + + # Resource configuration + # WebTransport is more resource-intensive due to QUIC crypto + resources: + limits: + cpu: "500m" # 0.5 CPU cores + memory: "768Mi" # 768 mebibytes + requests: + cpu: "500m" # 0.5 CPU cores (CPU-bound, request = limit) + memory: "384Mi" # 384 mebibytes + + # Kubernetes service configuration + service: + # NodePort or LoadBalancer required for UDP traffic + type: NodePort + + # WebTransport UDP port + port: 443 + + # Health check HTTP port (TCP) + healthPort: 444 + + # Load balancer annotations (cloud provider specific) + # Used when service.type is LoadBalancer + loadBalancerAnnotations: + # External DNS hostname registration + external-dns.alpha.kubernetes.io/hostname: "webtransport.YOUR_DOMAIN_NAME" + + # Example DigitalOcean annotations (adjust for your cloud provider) + # service.beta.kubernetes.io/do-loadbalancer-name: "webtransport-lb" + # service.beta.kubernetes.io/do-loadbalancer-protocol: "tcp" + # service.beta.kubernetes.io/do-loadbalancer-healthcheck-port: "444" + # service.beta.kubernetes.io/do-loadbalancer-healthcheck-path: "/healthz" + + # Horizontal Pod Autoscaler + autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 10 + targetCPUUtilizationPercentage: 80 + targetMemoryUtilizationPercentage: 80 + + # Pod configuration + podAnnotations: {} + podSecurityContext: {} + securityContext: {} + nodeSelector: {} + tolerations: [] + affinity: {} + +# ---------------------------------------------------------------------------- +# Website Component Configuration +# ---------------------------------------------------------------------------- +# Marketing and informational website (built with Leptos) +# Serves landing pages, documentation, and public content + +website: + # Enable or disable the website component deployment + enabled: true + + # Override the component name + nameOverride: "" + + # Override the full resource name + fullnameOverride: "" + + # Number of website pod replicas + replicaCount: 1 + + # Container image configuration + image: + # Website Docker image + repository: securityunion/video-call-rs-website + + # Image pull policy + pullPolicy: Always + + # Image tag + tag: latest + + # Environment variables for the website + env: + - name: RUST_LOG + # Logging level + value: info + + - name: LISTEN_URL + # HTTP listen address + value: "0.0.0.0:80" + + - name: LEPTOS_SITE_ADDR + # Leptos framework listen address + value: "0.0.0.0:80" + + # Resource configuration + # Static website requires minimal resources + resources: + limits: + cpu: "50m" # 0.05 CPU cores + memory: "128Mi" # 128 mebibytes + requests: + cpu: "20m" # 0.02 CPU cores + memory: "64Mi" # 64 mebibytes + + # Kubernetes service configuration + service: + # Service name (defaults to component name if not specified) + name: videocall-website + + # Service type + type: ClusterIP + + # Service port + port: 80 + + # Ingress configuration + ingress: + # Enable ingress + enabled: true + + # Ingress class + className: nginx + + # Annotations + annotations: + cert-manager.io/issuer: letsencrypt-prod + nginx.ingress.kubernetes.io/ssl-redirect: "true" + kubernetes.io/tls-acme: "true" + + # Multiple hostnames (apex and www) + hosts: + - host: www.videocall.rs + paths: + - path: / + pathType: Prefix + service: + name: videocall-website + port: + number: 80 + - host: videocall.rs + paths: + - path: / + pathType: Prefix + service: + name: videocall-website + port: + number: 80 + + # TLS configuration + tls: + - secretName: videocall-website-tls + hosts: + - videocall.rs + - www.videocall.rs + + # Horizontal Pod Autoscaler + autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 5 + targetCPUUtilizationPercentage: 80 + targetMemoryUtilizationPercentage: 80 + + # Pod configuration + podAnnotations: {} + podSecurityContext: {} + securityContext: {} + nodeSelector: {} + tolerations: [] + affinity: {} + +# ---------------------------------------------------------------------------- +# Additional Configuration +# ---------------------------------------------------------------------------- + +# Image pull secrets for private Docker registries +# Example: [{"name": "regcred"}] +imagePullSecrets: [] + +# Service account configuration (if needed) +serviceAccount: + # Specifies whether a service account should be created + create: false + + # Annotations to add to the service account + annotations: {} + + # The name of the service account to use + # If not set and create is true, a name is generated using fullname template + name: "" + +# ---------------------------------------------------------------------------- +# Metrics Client Component Configuration +# ---------------------------------------------------------------------------- +# Collects and aggregates client-side metrics from NATS +# Provides metrics endpoint for Prometheus scraping + +metricsClient: + # Enable or disable the metrics client component deployment + enabled: true + + # Override the component name + nameOverride: "" + + # Override the full resource name + fullnameOverride: "" + + # Number of metrics client pod replicas + # Typically one replica is sufficient for metrics collection + replicaCount: 1 + + # Container image configuration + image: + # Docker image repository (same as websocket/webtransport) + repository: securityunion/rustlemania-api + + # Image pull policy + pullPolicy: Always + + # Image tag + tag: latest + + # Container command override (runs metrics_server binary) + command: ["/usr/bin/metrics_server"] + + # Working directory inside container + workingDir: /app/actix-api + + # Environment variables for metrics client + env: + - name: METRICS_PORT + # Port for Prometheus metrics endpoint + value: "9091" + + - name: NATS_URL + # NATS connection for receiving metrics events + value: nats:4222 + + - name: REGION + # Deployment region + value: "us-east" + + - name: HOSTNAME + # Pod name via downward API + valueFrom: + fieldRef: + fieldPath: metadata.name + + - name: SERVER_ID + # Unique server ID + valueFrom: + fieldRef: + fieldPath: metadata.name + + - name: SERVICE_TYPE + # Service type identifier + value: metrics + + - name: RUST_LOG + # Logging level (reduced for metrics collection) + value: "warn,async_nats=warn" + + - name: TOKIO_WORKER_THREADS + # Single thread sufficient for I/O-bound metrics collection + value: "1" + + # Resource configuration (minimal for cost optimization) + resources: + limits: + cpu: "50m" # 0.05 CPU cores + memory: "128Mi" # 128 mebibytes + requests: + cpu: "25m" # 0.025 CPU cores + memory: "64Mi" # 64 mebibytes + + # Kubernetes service configuration + service: + # Service type + type: ClusterIP + + # Service port (Prometheus scrape port) + port: 9091 + + # Target port on pod + targetPort: 9091 + + # Liveness probe configuration + livenessProbe: + httpGet: + path: /health + port: 9091 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + + # Readiness probe configuration + readinessProbe: + httpGet: + path: /health + port: 9091 + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 3 + + # Pod annotations (e.g., for Prometheus scraping) + podAnnotations: + prometheus.io/scrape: "true" + prometheus.io/port: "9091" + prometheus.io/path: "/metrics" + + # Pod security context + podSecurityContext: + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + + # Container security context + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + + # Node selector for pod placement + nodeSelector: {} + + # Tolerations for node taints + tolerations: [] + + # Pod affinity/anti-affinity rules + affinity: {} + +# ---------------------------------------------------------------------------- +# Metrics Server Component Configuration +# ---------------------------------------------------------------------------- +# Tracks server connection statistics and publishes snapshots +# Separate from client metrics for different aggregation logic + +metricsServer: + # Enable or disable the metrics server component deployment + enabled: true + + # Override the component name + nameOverride: "" + + # Override the full resource name + fullnameOverride: "" + + # Number of metrics server pod replicas + # Single replica for stateless snapshot approach + replicaCount: 1 + + # Container image configuration + image: + # Docker image repository (same image, different binary) + repository: securityunion/rustlemania-api + + # Image pull policy + pullPolicy: Always + + # Image tag + tag: latest + + # Container command override (runs metrics_server_snapshot binary) + command: ["/usr/bin/metrics_server_snapshot"] + + # Working directory inside container + workingDir: /app/actix-api + + # Environment variables for metrics server + env: + - name: METRICS_PORT + # Port for Prometheus metrics endpoint (different from client) + value: "9092" + + - name: NATS_URL + # NATS connection for receiving server stats events + value: nats:4222 + + - name: REGION + # Deployment region + value: "us-east" + + - name: HOSTNAME + # Pod name via downward API + valueFrom: + fieldRef: + fieldPath: metadata.name + + - name: SERVER_ID + # Unique server ID + valueFrom: + fieldRef: + fieldPath: metadata.name + + - name: SERVICE_TYPE + # Service type identifier + value: server-stats + + - name: RUST_LOG + # Debug logging for server stats tracking + value: "debug,async_nats=info" + + - name: TOKIO_WORKER_THREADS + # Single thread for I/O-bound aggregation + value: "1" + + # Resource configuration + resources: + limits: + cpu: "100m" # 0.1 CPU cores (higher than client for aggregation) + memory: "128Mi" # 128 mebibytes + requests: + cpu: "50m" # 0.05 CPU cores + memory: "64Mi" # 64 mebibytes + + # Kubernetes service configuration + service: + # Service type + type: ClusterIP + + # Service port (Prometheus scrape port, different from client) + port: 9092 + + # Target port on pod + targetPort: 9092 + + # Liveness probe configuration + livenessProbe: + httpGet: + path: /health + port: 9092 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + + # Readiness probe configuration + readinessProbe: + httpGet: + path: /health + port: 9092 + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 3 + + # Pod annotations (for Prometheus scraping) + podAnnotations: + prometheus.io/scrape: "true" + prometheus.io/port: "9092" + prometheus.io/path: "/metrics" + + # Pod security context + podSecurityContext: + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + + # Container security context + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + + # Node selector for pod placement + nodeSelector: {} + + # Tolerations for node taints + tolerations: [] + + # Pod affinity/anti-affinity rules + affinity: {} + diff --git a/helm/website/.helmignore b/helm/website/.helmignore deleted file mode 100644 index e69de29bb..000000000 diff --git a/helm/website/Chart.yaml b/helm/website/Chart.yaml deleted file mode 100644 index 336106f18..000000000 --- a/helm/website/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v2 -name: website -description: A Helm chart for the website -type: application -version: 0.1.0 \ No newline at end of file diff --git a/helm/website/templates/_helpers.yaml b/helm/website/templates/_helpers.yaml deleted file mode 100644 index 904a3a4a7..000000000 --- a/helm/website/templates/_helpers.yaml +++ /dev/null @@ -1,62 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define "webtransport-rs.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "webtransport-rs.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "webtransport-rs.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "webtransport-rs.labels" -}} -helm.sh/chart: {{ include "webtransport-rs.chart" . }} -{{ include "webtransport-rs.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "webtransport-rs.selectorLabels" -}} -app.kubernetes.io/name: {{ include "webtransport-rs.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "webtransport-rs.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "webtransport-rs.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/helm/website/templates/deployment.yaml b/helm/website/templates/deployment.yaml deleted file mode 100644 index a6f10f59c..000000000 --- a/helm/website/templates/deployment.yaml +++ /dev/null @@ -1,69 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "webtransport-rs.fullname" . }} - labels: - {{- include "webtransport-rs.labels" . | nindent 4 }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - {{- include "webtransport-rs.selectorLabels" . | nindent 6 }} - template: - metadata: - {{- with .Values.podAnnotations }} - annotations: - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - {{- include "webtransport-rs.selectorLabels" . | nindent 8 }} - spec: - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} - containers: - - name: {{ include "webtransport-rs.fullname" . }} - securityContext: - {{- toYaml .Values.securityContext | nindent 12 }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" - command: {{ .Values.command }} - args: {{ .Values.args }} - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - {{- toYaml .Values.env | nindent 12 }} - ports: - - name: wt-udp - containerPort: {{ .Values.service.port }} - protocol: UDP - - name: http - containerPort: {{ .Values.service.appPort }} - protocol: TCP - - name: health - containerPort: {{ .Values.service.healthPort }} - protocol: TCP - resources: - {{- toYaml .Values.resources | nindent 12 }} - volumeMounts: - - name: tls - mountPath: "/certs" - readOnly: true - volumes: - - name: tls - secret: - secretName: {{ .Values.tlsSecret }} - optional: true - {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} - {{- end }} \ No newline at end of file diff --git a/helm/website/templates/ingress.yaml b/helm/website/templates/ingress.yaml deleted file mode 100644 index f4afcb6f6..000000000 --- a/helm/website/templates/ingress.yaml +++ /dev/null @@ -1,60 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $fullName := include "webtransport-rs.fullname" . -}} -{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} - {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} - {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} - {{- end }} -{{- end }} -{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1 -{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1beta1 -{{- else -}} -apiVersion: extensions/v1beta1 -{{- end }} -kind: Ingress -metadata: - name: {{ $fullName }} - labels: - {{- include "webtransport-rs.labels" . | nindent 4 }} - {{- with .Values.ingress.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} - ingressClassName: {{ .Values.ingress.className }} - {{- end }} - {{- if .Values.ingress.tls }} - tls: - {{- range .Values.ingress.tls }} - - hosts: - {{- range .hosts }} - - {{ . | quote }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} - {{- end }} - rules: - {{- range .Values.ingress.hosts }} - - host: {{ .host | quote }} - http: - paths: - {{- range .paths }} - - path: {{ .path }} - {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} - pathType: {{ .pathType }} - {{- end }} - backend: - {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} - service: - name: {{ .service.name }} - port: - number: {{ .service.port.number }} - {{- else }} - serviceName: {{ .service.name }} - servicePort: {{ .service.port.number }} - {{- end }} - {{- end }} - {{- end }} -{{- end }} \ No newline at end of file diff --git a/helm/website/templates/service.yaml b/helm/website/templates/service.yaml deleted file mode 100644 index d67385869..000000000 --- a/helm/website/templates/service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ include "webtransport-rs.fullname" . }} - labels: - {{- include "webtransport-rs.labels" . | nindent 4 }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.appPort }} - targetPort: http - protocol: TCP - name: http - selector: - {{- include "webtransport-rs.selectorLabels" . | nindent 4 }} \ No newline at end of file diff --git a/helm/website/values.yaml b/helm/website/values.yaml deleted file mode 100644 index ad5f451c7..000000000 --- a/helm/website/values.yaml +++ /dev/null @@ -1,72 +0,0 @@ -# Default values for webtransport-rs. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. -nameOverride: "" -fullnameOverride: "" -replicaCount: 1 -image: - repository: securityunion/video-call-rs-website - pullPolicy: Always - tag: 260113d -tlsSecret: videocall-rs-tls -env: - - name: RUST_LOG - value: info,quinn=warn - - name: LISTEN_URL - value: 0.0.0.0:443 - - name: LEPTOS_SITE_ADDR - value: 0.0.0.0:80 - - name: CERT_PATH - value: /certs/tls.crt - - name: KEY_PATH - value: /certs/tls.key -resources: {} -podAnnotations: {} -podSecurityContext: {} -securityContext: {} -service: - type: NodePort - appPort: 80 - port: 443 - healthPort: 8080 -nodeSelector: - node-role: worker -tolerations: [] -affinity: - podAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - - labelSelector: - matchExpressions: - - key: app - operator: Exists - topologyKey: "kubernetes.io/hostname" -ingress: - enabled: true - className: nginx - annotations: - cert-manager.io/issuer: letsencrypt-prod - nginx.ingress.kubernetes.io/ssl-redirect: "true" - kubernetes.io/tls-acme: "true" - external-dns.alpha.kubernetes.io/hostname: "videocall.rs" - hosts: - - host: www.videocall.rs - paths: - - path: / - pathType: Prefix - service: - name: videocall-rs - port: - number: 80 - - host: videocall.rs - paths: - - path: / - pathType: Prefix - service: - name: videocall-rs - port: - number: 80 - tls: - - secretName: webt-rs-tls - hosts: - - videocall.rs - - 'www.videocall.rs' \ No newline at end of file