网易云容器服务基于Kubernetes的实践探索
Kubernetes的特點(diǎn)
近年來(lái)Docker容器作為一種輕量級(jí)虛擬化技術(shù)革新了整個(gè)IT領(lǐng)域軟件開發(fā)部署流程,如何高效自動(dòng)管理容器和相關(guān)的計(jì)算、存儲(chǔ)等資源,將容器技術(shù)真正落地上線,則需要一套強(qiáng)大容器編排服務(wù),當(dāng)前大紅大紫的Kubernetes已經(jīng)被公認(rèn)為這個(gè)領(lǐng)域的領(lǐng)導(dǎo)者。Google基于內(nèi)部Borg十多年大規(guī)模集群管理經(jīng)驗(yàn)在2014年親自傾心打造了Kubernetes這個(gè)開源項(xiàng)目,欲倚之與AWS在云計(jì)算2.0時(shí)代一爭(zhēng)高下,即便如此,Kubernetes的定位主要是面向私有云市場(chǎng),它最典型的部署模式是在GCE或AWS平臺(tái)上基于云主機(jī)、云網(wǎng)絡(luò)、云硬盤及負(fù)載均衡等技術(shù)給用戶單獨(dú)部署一整套Kubernetes容器管理集群,其本質(zhì)上是賣的IAAS服務(wù),Kubernetes集群還是需要靠用戶自己維護(hù),大家知道Kubernetes雖然功能強(qiáng)大但使用、管理、運(yùn)維門檻也高,出問(wèn)題了大多數(shù)用戶會(huì)束手無(wú)策。
這幾年國(guó)內(nèi)容器云領(lǐng)域也是群雄割據(jù),但多數(shù)還是以私有云為主,提供公有云容器服務(wù)的卻很少,主要是公有云要考慮的問(wèn)題多、挑戰(zhàn)大。雖然如此,網(wǎng)易云的還是提供了公有云模式的容器服務(wù)。網(wǎng)易云從2015年開始做容器服務(wù)時(shí)也被Kubernetes強(qiáng)大的功能、插件化思想和背后強(qiáng)大的技術(shù)實(shí)力說(shuō)吸引,至今已經(jīng)跟隨Kubernetes一起走過(guò)兩年多,積累了不少經(jīng)驗(yàn)。因?yàn)槲覀兲貏e希望以公有云的方式提供一種更易用容器服務(wù),任何對(duì)容器感興趣的用戶都能快速上手,為此也遇到了很多私有云下不會(huì)出現(xiàn)的問(wèn)題。
列舉幾個(gè)Kubernetes在公有云容器場(chǎng)景下的需要特別解決的關(guān)鍵問(wèn)題。一是Kubernetes里沒有用戶(租戶)的概念,只有一個(gè)很弱的命名空間來(lái)做邏輯隔離。二是Kubernetes和Docker的安全問(wèn)題很突出,API訪問(wèn)控制較弱且沒有用戶流控機(jī)制,一些資源全局可見。而Docker容器與宿主機(jī)共享內(nèi)核的輕量級(jí)隔離從根本上沒法做到徹底安全。三是Kubernetes集群所需要IAAS資源(如Node,PV)都要預(yù)先準(zhǔn)備足夠,否則容器隨時(shí)會(huì)創(chuàng)建失敗,公有云這樣的話會(huì)造成嚴(yán)重的資源浪費(fèi),產(chǎn)生巨大的成本問(wèn)題。四是Kubernetes單個(gè)集群能支撐的節(jié)點(diǎn)總數(shù)有限,最大安全規(guī)模只有5千個(gè)Node,公有云下擴(kuò)展性將會(huì)有問(wèn)題。
網(wǎng)易云容器如何解決Kubernetes在公有云上的問(wèn)題
先看下網(wǎng)易云容器服務(wù)的架構(gòu)圖(如圖1),這里的Kubernetes處于底層IAAS服務(wù)和上層容器平臺(tái)的中間,因?yàn)槲覀兊娜萜鞣?wù)不僅僅提供Kubernetes本身容器編排管理功能,更是為提供一整套專業(yè)的容器解決方案,還包括容器鏡像服務(wù),負(fù)載均衡服務(wù),通過(guò)使用DevOps 工具鏈高效管理微服務(wù)架構(gòu)。考慮到Kubernetes概念較多、普通用戶使用復(fù)雜,也為了便于整合其他配套服務(wù),我們并沒有直接暴露Kubernetes的API和所有概念給普通用戶。
公有云租戶概念
網(wǎng)易云容器服務(wù)基于Kubernetes已有的Namespace的邏輯隔離特性,虛擬出一個(gè)租戶的概念,并與Namespace進(jìn)行永久綁定:一個(gè)Namespace只能屬于一個(gè)租戶,一個(gè)租戶則可以有多個(gè)Namespace。這樣Kubernetes里不同租戶之間的Pod、Service、Secret就能自然分割,而且可以直接在原生的Namespace/Resouce級(jí)別的認(rèn)證授權(quán)上進(jìn)行租戶級(jí)別的安全改造。
多租戶安全問(wèn)題
關(guān)于Kubernetes的API的安全訪問(wèn)控制,盡管網(wǎng)易云容器沒有直接暴露Kubernetes的API給用戶,但用戶容器所在的Node端也都要訪問(wèn)API,Node本質(zhì)就是用戶的資源。我們?cè)谧钤缁贙ubernetes 1.0開發(fā)的時(shí)候就專門增加了一套輕量級(jí)擴(kuò)展授權(quán)控制插件:基于規(guī)則訪問(wèn)控制,比如配置各租戶只能Get和Watch屬于自己Namespace下的Pod資源,解決對(duì)Kubernetes資源API權(quán)限控制粒度不夠精確且無(wú)法動(dòng)態(tài)增減租戶的問(wèn)題。值得欣慰的是幾個(gè)月前官方發(fā)布的1. 6新推出RBAC(基于角色訪問(wèn)控制)功能,使得授權(quán)管理機(jī)制得以增強(qiáng),但服務(wù)端對(duì)用戶Node端訪問(wèn)的異常流量控制的缺乏依然是一個(gè)隱患,為此,我們也在apiserver端增加請(qǐng)求數(shù)來(lái)源分類統(tǒng)計(jì)和控制模塊,避免有不良用戶從容器里逃逸到Node上進(jìn)行惡意攻擊。?
原生的kube-proxy提供的內(nèi)部負(fù)載必須要List&Watch集群所有Service和Endpoint,導(dǎo)致就算在多租戶場(chǎng)景下Service和Endpoint也要全部暴露,同時(shí)導(dǎo)致iptables規(guī)則膨脹轉(zhuǎn)發(fā)效率極低;為此我們對(duì)kube-proxy也做了優(yōu)化改造:每個(gè)租戶的Node上只會(huì)List&Watch自己的相關(guān)Namespace下資源即可,這樣既解決了安全問(wèn)題又優(yōu)化性能,一箭雙雕。
至于Docker的隔離不徹底的問(wèn)題,我們則選擇了最徹底的做法:在容器外加了一層用戶看不見的虛擬機(jī),通過(guò)IAAS層虛擬機(jī)的OS 內(nèi)核隔離保證容器的安全。
容器的IAAS資源管理
容器云作為新一代的基礎(chǔ)設(shè)施云服務(wù),資源管理必然也是非常關(guān)鍵的。私有云場(chǎng)景下整個(gè)集群資源都屬于企業(yè)自己,預(yù)留的所有資源都可以一起直接使用、釋放、重用;而公有云多租戶下的所有資源首先是要進(jìn)行租戶劃分的,一旦加入kubernetes集群,Node、PV、Network的屬主租戶便已確定不變,如果給每個(gè)租戶都預(yù)留資源,海量租戶累計(jì)起來(lái)就非常恐怖了,沒法接受。當(dāng)然,可以讓公有云用戶在創(chuàng)建容器前,提前把所有需要的資源都準(zhǔn)備好,但這樣又會(huì)讓用戶用起來(lái)更復(fù)雜,與容器平臺(tái)易用性的初衷不符,我們更希望能幫用戶把精力花在業(yè)務(wù)本身。
于是我們需要改造kubernetes,以支持按需動(dòng)態(tài)申請(qǐng)、釋放資源。既然要按需實(shí)時(shí)申請(qǐng)資源,那就先理下容器的創(chuàng)建流程,簡(jiǎn)單起見,我們直接創(chuàng)建Pod來(lái)說(shuō)明這個(gè)過(guò)程,如圖3所示。
Pod創(chuàng)建出來(lái)后,首先控制器會(huì)檢查是否有PV(網(wǎng)易云容器為支持網(wǎng)絡(luò)隔離還增加租戶Network資源),PV資源是否匹配,不匹配則等待。如果Pod不需要PV或者PV匹配后調(diào)度器才能正常調(diào)度Pod,然后scheduler從集群所有Ready的 Node列表找合適Node綁定到Pod上,沒有則調(diào)度失敗,并從1秒開始以2的指數(shù)倍回退(backoff)等待并重新加入調(diào)度隊(duì)列,直到調(diào)度成功。最后在調(diào)度的Node的kubelet上拉鏡像并把容器創(chuàng)建并運(yùn)行起來(lái)。
通過(guò)分析上述流程可以發(fā)現(xiàn),可以在控制器上匹配PV或Network時(shí)實(shí)時(shí)創(chuàng)建資源,然后在調(diào)度器因缺少Node而調(diào)度失敗時(shí)再實(shí)時(shí)創(chuàng)建Node(虛擬機(jī)VM),再等下次失敗backoff重新調(diào)度。但是仔細(xì)分析后會(huì)發(fā)現(xiàn)還有很多問(wèn)題,首先是IAAS中間層提供的創(chuàng)建資源接口都是異步的,輪詢等待效率會(huì)很多,而且PV,Network,Node都串行申請(qǐng)會(huì)非常慢,容器本來(lái)就是秒級(jí)啟動(dòng),不能到云服務(wù)上就變成分鐘級(jí)別;其次Node從創(chuàng)建VM,初始化安裝Docker、kubelet、kube-proxy到啟動(dòng)進(jìn)程并注冊(cè)到Kubernetes上時(shí)間漫長(zhǎng),調(diào)度器backoff重新調(diào)度多次也不一定就緒,最后,基于Kubernetes的修改要考慮少侵入,Kubernetes社區(qū)極度活躍一直保持3個(gè)月發(fā)布一個(gè)大版本的節(jié)奏,要跟上社區(qū)發(fā)展可能需要不斷升級(jí)線上版本。
最終,我們通過(guò)增加獨(dú)立的ResourceController,借助watch機(jī)制采用全異步非阻塞、全事件驅(qū)動(dòng)模式。資源不足就發(fā)起資源異步申請(qǐng),并接著處理后面流程,而資源一旦就緒立馬觸發(fā)再調(diào)度,申請(qǐng)Node時(shí)中間層也提前準(zhǔn)備虛擬機(jī)資源池,并將Node初始化、安裝步驟預(yù)先在虛擬機(jī)鏡像中準(zhǔn)備好。于是,我們?cè)敿?xì)的創(chuàng)建流程演變?yōu)閳D4所示。(注:最新Kubernetes 已經(jīng)通過(guò)StorageClass類型支持PV dynamic provisioning)?
與原生的Kubernetes相比,我們?cè)黾恿艘粋€(gè)獨(dú)立的 ResourceController管理所有IAAS資源相關(guān)的事情,具體的Pod創(chuàng)建步驟如下:
- 1、上層client請(qǐng)求apiserver創(chuàng)建一個(gè)Pod。
- 2、ResourceController watch到有新增Pod,檢查PV和Network是否已經(jīng)創(chuàng)建;?
同時(shí),另一邊的scheduler也發(fā)現(xiàn)有新Pod尚未調(diào)度,也嘗試對(duì)Pod進(jìn)行調(diào)度。 - 3、因?yàn)橘Y源都沒有提前準(zhǔn)備,最初ResourceController檢查時(shí)發(fā)現(xiàn)沒有與Pod匹配的PV和Network,會(huì)向IAAS中間層請(qǐng)求創(chuàng)建云盤和網(wǎng)絡(luò)資源;?
scheduler 則也因?yàn)檎也坏娇烧{(diào)度的Node也同時(shí)向IAAS中間層請(qǐng)求創(chuàng)建對(duì)應(yīng)規(guī)格的VM資源(Node),這時(shí)Pod也不再重入調(diào)度隊(duì)列,后面一切準(zhǔn)備就緒才會(huì)重調(diào)度。 - 4、因?yàn)镮AAS中間層創(chuàng)建資源相對(duì)較慢,也只提供異步接口,待底層資源準(zhǔn)備完畢,便立即通過(guò)apiserver注冊(cè)PV、Network、Node資源
- 5~6、ResourceController當(dāng)發(fā)現(xiàn)PV和Network都滿足了,就將他們與Pod綁定;當(dāng)發(fā)現(xiàn)Pod申請(qǐng)的Node注冊(cè)上來(lái),且PV和Network均綁定,會(huì)把Pod設(shè)置為ResourceReady就緒狀態(tài)
- 7、Scheduler再次watch到Pod處于ResourceReady狀態(tài),則重新觸發(fā)調(diào)度過(guò)程,
- 8、Pod調(diào)度成功與新動(dòng)態(tài)創(chuàng)建Node進(jìn)行綁定
- 9~10、對(duì)應(yīng)Node的kubelet watch到新調(diào)度的Pod還沒有啟動(dòng),則會(huì)先拉取鏡像再啟動(dòng)容器。
集群最大規(guī)模問(wèn)題
從正式發(fā)布1.0版本至今最新的1.7,Kubernetes共經(jīng)歷了2次大規(guī)模的性能優(yōu)化,從1.0的200個(gè)node主要通過(guò)增加apiserver cache提升到1000個(gè)node,再到1.6通過(guò)升級(jí)etcdv3和json改protobuf最終提升到5000 node。但是官方稱后續(xù)不會(huì)再考慮繼續(xù)優(yōu)化單集群規(guī)模了,已有的集群聯(lián)邦功能又太過(guò)簡(jiǎn)陋。如果公有云場(chǎng)景下隨著已有用戶規(guī)模不斷增大,一旦快接近集群最大規(guī)模時(shí),就只能將其中一些大用戶一批批遷移出去來(lái)騰空間給剩余用戶。
于是我們自己在社區(qū)版本基礎(chǔ)上又做了大量定制化的性能優(yōu)化,目前單集群性能測(cè)試最大安全規(guī)模已經(jīng)超過(guò)3萬(wàn),驗(yàn)收測(cè)試包括集群高水位下,大并發(fā)創(chuàng)建速度deployment和快速重啟master端服務(wù)和所有node端kubelet等在內(nèi)的多種極端異常操作,保證創(chuàng)建時(shí)間均值<5s,99值<15s,集群中心管控服務(wù)最差在3分鐘內(nèi)快速恢復(fù)正常。
具體的優(yōu)化措施包括:
- 1、 scheduler優(yōu)化?
根據(jù)租戶之間資源完全隔離互補(bǔ)影響的特性,我們將原有的串行調(diào)度流程,改造為租戶間完全并行的調(diào)度模式,再配合協(xié)程池來(lái)爭(zhēng)奪可并行的調(diào)度任務(wù)。在調(diào)度算法上,還采用預(yù)先排除資源不足的node、優(yōu)化過(guò)濾函數(shù)順序等策略進(jìn)行局部?jī)?yōu)化。 - 2、 Controller優(yōu)化?
熟悉Kubernetes的人都知道,Kubernetes有個(gè)核心特點(diǎn)就是事件驅(qū)動(dòng),實(shí)時(shí)性很好,但是有個(gè)Sync事件卻干擾了FIFO的順序,我們通過(guò)將Add、Update、Delete、Sync事件排序并增加多優(yōu)先級(jí)隊(duì)列的方式解決這種異常干擾。?
增加Secret本地緩存 - 3、 apiserver優(yōu)化?
apiserver的核心是提供類似CRUD的restful接口,優(yōu)化方向無(wú)外乎降低響應(yīng)時(shí)間,減少cpu、內(nèi)存消耗以提高吞吐量,我們最主要的一個(gè)優(yōu)化是增加以租戶ID為過(guò)濾條件的查詢索引,這樣就能實(shí)現(xiàn)在租戶內(nèi)跨Namespace聚合查詢的效果。另外apiserver的客戶端原生的流控策略太暴力,客戶端默認(rèn)在流控被限制后會(huì)反復(fù)重試,進(jìn)一步加劇apiserver的壓力,我們?cè)黾恿艘环N基于反饋的智能重試的策略抹平這種突發(fā)流量。 - 4、Node端優(yōu)化?
kube-proxy本來(lái)需要控制整個(gè)集群負(fù)載轉(zhuǎn)發(fā)的,Apiserver有了租戶查詢索引后,我們就能只watch自己租戶內(nèi)的Service/Endpoint,急劇縮小iptables規(guī)則數(shù)量,提高查找轉(zhuǎn)發(fā)效率。而且我們還精簡(jiǎn)kubelet和kube-proxy內(nèi)存占用和連接數(shù)。
網(wǎng)易云容器服務(wù)的其他實(shí)踐及總結(jié)
容器的網(wǎng)絡(luò)是非常復(fù)雜一塊,容器云服務(wù)至少要提供穩(wěn)定、靈活、高效的跨主機(jī)網(wǎng)絡(luò),雖然開源網(wǎng)絡(luò)實(shí)現(xiàn)很多,但是它們要么不支持多租戶、要么性能不好,且直接拿沒有經(jīng)過(guò)大規(guī)模線上考驗(yàn)的開源軟件問(wèn)題總會(huì)很多。幸運(yùn)的時(shí)網(wǎng)易云有自己專業(yè)的IAAS云網(wǎng)絡(luò)團(tuán)隊(duì),他們能提供專業(yè)級(jí)的VPC網(wǎng)絡(luò)解決方案,天生就支持多租戶、安全策略控制和高性能擴(kuò)展,已經(jīng)做到容器與虛擬主機(jī)的網(wǎng)絡(luò)是完全互通且地位對(duì)等的。
網(wǎng)易云容器服務(wù)還在Kubernetes社區(qū)版本基礎(chǔ)上結(jié)合產(chǎn)品需求新增了很多功能,包括支持特有的有狀態(tài)容器,及Node故障時(shí)容器系統(tǒng)目錄也能自動(dòng)遷移以保持?jǐn)?shù)據(jù)不變,多副本Pod可按Node的AvailableZone分布強(qiáng)制均衡調(diào)度(社區(qū)只盡力均衡)、容器垂直擴(kuò)容、有狀態(tài)容器動(dòng)態(tài)掛卸載外網(wǎng)IP等。
相比容器的輕量級(jí)虛擬化,虛擬機(jī)雖然安全級(jí)別更高,但是在cpu、磁盤、網(wǎng)絡(luò)等方面都存在一定的性能損耗,而有些業(yè)務(wù)卻又對(duì)性能要求非常高。針對(duì)這些特殊需求,最近我們也在開發(fā)基于Kubernetes的高性能裸機(jī)容器,繞過(guò)虛擬機(jī)將網(wǎng)絡(luò)、存儲(chǔ)等虛擬化技術(shù)直接對(duì)接到Docker容器里,在結(jié)合SR-IOV網(wǎng)絡(luò)技術(shù)、網(wǎng)易高性能云盤NBS(netease block storage)等技術(shù)將虛擬化的性能損耗降到最低。
最后,分享一些網(wǎng)易云容器服務(wù)上線近兩年來(lái)的遇到的比較典型的坑。
-
1、Apiserver作為集群hub中心本身是無(wú)狀態(tài)的可水平擴(kuò)展,但是多apiserver讀寫會(huì)在Apiserver切換時(shí)可能會(huì)出現(xiàn)寫入的數(shù)據(jù)不能立馬讀到的問(wèn)題,原因是etcd的raft協(xié)議不是所有節(jié)點(diǎn)強(qiáng)一致寫的。
-
2、haproxy連接的問(wèn)題,多Apiserver前用haproxy做負(fù)載均衡,haproxy很容易出現(xiàn)客戶端端口不夠用和連接數(shù)過(guò)多的問(wèn)題,可以通過(guò)擴(kuò)大端口范圍、增加源ip地址等方式解決端口問(wèn)題,通過(guò)增加client/service的心跳探活解決異常連接GC的問(wèn)題。
-
3、用戶覆蓋更新已有tag的私有容器鏡像問(wèn)題,強(qiáng)烈建議大家不要覆蓋已有tag的鏡像,也不要使用latest這樣模糊的鏡像標(biāo)簽,否則RS多Pod副本或者同一個(gè)Node上同鏡像容器很容易出現(xiàn)版本不一致的詭異問(wèn)題。
-
4、有些容器小文件非常多,很容易把inode用光而磁盤空間卻剩余很多的問(wèn)題,建議把這種類型應(yīng)用調(diào)度到inode配置多的node上,另外原生kubelet也存在不會(huì)檢查inode過(guò)多觸發(fā)鏡像回收的問(wèn)題。
-
5、有些Pod刪除時(shí)銷毀過(guò)慢的問(wèn)題,Pod支持graceful刪除,但是如果容器鏡像啟動(dòng)命令寫得不好,可能會(huì)導(dǎo)致信號(hào)丟失不光沒法graceful刪除還會(huì)導(dǎo)致延遲30s的問(wèn)題
總之,在公有云場(chǎng)景下,用戶來(lái)源廣泛,使用習(xí)慣千變?nèi)f化沒法控制,我們已經(jīng)碰到過(guò)很多純私有云場(chǎng)景下很難出現(xiàn)的問(wèn)題,如用戶鏡像跑起不來(lái),Pod多容器端口沖突,日志直接輸出到標(biāo)準(zhǔn)輸出,或者日志寫太快沒有切割,甚至把容器磁盤100%寫滿等,因?yàn)槠邢?#xff0c;所以只能挑選幾個(gè)有代表性的專門說(shuō)明。因?yàn)樵粕弦紤]的問(wèn)題太多,特別是這種基礎(chǔ)設(shè)施服務(wù)類的,使用場(chǎng)景又非常靈活,線上出現(xiàn)的一些問(wèn)題之前完全想不到,包括很多還是用戶自己使用的問(wèn)題,但為了要讓用戶有更好的體驗(yàn),也只能盡力而為,優(yōu)先選擇一些通用的問(wèn)題去解決。
作者:婁超,網(wǎng)易云容器編排技術(shù)負(fù)責(zé)人。曾經(jīng)參與淘寶分布式文件系統(tǒng)tfs和阿里云緩存服務(wù)研發(fā),2015年加入網(wǎng)易參與網(wǎng)易云容器服務(wù)研發(fā),經(jīng)歷網(wǎng)易云基礎(chǔ)服務(wù)(蜂巢)v1.0,v2.0的容器編排相關(guān)的設(shè)計(jì)和研發(fā)工作,并推動(dòng)網(wǎng)易云內(nèi)部Kubernetes版本不斷升級(jí)。?
本文為《程序員》原創(chuàng)文章,未經(jīng)允許不得轉(zhuǎn)載,更多精彩文章請(qǐng)訂閱《程序員》,給我們投稿請(qǐng)聯(lián)系郵箱weiwei@csdn.net。(責(zé)編/魏偉)
歡迎掃描下方二維碼,關(guān)注CSDN云計(jì)算微信,獲取更多干貨原創(chuàng)內(nèi)容。
總結(jié)
以上是生活随笔為你收集整理的网易云容器服务基于Kubernetes的实践探索的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: zmbx是哪个保险公司
- 下一篇: [重磅] 如何更好地实现服务调用和消息推