本文做者: 柴克斌 (網易傳媒技術團隊)web
網易傳媒作爲國內最先的內容資訊平臺,隨着業務體量的增長,業務迭代的速度加快,基礎架構也面臨着不少挑戰,爲了能提供快速、穩定、安全的基礎架構及基礎服務,傳媒在2019年初進行了一次基礎架構的容器化升級,本文就傳媒基礎架構在容器化升級方面所作的工做、面臨的問題、提出的解決方案及將來的規劃都作一些詳細描述,但願能給也在容器化升級的讀者有所借鑑算法
隨着傳媒業務的不斷增長,基礎架構也面臨着不少挑戰,主要包括如下幾類問題sql
資源利用率:傳媒基礎架構在容器化以前,資源使用率在20%左右,存在着波峯波谷,波谷時期總體利用率得不到有效的利用數據庫
流程繁瑣,人工操做較多:業務在申請資源的時候,須要通過流程審批,耗時比較長,在遇到流量高峯的時候,擴容資源比較耗時,流量高峯後,運維還須要手動將資源下線api
頻繁的數據爬取:傳媒一些核心接口,一直存在被外網爬取的狀況,致使了服務的不穩定及流量突增安全
手動擴容、縮容,耗費人力:業務比較難設置合理的資源使用量,當出現業務高峯時,就須要擴容,高峯事後,又須要手動縮容restful
服務依賴拓撲不清晰:當服務要作遷移或下線時,服務提供方須要經過各類人工方式找到全部的服務依賴方,並作下線通知,人工方式常常會找不全全部依賴方,致使服務提供方下線後,消費方出現了故障markdown
爲了應對上述的挑戰,傳媒決定對基礎架構作一次總體的升級,但願達到以下目標網絡
提高資源總體利用率:傳媒但願總體資源利用率提高至50%~60%,而且將波谷資源充分利用起來,可以優化成本架構
提升效率:傳媒計劃取消一些繁瑣的流程,業務方隨時從資源池中獲取資源,咱們會監控用戶對資源的使用狀況,對於資源使用率低的業務進行資源優化
加固安全:傳媒須要搭建網關服務,爲用戶提供統一的流量入口,在網關上增長熔斷降級、安全、審計等方面的能力
保障穩定:資源出現故障後業務能快速遷移,流量突增後能快速擴容,流量恢復後也能自動縮容
快速定位業務依賴:傳媒但願可以快速、準確的定位到業務的依賴,可以看到總體的業務依賴拓撲圖,可以看到核心接口的URL調用拓撲圖
傳媒的架構演進主要經歷了四個階段
物理機階段:最先傳媒業務都在物理機上進行部署
虛擬化階段:爲了節約成本,傳媒總體業務都遷移到了專屬雲
容器化階段:爲了進一步節約成本、提升效率、保障穩定、加固安全,傳媒總體業務都遷移到了容器雲,資源作到了池化,業務隨用隨取
容器雲升級階段:遷移到容器雲後,基礎資源管理更爲方便,爲彈性、精細化資源管理提供了強大的基礎
本文主要介紹傳媒容器化階段所作的工做
在對業務架構和需求瞭解後,咱們規劃了三個資源池
容器資源池:全部無狀態業務都容器化,運行在容器資源池內
雲主機資源池:有些使用了rsync、IP綁定、IP哈希、有狀態的服務,暫時沒有時間進行架構改造,就使用雲主機資源池
物理機資源池:有些使用資源很大的應用(推薦、算法等)沒有必要進行容器化改造和雲主機遷移的應用,仍是保留物理機
容器資源池和雲主機資源池在一個大的VPC內,物理機在VPC外,之間的通訊使用DGW網關和NLB進行
容器資源池,咱們劃分爲如下7類
APP:這個資源池部署全部的業務應用
Redis:Redis屬於敏感性業務,單獨劃分資源池,對這個資源池的使用作獨立的配置
PUSH:PUSH業務白天的時候會佔用70%以上的資源,但夜晚的資源使用率很低,獨立一個資源池,防止PUSH在白天高峯的時候對其餘業務產生影響
Rec:推薦資源池,推薦業務要求獨立資源池,不想與其餘業務共同使用資源池
Kafka:Kafka Operator資源池,部署全部Kafka服務
ES:ES Operator資源池,部署全部ES服務
GW:網關資源池,部署全部容器網關
咱們規劃了容器資源池、虛擬機資源池和物理機資源池,但容器內外的服務如何互相調用,通過討論和設計,咱們採用以下的方式進行容器內外的調用
容器外調用容器外服務:咱們使用傳媒本身的服務框架NDSF作爲服務調用的框架,使用Consul作爲服務註冊中心
容器內調用容器內服務:容器內咱們直接使用ServiceName進行調用
容器內調用容器外服務:容器內調用容器外服務,咱們也使用NDSF服務框架,使用Consul作爲服務註冊中心
容器外調用容器內服務:容器外服務調用統一通過入口網關
爲了徹底隔離生產環境和測試環境,咱們獨立建立了Beta環境,Beta環境與生產環境網絡設備,機櫃和機器徹底隔離,Beta環境有獨立的VPC資源池,也有獨立的容器雲資源池和雲主機資源池
默認狀況下,Beta環境是不能訪問生產環境的,但有些業務方有Beta環境訪問生產環境的需求,爲此,咱們設置了白名單安全組,若是有須要訪問生產環境的業務需求,將IP列表加入白名單便可訪問生產環境
咱們建立了容器資源池和雲主機資源池,容器資源池的網絡使用了OVS,在整個VPC環境內和虛機都是網絡平行的,咱們劃分了一個大的網段,並在這個大網段中劃分了若干子網
容器公網網段:這個網段容許訪問公網
容器內網網段:這個網段不容許訪問公網,大部分容器實例都在這個網段
雲機公網網段:這個網段容許訪問公網
雲機內網網段:這個網段不容許訪問公網,大部分虛機實例都在這個網段
網關網段:容器網關所使用的子網
Redis網段:Redis所使用的子網
Kafka網段:Kafka所使用的子網
ES網段:ES所使用的子網
管控網段:Kubernetes管控組件所使用的子網
7**.技術選型**
專屬雲環境咱們選擇了網易杭研提供的雲1.0,雲1.0基於OpenStack擴展,提供了虛擬機、RDS、NCR、LB等基礎資源和公共中間件,網絡使用OVS,雲1.0是咱們一直使用的雲環境,比較穩定,可靠,運維團隊對這個環境也很是的熟悉
容器雲環境咱們使用了網易杭研提供的輕舟平臺,輕舟平臺是在社區Kubernetes的基礎上推出的PAAS平臺,輕舟自己基於社區,但在社區提供的能力基礎上,穩定性和可用性方面都作了很大的提高,符合生產環境的使用要求,咱們使用了輕舟的如下組件
NCS:容器服務,提供基礎、可靠的容器實例服務
NSF:容器ServiceMesh,使用Envoy和Istio,並在社區開源的基礎上支持了Dubbo、Thrift協議,支持了熱升級、懶加載、服務治理能力等。咱們在使用NSF時,只啓動了調用端攔截
混部:離線/在線業務混部平臺,用於總體提升CPU的使用率
容器網關:容器池外訪問容器內服務的惟一入口,用於安全,審計,熔斷/降級,監控等能力
Redis Operator:容器Redis PAAS服務
Kafka Operator:容器Kafka PAAS服務
HPA:Kubernetes默認支持的能力,使用HPA實現彈性擴縮容,支持了CPU負載,QPS,任務積壓量等指標的彈性擴縮容
通過1年左右的努力,傳媒已經創建起來了容器資源池、雲機資源池和物理機資源池,容器資源池運行了上萬個POD,上千個Service,核心業務都已經遷移到了容器環境,80%的物理機資源都進入了容器資源池
服務調度和治理框架作爲微服務的基礎框架,起到了很是重要的做用,市面上有不少可用的開源框架,好比:Dubbo、Spring Cloud等,傳媒容器化以前有本身的一套服務調用與治理框架,咱們命名爲NDSF。
NDSF的功能架構圖以下所示:
NDSF框架主要包括三大塊內容
SDK:提供了數據庫、中間件的Client SDK,這些SDK封裝了用戶密碼,訪問地址等敏感信息,同時也提供了核心指標的調用統計能力
Framework:提供了微服務啓動的基礎能力,包括:服務上線/下線、服務狀態查看、服務拓撲上報、服務健康狀態監控等基礎能力
服務調用:服務框架調用、服務註冊、服務發現、負載均衡、服務治理能力的提供
NDSF作爲傳媒的基礎框架,基本全部服務都在使用,在服務調用和服務治理層面,NDSF框架使用Consul作爲服務註冊中心,基於HTTP2.0C的服務調用框架,服務的調用實現了Jar包調用和Proxy調用兩種能力
Jar包方式調用:適用於Java語言的微服務,經過在工程裏引入NDSF Jar包實現服務的調用、註冊和治理
Proxy方式調用:適用於非Java語言的微服務,經過在每臺機器上部署一個Proxy實現服務的調用、註冊和治理
NDSF目前已經覆蓋了傳媒80%以上的業務,在業務方接入完成,使用過程當中,也出現了不少問題,主要的問題以下
框架的升級須要業務方的感知,業務方須要配合升級Jar包,從新發布應用,這種方式對升級形成了很大的阻礙
業務在接入或升級過程當中,比較容易引發Jar包衝突,致使業務方進行修復,增長了業務方接入成本和時間
業務方接入NDSF時須要修改服務調用代碼,對接入也形成了不少困難
爲了作到讓業務無感知,也不須要作任何改動,咱們決定使用ServiceMesh作爲整個服務治理的框架,經過ServiceMesh,咱們想達到如下幾個目的
業務無感知:對業務代碼無需修改,業務代碼無需引入Jar包
語言無關:業務方所使用的語言都能支持
多協議支持:支持常見的Dubbo、Thrift、HTTP、gRPC協議
動態生效:服務治理、服務發現、服務註冊都可以動態生效,版本升級也對業務無感知
完善的服務治理能力:可以支持超時重試、熔斷降級、黑/白名單、限流等服務治理能力
在ServiceMesh方案選型方面,咱們使用了NSF作爲ServiceMesh的底層支撐,NSF是基於Istio和Envoy作了加強,不只支持了Dubbo和Thrift,也在動態升級、動態攔截、服務兜底策略方面作了比較大的升級
因爲傳媒有部分服務使用的Dubbo,ServiceMesh須要對Dubbo協議作一些支持,NSF在Istio和Envoy的基礎上,增長了對Dubbo的支持,主要的架構以下:
業務方使用Dubbo直接調用目標IP的方式
經過 iptable ⽅式對指定端⼝(⽬前10000端⼝)的流量進⾏攔截,重定向到 envoy
保留 zk 註冊中⼼,擴展 galley 組件從 zk 拉取 dubbo 服務的註冊信息及服務依賴
galley 組件經過 mcp 上報 service entry 資源給 pilot,擴展字段⾥包含了 dubbo 服務的依賴關係
pilot 在同步 xds 配置的時候根據 service entry 上的依賴關係,按需下發所需的配置
VirtualService協議上面擴展了Dubbo
ServiceMesh目前支持的能力以下表所示
傳媒容器化的主要一個目標之一就是可以提升總體CPU的利用率,節省資源。目前傳媒總體資源利用率在20%左右,波谷的資源得不到有效的利用,咱們但願總體資源利用率可以達到50%~60%,而且不能影響總體服務的穩定性,通過分析後,將資源的使用狀況分爲如下三類
資源利用率很低,在3%~5%左右,這類應用業務比較敏感,不能有延遲,比較典型的就是Redis集羣
存在明顯的波峯波谷,在線資源在波谷的狀況下,會空閒出大量的計算資源
在線資源的使用率不是很低,通常在15%~20%左右,這些業務不是很敏感,比較典型的就是無狀態服務
咱們對目前的資源使用狀況和業務進行了分析,將總體業務區分爲在線業務和離線業務兩種類型,這兩種業務的主要特色以下:
咱們對離線業務/在線業務混部作了以下限制:
離線業務不能影響在線業務
優先在線服務可用的資源保證
在線服務資源使用率低的狀況下,離線服務使用資源,保證總體資源使用率在必定水位
容器資源池,按照在線/離線維度,劃分爲三類資源池
在線資源池:只能調度在線業務上來
離線資源池:只能調度離線業務上來
混部資源池:能夠混合調度在線、離線業務上來業務類型
容器內部署的業務類型,劃分爲四類業務類型
Job:離線任務,會調度到離線資源池
Serivce:在線任務,會調度到在線資源池
Colocation-job:容許混部的Job,會調度到混部資源池
Colocation-service:容許混部的service,會調度到混部資源池
咱們使用了輕舟團隊提供的Zeus混部系統作爲傳媒混部的基礎平臺,Zeus能保證在線業務穩定的前提下,最大化利用CPU資源,而且支持靈活的混部策略和彈性擴縮容
Zeus主要架構以下圖所示:
混部系統主要包括六個組件,管控面有四個組件:
zeus-webhook-server:基於kubernetes dynamic admission control開發的准入控制插件。攔截用戶請求,進行默認值的設置和字段的合法性檢查
zeus-manager:基於kubernetes的 operator 模式開發的控制器。實現CRD資源的生命週期管理、離線任務重調度等
zeus-scheduler-extender:基於kubernetes的 scheduler http extender機制 開發的用來實現離線業務動態調度的擴展調度器
zeus-exporter: 相似於kube-state-metrics組件,統計彙總各類資源數據,推送到prometheus
數據面有兩個組件:
zeus-monitor-agent:採集節點監控數據的agent,運行在混部資源池的每一個節點上。monitor組件將節點的負載狀況按期更新到NodeProfile(custom resource)資源中,而且提供本地restful api,提供給zeus-isolation-agent查詢
zeus-isolation-agent:是一個負責實如今/離線業務資源隔離的組件,運行在混部資源池的每一個節點上。訪問 zeus-monitor-agent 獲取監控數據,按期執行隔離規則。
咱們依據業務使用資源的特性,將整個容器混部資源池劃分爲三類
APP:在線應用資源使用率較高,有可能存在突增現象
NCR:在線應用資源使用率很低,但比較敏感,離線不能佔用太多資源,防止抖動
PUSH:在線應用有明顯的波峯波谷,波谷資源利用率須要提升
在合理估算離線任務可以使用的CPU的方面,若是在線業務負載較高,節點資源利用率高,那麼分配給離線業務的資源就會少或者該節點就徹底不須要混部離線業務;若是在線業務負載較低,節點資源利用率低,那麼分配給離線業務的資源就能夠變多,基於以上的分析,咱們定義了以下公式
Capacity = MAX(節點可分配資源總量 * 節點目標利用率 - 在線業務使用量, 最低資源保證核數)
複製代碼
節點目標利用率是咱們根據每一個資源池的敏感狀況動態設置的
好比一個混部節點的cpu capacity爲56核,allocatable爲55核,該節點上的在線業務實際使用了10核,而且該節點的CPU目標利用率配置爲50%,最低資源保證爲2核,則該混部節點的可用CPU核數爲:
Capacity = Max( 55*50% - 10 , 2 ) = 12.5 核
複製代碼
通過在線/離線混部,目前資源總體利用率獲得了很大提高,節省了30%左右的資源
咱們對預約義的混部資源池進行監控,總體資源使用趨勢以下:
必須對業務進行容量評估
須要對進入容器的業務提早進行容量的評估,以防止容器集羣總體壓力增大而致使的故障,評估的主要內容包括:網絡帶寬、PPS、QPS、CPU算力、內存大小、磁盤IO、業務特性、LB帶寬、網關帶寬等關鍵項和指標,以確保新業務進入容器集羣后,容器集羣也可以支持這個流量
節點標籤不宜打太多
K8S可用經過在節點上打不一樣的Tag,業務在部署的時候能夠選擇不一樣的資源池進行部署,若是資源池的Tag打的過多,則會帶來很大的管理難度,對於資源的合理應用也會形成很大的阻礙,建議業務部署選擇的資源池按業務特性進行選擇,傳媒目前主要的資源池包括:APP、網關、Redis、Kafka、PUSH、推薦、ES,這些資源池都有獨立的特性,不能互相影響
合理建立Service
若是服務須要用到Service資源,再去建立。Service資源建立後,當業務發佈、擴容、縮容、更新後,都會致使Endpoint發生變化,IPTables會全量刷新,若是Service下的POD不少,全量刷新會很慢,對整個網絡也會形成沒必要要的影響
容器IP不宜粒度太細
用戶在訪問Mysql數據庫的時候,爲了數據安全,都會對要訪問的庫增長IP白名單限制,在使用雲機和物理的時候,IP都能固定住,但在容器的場景下,IP地址是在一個大網段隨機分配的,若是要細粒度管理IP資源,就須要用到IPPool,爲每個集羣建立本身的IPPool,這樣對於管理複雜度有很大的增長,並且對於IP資源也有很大的浪費,由於對每個集羣,都須要預留必定數量的IP作爲備份,建議在容器集羣下,就不要限制Mysql數據庫白名單,或者限定容器集羣的一個大段,在管理上會方便不少
目前,傳媒的核心業務都已經進入了容器,對基礎資源的管理作到了下沉,後續,在K8S的基礎上主要作如下幾件事
資源精細化管理:咱們分析目前容器集羣的使用狀況,發現業務申請資源和實際使用的資源差距很大,致使業務佔用了不少資源,但其餘業務沒法從資源池中獲取須要的資源,接下來,咱們將會細化每一個集羣的資源申請量和實際使用量之間的差距,爭取縮小二者的差距
資源使用自動推薦:依據集羣歷史實際資源的使用狀況,可以給應用一個合理的資源量,讓業務能有個參考
資源彈性:爲了應對流量的徒增能快速擴容,須要增長容器的彈性,目前已經在使用HPA解決資源的彈性,也在嘗試VPA方面解決資源的彈性問題
推廣ServiceMesh:服務治理能力下沉,讓業務方更關注於業務自己,目前咱們已經支持了ServiceMesh的能力,接下來會給業務推廣這樣的能力
容量管理:容器集羣內的總體容量監控,包括:網絡、計算、內存、磁盤等資源的總體容量監控,爲新業務進入容器作到準確的評估