日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

当SRS遇到K8s:如何实现高可用、回滚与灰度发布?

發布時間:2024/4/11 117 豆豆
生活随笔 收集整理的這篇文章主要介紹了 当SRS遇到K8s:如何实现高可用、回滚与灰度发布? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Photo by?Luis Quintero?from?Pexels

本文來自流媒體直播集群SRS的官方wiki(https://github.com/ossrs/srs/wiki/v4_CN_K8s),由SRS的創始作者楊成立授權發布。

文 / 楊成立

相關文章:

當SRS遇到K8s:快速構建高并發直播集群

當SRS遇到K8s:如何構建海量推流源站?

?

服務的更新、回滾和灰度,是個簡單的問題,如果加上一個條件"不中斷服務的前提下",那么就是一個難題,如果再加上"大規模",那么就是K8S要解決的核心問題之一。壞消息是這個難搞的問題還真是流媒體服務的核心的、關鍵的、不可忽視的關鍵能力之一,好消息是K8S和云計算讓這個難題稍微好一點點了。

我們在什么場景下會遇到更新、回滾和灰度的問題:

  • SRS需要升級新版本,如何知道升級后對現有業務沒有影響?如果選擇業務量小升級,那一般常態會是半夜三更、凌晨三四點,還要不要頭發了呢?

  • 改進了新的功能或優化,根據業務定制了新的東西(完全直接使用SRS也得有自己的業務服務器),如何只在一部分機器發布,看看效果有沒有達到預期?

  • 更新新版本后,如果發現有問題,影響了用戶服務,如何在最短時間內回滾到之前的版本?問題出現時首先是要確認問題后(若由升級引起則)回滾,而不是很費時間的找Bug。

在這個場景下,對比K8S和傳統部署方式的差異:

對比項

ECS

K8S

說明

部署

安裝包

鏡像

Docker鏡像可回滾,開發和生產環境一致,可Cache,高效率和高密度,高可移植性,資源隔離可預測程序性能

看門狗

手動

自動

SRS異常退出由看門狗重新拉起,非K8S需要手動安裝,K8S自動管理和拉起服務

更新

手動

自動

傳統方式用腳本下載和更新二進制,人工分批更新,K8S自動Rolling Update,自動下載鏡像和分批更新

灰度

手動

自動

傳統方式手動操作SLB決定切量比例,K8S通過Replicas控制比例,自動切量

回滾

手動

自動

傳統方式手動回滾,K8S有版本管理和回滾機制

Note:平滑更新的關鍵是平滑退出,重點是邊緣集群的更新,對于源站集群我們可以選擇直接重啟,因為一般會有邊緣集群作為代理,源站斷開后邊緣會重試,不影響用戶,參考#1579(https://github.com/ossrs/srs/issues/1579#issuecomment-587233844)。

我們重點關注邊緣集群的平滑退出,SRS邊緣屬于長連接無狀態服務。和Nginx一樣,SRS使用SIGQUIT作為信號,同時配置force_grace_quit認為SIGTERM也是平滑退出,收到SIGQUIT信號后,會等待grace_start_wait指定的時間,然后關閉Listeners新的連接不會分配到這個服務器,然后開始清理并等待現有連接退出,所有連接退出后還會等待grace_final_wait指定的時間,才會退出。

以之前部署的SRS源站和邊緣集群為例,參考SRS Origin Cluster for a Large Number of Streams,SRS邊緣的Pod的配置,需要指定平滑退出的參數,例如:

cat <<EOF | kubectl apply -f -

apiVersion: v1

kind: ConfigMap

metadata:

?name: srs-edge-config

data:

?srs.conf: |-

???listen????????????? 1935;

???max_connections???? 1000;

???daemon????????????? off;

???grace_start_wait??? 700;

???grace_final_wait??? 800;

???force_grace_quit??? on;

???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;

???????}

??? }

EOF

Remark:一定要開啟force_grace_quit,不開啟(默認)將使用暴力更新,直接斷開現有的連接,參考#1579(https://github.com/ossrs/srs/issues/1579#issuecomment-587233844)。

Note:在K8S中開始刪除Pod時,會快速從Service刪除Pod,所以我們將grace_start_wait和grace_final_wait設置時間短一些,只需要幾百毫秒就足夠了。

