Helm 部署
什么时候使用 Helm?
Section titled “什么时候使用 Helm?”Helm 是 Kubernetes 多副本和平台化运维路径,不是第一次接触 SyncTV 的默认入口。开始前应明确 Secret、PVC、Ingress、ServiceMonitor/VMServiceScrape、滚动更新和数据库/Redis 运维边界。
如果你只是想在一台机器上长期运行 SyncTV,先使用 单机生产 Compose。如果还没决定路径,先读 部署路径选择。
生产前必须先决定
Section titled “生产前必须先决定”| 决策 | 默认选择 | 不要忽略的风险 |
|---|---|---|
| PostgreSQL | 托管数据库、平台数据库 Operator,或 chart standard 模式 | 必须持久化并可恢复 |
| Redis | 生产配置,多副本必需 | 多副本不能使用不同 Redis 或冲突 key prefix |
| Secret | 使用外部 Secret 或受控 Secret 管理 | OPAQUE 和 credential key 不能随发布随机变化 |
| HTTP/gRPC Ingress | HTTP 和 gRPC 分开 | gRPC Ingress 需要独立 backend protocol |
| HLS 存储 | 小规模用 publisher-node proxy,高流量用 RWX/OSS | 不要把 emptyDir 当共享 HLS 存储 |
| metrics | 私网抓取并启用鉴权 | 不要把 /metrics 直接暴露公网 |
最小生产 values 骨架:
config: bootstrap: createRootUser: true cluster: enabled: false
existingSecret: "synctv-production-secret"
ingress: enabled: true hosts: - host: synctv.example.comChart 结构
Section titled “Chart 结构”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。
安装发布版 Chart
Section titled “安装发布版 Chart”通过 OCI registry 安装:
helm install synctv oci://ghcr.io/zijiren233/synctv/charts/synctv \--version 0.1.0 \--namespace synctv --create-namespace默认父级 OCI repository 是 ghcr.io/zijiren233/synctv/charts。Helm 会追加 chart 名,因此安装引用最后仍是 /synctv。维护者可以通过 HELM_OCI_REPOSITORY 覆盖发布目标。
通过传统 Helm repository 安装:
helm repo add synctv https://zijiren233.github.io/synctvhelm repo updatehelm 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 分支提供内容。
helm install synctv ./helm/synctv \ --namespace synctv \ --create-namespace生产环境使用自己的 values 文件:
helm install synctv ./helm/synctv \ --namespace synctv \ --create-namespace \ --values my-values.yamlHTTP 和 gRPC Service
Section titled “HTTP 和 gRPC Service”SyncTV 进程内部 HTTP REST 和 gRPC 使用同一个容器端口,但 Helm chart 会创建两个独立 Service:
| Service | 用途 | 端口名 |
|---|---|---|
synctv | HTTP/REST API 入口 | api |
synctv-rtmp | rtmpService.enabled=true 时的 RTMP 推流入口 | rtmp |
synctv-stun | stunService.enabled=true 且 config.webrtc.enableBuiltinStun=true 时的内置 UDP STUN | stun |
synctv-metrics | metrics.enabled=true 时的专用指标入口 | metrics |
synctv-grpc | gRPC 专用入口 | grpc |
为什么拆开:
- Ingress controller 通常需要对 gRPC backend 使用独立协议配置。
- HTTP 和 gRPC 虽然同端口,但 Kubernetes Service/Ingress 层需要不同语义。
- metrics selector 可以只匹配专用 metrics Service,避免误抓公网 API/RTMP 或 gRPC Service。
config.server.grpcCompressionEnabled 默认是 true,会让 gRPC 客户端和服务端协商 gzip 压缩。跨节点调用、Ingress 转发、批量响应较多时通常保持开启;如果你的 gRPC 调用都在本地低延迟网络且 CPU 比带宽更紧张,可以显式关闭。
config.fileStorage.backends.<name>.database.compression 控制数据库文件存储后端写入 PostgreSQL file_blob_parts 永久分段的压缩算法,默认 zstd。compressionMinSizeBytes 默认 4096,compressionMinSavingsPercent 默认 10,压缩收益低于阈值时写入原始 bytes。Database 文件存储使用永久分段并从分段服务 HTTP Range;S3 文件存储使用原生 multipart 直传支持 GB 级断点续传。
S3 文件存储凭证建议挂载 Kubernetes Secret,并在 Helm values 中设置 camelCase 的 accessKeyIdFile / secretAccessKeyFile。生成的 SyncTV YAML 会使用 snake_case 的 access_key_id_file / secret_access_key_file 路径,并在启动时读取 Secret 文件。
config: fileStorage: defaultBackend: s3_public backends: s3_public: type: s3 s3: endpoint: https://s3.example.com bucket: synctv-files region: auto basePath: files/ publicBaseUrl: https://cdn.example.com/files accessKeyIdFile: /run/secrets/file-storage-s3/access_key_id secretAccessKeyFile: /run/secrets/file-storage-s3/secret_access_key
extraVolumes: - name: file-storage-s3 secret: secretName: synctv-file-storage-s3extraVolumeMounts: - name: file-storage-s3 mountPath: /run/secrets/file-storage-s3 readOnly: trueIngress
Section titled “Ingress”默认 HTTP Ingress 使用:
ingress: enabled: true hosts: - host: synctv.example.comgRPC 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。
Secret
Section titled “Secret”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 standard 模式、external 模式和 KubeBlocks 应用账号。SYNCTV_REDIS_PASSWORD,Redis 使用 standard 模式时必需;external 模式只在外部 Redis 需要密码时提供;KubeBlocks 模式不需要提供。SYNCTV_JWT_SECRETSYNCTV_CLUSTER_SECRETSYNCTV_SECURITY_CREDENTIAL_ENCRYPTION_KEYSYNCTV_SECURITY_OPAQUE_SERVER_SETUP_SECRETSYNCTV_BOOTSTRAP_ROOT_PASSWORD,如果config.bootstrap.createRootUser=true。SYNCTV_MANAGEMENT_AUTH_TOKEN,如果 management 使用 TCP。SYNCTV_EMAIL_SMTP_USERNAME和SYNCTV_EMAIL_SMTP_PASSWORD,如果配置了config.email.smtpHost且 SMTP 需要认证。SYNCTV_METRICS_AUTH_BEARER_TOKEN,如果metrics.enabled=true且metrics.auth.mode=bearer_token。SYNCTV_METRICS_AUTH_BASIC_USERNAME和SYNCTV_METRICS_AUTH_BASIC_PASSWORD,如果metrics.enabled=true且metrics.auth.mode=basic。SYNCTV_LIVESTREAM_HLS_OSS_ACCESS_KEY_ID和SYNCTV_LIVESTREAM_HLS_OSS_SECRET_ACCESS_KEY,如果config.livestream.hlsStorageBackend=oss。
服务端出站请求使用 config.security.ssrf 中的全局 SSRF 策略。默认关闭 SSRF 防护,方便自托管环境使用内网媒体源。公网部署建议启用 SSRF 防护,并为可信内网媒体端点配置显式 allowlist:
config: security: ssrf: enabled: true allowPrivateNetworkTargets: false allowedHosts: - nas.example.internal allowedIpRanges: - 10.0.8.0/24只有在所有用户和 provider endpoint 都可信的私有部署里,才应设置 allowPrivateNetworkTargets=true。
PostgreSQL 和 Redis 模式
Section titled “PostgreSQL 和 Redis 模式”standard
Section titled “standard”默认模式。Chart 自己创建 StatefulSet/Service。
postgresql: mode: standard
redis: mode: standardkubeblocks
Section titled “kubeblocks”如果集群安装了 KubeBlocks,可以让 chart 创建 KubeBlocks Cluster。
postgresql: mode: kubeblocks
redis: mode: kubeblocksKubeBlocks 模式下,数据库账号密码来自 KubeBlocks 生成的 Secret。
PostgreSQL 场景中,SyncTV 只在 init container 启动阶段使用 KubeBlocks 的 postgres 系统账号,用它创建或修正 postgresql.kubeblocks.appUsername 和 postgresql.kubeblocks.database;主容器随后使用这个应用账号连接数据库。应用账号密码保存在 Chart Secret 的 SYNCTV_DATABASE_PASSWORD 中;如果配置了 existingSecret,需要自行提供这个 key。
注意:KubeBlocks Redis Sentinel 组件属于数据库 Operator 的内部拓扑,不等同于把 SyncTV 配置成 redis.deployment_mode=sentinel。Helm 默认仍向 SyncTV 注入稳定 Redis Service endpoint;SyncTV 集群模式不能与 SyncTV Sentinel mode 同时使用。
external
Section titled “external”如果 PostgreSQL 或 Redis 由云厂商、平台团队或其他 Operator 管理,使用 external 模式。Chart 不会创建对应的 StatefulSet、Service 或 KubeBlocks Cluster,只会把连接参数注入 SyncTV。
postgresql: mode: external external: host: "postgres.example.internal" port: 5432 username: "synctv" database: "synctv"
redis: mode: external external: host: "redis.example.internal" port: 6379 username: "" database: 0external PostgreSQL 必须通过 existingSecret 的 SYNCTV_DATABASE_PASSWORD 或 secrets.database.password 提供密码。external Redis 的 SYNCTV_REDIS_PASSWORD 是可选的:只有外部 Redis 启用了密码认证时才需要提供。
如果同时启用 networkPolicy.enabled=true,external PostgreSQL/Redis 以及对外 HTTP/HTTPS egress 会使用 ipBlock CIDR,而不是匹配 Chart 内部 Pod label;这些规则默认 fail-closed:external PostgreSQL 或 Redis 模式要求设置 networkPolicy.externalPostgresqlCIDRs / networkPolicy.externalRedisCIDRs,或者显式设置 networkPolicy.allowAnyExternalDatabaseEgress=true;对外 OAuth、媒体源 HTTP、HLS OSS 和 S3-compatible 对象存储 endpoint 要求设置 networkPolicy.externalHttpCIDRs,或者显式设置 networkPolicy.allowAnyExternalHttpEgress=true。
应用 Service、PDB 和应用 NetworkPolicy 只选择带有 app.kubernetes.io/component=app 的 Pod。Chart 管理的 PostgreSQL 和 Redis 使用各自的 component label;启用 NetworkPolicy ingress 隔离时,Chart 会为它们渲染依赖专用 ingress policy,只允许 SyncTV 应用 Pod 访问对应端口。因此启用 NetworkPolicy 不会把 API 流量路由到依赖 Pod,也不会把依赖和 SyncTV 自身隔离开。
Redis 连接管理相关的 Helm 值:
config: redis: connectTimeoutSeconds: 5 responseTimeoutSeconds: 5 pipelineBufferSize: 512responseTimeoutSeconds 限制 Redis 命令等待响应的时间;pipelineBufferSize 控制 connection manager 内部 pipeline buffer。高并发短命令场景可以适度调大,普通部署保持默认即可。
config.dataDir
Section titled “config.dataDir”Helm 默认:
config: dataDir: "/data"Deployment 会挂载 /data。默认是 emptyDir,适合运行时临时文件。如果需要持久化运行时文件,可以设置 persistence.data.existingClaim。
HLS 多副本注意事项
Section titled “HLS 多副本注意事项”Helm 默认不启用集群模式。多副本 HLS 可以先使用 publisher-node HLS proxy;生产高流量场景使用 shared_file 或 OSS。shared_file 的 TS 分片由当前节点从共享路径读取。
本地 backend 示例:
config: cluster: enabled: true livestream: hlsStorageBackend: "memory"这种配置不需要 HLS PVC,但非 publisher Pod 的 playlist/segment 请求会通过 gRPC 回源到 publisher Pod。
共享文件系统示例:
config: cluster: enabled: true livestream: hlsStorageBackend: "shared_file" hlsStoragePath: "/var/lib/synctv/hls"
persistence: hls: existingClaim: "synctv-hls-rwx"Helm 会提前拒绝以下组合:
hlsStorageBackend不是memory、file、shared_file或oss。hlsStorageBackend=file/shared_file但hlsStoragePath为空。- Kubernetes 中
hlsStorageBackend=file/shared_file但hlsStoragePath不是绝对路径。 hlsStorageBackend=shared_file但没有配置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_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_NAME 和 POD_NAMESPACE。如果 config.cluster.leaderElectionMode=k8s_lease,Chart 会注入 POD_NAME 和 POD_NAMESPACE。这两种模式都要求镜像构建包含 k8s feature。
Metrics
Section titled “Metrics”开启 metrics:
metrics: enabled: true auth: mode: bearer_tokenServiceMonitor:
metrics: serviceMonitor: enabled: trueVMServiceScrape:
metrics: vmServiceScrape: enabled: truemetrics Service selector 会匹配独立的 metrics Service,避免抓到公网 API/RTMP Service 或 gRPC Service。
如果使用 metrics.auth.mode=kubernetes,镜像内的 SyncTV 二进制必须启用 k8s feature。Helm 只负责 RBAC、ServiceAccount token 和抓取资源,不能改变镜像编译特性。
临时检查:
helm lint ./helm/synctvhelm template synctv ./helm/synctvhelm template synctv ./helm/synctv --set ingress.grpc.enabled=true如果模板能渲染,不代表业务配置一定安全。还要在实际容器中运行配置校验或检查启动日志。