K8S
流媒体服务和流媒体服务器的关键差异是什么?高效的运维能力是其中极其关键的差异之一,云计算+Docker+K8S让开源项目也能拥有这种能力,让每个人都能具备互联网流媒体服务能力,正如:旧时 王谢堂前燕,飞入寻常百姓家!
为何要用k8s部署SRS集群?
- Simple(简单有效): 这玩意儿真的非常简单、高效便捷、直击服务部署和维护的痛点。羽扇纶巾,谈笑间强撸灰飞湮灭,不信一起来看QuickStart.
- Declarative deployment(声明式部署):只需要根据业务量声明需要多少个SRS,自动配置和更新SLB,不用启动服务和看门狗,也不用机器故障时一顿操作猛如虎的迁移和更新。
- Expand easily(扩容很容易): K8S可以自动扩容底层基础设施,例如可通过ESS自动,而业务集群(如SRS Edge)通过修改Pod数量(或根据策略)实现扩容。
- Rolling Update(滚动式更新): K8S可以在不中断服务的前提下,实现服务的更新、回滚和灰度发布,这是提供稳定可靠高效服务的大杀器,总不能每次更新就被用户投诉吧?总不能每次都半夜三更提心吊胆吧?
本文介绍了,在不同的业务场景下,如何使用ACK(AlibabaCloud Container Service for Kubernetes)构建SRS集群。
- Deploy to Cloud Platforms: 直接部署GitHub项目到云平台K8s。
- Quick Start: 快速入门,在ACK中部署单SRS源站服务。
- SRS Shares Volume with Nginx: SRS能分发简单的HTTP,也能和Nginx配合工作提供更强大的HTTP能力,比如:SRS分发RTMP/HTTP-FLV等流协议,Nginx分发HLS。
- SRS Edge Cluster for High Concurrency Streaming: SRS边缘集群,支持高并发流媒体播放,减轻源站压力,分离源站关键业务,在SLB下自动扩容和更新。
- SRS Origin Cluster for a Large Number of Streams: SRS源站集群,支持大规模的推流,流的自动发现,以及流的灾备。
- SRS Cluster Update, Rollback, Gray Release with Zero Downtime: 如何在不中断服务的前提下,实现SRS集群的更新、回滚和灰度发布。
- SRS Cluster Rolling Update: 在平滑退出基础上的滚动更新,集群更新的基础机制。
- SRS Cluster Rolling Back: 在平滑退出基础上的发布回滚,发布遇到问题首先考虑回滚。
- SRS Cluster Canary Release: 金丝雀升级,可精确控制的流量控制和回滚。
- Useful Tips: 补充的实用话题和场景
- Create K8S Cluster in ACK: 在阿里云ACK创建你的K8S集群。
- Publish Demo Streams to SRS: 推送SRS的演示流,可直接推源站,也可以推边缘集群。
- Cleanup For DVR/HLS Temporary Files: 定期,比如每天凌晨1点,清理临时文件。
- Use One SLB and EIP for All Streaming Service: 使用一个SLB(EIP)对外提供RTMP、HTTP-FLV、HLS等服务。
- Build SRS Origin Cluster as Deployment: 除了以StatefulSet有状态应用方式部署Origin Cluster,我们还可以选择Deployment无状态应用方式。
- Managing Compute Resources for Containers: 资源的申请和限制,以及如何调度和限制如何生效。
- Auto Reload by Inotify: SRS侦听ConfigMap的变更,并支持自动reload。
Deploy to Cloud Platforms
SRS提供了一系列的模版项目,可以快速部署到云平台K8s:
Quick Start
假设你有一个k8s集群(如果没有可以从Create K8S Cluster in ACK轻松创建),执行下面的命令应该是成功的:
kubectl cluster-info
基于K8S,我们可以快速构建一个流媒体服务,尽管只有一个SRS源站。
在这个场景下,对比K8S和传统部署方式的差异:
对比项 | ECS | K8S | 说明 |
---|---|---|---|
资源 | 手动 | 自动 | 部署时,传统方式需要手动购买相关资源, K8S自动购买需要的资源比如ECS、SLB和EIP等 |
部署 | 安装包 | 镜像 | Docker镜像可回滚,开发和生产环境一致 ,可Cache, 高效率和高密度,高可移植性,资源隔离可预测程序性能 |
看门狗 | 手动 | 自动 | SRS异常退出由看门狗重新拉起,非K8S需要手动安装, K8S自动管理和拉起服务 |
迁移 | 手动 | 自动 | ECS更换时,非K8S需要手动申请,修改SLB,安装服务, K8S自动迁移服务,更新SLB配置监听和保活等 |
实现该场景的架构图如下所示:
Step 1: 创建一个无状态应用k8s deployment,运行SRS源站服务器:
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: srs-deploy
labels:
app: srs
spec:
replicas: 1
selector:
matchLabels:
app: srs
template:
metadata:
labels:
app: srs
spec:
containers:
- name: srs
image: ossrs/srs:3
imagePullPolicy: IfNotPresent
ports:
- containerPort: 1935
- containerPort: 1985
- containerPort: 8080
EOF
Step 2: 创建一个服务k8s service,自动创建SLB和EIP,对外提供流媒体服务:
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
name: srs-origin-service
spec:
type: LoadBalancer
selector:
app: srs
ports:
- name: srs-origin-service-1935-1935
port: 1935
protocol: TCP
targetPort: 1935
- name: srs-origin-service-1985-1985
port: 1985
protocol: TCP
targetPort: 1985
- name: srs-origin-service-8080-8080
port: 8080
protocol: TCP
targetPort: 8080
EOF
Note: 如果是自动创建SLB和EIP,那么HLS和RTMP/HTTP-FLV的IP是不一样的,你可以选择手动指定SLB,这两个服务可以用同一个SLB,参考Use One SLB and EIP for All Streaming Service。
Step 3: 大功告成。查询服务的EIP地址,你就可以推拉流了。
执行命令kubectl get svc/srs-origin-service
,可以查看服务的ExternalIP,也就是公网IP:
NAME TYPE CLUSTER-IP EXTERNAL-IP
srs-origin-service LoadBalancer 172.21.12.131 28.170.32.118
例子中的IP是28.170.32.118
,就可以推流到这个公网IP地址,也可以从这个地址播放:
- Publish RTMP to
rtmp://28.170.32.118/live/livestream
or Publish Demo Streams to SRS. - Play RTMP from rtmp://28.170.32.118/live/livestream
- Play HTTP-FLV from http://28.170.32.118:8080/live/livestream.flv
- Play HLS from http://28.170.32.118:8080/live/livestream.m3u8
SRS Shares Volume with Nginx
本章描述了基于K8S,SRS如何和Nginx配合提供更丰富的HTTP服务。
我们可以用SRS分发RTMP和HTTP-FLV等流媒体,并生成HLS切片到共享Volume,然后Nginx读取Volume并分发HLS。当然SRS也可以直接分发HLS切片,之所以用Nginx,这个场景可以用在:
- 已经有Nginx和Web服务,SRS无法使用80端口,可以选择共享Volume方式给Nginx,当然也可以配置Nginx代理特定的URL。
- SRS不支持HTTPS。Nginx可以支持HTTPS,配置Nginx支持证书后,可以将SRS生成的HLS,通过HTTPS分发。
- SRS不支持HLS的鉴权。Nginx或其他Web框架,可以在用户访问HLS文件时,实现鉴权的逻辑。
- SRS只支持HTTP/1.1部分协议。Nginx有更完善的HTTP功能,比如HTTP/2,完整的HTTP协议支持。
在这个场景下,对比K8S和传统部署方式的差异:
对比项 | ECS | K8S | 说明 |
---|---|---|---|
资源 | 手动 | 自动 | 部署时,传统方式需要手动购买相关资源, K8S自动购买需要的资源比如ECS、SLB和EIP等 |
部署 | 安装包 | 镜像 | Docker镜像可回滚,开发和生产环境一致,可Cache, 高效率和高密度,高可移植性,资源隔离可预测程序性能 |
看门狗 | 手动 | 自动 | SRS异常退出由看门狗重新拉起,非K8S需要手动安装, K8S自动管理和拉起服务 |
迁移 | 手动 | 自动 | ECS更换时,非K8S需要手动申请,修改SLB,安装服务, K8S自动迁移服务,更新SLB配置监听和保活等 |
实现该场景的架构图如下所示:
Step 1: 创建一个无状态应用k8s deployment,运行SRS和Nginx,HLS写入共享Volume:
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: srs-deploy
labels:
app: srs
spec:
replicas: 1
selector:
matchLabels:
app: srs
template:
metadata:
labels:
app: srs
spec:
volumes:
- name: cache-volume
emptyDir: {}
containers:
- name: srs
image: ossrs/srs:3
imagePullPolicy: IfNotPresent
ports:
- containerPort: 1935
- containerPort: 1985
- containerPort: 8080
volumeMounts:
- name: cache-volume
mountPath: /usr/local/srs/objs/nginx/html
readOnly: false
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
volumeMounts:
- name: cache-volume
mountPath: /usr/share/nginx/html
readOnly: true
- name: srs-cp-files
image: ossrs/srs:3
imagePullPolicy: IfNotPresent
volumeMounts:
- name: cache-volume
mountPath: /tmp/html
readOnly: false
command: ["/bin/sh"]
args:
- "-c"
- >
if [[ ! -f /tmp/html/index.html ]]; then
cp -R ./objs/nginx/html/* /tmp/html
fi &&
sleep infinity
EOF
Note: Nginx的默认目录是
/usr/share/nginx/html
,若不是请改成你自己的目录。
Note: SRS和Nginx挂载了emptyDir Volume共享HLS文件,默认是空目录,会随着Pod的销毁而清空。
Note: 由于共享目录是空目录,我们启动了一个
srs-cp-files
的container,拷贝SRS默认的文件,参考#1603.
Step 2: 创建一个服务k8s service,使用SLB对外提供流媒体服务:
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
name: srs-origin-service
spec:
type: LoadBalancer
selector:
app: srs
ports:
- name: srs-origin-service-80-80
port: 80
protocol: TCP
targetPort: 80
- name: srs-origin-service-1935-1935
port: 1935
protocol: TCP
targetPort: 1935
- name: srs-origin-service-1985-1985
port: 1985
protocol: TCP
targetPort: 1985
- name: srs-origin-service-8080-8080
port: 8080
protocol: TCP
targetPort: 8080
EOF
Note: 我们通过Service暴露端口,对外提供服务,其中RTMP(1935)/FLV(8080)/API(1985)由SRS提供服务,HLS(80)由Nginx提供服务。
Note: 这里我们选择ACK自动创建SLB和EIP,也可以手动指定SLB,参考Use One SLB and EIP for All Streaming Service。
Step 3: 大功告成。你可以推拉流了,其中HLS流可以从SRS(8080)播放,也可以从Nginx(80)播放:
- Publish RTMP to
rtmp://28.170.32.118/live/livestream
or Publish Demo Streams to SRS. - Play RTMP from rtmp://28.170.32.118/live/livestream
- Play HTTP-FLV from http://28.170.32.118:8080/live/livestream.flv
- Play HLS from http://28.170.32.118:8080/live/livestream.m3u8
- Play HLS from http://28.170.32.118/live/livestream.m3u8
Note: 请将上面的EIP换成你自己的,可用命令
kubectl get svc/srs-origin-service
查看你的EIP。
SRS Edge Cluster for High Concurrency Streaming
本章描述了基于K8S,如何构建Edge Cluster实现高并发流媒体播放。
Edge Cluster实现了合并回源,对于某一路流,不管有多少客户端播放,Edge Server都只会从Origin Server取一路流,这样可以通过扩展Edge Cluster来增加支持的播放能力,也就是CDN网络具备的重要能力:高并发。
Note: Edge Cluster根据客户端播放的协议不同,可以分为RTMP Edge Cluster或HTTP-FLV Edge Cluster,详细请参考相关Wiki。
对于自建源站,没有那么多播放量,为何不建议使用SRS单源站直接提供服务,而要用Edge Cluster呢?主要场景分析如下:
- 防止Origin过载,即使推流非常少而且播放的流也不多,比如自建源站后使用CDN回源,在多家CDN回源时,也可能一个CDN一条流会有多个回源连接。使用Edge能保护Origin不因为回源造成Origin问题,最多就是某些Edge被回源打挂。
- 可以使用多个Edge Cluster(只需要再加srs-edge-service就可以),对外用不同的SLB暴露,可以针对每个SLB限流,防止CDN之间互相干扰。这样能保证某些CDN是可用的,而不是Origin挂了后所有CDN都不可用。
- 分离Origin关键业务,将下行流媒体分发业务交给Edge Cluster,Origin可以做切片、DVR、鉴权等关键业务,避免业务之间互相干扰。
在这个场景下,对比K8S和传统部署方式的差异:
对比项 | ECS | K8S | 说明 |
---|---|---|---|
资源 | 手动 | 自动 | 部署时,传统方式需要手动购买相关资源, K8S自动购买需要的资源比如ECS、SLB和EIP等 |
部署 | 安装包 | 镜像 | Docker镜像可回滚,开发和生产环境一致,可Cache, 高效率和高密度,高可移植性,资源隔离可预测程序性能 |
看门狗 | 手动 | 自动 | SRS异常退出由看门狗重新拉起,非K8S需要手动安装, K8S自动管理和拉起服务 |
迁移 | 手动 | 自动 | ECS更换时,非K8S需要手动申请,修改SLB,安装服务, K8S自动迁移服务,更新SLB配置监听和保活等 |
配置 | 文件 | Volume | ECS需要手动管理配置;K8S配置在ConfigMap, 通过Volume挂载为配置文件,扩容时不用变更 |