SRS邊緣的配置,也需要在lifecycle.preStop事件時啟動平滑退出,并設置terminationGracePeriodSeconds等待時間,例如:

cat <<EOF | kubectl apply --record -f -

apiVersion: apps/v1

kind: Deployment

metadata:

?name: srs-edge-deploy

?labels:

???app: srs-edge

spec:

?replicas: 2

?revisionHistoryLimit: 10

?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:v4.0.5

???????imagePullPolicy: IfNotPresent

???????ports:

???????- containerPort: 1935

???????- containerPort: 1985

???????- containerPort: 8080

???????volumeMounts:

???????- name: config-volume

?????????mountPath: /usr/local/srs/conf

???????lifecycle:

?????????preStop:

???????????exec:

????????????? command:["/usr/local/srs/etc/init.d/srs", "grace"]

?????terminationGracePeriodSeconds: 120

EOF

Note:?kubectl apply增加了一個參數--record,后面回滾會用到。

Note:?terminationGracePeriodSeconds等待退出時間我們設置2分鐘,線上服務可以設置更長,比如12小時。

Remark:為了更好體現平滑更新的邏輯,我們設置Replicas=2可以更容易演示。

Remark:我們使用SRS4演示,例如v4.0.5,實際上SRS3也可以的比如v3.0-b1等。

我們停掉了之前srs-demo-deploy推的兩個DEMO流,采用手動推流到Edge,方便演示升級時有長連接需要服務的情況:

ffmpeg -re -i ./doc/source.200kbps.768x320.flv-c copy \

??? -fflv rtmp://28.170.32.118/live/livestream

Note:請將上面的EIP換成你自己的,可用命令kubectlget svc/srs-edge-service查看你的EIP。

咱們可以看到目前啟動了2個Edge,可以看下它的版本,是通過Pod(z9gbm)推流:

kubectl get po|grep edge

srs-edge-deploy-58d9999b7c-pnr2f?????? 1/1????Running?? 0????????? 16s

srs-edge-deploy-58d9999b7c-z9gbm?????? 1/1????Running?? 0????????? 16s

?

kubectl exec srs-edge-deploy-58d9999b7c-pnr2f-- ./objs/srs -v

4.0.5

kubectl exec srs-edge-deploy-58d9999b7c-pnr2f-- yum install -y net-tools

kubectl exec srs-edge-deploy-58d9999b7c-pnr2f-- netstat -anp|grep 1935

tcp???????0????? 0 0.0.0.0:1935??????????? 0.0.0.0:*?????????????? LISTEN????? 1/./objs/srs

?

kubectl exec srs-edge-deploy-58d9999b7c-z9gbm-- ./objs/srs -v

4.0.5

kubectl exec srs-edge-deploy-58d9999b7c-z9gbm-- yum install -y net-tools

kubectl exec srs-edge-deploy-58d9999b7c-z9gbm-- netstat -anp|grep 1935

tcp???????0????? 0 0.0.0.0:1935??????????? 0.0.0.0:*?????????????? LISTEN????? 1/./objs/srs

tcp???????0????? 0 172.20.0.62:46482?????? 172.20.0.41:1935??????? ESTABLISHED 1/./objs/srs

tcp???????0????? 0 172.20.0.62:1935??????? 172.20.0.1:12066??????? ESTABLISHED 1/./objs/srs

Note:我們只推流一個流,會有兩個連接,一個是客戶端到Edge的連接,一個是Edge回源到Origin的連接。

