跳转到内容

Helm 部署

Helm chart 位于:

helm/synctv

默认会创建:

  • SyncTV Deployment。
  • HTTP/API Service。
  • gRPC Service。
  • PostgreSQL。
  • Redis。
  • ConfigMap。
  • Secret。
  • Ingress。
  • ServiceAccount、Role、RoleBinding。
  • 可选 metrics、ServiceMonitor、VMServiceScrape、PrometheusRule、NetworkPolicy、HPA、PDB。

通过 OCI registry 安装:

Terminal window
helm install synctv oci://ghcr.io/synctv-org/synctv/charts/synctv \
--version 0.1.0 \
--namespace synctv \
--create-namespace

默认父级 OCI repository 是 ghcr.io/synctv-org/synctv/charts。Helm 会追加 chart 名,因此安装引用最后仍是 /synctv。维护者可以通过 HELM_OCI_REPOSITORY 覆盖发布目标。

通过传统 Helm repository 安装:

Terminal window
helm repo add synctv https://synctv-org.github.io/synctv
helm repo update
helm install synctv synctv/synctv \
--version 0.1.0 \
--namespace synctv \
--create-namespace

发布版 Chart 由 release workflow 自动生成。源码仓库只维护 helm/synctv 下的 chart 源码;打包后的 .tgz 和 Helm repository 的 index.yaml 在发布时生成。公开安装要求 GHCR chart package 设为 public,并且 GitHub Pages 使用 helm-charts 分支提供内容。

Terminal window
helm install synctv ./helm/synctv \
--namespace synctv \
--create-namespace

生产环境建议使用自己的 values 文件:

Terminal window
helm install synctv ./helm/synctv \
--namespace synctv \
--create-namespace \
--values my-values.yaml

SyncTV 进程内部 HTTP REST 和 gRPC 使用同一个容器端口,但 Helm chart 会创建两个独立 Service:

Service用途端口名
synctvHTTP/REST,同时包含 RTMP、STUN、metrics 等端口api
synctv-grpcgRPC 专用入口grpc

为什么拆开:

  • Ingress controller 通常需要对 gRPC backend 使用独立协议配置。
  • HTTP 和 gRPC 虽然同端口,但 Kubernetes Service/Ingress 层需要不同语义。
  • metrics selector 也能只匹配 HTTP/API Service,避免误抓 gRPC Service。

默认 HTTP Ingress 使用:

ingress:
enabled: true
hosts:
- host: synctv.example.com

gRPC Ingress 独立配置:

ingress:
grpc:
enabled: true
hosts:
- host: grpc.synctv.example.com
paths:
- path: /
pathType: Prefix
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "GRPC"

注意:gRPC annotations 是独立的 ingress.grpc.annotations,不会复用 HTTP Ingress annotations。

Chart 默认会生成并保存 Secret。生产环境建议显式配置:

secrets:
jwt:
secret: "replace-with-strong-secret"
cluster:
grpcSecret: "replace-with-cluster-secret"
security:
credentialEncryptionKey: "64-hex-character-key"
opaqueServerSetupSecret: "stable-random-secret"
bootstrap:
rootPassword: "StrongRootPass12345"

如果使用外部 Secret:

existingSecret: "my-external-synctv-secret"

需要提供这些 key:

  • SYNCTV_DATABASE_PASSWORD,除非 PostgreSQL 使用 KubeBlocks 模式。
  • SYNCTV_REDIS_PASSWORD,除非 Redis 使用 KubeBlocks 模式。
  • SYNCTV_JWT_SECRET
  • SYNCTV_SERVER_CLUSTER_SECRET
  • SYNCTV_SECURITY_CREDENTIAL_ENCRYPTION_KEY
  • SYNCTV_SECURITY_OPAQUE_SERVER_SETUP_SECRET
  • SYNCTV_BOOTSTRAP_ROOT_PASSWORD,如果 config.bootstrap.createRootUser=true
  • SYNCTV_MANAGEMENT_AUTH_TOKEN,如果 management 使用 TCP。
  • SYNCTV_EMAIL_SMTP_USERNAMESYNCTV_EMAIL_SMTP_PASSWORD,如果配置了 config.email.smtpHost 且 SMTP 需要认证。
  • SYNCTV_METRICS_AUTH_BEARER_TOKEN,如果 metrics.enabled=truemetrics.auth.mode=bearer_token
  • SYNCTV_METRICS_AUTH_BASIC_USERNAMESYNCTV_METRICS_AUTH_BASIC_PASSWORD,如果 metrics.enabled=truemetrics.auth.mode=basic
  • SYNCTV_LIVESTREAM_HLS_OSS_ACCESS_KEY_IDSYNCTV_LIVESTREAM_HLS_OSS_SECRET_ACCESS_KEY,如果 config.livestream.hlsStorageBackend=oss

