当SRS遇到K8s:如何构建海量推流源站?
Photo by?Oscar Ivan Esquivel Arteaga?on?Unsplash
本文來自流媒體直播集群SRS的官方wiki(https://github.com/ossrs/srs/wiki/v4_CN_K8s),由SRS的創(chuàng)始作者楊成立授權(quán)發(fā)布。
文 / 楊成立
相關(guān)文章:當(dāng)SRS遇到K8s:快速構(gòu)建高并發(fā)直播集群
本章描述了基于K8s,如何構(gòu)建Origin Cluster支持超多推流場(chǎng)景。
Origin Cluster通過配置其他源站的信息,在本源站沒有流時(shí)查詢到流的位置,通過RTMP302定向到指定源站,具體原理可以參考#464。主要應(yīng)用場(chǎng)景如下:
源站災(zāi)備:即使流比較少,也可以用兩個(gè)源站,這樣可以將流分散到不同的源站,避免源站出現(xiàn)問題時(shí)影響所有的流。
海量推流:單源站可以支持1000到3000路流,高碼率的流支持的路數(shù)更少,有DVR和HLS時(shí)支持的路更少,源站集群有多個(gè)源站同時(shí)接收推流,可以支持10k~100k推流,參考規(guī)格。
復(fù)雜源站業(yè)務(wù):源站除了支持推流和拉流,還有重要的功能是DVR、轉(zhuǎn)碼、轉(zhuǎn)HLS,DVR和HLS涉及磁盤,轉(zhuǎn)碼涉及CPU,都是容易發(fā)生瓶頸的資源依賴,源站集群擴(kuò)展能力更強(qiáng)。
在這個(gè)場(chǎng)景下,對(duì)比K8s和傳統(tǒng)使用方式的差異:
對(duì)比 | ECS | K8s | 說明 |
申請(qǐng)ECS | 手動(dòng) | 自動(dòng) | 部署時(shí),ECS需要手動(dòng)申請(qǐng),K8s自動(dòng)申請(qǐng) |
安裝包 | 腳本 | 鏡像 | Docker方式更優(yōu),版本管理,可Cache |
看門狗 | 手動(dòng) | 自動(dòng) | SRS異常退出由看門狗重新拉起,非K8s需要手動(dòng)安裝, |
更換ECS | 手動(dòng) | 自動(dòng) | ECS更換時(shí),非K8s需要手動(dòng)申請(qǐng),修改SLB,安裝服務(wù),K8s自動(dòng)遷移服務(wù),更新SLB配置監(jiān)聽和?;畹?/p> |
配置 | 文件 | Volume | ECS需要手動(dòng)管理配置;K8s配置在ConfigMap,通過Volume掛載為配置文件,擴(kuò)容時(shí)源站手動(dòng)更新自動(dòng)推送,邊緣擴(kuò)容自動(dòng)更新 |
擴(kuò)容 | 手動(dòng) | 自動(dòng) | 需要新開進(jìn)程時(shí),ECS需要申請(qǐng)部署和配置,K8s只需要修改Replicas數(shù)目即可(也可自動(dòng)擴(kuò)容) |
發(fā)現(xiàn) | 手動(dòng) | 自動(dòng) | Origin變更IP時(shí),ECS需要手動(dòng)修改配置,K8s在遷移源站Pod時(shí)會(huì)保持,或自動(dòng)更新 |
SLB | 手動(dòng) | 自動(dòng) | 新增Origin時(shí),ECS需要手動(dòng)安裝和更新配置,K8s自動(dòng)安裝,手動(dòng)更新但自動(dòng)推送配置 |
存儲(chǔ) | 手動(dòng) | 自動(dòng) | 擴(kuò)容存儲(chǔ)時(shí),ECS需要手動(dòng)安裝和更新,K8s會(huì)自動(dòng)更新,不影響業(yè)務(wù) |
Step 1:?由于SRS和Nginx不在一個(gè)Pod可能也不在一個(gè)Node,需要?jiǎng)?chuàng)建依賴的PV(Persistent Volume)持久化卷,可購(gòu)買NAS例如:
驅(qū)動(dòng)類型(PV ? ? driver):alicloud/nas
掛載點(diǎn)(PV ? ? server),可在控制臺(tái)創(chuàng)建、查看和復(fù)制:1abb5492f7-ubq80.cn-beijing.nas.aliyuncs.com
NFS版本(PV vers):3
在NAS基礎(chǔ)上可以創(chuàng)建PV,以及PVC:
pv-nas,從NAS存儲(chǔ)創(chuàng)建的PV,支持多寫和多讀,Pod不使用存儲(chǔ)后會(huì)回收,也就是刪除這些數(shù)據(jù)。
pvc-nas,SRS和Nginx源站使用的PVC,具有讀寫權(quán)限。讀取SRS的靜態(tài)文件和HLS并分發(fā)。
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolume
metadata:
?name: pv-nas
?labels:
???pv: nfs-pv
spec:
?capacity:
???storage: 100Gi
?storageClassName: nas
?accessModes:
??? -ReadWriteMany
??? -ReadOnlyMany
?persistentVolumeReclaimPolicy: Retain
?flexVolume:
???driver: "alicloud/nas"
???options:
?????server: "1abb5492f7-ubq80.cn-beijing.nas.aliyuncs.com"
??? ??path: "/k8s"
?????vers: "3"
?????options: "nolock,tcp,noresvport"
?
---
?
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
?name: pvc-nas
spec:
?accessModes:
??? -ReadWriteMany
?storageClassName: nas
?resources:
???requests:
?????storage: 100Gi
?selector:
???matchLabels:
?????pv: nfs-pv
EOF
Note:請(qǐng)將上面的掛載點(diǎn)(PV server)替換成你的。
Step 2:?創(chuàng)建SRS源站集群和Nginx源站應(yīng)用和服務(wù)。
srs-origin-config: 創(chuàng)建一個(gè)配置k8s ConfigMap,存儲(chǔ)了SRS Origin Server使用的配置文件。
socs: 創(chuàng)建一個(gè)Headless服務(wù)k8s service,基于Headless ? ? Service提供Origin服務(wù),每個(gè)Origin都有自己的服務(wù)地址,例如srs-origin-0.socs,供內(nèi)部Edge Server調(diào)用。
srs-origin: 創(chuàng)建一個(gè)有狀態(tài)應(yīng)用k8s StatefulSet,運(yùn)行SRS Origin Cluster,HLS寫入共享存儲(chǔ)PV。
nginx-origin-deploy: 創(chuàng)建一個(gè)無狀態(tài)應(yīng)用k8s deployment,運(yùn)行Nginx,將SRS靜態(tài)文件寫入PV,從共享存儲(chǔ)PV讀取HLS和靜態(tài)文件。
srs-http-service: 創(chuàng)建一個(gè)服務(wù)k8s service,基于SLB提供HTTP服務(wù),Nginx對(duì)外提供HLS服務(wù)。
srs-api-service: 創(chuàng)建一個(gè)服務(wù)k8s service,基于SLB提供HTTP服務(wù),SRS第一個(gè)源站提供API服務(wù),標(biāo)簽為statefulset.kubernetes.io/pod-name: ? ? srs-origin-0。
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
?name: srs-origin-config
data:
?srs.conf: |-
???listen????????????? 1935;
??? max_connections???? 1000;
???daemon????????????? off;
???http_api {
???????enabled???????? on;
???????listen????????? 1985;
??? }
???http_server {
???????enabled???????? on;
???????listen????????? 8080;
??? }
???vhost __defaultVhost__ {
???????cluster {
???????????origin_cluster? on;
???????????coworkers?????? srs-origin-0.socssrs-origin-1.socs srs-origin-2.socs;
???????}
???????http_remux {
???????????enabled???? on;
???????}
???????hls {
???????????enabled???????? on;
???????}
??? }
?
---
?
apiVersion: v1
kind: Service
metadata:
?name: socs
spec:
?clusterIP: None
?selector:
???app: srs-origin
?ports:
? -name: socs-1935-1935
???port: 1935
???protocol: TCP
???targetPort: 1935
?
---
?
apiVersion: apps/v1
kind: StatefulSet
metadata:
?name: srs-origin
?labels:
???app: srs-origin
spec:
?serviceName: "socs"
?replicas: 3
?selector:
???matchLabels:
?????app: srs-origin
?template:
???metadata:
?????labels:
???????app: srs-origin
???spec:
?????volumes:
?????- name: cache-volume
???????persistentVolumeClaim:
?????????claimName: pvc-nas
?????- name: config-volume
???????configMap:
?????????name: srs-origin-config
?????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: config-volume
?????????mountPath: /usr/local/srs/conf
?
---
?
apiVersion: apps/v1
kind: Deployment
metadata:
?name: nginx-origin-deploy
?labels:
???app: nginx-origin
spec:
?replicas: 1
?selector:
???matchLabels:
?????app: nginx-origin
?template:
???metadata:
?????labels:
???????app: nginx-origin
???spec:
?????volumes:
?????- name: cache-volume
???????persistentVolumeClaim:
?????????claimName: pvc-nas
?????containers:
?????- 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", "cp -R ./objs/nginx/html/* /tmp/html/; sleepinfinity"]
?
---
?
apiVersion: v1
kind: Service
metadata:
?name: srs-http-service
spec:
?type: LoadBalancer
?selector:
???app: nginx-origin
?ports:
? -name: nginx-origin-service-80-80
???port: 80
???protocol: TCP
???targetPort: 80
?
---
?
apiVersion: v1
kind: Service
metadata:
?name: srs-api-service
spec:
?type: LoadBalancer
?selector:
???statefulset.kubernetes.io/pod-name: srs-origin-0
?ports:
? -name: srs-api-service-1985-1985
???port: 1985
???protocol: TCP
??? targetPort:1985
EOF
Remark:假設(shè)SRS源站有狀態(tài)服務(wù)srs-origin配置的Replicas為2,則會(huì)生成兩個(gè)源站srs-origin-0.socs和srs-origin-1.socs,若新增了源站比如Replicas為3,則需要在配置中加上srs-origin-2.socs。
Remark:我們啟動(dòng)了一個(gè)srs-cp-files的container,拷貝SRS默認(rèn)的文件,參考#1603.
Note:Origin Server在集群內(nèi)部提供流媒體源站服務(wù),內(nèi)部域名為srs-origin-0.socs和srs-origin-1.socs,EdgeServer會(huì)通過該域名連接到OriginServer。
Note:Nginx通過SharedVolume(PV)讀取SRSOrigin生成的切片,對(duì)外提供HLS服務(wù)。
Note:這里我們選擇ACK自動(dòng)創(chuàng)建SLB和EIP,也可以手動(dòng)指定SLB,參考指定購(gòu)買的SLB和EIP。
Step 3:?創(chuàng)建SRS邊緣配置、應(yīng)用和服務(wù)。
srs-edge-config: 創(chuàng)建一個(gè)配置k8s ConfigMap,存儲(chǔ)了SRS Edge Server使用的配置文件。
srs-edge-deploy: 創(chuàng)建一個(gè)無狀態(tài)應(yīng)用k8s deployment,運(yùn)行多個(gè)SRS Edge Server。
srs-edge-service: 創(chuàng)建一個(gè)服務(wù)k8s service基于SLB對(duì)外提供流媒體服務(wù)。
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
?name: srs-edge-config
data:
?srs.conf: |-
???listen????????????? 1935;
???max_connections???? 1000;
???daemon????????????? off;
???http_api {
???????enabled???????? on;
???????listen????????? 1985;
??? }
???http_server {
???????enabled???????? on;
???????listen????????? 8080;
??? }
???vhost __defaultVhost__ {
???????cluster {
???????????mode??????????? remote;
???????????origin????????? srs-origin-0.socssrs-origin-1.socs srs-origin2.socs;
???????}
???????http_remux {
???????????enabled???? on;
???????}
??? }
?
---
?
apiVersion: apps/v1
kind: Deployment
metadata:
?name: srs-edge-deploy
?labels:
???app: srs-edge
spec:
?replicas: 4
?selector:
???matchLabels:
?????app: srs-edge
?template:
???metadata:
?????labels:
???????app: srs-edge
???spec:
?????volumes:
?????- name: config-volume
???????configMap:
?????????name: srs-edge-config
?????containers:
?????- name: srs
???????image: ossrs/srs:3
???????imagePullPolicy: IfNotPresent
???????ports:
???????- containerPort: 1935
???????- containerPort: 1985
???????- containerPort: 8080
???????volumeMounts:
???????- name: config-volume
?????????mountPath: /usr/local/srs/conf
?
---
?
apiVersion: v1
kind: Service
metadata:
?name: srs-edge-service
spec:
?type: LoadBalancer
?selector:
???app: srs-edge
?ports:
? -name: srs-edge-service-1935-1935
???port: 1935
???protocol: TCP
???targetPort: 1935
? -name: srs-edge-service-8080-8080
???port: 8080
???protocol: TCP
???targetPort: 8080
EOF
Remark:假設(shè)SRS源站有狀態(tài)服務(wù)srs-origin配置的Replicas為2,則會(huì)生成兩個(gè)源站srs-origin-0.socs和srs-origin-1.socs,若新增了源站比如Replicas為3,則需要在配置中加上srs-origin-2.socs。
Note:Edge Server的配置中,通過源站在HeadlessService注冊(cè)的內(nèi)部域名srs-origin-0.socs等等,連接到OriginServer。
Note:這里我們選擇ACK自動(dòng)創(chuàng)建SLB和EIP,也可以手動(dòng)指定SLB,參考指定購(gòu)買的SLB和EIP。
Step 4:?大功告成。你可以推拉流了,其中HLS流可以從Nginx(80)播放,RTMP和HTTP-FLV從SRS播放:
Publish RTMP to?rtmp://28.170.32.118/live/livestream?or?to origin?or?to edge.
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/live/livestream.m3u8
Note:請(qǐng)將上面的EIP換成你自己的,可用命令kubectlget svc/srs-http-service或kubectl get svc/srs-edge-service查看你的EIP。
Note:如果是自動(dòng)創(chuàng)建SLB和EIP,那么HLS和RTMP/HTTP-FLV的IP是不一樣的,你可以選擇手動(dòng)指定SLB,這兩個(gè)服務(wù)可以用同一個(gè)SLB,參考指定購(gòu)買的SLB和EIP。
這里我們選擇的是有狀態(tài)集群方式,也可以選擇以無狀態(tài)應(yīng)用(Deployment)方式部署源站,區(qū)別在于每個(gè)源站都需要?jiǎng)?chuàng)建一個(gè)Deployment和Service,參考源站集群部署方式,例如:
第0個(gè)源站,Deployment命名為srs-origin-0-deploy,ClusterIP服務(wù)命名為srs-origin-0。
第1個(gè)源站,Deployment命名為srs-origin-1-deploy,ClusterIP服務(wù)命名為srs-origin-1。
第2個(gè)源站,Deployment命名為srs-origin-2-deploy,ClusterIP服務(wù)命名為srs-origin-2。
源站配置改成coworkers srs-origin-0 srs-origin-1 ? ? srs-origin-2;。
邊緣配置改成origin srs-origin-0 srs-origin-1 ? ? srs-origin-2;。
?
LiveVideoStackCon 2020
上海/北京/舊金山 講師招募
2020年LiveVideoStackCon將持續(xù)迭代,LiveVideoStackCon將分別在上海(6月13-14日),北京(9月11-12日)和舊金山(11月)舉行。歡迎將你的技術(shù)實(shí)踐、踩坑與填坑經(jīng)歷、技術(shù)與商業(yè)創(chuàng)業(yè)的思考分享出來,獨(dú)樂不如眾樂。請(qǐng)將個(gè)人資料和話題信息郵件到 speaker@livevideostack.com 或點(diǎn)擊【閱讀原文】了解成為L(zhǎng)iveVideoStackCon講師的權(quán)益與義務(wù),我們會(huì)在48小時(shí)內(nèi)回復(fù)。
總結(jié)
以上是生活随笔為你收集整理的当SRS遇到K8s:如何构建海量推流源站?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LiveVideoStack线上分享第五
- 下一篇: Netflix选择AVIF作为下一代图片