下面我們會分幾個部分,看發布中遇到的問題:

  • SRS Cluster Rolling Update: 在平滑退出基礎上的滾動更新,集群更新的基礎機制。

  • SRS Cluster Rolling Back: 在平滑退出基礎上的發布回滾,發布遇到問題首先考慮回滾。

  • SRS Cluster Canary Release: 金絲雀升級,可精確控制的流量控制和回滾。

  • SRS Cluster Rolling Update

    K8S的更新是Rolling Update,也就是修改和更新Pods時,會分批次執行。比如,上面的例子中SRS邊緣的版本是v4.0.5,若我們現在需要更新到4.0.6,鏡像已經打好了ossrs/srs:v4.0.6,那么我們可以用命令更新:

    kubectl set image deploy/srs-edge-deploy srs=ossrs/srs:v4.0.6 --record

    可以看這兩個Pod的日志,沒有連接的Pod很快就退出了,而有連接的Pod經過了一定的時間才退出(若客戶端連接主動斷開會更快退出):

    kubectl exec srs-edge-deploy-58d9999b7c-pnr2f -- tail -f objs/srs.log

    [2020-02-19 11:07:20.818][Trace][1][937]sig=3, user start gracefully quit

    [2020-02-19 11:07:20.960][Trace][1][937]force gracefully quit, signo=15

    [2020-02-19 11:07:21.772][Trace][1][932]cleanup for quitsignal fast=0, grace=1

    [2020-02-19 11:07:21.772][Warn][1][932][11]main cycle terminated, system quit normally.

    commandterminated with exit code137

    ?

    kubectl exec srs-edge-deploy-58d9999b7c-z9gbm -- tail -f objs/srs.log

    [2020-02-19 11:07:23.095][Trace][1][1009]sig=3, user start gracefully quit

    [2020-02-19 11:07:23.316][Trace][1][1009]force gracefully quit, signo=15

    [2020-02-19 11:07:23.784][Trace][1][1004]cleanup for quitsignal fast=0, grace=1

    [2020-02-1911:07:23.784][Warn][1][1004][11] main cycle terminated, system quit normally.

    [2020-02-19 11:07:24.784][Trace][1][1004] waitfor 1 conns to quit

    [2020-02-19 11:07:26.968][Trace][1][1010] <- CPB time=120041497, okbps=0,0,0,ikbps=252,277,0, mr=0/350, p1stpt=20000, pnt=5000

    [2020-02-19 11:08:26.791][Trace][1][1004] waitfor 1 conns to quit

    [2020-02-19 11:08:52.602][Trace][1][1010]edge change from 200 to state 0 (init).

    [2020-02-19 11:08:52.792][Trace][1][1004] waitfor 0 conns to quit

    commandterminated with exit code137

    ?

    kubectl get po |grep edge

    NAME?????????????????????????????????? READY?? STATUS???????RESTARTS?? AGE

    srs-edge-deploy-58d9999b7c-z9gbm?????? 0/1????Terminating?? 0????????? 3m52s

    srs-edge-deploy-76fcbfb848-z5rmn?????? 1/1????Running?????? 0????????? 104s

    srs-edge-deploy-76fcbfb848-zt4wv?????? 1/1????Running?????? 0????????? 106s

    Remark:注意我們現在是有一個Pod有客戶端在推流的。同樣,我們指定了參數--record,會在后面回滾時用得著。

    若RollingUpdate期間,我們需要暫停更新,可以用kubectl rollout暫停和恢復:

    kubectl rollout pausedeploy/srs-edge-deploy

    kubectl rollout resumedeploy/srs-edge-deploy

    SRS Cluster Rolling Back

    每次發布K8S都會記錄一個Revision,若我們傳遞了--record參數(正如前面我們做的),則會記錄更詳細的CHANGE-CAUSE,比如:

    kubectl rollout history deploy/srs-edge-deploy

    REVISION?CHANGE-CAUSE

    1????????kubectl apply --record=true --filename=-

    2 ?????? kubectl set imagedeploy/srs-edge-deploy srs=ossrs/srs:v4.0.6 --record=true

    Note:默認ACK只保留10個Revision,可以通過設置revisionHistoryLimit增加可回滾的版本。

    若出現異常,可以回滾到之前的版本,例如:

    kubectl rollout undo deploy/srs-edge-deploy--to-revision=1

    實際上回滾的過程也是Rolling Update的過程,只是不用指定修改什么配置,而是指定的哪個歷史版本的配置。回滾后,新增了一個版本3,和1是一樣的:

    REVISION?CHANGE-CAUSE

    1????????kubectl apply --record=true --filename=-

    2 ?????? kubectl set image deploy/srs-edge-deploy srs=ossrs/srs:v4.0.6--record=true

    3????????kubectl apply --record=true --filename=-

    Note:可以在阿里云控制臺來選擇回滾到哪個版本。

    SRS Cluster Canary Release

    Canary是金絲雀發布,指試探性的發布一些版本,沒有問題就繼續擴大比例。由于涉及到具體的發布比例,所以我們要在RollingUpdate基礎上,能控制新老Pods的數目,這就需要使用SLB了,參考Kubernetes集群中使用阿里云 SLB 實現四層金絲雀發布。

    Note:關于金絲雀發布,最初發布的版本就好比金絲雀,在以前煤礦中會把金絲雀先送下去,如果缺氧雀兒就掛了。

    以上面的Edge集群為例,假設目前版本是v4.0.5,有三個Edge Pod在運行,通過SLB對外提供服務:

    cat <<EOF | kubectl apply --record -f -

    apiVersion: apps/v1

    kind: Deployment

    metadata:

    ?name: srs-edge-r5-deploy

    ?labels:

    ???run: srs-edge-r5

    spec:

    ?replicas: 3

    ?selector:

    ???matchLabels:

    ?????run: srs-edge-r5

    ?template:

    ???metadata:

    ?????labels:

    ???????run: srs-edge-r5

    ???????app: srs-edge

    ???spec:

    ?????volumes:

    ?????- name: config-volume

    ???????configMap:

    ?????????name: srs-edge-config

    ?????containers:

    ?????- name: srs

    ???????image: ossrs/srs:v4.0.5

    ???????imagePullPolicy: IfNotPresent

    ???????ports:

    ???????- containerPort: 1935

    ???????- containerPort: 1985

    ???????- containerPort: 8080

    ???????volumeMounts:

    ???????- name: config-volume

    ?????????mountPath: /usr/local/srs/conf

    ???????lifecycle:

    ?????????preStop:

    ???????????exec:

    ????????????? command:["/usr/local/srs/etc/init.d/srs", "grace"]

    ?????terminationGracePeriodSeconds: 120

    EOF

    Remark:注意Pod的labels有兩個,一個是run:srs-edge-r5是這個應用所使用的,另外一個是app: srs-edge是Service用的,新老的SRS都有這個標簽這樣Service就可以都轉發了。

    執行命令后,可以看到三個Pod在運行:

    kubectl get po

    NAME?????????????????????????????????? READY?? STATUS???RESTARTS?? AGE

    srs-edge-r5-deploy-6c84cdc77b-q2j97??? 1/1????Running?? 0????????? 3m15s

    srs-edge-r5-deploy-6c84cdc77b-s6pzh??? 1/1????Running?? 0????????? 3m15s

    srs-edge-r5-deploy-6c84cdc77b-wjdtl??? 1/1????Running?? 0????????? 3m15s

    如果我們要升級到v4.0.6,但是只想先升級一臺,這臺就是金絲雀了。我們可以創建另外一個Deployment,他們的name不一樣,但使用同樣的Service:

    cat <<EOF | kubectl apply --record -f -

    apiVersion: apps/v1

    kind: Deployment

    metadata:

    ?name: srs-edge-r6-deploy

    ?labels:

    ???run: srs-edge-r6

    spec:

    ?replicas: 1

    ?selector:

    ???matchLabels:

    ?????run: srs-edge-r6

    ?template:

    ???metadata:

    ?????labels:

    ???????run: srs-edge-r6

    ???????app: srs-edge

    ???spec:

    ?????volumes:

    ?????- name: config-volume

    ???????configMap:

    ?????????name: srs-edge-config

    ?????containers:

    ?????- name: srs

    ???????image: ossrs/srs:v4.0.6

    ???????imagePullPolicy: IfNotPresent

    ???????ports:

    ???????- containerPort: 1935

    ???????- containerPort: 1985

    ???????- containerPort: 8080

    ???????volumeMounts:

    ???????- name: config-volume

    ?????????mountPath: /usr/local/srs/conf

    ???????lifecycle:

    ?????????preStop:

    ???????????exec:

    ????????????? command:["/usr/local/srs/etc/init.d/srs", "grace"]

    ?????terminationGracePeriodSeconds: 120

    EOF

    Remark:注意Pod的labels有兩個,一個是run:srs-edge-r6是這個應用所使用的,另外一個是app: srs-edge是Service用的,和之前的老版本是一樣的,這樣Service就可以都轉發了。

    執行命令后,可以看到四個Pod在運行,三個老的,一個新的,這樣就灰度了25%的流量到了新版本:

    kubectl get po

    NAME?????????????????????????????????? READY?? STATUS???RESTARTS?? AGE

    srs-edge-r5-deploy-6c84cdc77b-q2j97??? 1/1????Running?? 0????????? 3m30s

    srs-edge-r5-deploy-6c84cdc77b-s6pzh??? 1/1????Running?? 0????????? 3m30s

    srs-edge-r5-deploy-6c84cdc77b-wjdtl??? 1/1????Running?? 0????????? 3m30s

    srs-edge-r6-deploy-598f4698d-kkfnb???? 1/1????Running?? 0????????? 6s

    ?

    whiletrue;do ffmpeg -f flv -irtmp://r.ossrs.net/live/livestream 2>&1|grep server_version; sleep 1;done

    ???server_version? : 4.0.5

    ???server_version? : 4.0.5

    ???server_version? : 4.0.5

    ???server_version? : 4.0.5

    ???server_version? : 4.0.5

    ???server_version? : 4.0.5

    ???server_version? : 4.0.6 # 這是新版本

    ???server_version? : 4.0.5

    ???server_version? : 4.0.5

    ???server_version? : 4.0.6 # 這是新版本

    那么接下來,只需要調整新老的Deployment的Replicas,就能調整流量的比例了,比如我們增加新版本比重,只留一臺老的:

    kubectl scale --replicas=3deploy/srs-edge-r6-deploy

    kubectl scale --replicas=1deploy/srs-edge-r5-deploy

    可以看到經過Gracefully Quit平滑升級和退出,最終變成了我們聲明的那個樣子,對業務不影響:

    kubectl get po

    NAME?????????????????????????????????? READY?? STATUS???RESTARTS?? AGE

    nginx-origin-deploy-85f4695685-gn2df?? 3/3????Running?? 0????????? 5h31m

    srs-edge-r5-deploy-6c84cdc77b-s6pzh??? 1/1????Running?? 0????????? 25m

    srs-edge-r6-deploy-f6b59c6c6-ddgxw???? 1/1????Running?? 0????????? 2m59s

    srs-edge-r6-deploy-f6b59c6c6-gvnd8???? 1/1????Running?? 0????????? 2m54s

    srs-edge-r6-deploy-f6b59c6c6-j46b5???? 1/1????Running?? 0????????? 2m58s

    ?

    whiletrue;do ffmpeg -f flv -irtmp://r.ossrs.net/live/livestream 2>&1|grep server_version; sleep 1;done

    ?? ?server_version?: 4.0.6

    ???server_version? : 4.0.6

    ???server_version? : 4.0.6

    ???server_version? : 4.0.6

    ???server_version? : 4.0.6

    ???server_version? : 4.0.6

    ???server_version? : 4.0.5 # 這是老版本

    ???server_version? : 4.0.6

    ???server_version? : 4.0.6

    ???server_version? : 4.0.6

    ???server_version? : 4.0.6

    ???server_version? : 4.0.6

    ???server_version? : 4.0.5 # 這是老版本

    ???server_version? : 4.0.6

    ???server_version? : 4.0.6

    最終我們只要把老的Replicas設為0,然后就可以刪除老的應用srs-edge-r5-deploy了,系統全部變成新的版本了,如下圖所示:

    親,爽嗎?干凈利落,談笑間,強擼灰飛湮滅啦。

    LiveVideoStackCon 2020

    上海/北京/舊金山 講師招募

    2020年LiveVideoStackCon將持續迭代,LiveVideoStackCon將分別在上海(6月13-14日),北京(9月11-12日)和舊金山(11月)舉行。歡迎將你的技術實踐、踩坑與填坑經歷、技術與商業創業的思考分享出來,獨樂不如眾樂。請將個人資料和話題信息郵件到 speaker@livevideostack.com 或點擊【閱讀原文】了解成為LiveVideoStackCon講師的權益與義務,我們會在48小時內回復。

    超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生

    總結

    以上是生活随笔為你收集整理的当SRS遇到K8s:如何实现高可用、回滚与灰度发布?的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。