默认模式。Chart 自己创建 StatefulSet/Service。

postgresql:
mode: standard
redis:
mode: standard

如果集群安装了 KubeBlocks,可以让 chart 创建 KubeBlocks Cluster。

postgresql:
mode: kubeblocks
redis:
mode: kubeblocks

KubeBlocks 模式下,数据库账号密码来自 KubeBlocks 生成的 Secret。

注意:KubeBlocks Redis Sentinel 组件属于数据库 Operator 的内部拓扑,不等同于把 SyncTV 配置成 redis.deployment_mode=sentinel。Helm 默认仍向 SyncTV 注入稳定 Redis Service endpoint;SyncTV 集群模式不能与 SyncTV Sentinel mode 同时使用。

Helm 默认:

config:
dataDir: "/data"

Deployment 会挂载 /data。默认是 emptyDir,适合运行时临时文件。如果需要持久化运行时文件,可以设置 persistence.data.existingClaim

Helm 默认不启用集群模式,也不把 HLS 声明为共享存储。多副本 HLS 有两种模型:本地 backend 通过 publisher-node HLS proxy 工作;共享文件系统或 OSS 让任意副本直接读取分片,更适合生产高流量。

本地 backend 示例:

config:
cluster:
enabled: true
livestream:
hlsStorageBackend: "memory"

这种配置不需要 HLS PVC,但非 publisher Pod 的 playlist/segment 请求会通过 gRPC 回源到 publisher Pod。

共享文件系统示例:

config:
cluster:
enabled: true
livestream:
hlsStorageBackend: "file"
hlsSharedStorage: true
hlsStoragePath: "/var/lib/synctv/hls"
persistence:
hls:
existingClaim: "synctv-hls-rwx"

Helm 会提前拒绝以下组合:

  • hlsStorageBackend 不是 memoryfileoss
  • hlsStorageBackend=filehlsStoragePath 为空。
  • Kubernetes 中 hlsStorageBackend=filehlsStoragePath 不是绝对路径。
  • hlsSharedStorage=true 但没有配置 persistence.hls.existingClaim,避免把 emptyDir 误当成共享存储。

OSS 示例:

config:
cluster:
enabled: true
livestream:
hlsStorageBackend: "oss"
hlsOss:
endpoint: "https://s3.example.com"
bucket: "synctv-hls"
basePath: "synctv/hls/"
secrets:
livestream:
hlsOss:
accessKeyId: "..."
secretAccessKey: "..."

只要开启 config.cluster.enabled=true,应用启动校验还要求 Redis 可用、SYNCTV_SERVER_CLUSTER_SECRET 稳定且所有副本一致,并且每个 Pod 具备可用于节点互联的 SYNCTV_SERVER_ADVERTISE_HOST。Helm 默认会注入 Redis 连接、自动生成 cluster secret,并用 Pod IP 作为 advertise host;如果你裁剪 values 或使用外部 Secret,需要保留这些条件。直播 HLS 选择本地 backend 时,还要确保 Pod 间 gRPC 路径可达,因为远端分片读取依赖 publisher-node proxy。

如果 config.cluster.discoveryMode=k8s_dns,Chart 会自动渲染 headless Service,并注入 HEADLESS_SERVICE_NAMEPOD_NAMESPACE。如果 config.cluster.leaderElectionMode=k8s_lease,Chart 会注入 POD_NAMEPOD_NAMESPACE。这两种模式都要求镜像构建包含 k8s feature。

开启 metrics:

metrics:
enabled: true
auth:
mode: bearer_token

ServiceMonitor:

metrics:
serviceMonitor:
enabled: true

VMServiceScrape:

metrics:
vmServiceScrape:
enabled: true

metrics Service selector 会只匹配 app.kubernetes.io/component: api 的 Service,避免抓到 gRPC Service。

如果使用 metrics.auth.mode=kubernetes,镜像内的 SyncTV 二进制必须启用 k8s feature。Helm 只负责 RBAC、ServiceAccount token 和抓取资源,不能改变镜像编译特性。

临时检查:

Terminal window
helm lint ./helm/synctv
helm template synctv ./helm/synctv
helm template synctv ./helm/synctv --set ingress.grpc.enabled=true

如果模板能渲染,不代表业务配置一定安全。还要在实际容器中运行配置校验或检查启动日志。