內(nèi)容來源:2017年2月14日,來自騰訊互娛高級(jí)工程師黃惠波帶來了精彩的干貨分享,本文由IT大咖說(id:itdakashuo)整理轉(zhuǎn)自數(shù)人云公眾號(hào)(id:dmesos)傻铣。
摘要
騰訊游戲是國內(nèi)最大的網(wǎng)絡(luò)游戲社區(qū)止后,致力為游戲玩家提供完整的快樂解決方案须揣。騰訊互娛高級(jí)工程師黃惠波通過一些實(shí)際場景為大家解析kubernetes在騰訊游戲中的應(yīng)用實(shí)踐近哟。
大咖干貨地址:http://t.cn/RS1nMFy
騰訊在線游戲的容器化應(yīng)用場景
2014年驮审,我們開啟了容器化探索之路鲫寄,先回顧一下之前遇到的一些問題吉执。
在物理機(jī)時(shí)代,資源的交付時(shí)間較長地来,資源的利用率較低戳玫,也不能做到隔離。到了xen\kvm虛擬機(jī)時(shí)代未斑,問題得到了初步的解決咕宿,但在彈性伸縮方面仍有不足。隨著Docker技術(shù)的興起蜡秽,我們開始調(diào)研Docker在游戲容器化方面的應(yīng)用府阀。我們的目標(biāo)有兩個(gè),一是提高資源利用率芽突,二是通過Docker鏡像來標(biāo)準(zhǔn)化部署流程试浙。
選擇Docker技術(shù)之后,我們開始了容器調(diào)度平臺(tái)的選型寞蚌。我們當(dāng)時(shí)也調(diào)研了其它的一些組件田巴,比如Shipyard、Fig等挟秤,但這些組件無法支撐海量游戲容器調(diào)度壹哺。而自建調(diào)度平臺(tái)的話,時(shí)間成本非常的高艘刚。就在那時(shí)管宵,Google開源了kubernetes(當(dāng)時(shí)的版本是kubernetes v0.4),我們基于這個(gè)版本進(jìn)行了定制和開發(fā)攀甚,使其成為我們游戲容器的調(diào)度管理平臺(tái)啄糙。
在2015年初的時(shí)候,TDocker平臺(tái)上線云稚。之后隧饼,我們開始逐步接入業(yè)務(wù)。一開始的模式非常簡單静陈,就是把Docker當(dāng)成虛擬機(jī)來使用燕雁,但這不意味著游戲全容器化的實(shí)現(xiàn)诞丽。
大家知道,對(duì)于一項(xiàng)新技術(shù)來說拐格,大家都很謹(jǐn)慎僧免,會(huì)通過不斷的灰度上線,由點(diǎn)到面的策略推動(dòng)捏浊。截至目前懂衩,在全國各地以及加拿大等地區(qū),都有我們的部署點(diǎn)金踪;接入容器數(shù)超過兩萬浊洞,接入的業(yè)務(wù)也有兩百多款,包括手游胡岔、端游法希、頁游。在這么多的業(yè)務(wù)中靶瘸,主要分為兩種場景苫亦,第一種場景是輕量級(jí)虛擬機(jī)模式,這類容器承載多個(gè)服務(wù)進(jìn)程怨咪,需要一個(gè)具體的內(nèi)網(wǎng)IP屋剑,可以通稿SSH登錄。另一種是微服務(wù)化模式诗眨,這種模式會(huì)拆分得非常細(xì)唉匾,每一個(gè)容器對(duì)應(yīng)一個(gè)服務(wù)進(jìn)程,不需要對(duì)外可見的內(nèi)網(wǎng)IP辽话,可以使用虛擬IP肄鸽。
接下來會(huì)對(duì)每一個(gè)場景做一些分享。首先來看一下傳統(tǒng)游戲下的架構(gòu)油啤。這是非常典型的三層服務(wù)架構(gòu)典徘,包括了接入層、邏輯層益咬、數(shù)據(jù)庫層逮诲。同時(shí),游戲又分為:全區(qū)全服幽告、分區(qū)分服兩種類型梅鹦。對(duì)于分區(qū)分服類游戲,滾服對(duì)資源的調(diào)度非常頻繁冗锁,所以我們需要一個(gè)高效的調(diào)度平臺(tái)齐唆。
容器資源的調(diào)度管理基于kubernetes v0.4版本,上圖是一個(gè)簡化后的調(diào)度框架冻河。在Master端包括ApiServer和Scheduler箍邮,接收Web請(qǐng)求茉帅,然后做資源調(diào)度。在每個(gè)node節(jié)點(diǎn)上锭弊,包括agent進(jìn)程堪澎、Docker進(jìn)程,還有Lxcfs進(jìn)程味滞。在鏡像存儲(chǔ)方面樱蛤,當(dāng)時(shí)用的是Registry V1版,后端用的是ceph存儲(chǔ)〗0埃現(xiàn)在昨凡,我們自己維護(hù)了一個(gè)分支,功能上已滿足當(dāng)前的游戲需求攒暇,并保證運(yùn)行的穩(wěn)定土匀。所以在虛擬機(jī)模式下子房,我們不會(huì)升級(jí)kubernetes形用,而是把一些好用的功能合并進(jìn)來。
基于Kubernetes的功能定制與優(yōu)化
首先講調(diào)度器证杭,調(diào)度器為數(shù)以萬計(jì)的容器提供了一個(gè)靈活田度、穩(wěn)定、可靠的底層資源計(jì)算調(diào)度引擎解愤。資源的合理分配像是一場博弈镇饺,里面有很多矛盾的地方,需要我們根據(jù)游戲的特點(diǎn)做取舍送讲。
我們?cè)谠械恼{(diào)度策略上根據(jù)游戲特點(diǎn)做了一些定制奸笤。比如在網(wǎng)絡(luò)方面,傳統(tǒng)游戲的每個(gè)容器都需要一個(gè)對(duì)外可見的實(shí)體IP哼鬓,用戶可以通過SSH登錄到容器里面监右,因此對(duì)網(wǎng)絡(luò)資源進(jìn)行調(diào)度。部署容器的時(shí)候异希,會(huì)申請(qǐng)network的資源(比如IP)然后進(jìn)行劃分健盒,綁定到minions對(duì)象。這樣調(diào)度器調(diào)度的時(shí)候称簿,就可以通過這些配置信息給容器分配好網(wǎng)絡(luò)資源扣癣。
在社區(qū)中,CPU的分配用的是共享CPU的方式憨降,游戲采用的是一種混部的模式父虑。也就是說,將不同游戲業(yè)務(wù)部署到同一臺(tái)母機(jī)授药,采用綁定核的方式士嚎。這樣做一方面可以防止不同游戲之間的CPU搶占垂涯,另一方面對(duì)游戲成本的核算也會(huì)更加精細(xì)。例如航邢,某個(gè)游戲用了多少CPU這些指標(biāo)都是可以量化的耕赘。在容器分配CPU時(shí),結(jié)全numa技術(shù)膳殷,對(duì)于CPU CORE的分配會(huì)盡量地分配到同一個(gè)numa node上操骡,這樣可以提升性能,因?yàn)橥瑐€(gè)numa node的CPU訪問只需通過自身的local memory,無需通過系統(tǒng)總線赚窃。
在磁盤容量分配方面册招,由于游戲業(yè)務(wù)是有狀態(tài)的服務(wù),需要存儲(chǔ)勒极,所以我們把磁盤也作為一個(gè)可調(diào)度的資源分配給容器是掰。還有非親和性的調(diào)度。我們知道辱匿,在容器的可靠性與碎片優(yōu)化之間需要一個(gè)權(quán)衡键痛,讓用戶根據(jù)這些策略去選擇、部署自己的容器匾七。例如在非親和性的策略中絮短,用戶希望把容器是分散到各個(gè)母機(jī)上的,在母機(jī)宕機(jī)時(shí)昨忆,可以減少對(duì)游戲的影響丁频。
在IDC Module分配方面,游戲容器的部署會(huì)按地區(qū)劃分邑贴,比如按照上海席里、深圳或天津地區(qū)的IDC來劃分,所以我們提供了IDC部署策略拢驾。由于游戲需要考慮IDC的穿越流量問題奖磁,還有網(wǎng)絡(luò)延時(shí)的問題,所以同一個(gè)游戲的的不同模塊一般會(huì)部署到同一個(gè)IDC Module下面独旷。
海量應(yīng)用過程中遇到的問題與解決方案
以上是基于游戲行業(yè)特點(diǎn)定制的調(diào)度規(guī)劃署穗。在資源調(diào)度過程中,也遇到過一些問題嵌洼,例如容器資源的重復(fù)調(diào)度案疲。首先在調(diào)度過程中它會(huì)跟ScheduledPod(已完全調(diào)度的容器)進(jìn)行比較,判斷現(xiàn)在是不是有足夠的資源分配給待調(diào)度容器麻养,最后通過Bind(異步)把Pod信息寫入到ETCD褐啡。這里就會(huì)出現(xiàn)一個(gè)問題,那就是異步寫入慢了或者ScheduledPod同步慢了導(dǎo)致ScheduledPods不能及時(shí)刷新鳖昌,Scheduler計(jì)算出錯(cuò)备畦,從而造成資源重復(fù)計(jì)算低飒。針對(duì)這個(gè)問題,我們的解決方案是在資源調(diào)度完成后懂盐,做一個(gè)檢測的邏輯褥赊,檢測調(diào)度的容器信息是否已在ScheduledPod Cache這里,然后再進(jìn)入下一個(gè)容器的調(diào)度莉恼。當(dāng)然這會(huì)帶來一定的性能損耗拌喉。
解決了這個(gè)問題,又產(chǎn)生了另外一些問題俐银,那就是性能的問題尿背。在0.4版本的pod接口是非常低效的,在查每一個(gè)pod狀態(tài)的時(shí)候捶惜,會(huì)通過實(shí)時(shí)查所有的Host來確定田藐,設(shè)計(jì)不太合理。社區(qū)也做了一些方案吱七,當(dāng)時(shí)我們也是參考了社區(qū)的一些方案做了一些改造汽久,把pod狀態(tài)放在Cache里面,定時(shí)更新陪捷,從而提高查詢效率回窘。
還有一點(diǎn)就是RESTClient诺擅。在kubernetes中市袖,rest API大部分是異步進(jìn)行,對(duì)于這些異步的接口的請(qǐng)求烁涌,并不會(huì)立刻返回結(jié)果苍碟。這里有一個(gè)輪詢檢測狀態(tài)的邏輯,在檢測輪詢的時(shí)候有幾秒的休眠撮执,然后進(jìn)再行下一個(gè)輪詢微峰。默認(rèn)的休眠時(shí)間是2秒,這個(gè)時(shí)間對(duì)大部分場景來說有點(diǎn)過長抒钱,我們通過一些功能點(diǎn)的調(diào)整蜓肆,從物理機(jī)的小時(shí)級(jí)到虛擬機(jī)分鐘級(jí)的調(diào)度,再到還未調(diào)整之前的秒級(jí)調(diào)度谋币,到現(xiàn)在達(dá)到的毫秒級(jí)調(diào)度仗扬,現(xiàn)在的調(diào)度能力已能滿足游戲的需求。
講完調(diào)度蕾额,再看一下網(wǎng)絡(luò)方面早芭。網(wǎng)絡(luò)是非常關(guān)鍵酒繁、也是最為復(fù)雜的一環(huán)治宣。在虛擬機(jī)模式下纱皆,結(jié)合公司網(wǎng)絡(luò)環(huán)境為游戲提供高性能南蓬、穩(wěn)定的網(wǎng)絡(luò)環(huán)境,包括Bridge+VLAN\SR-IOV兩種方案语盈。
先來說舱馅,Docker的網(wǎng)絡(luò)還有kubernetes的網(wǎng)絡(luò)。對(duì)于Docker的NAT網(wǎng)絡(luò)來說刀荒,性能是最大的瓶頸习柠,同時(shí)它與物理機(jī)或虛擬機(jī)的通信路徑不一致也會(huì)對(duì)業(yè)務(wù)帶來一些未知的影響。比如照棋,外界不能看到容器真實(shí)的IP(必須要使用主機(jī)IP+port方式,端口本身就是稀缺資源资溃,并且ip+port的方式,無疑增加了復(fù)雜度)烈炭,TGW仍然可以為業(yè)務(wù)程序服務(wù)溶锭。Host模式?jīng)]有隔離,也不符合需求符隙。在kubernetes中趴捅,pod作為最小調(diào)度單元,每個(gè)pod有兩個(gè)容器霹疫,一個(gè)就是網(wǎng)絡(luò)容器拱绑,接管pod的網(wǎng)絡(luò),提供網(wǎng)絡(luò)服務(wù)丽蝎,并與其它容器共享net\IPC猎拨。另一個(gè)是App Container,也就是業(yè)務(wù)容器屠阻,使用第一個(gè)網(wǎng)絡(luò)容器的網(wǎng)絡(luò)红省。在這種模式下,容器之間的通訊是非常簡單的国觉。對(duì)于pod到pod吧恃、pod到物理機(jī)、物理機(jī)到pod的通訊麻诀,我們?yōu)槊總€(gè)pod分配一個(gè)內(nèi)網(wǎng)IP痕寓,對(duì)外可見,也可以互相通訊蝇闭。
接下來呻率,通過兩個(gè)方案給大家分析。首先是Bridge+Vlan的方案丁眼,母機(jī)都是部署在虛擬化區(qū)上筷凤,通過Vlan做網(wǎng)絡(luò)的隔離。在母機(jī)上架部署時(shí),創(chuàng)建Bridge設(shè)備和VLAN設(shè)備并將它們進(jìn)行關(guān)聯(lián)藐守。創(chuàng)建容器的時(shí)候,使用pipework腳本創(chuàng)建容器所需要的虛擬網(wǎng)卡設(shè)備挪丢,并把它們綁定到容器和Bridge上,同時(shí)會(huì)設(shè)置容器內(nèi)的IP卢厂、MAC地址以及路由等信息乾蓬。從而打通容器到外界的網(wǎng)絡(luò)通信。這里也做了一些優(yōu)化以提高性能慎恒,這里可以看到一個(gè)性能的對(duì)比任内,其中Bridge相對(duì)NAT網(wǎng)絡(luò)有相當(dāng)大的提升。這種方式可以滿足一部分游戲的需求融柬,而有一些業(yè)務(wù)死嗦,像FPS、Moba游戲等大流量粒氧,對(duì)網(wǎng)絡(luò)要求非常高的業(yè)務(wù)越除,還有類似MySQL-Proxy這種組件,在Bridge場景下是無法滿足需求的外盯。
所以我們探索了另一種網(wǎng)絡(luò)方式摘盆,就是SR-IOV模式,這種模式在zen\kvm虛擬化上用的比較多饱苟,游戲也需要這種網(wǎng)絡(luò)方案孩擂,因此我們把這種網(wǎng)絡(luò)方案也結(jié)合到Docker容器里面。
這里需要硬件的支持箱熬,結(jié)合SR-IOV技術(shù)的網(wǎng)卡类垦,在Docker容器內(nèi)就可以直接通過驅(qū)動(dòng)來加載虛擬的網(wǎng)卡并使用。使用的方式就如同在一臺(tái)物理機(jī)上使用一個(gè)真實(shí)的物理網(wǎng)卡一樣坦弟,這個(gè)虛擬網(wǎng)卡也擁有驅(qū)動(dòng)程序护锤,也擁有PCI BUSID,因此所有的虛擬機(jī)網(wǎng)絡(luò)操作都如同操作普通網(wǎng)卡一般酿傍,從而在性能上得到提升。為了進(jìn)一步發(fā)揮SR-IOV的網(wǎng)絡(luò)性能驱入,還需要對(duì)容器的相關(guān)網(wǎng)絡(luò)參數(shù)進(jìn)行配置赤炒,主要包括以下幾個(gè)方面:VF中斷CPU綁定;關(guān)閉物理機(jī)的irqbalance亏较;容器內(nèi)設(shè)置RPS(軟中斷均衡)網(wǎng)卡不能中斷均衡莺褒,對(duì)高性能的網(wǎng)絡(luò)形成了阻礙。為了解決這個(gè)問題雪情,需要設(shè)置容器內(nèi)的軟中斷均衡遵岩。通過上述的調(diào)整,性能得到了大幅度提升。
這是我們測試的一個(gè)結(jié)果尘执,這邊是物理機(jī)的舍哄,這是Bridge,這是SR-IOV誊锭,SR-IOV在網(wǎng)絡(luò)性能方面基本上已經(jīng)接近了物理機(jī)表悬,所以這個(gè)對(duì)于游戲大包量、大流量的應(yīng)用是非常適合的丧靡,現(xiàn)在我們把SR-IOV網(wǎng)絡(luò)作為傳統(tǒng)游戲里默認(rèn)的網(wǎng)絡(luò)模式蟆沫。
在游戲容器化過程中,我們希望資源的使用是明確的温治、合理的饭庞、可量化的。所以我們會(huì)為每個(gè)容器分配固定的資源熬荆,比如多少CPU但绕、多少內(nèi)存,還有需要多大磁盤惶看、IO帶寬捏顺。在啟動(dòng)容器的時(shí)候,比如CPU/Memory纬黎,通過Cgroup去做一個(gè)限制幅骄,disk通過xfs quota去做配額的限制。還有Buffered-IO帶寬的限制本今。
在資源分配方面拆座,我們開始做的是限定的CPU、內(nèi)存的分配冠息。在容器的整個(gè)生命周期挪凑,這個(gè)配置并非一沉不變,比如在業(yè)務(wù)運(yùn)行過程中都會(huì)有一些起伏和動(dòng)態(tài)調(diào)整逛艰,這是游戲的一張生命周期圖像躏碳,生命周期比較短,可能是一年半載的時(shí)間散怖,而且這里在線人數(shù)起伏也會(huì)比較大菇绵,需要?jiǎng)討B(tài)調(diào)整。而動(dòng)態(tài)調(diào)整就會(huì)涉及兩個(gè)方面镇眷,一是橫向的水平擴(kuò)展咬最,二是垂直伸縮。
每個(gè)游戲都會(huì)有一個(gè)IP欠动,因此橫向拓展比較困難永乌,因而更傾向于穩(wěn)定的垂直擴(kuò)縮。在虛擬化時(shí)代,擴(kuò)縮容是有損的翅雏,需要重啟機(jī)器來實(shí)現(xiàn)圈驼,而Docker可以做到無損的擴(kuò)縮容。我們對(duì)這個(gè)需求做了一些定制開發(fā)枚荣,比如CPU或者內(nèi)存碗脊,通過修改Cgroup的配額去把它提升上去或是削減下來。
當(dāng)在線人數(shù)上來的時(shí)候橄妆,我們可以給業(yè)務(wù)做到無損擴(kuò)容衙伶,不影響業(yè)務(wù)服務(wù)。過了一段時(shí)間害碾,當(dāng)人數(shù)降下來時(shí)矢劲,資源會(huì)閑置,我們會(huì)對(duì)空閑的資源做一些重復(fù)利用慌随,將其回收芬沉。這個(gè)時(shí)候做一些縮容,針對(duì)縮容我們做一個(gè)常態(tài)的動(dòng)作阁猜,檢測這些容器的CPU丸逸、內(nèi)存,結(jié)合業(yè)務(wù)的負(fù)載剃袍、活動(dòng)黄刚、定時(shí)驅(qū)動(dòng)。
Buffered IO Throttle需要內(nèi)核支持民效,我們與內(nèi)核團(tuán)隊(duì)進(jìn)地了緊密的合作憔维,提供了支持 Buffered IO Throttle功能的內(nèi)核版本。根據(jù)容器在母機(jī)資源的占比分配一定比例的IO帶寬畏邢。這在某種程序上解決了游戲之間互相影響的問題业扒。
監(jiān)控、告警是整個(gè)游戲運(yùn)營過程中最為核心的功能之一舒萎。容器上的監(jiān)控有別于物理機(jī)程储,cAdvisor和kubenetes結(jié)合得比較緊密,是個(gè)不錯(cuò)的方案逆甜。但它也會(huì)帶來問題虱肄,那就是需要自建監(jiān)控平臺(tái),而且它與周邊各系統(tǒng)的兼容性也有待考驗(yàn)交煞,同時(shí)改變運(yùn)維的使用習(xí)慣也需要時(shí)間。綜合考慮各種因素后斟或,我們放棄了cAdvisor素征,重新調(diào)研其它方案,希望可以沿用公司成熟的監(jiān)控平臺(tái),而且兼容周邊系統(tǒng)御毅。最終我們選用的是lxcfs + 公司agent的方案根欧,通過lxcfs去實(shí)現(xiàn)Docker容器內(nèi)的虛擬proc文件系統(tǒng),增強(qiáng)容器的隔離性端蛆。
我們這里以meminfo內(nèi)存統(tǒng)計(jì)信息為例凤粗,為大家講解如何通過lxcfs用戶態(tài)文件系統(tǒng)實(shí)現(xiàn)Docker容器內(nèi)的虛擬proc文件系。掛載虛擬proc文件系統(tǒng)到Docker容器今豆,通過Docker的volume功能嫌拣,將母機(jī)上的/var/lib/dockerfs/docker-xxx/proc掛載到Docker容器內(nèi)部的虛擬proc文件系統(tǒng)目錄下/proc/。此時(shí)在容器內(nèi)部/proc/目錄下可以看到一些列proc文件呆躲,其中包括meminfo异逐。用戶在容器內(nèi)讀取/proc/meminfo時(shí),實(shí)際上是讀取宿主機(jī)上的/var/lib/dockerfs/docker-xxx/proc/meminfo掛載到容器內(nèi)部的meminfo文件插掂。內(nèi)核VFS將用戶請(qǐng)求轉(zhuǎn)發(fā)到具體文件系統(tǒng)——fuse灰瞻,fuse文件系統(tǒng)封裝VFS請(qǐng)求,將請(qǐng)求轉(zhuǎn)發(fā)給Fuse設(shè)備(/dev/fuse)。如果設(shè)備上有已經(jīng)處理完成的請(qǐng)求(例如Cache)辅甥,文件系統(tǒng)獲取處理結(jié)果并返回給VFS酝润,VFS再反饋給用戶。用戶庫(fuse daemon)直接訪問Fuse設(shè)備璃弄,讀取文件系統(tǒng)轉(zhuǎn)發(fā)到設(shè)備上的請(qǐng)求要销,分析請(qǐng)求類型,調(diào)用用戶接口處理請(qǐng)求谢揪,處理完成后將處理結(jié)果返回給設(shè)備蕉陋,再由設(shè)備返回給VFS,VFS再反饋給用戶拨扶,從而實(shí)現(xiàn)容器內(nèi)的隔離凳鬓。公司agent可以通過讀取memory等信息,上報(bào)到監(jiān)控平臺(tái)做分析與報(bào)警患民。同時(shí)運(yùn)維通過SSH登錄到這個(gè)容器缩举,通過free、top等命令查看性能匹颤,維持了運(yùn)維原來的使用習(xí)慣仅孩。
在傳統(tǒng)游戲里,更多的是有狀態(tài)的服務(wù)會(huì)涉及到數(shù)據(jù)的存儲(chǔ)印蓖,我們通過Docker的volume提供持久化存儲(chǔ)辽慕。最開始我們采用HostPath方式,把host上的目錄掛載到容器里(例如/data)作為數(shù)據(jù)存儲(chǔ)赦肃。這種做法非常方便溅蛉、簡單公浪,無需額外的支持,但數(shù)據(jù)的安全性船侧、可靠性方面比較差欠气。所以我們采用了另外一種方案,即Ceph镜撩。改造kubenetes支持ceph预柒,通過volume掛載,提供更安全袁梗、更可靠的數(shù)據(jù)存儲(chǔ)方案宜鸯。解決在host故障時(shí),數(shù)據(jù)丟失的問題围段,應(yīng)用場景也變得更加廣泛顾翼,包括數(shù)據(jù)庫存儲(chǔ),鏡像存儲(chǔ)奈泪,容器遷移等适贸。
今年,我們開始支撐第一款微服務(wù)化游戲(極品飛車online)涝桅,源于之前對(duì)kubernetes的使用經(jīng)驗(yàn)拜姿。在微服化容器的調(diào)度中我們沿用了kubernetes,但在版本上重新做了選擇冯遂,跟隨著社區(qū)的發(fā)展蕊肥,選用了v1.2版。在微服務(wù)化模式下蛤肌,游戲的架構(gòu)產(chǎn)生了很大的變化壁却。按功能細(xì)分到各個(gè)小模塊,通過鏡像交付裸准、分發(fā)展东,最后以容器來部署服務(wù)。每個(gè)模塊相對(duì)獨(dú)立炒俱,之間信息流交互通過消息組件(例如RabbitMQ)來實(shí)現(xiàn)盐肃。同時(shí)每個(gè)容器無須配置內(nèi)網(wǎng)IP,可以通過域名來訪問权悟。所以在網(wǎng)絡(luò)方面也有所調(diào)整砸王,我們也評(píng)估了docker overlay、flannel峦阁、vxlan谦铃、maxvlan、SR-IOV等榔昔,結(jié)合其中的優(yōu)缺點(diǎn)荷辕,最后我們選定的方案如下:
1凿跳、集群內(nèi)pod與pod的之間的通信件豌,由于不需要內(nèi)網(wǎng)IP(可以用虛擬IP)所以采用overlay網(wǎng)絡(luò)疮方,由flannel組件實(shí)現(xiàn)。
2茧彤、公司內(nèi)網(wǎng)到集群內(nèi)pod通信骡显,例如HAProxy,游戲某些模塊曾掂,采用SR-IOV網(wǎng)絡(luò)惫谤,由自己定制的sriov-cni組件實(shí)現(xiàn)。這類pod具備雙重網(wǎng)絡(luò)珠洗,eth0對(duì)應(yīng)overlay網(wǎng)絡(luò)溜歪,eth1對(duì)應(yīng)SR-IOV網(wǎng)絡(luò)。
3许蓖、pod到公司內(nèi)網(wǎng)之間的通信蝴猪。在微服務(wù)場景下,游戲的數(shù)據(jù)存儲(chǔ)膊爪,周邊系統(tǒng)等自阱,部署在物理機(jī)或者虛擬機(jī)上,因此pod到這些模塊米酬、系統(tǒng)的訪問沛豌,走的是NAT網(wǎng)絡(luò)。
4赃额、公網(wǎng)(Internet)接入加派,采用公司的TGW方案。
在整個(gè)微服化平臺(tái)上跳芳,涉及到的關(guān)健技術(shù)點(diǎn)會(huì)更多:
1芍锦、網(wǎng)絡(luò)方案:即上述講到了overlay + SR-IOV + TGW + NAT方案
2、日志筛严,監(jiān)控:對(duì)于微服務(wù)化架構(gòu)的游戲醉旦,版本的交付都是通過鏡像,不會(huì)把公司的agent打到鏡像桨啃,所以原來的lxcfs + agent監(jiān)控就不適應(yīng)了车胡,所以這里我們重新打造了一個(gè)新的日志、監(jiān)控平臺(tái)照瘾,與藍(lán)鯨團(tuán)隊(duì)合作匈棘,實(shí)現(xiàn)了游戲業(yè)務(wù)日志采集;容器健康狀態(tài)析命、性能的監(jiān)控
3主卫、高可用方案:在資源的部署方面逃默,我們采用了replication controller方式,通過kubernetes的controller manager模塊來監(jiān)測pod的狀態(tài)簇搅,在發(fā)生故障的時(shí)候完域,實(shí)現(xiàn)快速的遷移、恢復(fù)服務(wù)瘩将。另一方面吟税,在load balance場景下,我們采用了HAProxy來實(shí)現(xiàn)
4姿现、安全方面:kubernetes集群承載著整個(gè)游戲容器資源的調(diào)度肠仪、管理。不管是人為誤操作备典,還是黑客入侵异旧,造成的影響將是非常之大。所以安全是我們需要考慮的重點(diǎn)提佣,結(jié)合kubernetes吮蛹,我們目前做了以幾方面,后面會(huì)有更加的安全策略提供
4.1 Authentication 和 Authorization镐依。使用https來加密流量匹涮,同時(shí)在用戶權(quán)限驗(yàn)證上,提供了token驗(yàn)證方式槐壳、ABAC權(quán)限認(rèn)證方式
4.2 Admission Controllers:配置具體的準(zhǔn)入規(guī)則
4.3 ServiceAccount:主要解決運(yùn)行在pod里的進(jìn)程需要調(diào)用kubernetes API以及非kubernetes API的其它服務(wù)問題
5然低、配置管理:通過configmap\secret為游戲提供簡易的配置管理
6、服務(wù)發(fā)現(xiàn):kubernetes會(huì)為每個(gè)pod分配一個(gè)虛擬的IP务唐,但這個(gè)IP是非固定的雳攘,例如pod發(fā)生故障遷移后,那么IP就會(huì)發(fā)生變化枫笛。所以在微服務(wù)化游戲架構(gòu)下吨灭,業(yè)務(wù)pod之間的訪問更多地采用域名方式進(jìn)行訪問。在kubernetes生態(tài)鏈中刑巧,提供了skydns作為DNS服務(wù)器喧兄,結(jié)合kubernetes的server可以很好的解決域名訪問問題
開始講游戲容器化的時(shí)候談到用鏡像來標(biāo)準(zhǔn)化部署,所以我們花了很多時(shí)間打造企業(yè)級(jí)的鏡像倉庫啊楚。目前支持registry v1\v2兩個(gè)版本吠冤,如右圖所示,在client端(docker)與registry之間采用nginx作為代理恭理,實(shí)現(xiàn)v1\v2不同請(qǐng)求的轉(zhuǎn)發(fā)拯辙,這樣一來,用戶無需關(guān)心到底請(qǐng)求的是v1還是v2颜价。在安全方面涯保,不同類型用戶不同的權(quán)限驗(yàn)證方案诉濒。公司內(nèi)部用戶接入OA認(rèn)證,與公司平臺(tái)打通夕春。外部用戶需要申請(qǐng)?jiān)L問權(quán)限未荒,由管理員分配帳號(hào),然后通過分配的帳號(hào)來請(qǐng)求撇他。在大批量拉取鏡像的時(shí)候茄猫,鏡像中心的性能、效率是我們需要考慮的問題困肩。前期我們通過mirror方案來實(shí)現(xiàn),在主要城市部署mirror registry脆侮,通過就近原則來拉取鏡像锌畸,解決性能瓶頸。后續(xù)我們還會(huì)采用P2P方案來提升鏡像拉取性能靖避。同時(shí)我們定制了Notification Server潭枣,用于鏡像pull\push日志記錄,便于后續(xù)分析與審計(jì)幻捏。在鏡像后端存儲(chǔ)方面盆犁,采用ceph集群方案,從而提供穩(wěn)定篡九、強(qiáng)大的數(shù)據(jù)存儲(chǔ)谐岁。
微服務(wù)化之路我們剛剛起航,在面臨挑戰(zhàn)的同時(shí)也帶來了機(jī)遇榛臼。不僅僅是在線業(yè)務(wù)的探索伊佃,我們也會(huì)探索離線計(jì)算、深度學(xué)習(xí)等系統(tǒng)的支持沛善。
來源于社區(qū)航揉,回饋于社區(qū)。后續(xù)我們還會(huì)更多地參與社區(qū)互動(dòng)金刁,為社區(qū)做貢獻(xiàn)帅涂。這也是我們想去做的一點(diǎn)。目前有個(gè)開源的項(xiàng)目尤蛮,sriov kubernetes的網(wǎng)絡(luò)插件(https://github.com/hustcat/sriov-cni)媳友,集中了騰訊游戲兩種模式下容器的高性能網(wǎng)絡(luò)經(jīng)驗(yàn),大家感興趣的可以關(guān)注下抵屿。