当SRS遇到K8s:如何构建海量推流源站?
Photo by?Oscar Ivan Esquivel Arteaga?on?Unsplash
本文來自流媒體直播集群SRS的官方wiki(https://github.com/ossrs/srs/wiki/v4_CN_K8s),由SRS的創始作者楊成立授權發布。
文 / 楊成立
相關文章:當SRS遇到K8s:快速構建高并發直播集群
本章描述了基于K8s,如何構建Origin Cluster支持超多推流場景。
Origin Cluster通過配置其他源站的信息,在本源站沒有流時查詢到流的位置,通過RTMP302定向到指定源站,具體原理可以參考#464。主要應用場景如下:
源站災備:即使流比較少,也可以用兩個源站,這樣可以將流分散到不同的源站,避免源站出現問題時影響所有的流。
海量推流:單源站可以支持1000到3000路流,高碼率的流支持的路數更少,有DVR和HLS時支持的路更少,源站集群有多個源站同時接收推流,可以支持10k~100k推流,參考規格。
復雜源站業務:源站除了支持推流和拉流,還有重要的功能是DVR、轉碼、轉HLS,DVR和HLS涉及磁盤,轉碼涉及CPU,都是容易發生瓶頸的資源依賴,源站集群擴展能力更強。
在這個場景下,對比K8s和傳統使用方式的差異:
對比 | ECS | K8s | 說明 |
申請ECS | 手動 | 自動 | 部署時,ECS需要手動申請,K8s自動申請 |
安裝包 | 腳本 | 鏡像 | Docker方式更優,版本管理,可Cache |
看門狗 | 手動 | 自動 | SRS異常退出由看門狗重新拉起,非K8s需要手動安裝, |
更換ECS | 手動 | 自動 | ECS更換時,非K8s需要手動申請,修改SLB,安裝服務,K8s自動遷移服務,更新SLB配置監聽和保活等 |
配置 | 文件 | Volume | ECS需要手動管理配置;K8s配置在ConfigMap,通過Volume掛載為配置文件,擴容時源站手動更新自動推送,邊緣擴容自動更新 |
擴容 | 手動 | 自動 | 需要新開進程時,ECS需要申請部署和配置,K8s只需要修改Replicas數目即可(也可自動擴容) |
發現 | 手動 | 自動 | Origin變更IP時,ECS需要手動修改配置,K8s在遷移源站Pod時會保持,或自動更新 |
SLB | 手動 | 自動 | 新增Origin時,ECS需要手動安裝和更新配置,K8s自動安裝,手動更新但自動推送配置 |
存儲 | 手動 | 自動 | 擴容存儲時,ECS需要手動安裝和更新,K8s會自動更新,不影響業務 |
Step 1:?由于SRS和Nginx不在一個Pod可能也不在一個Node,需要創建依賴的PV(Persistent Volume)持久化卷,可購買NAS例如:
驅動類型(PV ? ? driver):alicloud/nas
掛載點(PV ? ? server),可在控制臺創建、查看和復制:1abb5492f7-ubq80.cn-beijing.nas.aliyuncs.com
NFS版本(PV vers):3
在NAS基礎上可以創建PV,以及PVC:
pv-nas,從NAS存儲創建的PV,支持多寫和多讀,Pod不使用存儲后會回收,也就是刪除這些數據。
pvc-nas,SRS和Nginx源站使用的PVC,具有讀寫權限。讀取SRS的靜態文件和HLS并分發。
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:請將上面的掛載點(PV server)替換成你的。
Step 2:?創建SRS源站集群和Nginx源站應用和服務。
srs-origin-config: 創建一個配置k8s ConfigMap,存儲了SRS Origin Server使用的配置文件。
socs: 創建一個Headless服務k8s service,基于Headless ? ? Service提供Origin服務,每個Origin都有自己的服務地址,例如srs-origin-0.socs,供內部Edge Server調用。
srs-origin: 創建一個有狀態應用k8s StatefulSet,運行SRS Origin Cluster,HLS寫入共享存儲PV。
nginx-origin-deploy: 創建一個無狀態應用k8s deployment,運行Nginx,將SRS靜態文件寫入PV,從共享存儲PV讀取HLS和靜態文件。
srs-http-service: 創建一個服務k8s service,基于SLB提供HTTP服務,Nginx對外提供HLS服務。
srs-api-service: 創建一個服務k8s service,基于SLB提供HTTP服務,SRS第一個源站提供API服務,標簽為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:假設SRS源站有狀態服務srs-origin配置的Replicas為2,則會生成兩個源站srs-origin-0.socs和srs-origin-1.socs,若新增了源站比如Replicas為3,則需要在配置中加上srs-origin-2.socs。
Remark:我們啟動了一個srs-cp-files的container,拷貝SRS默認的文件,參考#1603.
Note:Origin Server在集群內部提供流媒體源站服務,內部域名為srs-origin-0.socs和srs-origin-1.socs,EdgeServer會通過該域名連接到OriginServer。
Note:Nginx通過SharedVolume(PV)讀取SRSOrigin生成的切片,對外提供HLS服務。
Note:這里我們選擇ACK自動創建SLB和EIP,也可以手動指定SLB,參考指定購買的SLB和EIP。
Step 3:?創建SRS邊緣配置、應用和服務。
srs-edge-config: 創建一個配置k8s ConfigMap,存儲了SRS Edge Server使用的配置文件。
srs-edge-deploy: 創建一個無狀態應用k8s deployment,運行多個SRS Edge Server。
srs-edge-service: 創建一個服務k8s service基于SLB對外提供流媒體服務。
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:假設SRS源站有狀態服務srs-origin配置的Replicas為2,則會生成兩個源站srs-origin-0.socs和srs-origin-1.socs,若新增了源站比如Replicas為3,則需要在配置中加上srs-origin-2.socs。
Note:Edge Server的配置中,通過源站在HeadlessService注冊的內部域名srs-origin-0.socs等等,連接到OriginServer。
Note:這里我們選擇ACK自動創建SLB和EIP,也可以手動指定SLB,參考指定購買的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:請將上面的EIP換成你自己的,可用命令kubectlget svc/srs-http-service或kubectl get svc/srs-edge-service查看你的EIP。
Note:如果是自動創建SLB和EIP,那么HLS和RTMP/HTTP-FLV的IP是不一樣的,你可以選擇手動指定SLB,這兩個服務可以用同一個SLB,參考指定購買的SLB和EIP。
這里我們選擇的是有狀態集群方式,也可以選擇以無狀態應用(Deployment)方式部署源站,區別在于每個源站都需要創建一個Deployment和Service,參考源站集群部署方式,例如:
第0個源站,Deployment命名為srs-origin-0-deploy,ClusterIP服務命名為srs-origin-0。
第1個源站,Deployment命名為srs-origin-1-deploy,ClusterIP服務命名為srs-origin-1。
第2個源站,Deployment命名為srs-origin-2-deploy,ClusterIP服務命名為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將持續迭代,LiveVideoStackCon將分別在上海(6月13-14日),北京(9月11-12日)和舊金山(11月)舉行。歡迎將你的技術實踐、踩坑與填坑經歷、技術與商業創業的思考分享出來,獨樂不如眾樂。請將個人資料和話題信息郵件到 speaker@livevideostack.com 或點擊【閱讀原文】了解成為LiveVideoStackCon講師的權益與義務,我們會在48小時內回復。
總結
以上是生活随笔為你收集整理的当SRS遇到K8s:如何构建海量推流源站?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LiveVideoStack线上分享第五
- 下一篇: Netflix选择AVIF作为下一代图片