最近在反思,為什么在支撐容器平臺(tái)和微服務(wù)的競爭中芹血,Kubernetes會(huì)取得最終的勝出贮泞。因?yàn)樵诤芏嘟嵌葋碇v三大容器平臺(tái)從功能角度來說,最后簡直是一摸一樣幔烛,具體的比較可以參考本人前面的兩篇文章啃擦。
《Docker, Kubernetes, DCOS 不談信仰談技術(shù)》
《容器平臺(tái)選型的十大模式:Docker、DC/OS饿悬、K8S誰與當(dāng)先令蛉?》
經(jīng)過一段時(shí)間的思索,并采訪了從早期就開始實(shí)踐Kubernetes的網(wǎng)易云架構(gòu)師們,從而有了今天的分享珠叔。
一蝎宇、從企業(yè)上云的三大架構(gòu)看容器平臺(tái)的三種視角
一切都從企業(yè)上云的三大架構(gòu)開始。
如圖所示祷安,企業(yè)上的三大架構(gòu)為IT架構(gòu)姥芥,應(yīng)用架構(gòu)和數(shù)據(jù)架構(gòu),在不同的公司汇鞭,不同的人凉唐,不同的角色,關(guān)注的重點(diǎn)不同霍骄。
對(duì)于大部分的企業(yè)來講台囱,上云的訴求是從IT部門發(fā)起的,發(fā)起人往往是運(yùn)維部門读整,他們關(guān)注計(jì)算玄坦,網(wǎng)絡(luò),存儲(chǔ)绘沉,試圖通過云計(jì)算服務(wù)來減輕CAPEX和OPEX煎楣。
有的公司有ToC的業(yè)務(wù),因而累積了大量的用戶數(shù)據(jù)车伞,公司的運(yùn)營需要通過這部分?jǐn)?shù)據(jù)進(jìn)行大數(shù)據(jù)分析和數(shù)字化運(yùn)營择懂,因而在這些企業(yè)里面往往還需要關(guān)注數(shù)據(jù)架構(gòu)。
從事互聯(lián)網(wǎng)應(yīng)用的企業(yè)另玖,往往首先關(guān)注的是應(yīng)用架構(gòu)困曙,是否能夠滿足終端客戶的需求,帶給客戶良好的用戶體驗(yàn)谦去,業(yè)務(wù)量往往會(huì)在短期內(nèi)出現(xiàn)爆炸式的增長慷丽,因而關(guān)注高并發(fā)應(yīng)用架構(gòu),并希望這個(gè)架構(gòu)可以快速迭代鳄哭,從而搶占風(fēng)口要糊。
在容器出現(xiàn)之前,這三種架構(gòu)往往通過虛擬機(jī)云平臺(tái)的方式解決妆丘。
當(dāng)容器出現(xiàn)之后锄俄,容器的各種良好的特性讓人眼前一亮,他的輕量級(jí)勺拣、封裝奶赠、標(biāo)準(zhǔn)、易遷移药有、易交付的特性毅戈,使得容器技術(shù)迅速被廣泛使用。
然而一千個(gè)人心中有一千個(gè)哈姆雷特,由于原來工作的關(guān)系苇经,三類角色分別從自身的角度看到了容器的優(yōu)勢(shì)給自己帶來的便捷赘理。
對(duì)于原來在機(jī)房里面管計(jì)算、網(wǎng)絡(luò)塑陵、存儲(chǔ)的IT運(yùn)維工程師來講感憾,容器更像是一種輕量級(jí)的運(yùn)維模式蜡励,在他們看來令花,容器和虛擬機(jī)的最大的區(qū)別就是輕量級(jí),啟動(dòng)速度快凉倚,他們往往引以為豪的推出虛擬機(jī)模式的容器兼都。
對(duì)于數(shù)據(jù)架構(gòu)來講,他們每天都在執(zhí)行各種各樣的數(shù)據(jù)計(jì)算任務(wù)稽寒,容器相對(duì)于原來的JVM扮碧,是一種隔離性較好,資源利用率高的任務(wù)執(zhí)行模式杏糙。
從應(yīng)用架構(gòu)的角度出發(fā)慎王,容器是微服務(wù)的交付形式,容器不僅僅是做部署的宏侍,而是做交付的赖淤,CI/CD中的D的。
所以這三種視角的人谅河,在使用容器和選擇容器平臺(tái)時(shí)方法會(huì)不一樣咱旱。
二、Kubernetes才是微服務(wù)和DevOps的橋梁
Swarm:IT運(yùn)維工程師
從IT運(yùn)維工程師的角度來看:容器主要是輕量級(jí)绷耍、啟動(dòng)快吐限。而且自動(dòng)重啟,自動(dòng)關(guān)聯(lián)褂始。彈性伸縮的技術(shù)诸典,使得IT運(yùn)維工程師似乎不用再加班。
Swarm的設(shè)計(jì)顯然更加符合傳統(tǒng)IT工程師的管理模式崎苗。
他們希望能夠清晰地看到容器在不同機(jī)器的分布和狀態(tài)搂赋,可以根據(jù)需要很方便地SSH到一個(gè)容器里面去查看情況。
容器最好能夠原地重啟益缠,而非隨機(jī)調(diào)度一個(gè)新的容器脑奠,這樣原來在容器里面安裝的一切都是有的。
可以很方便的將某個(gè)運(yùn)行的容器打一個(gè)鏡像幅慌,而非從Dockerfile開始宋欺,這樣以后啟動(dòng)就可以復(fù)用在這個(gè)容器里面手動(dòng)做的100項(xiàng)工作。
容器平臺(tái)的集成性要好,用這個(gè)平臺(tái)本來是為了簡化運(yùn)維的齿诞,如果容器平臺(tái)本身就很復(fù)雜酸休,像Kubernetes這種本身就這么多進(jìn)程,還需要考慮它的高可用和運(yùn)維成本祷杈,這個(gè)不劃算斑司,一點(diǎn)都沒有比原來省事,而且成本還提高了但汞。
最好薄薄得一層宿刮,像一個(gè)云管理平臺(tái)一樣,只不過更加方便做跨云管理私蕾,畢竟容器鏡像很容易跨云遷移僵缺。
Swarm的使用方式比較讓IT工程師以熟悉的味道,其實(shí)OpenStack所做的事情它都能做踩叭,速度還快磕潮。
Swarm的問題
然而容器作為輕量級(jí)虛擬機(jī),暴露出去給客戶使用容贝,無論是外部客戶自脯,還是公司內(nèi)的開發(fā),而非IT人員自己使用的時(shí)候斤富,他們以為和虛擬機(jī)一樣膏潮,但是發(fā)現(xiàn)了不一樣的部分,就會(huì)很多的抱怨茂缚。
例如自修復(fù)功能戏罢,重啟之后,原來SSH進(jìn)去手動(dòng)安裝的軟件不見了脚囊,甚至放在硬盤上的文件也不見了龟糕,而且應(yīng)用沒有放在Entrypoint里面自動(dòng)啟動(dòng),自修復(fù)之后進(jìn)程沒有跑起來悔耘,還需要手動(dòng)進(jìn)去啟動(dòng)進(jìn)程讲岁,客戶會(huì)抱怨你這個(gè)自修復(fù)功能有啥用?
例如有的用戶會(huì)ps一下衬以,發(fā)現(xiàn)有個(gè)進(jìn)程他不認(rèn)識(shí)缓艳,于是直接kill掉了,結(jié)果是Entrypoint的進(jìn)程看峻,整個(gè)容器直接就掛了阶淘,客戶抱怨你們的容器太不穩(wěn)定,老是掛互妓。
容器自動(dòng)調(diào)度的時(shí)候溪窒,IP是不保持的坤塞,所以往往重啟原來的IP就沒了,很多用戶會(huì)提需求澈蚌,這個(gè)能不能保持啊摹芙,原來配置文件里面都配置的這個(gè)IP的,掛了重啟就變了宛瞄,這個(gè)怎么用啊浮禾,還不如用虛擬機(jī),至少?zèng)]那么容易掛份汗。
容器的系統(tǒng)盤盈电,也即操作系統(tǒng)的那個(gè)盤往往大小是固定的,雖然前期可以配置裸影,后期很難改變挣轨,而且沒辦法每個(gè)用戶可以選擇系統(tǒng)盤的大小军熏。有的用戶會(huì)抱怨轩猩,我們?cè)瓉肀緛砭秃芏鄸|西直接放在系統(tǒng)盤的,這個(gè)都不能調(diào)整荡澎,叫什么云計(jì)算的彈性啊均践。
如果給客戶說容器掛載數(shù)據(jù)盤,容器都啟動(dòng)起來了摩幔,有的客戶想像云主機(jī)一樣彤委,再掛載一個(gè)盤,容器比較難做到或衡,也會(huì)被客戶罵焦影。
如果容器的使用者不知道他們?cè)谟萌萜鳎?dāng)虛擬機(jī)來用封断,他們會(huì)覺得很難用斯辰,這個(gè)平臺(tái)一點(diǎn)都不好。
Swarm上手雖然相對(duì)比較容易坡疼,但是當(dāng)出現(xiàn)問題的時(shí)候彬呻,作為運(yùn)維容器平臺(tái)的人,會(huì)發(fā)現(xiàn)問題比較難解決柄瑰。
Swarm內(nèi)置的功能太多闸氮,都耦合在了一起,一旦出現(xiàn)錯(cuò)誤教沾,不容易debug蒲跨。如果當(dāng)前的功能不能滿足需求,很難定制化授翻。很多功能都是耦合在Manager里面的或悲,對(duì)Manager的操作和重啟影響面太大镐作。
Mesos:數(shù)據(jù)運(yùn)維工程師
從大數(shù)據(jù)平臺(tái)運(yùn)維的角度來講,如何更快的調(diào)度大數(shù)據(jù)處理任務(wù)隆箩,在有限的時(shí)間和空間里面该贾,更快的跑更多的任務(wù),是一個(gè)非常重要的要素捌臊。
所以當(dāng)我們?cè)u(píng)估大數(shù)據(jù)平臺(tái)牛不牛的時(shí)候杨蛋,往往以單位時(shí)間內(nèi)跑的任務(wù)數(shù)目以及能夠處理的數(shù)據(jù)量來衡量。
從數(shù)據(jù)運(yùn)維的角度來講理澎,Mesos是一個(gè)很好的調(diào)度器逞力,既然能夠跑任務(wù),也就能夠跑容器糠爬,Spark和Mesos天然的集成寇荧,有了容器之后,可以用更加細(xì)粒度的任務(wù)執(zhí)行方式执隧。
在沒有細(xì)粒度的任務(wù)調(diào)度之前揩抡,任務(wù)的執(zhí)行過程是這樣的。任務(wù)的執(zhí)行需要Master的節(jié)點(diǎn)來管理整個(gè)任務(wù)的執(zhí)行過程镀琉,需要Worker節(jié)點(diǎn)來執(zhí)行一個(gè)個(gè)子任務(wù)峦嗤。在整個(gè)總?cè)蝿?wù)的一開始,就分配好Master和所有的Work所占用的資源屋摔,將環(huán)境配置好烁设,等在那里執(zhí)行子任務(wù),沒有子任務(wù)執(zhí)行的時(shí)候钓试,這個(gè)環(huán)境的資源都是預(yù)留在那里的装黑,顯然不是每個(gè)Work總是全部跑滿的,存在很多的資源浪費(fèi)弓熏。
在細(xì)粒度的模式下恋谭,在整個(gè)總?cè)蝿?wù)開始的時(shí)候,只會(huì)為Master分配好資源硝烂,不給Worker分配任何的資源箕别,當(dāng)需要執(zhí)行一個(gè)子任務(wù)的時(shí)候,Master才臨時(shí)向Mesos申請(qǐng)資源滞谢,環(huán)境沒有準(zhǔn)備好怎么辦串稀?好在有Docker,啟動(dòng)一個(gè)Docker狮杨,環(huán)境就都有了母截,在里面跑子任務(wù)。在沒有任務(wù)的時(shí)候橄教,所有的節(jié)點(diǎn)上的資源都是可被其他任務(wù)使用的清寇,大大提升了資源利用效率喘漏。
這是Mesos的最大的優(yōu)勢(shì),在Mesos的論文中华烟,最重要闡述的就是資源利用率的提升翩迈,而Mesos的雙層調(diào)度算法是核心。
原來大數(shù)據(jù)運(yùn)維工程師出身的盔夜,會(huì)比較容易選擇Mesos作為容器管理平臺(tái)负饲。只不過原來是跑短任務(wù),加上marathon就能跑長任務(wù)喂链。但是后來Spark將細(xì)粒度的模式deprecated掉了返十,因?yàn)樾蔬€是比較差。
Mesos的問題
調(diào)度在大數(shù)據(jù)領(lǐng)域是核心中的核心椭微,在容器平臺(tái)中是重要的洞坑,但是不是全部。所以容器還需要編排蝇率,需要各種外圍組件迟杂,讓容器跑起來運(yùn)行長任務(wù),并且相互訪問瓢剿。Marathon只是萬里長征的第一步逢慌。
所以早期用Marathon + Mesos的廠商悠轩,多是裸用Marathon和Mesos的间狂,由于周邊不全,因而要做各種的封裝火架,各家不同鉴象。大家有興趣可以到社區(qū)上去看裸用Marathon和Mesos的廠商,各有各的負(fù)載均衡方案何鸡,各有各的服務(wù)發(fā)現(xiàn)方案纺弊。
所以后來有了DCOS,也就是在Marathon和Mesos之外骡男,加了大量的周邊組件淆游,補(bǔ)充一個(gè)容器平臺(tái)應(yīng)有的功能,但是很可惜隔盛,很多廠商都自己定制過了犹菱,還是裸用Marathon和Mesos的比較多。
而且Mesos雖然調(diào)度牛吮炕,但是只解決一部分調(diào)度腊脱,另一部分靠用戶自己寫framework以及里面的調(diào)度,有時(shí)候還需要開發(fā)Executor龙亲,這個(gè)開發(fā)起來還是很復(fù)雜的陕凹,學(xué)習(xí)成本也比較高悍抑。
雖然后來的DCOS功能也比較全了,但是感覺沒有如Kubernetes一樣使用統(tǒng)一的語言杜耙,而是采取大雜燴的方式搜骡。在DCOS的整個(gè)生態(tài)中,Marathon是Scala寫的佑女,Mesos是C++寫的浆兰,Admin Router是Nginx+lua,Mesos-DNS是Go珊豹,Marathon-lb是Python簸呈,Minuteman是Erlang,這樣太復(fù)雜了吧店茶,林林總總蜕便,出現(xiàn)了Bug的話,比較難自己修復(fù)贩幻。
Kubernetes
而Kubernetes不同轿腺,初看Kubernetes的人覺得他是個(gè)奇葩所在,容器還沒創(chuàng)建出來丛楚,概念先來一大堆族壳,文檔先讀一大把,編排文件也復(fù)雜趣些,組件也多仿荆,讓很多人望而卻步。我就想創(chuàng)建一個(gè)容器玩玩坏平,怎么這么多的前置條件拢操。如果你將Kubernetes的概念放在界面上,讓客戶去創(chuàng)建容器舶替,一定會(huì)被客戶罵令境。
在開發(fā)人員角度,使用Kubernetes絕對(duì)不是像使用虛擬機(jī)一樣顾瞪,開發(fā)除了寫代碼舔庶,做構(gòu)建,做測試陈醒,還需要知道自己的應(yīng)用是跑在容器上的惕橙,而不是當(dāng)甩手掌柜。開發(fā)人員需要知道孵延,容器是和原來的部署方式不一樣的存在吕漂,你需要區(qū)分有狀態(tài)和無狀態(tài),容器掛了起來尘应,就會(huì)按照鏡像還原了惶凝。開發(fā)人員需要寫Dockerfile吼虎,需要關(guān)心環(huán)境的交付,需要了解太多原來不了解的東西苍鲜。實(shí)話實(shí)說思灰,一點(diǎn)都不方便。
在運(yùn)維人員角度混滔,使用Kubernetes也絕對(duì)不是像運(yùn)維虛擬機(jī)一樣澄峰,我交付出來了環(huán)境饿这,應(yīng)用之間互相怎么調(diào)用奢米,我才不管检激,我就管網(wǎng)絡(luò)通不通。在運(yùn)維眼中做了過多他不該關(guān)心的事情领跛,例如服務(wù)的發(fā)現(xiàn)乏德,配置中心,熔斷降級(jí)吠昭,這都應(yīng)該是代碼層面關(guān)心的事情喊括,應(yīng)該是SpringCloud和Dubbo關(guān)心的事情,為什么要到容器平臺(tái)層來關(guān)心這個(gè)矢棚。
Kubernetes + Docker郑什,卻是Dev和Ops融合的一個(gè)橋梁。
Docker是微服務(wù)的交付工具蒲肋,微服務(wù)之后蘑拯,服務(wù)太多了,單靠運(yùn)維根本管不過來肉津,而且很容易出錯(cuò)强胰,這就需要研發(fā)開始關(guān)心環(huán)境交付這件事情。例如配置改了什么妹沙,創(chuàng)建了哪些目錄,如何配置權(quán)限熟吏,只有開發(fā)最清楚距糖,這些信息一方面很難通過文檔的方式,又及時(shí)又準(zhǔn)確的同步到運(yùn)維部門來牵寺,就算是同步過來了悍引,運(yùn)維部門的維護(hù)量也非常的大。
所以帽氓,有了容器趣斤,最大的改變是環(huán)境交付的提前,是每個(gè)開發(fā)多花5%的時(shí)間黎休,去換取運(yùn)維200%的勞動(dòng)浓领,并且提高穩(wěn)定性玉凯。
而另一方面,本來運(yùn)維只管交付資源联贩,給你個(gè)虛擬機(jī)漫仆,虛擬機(jī)里面的應(yīng)用如何相互訪問我不管,你們愛咋地咋地泪幌,有了Kubernetes以后盲厌,運(yùn)維層要關(guān)注服務(wù)發(fā)現(xiàn),配置中心祸泪,熔斷降級(jí)吗浩。
兩者融合在了一起。
在微服務(wù)化的研發(fā)的角度來講没隘,Kubernetes雖然復(fù)雜拓萌,但是設(shè)計(jì)的都是有道理的,符合微服務(wù)的思想升略。
三微王、微服務(wù)化的十個(gè)設(shè)計(jì)要點(diǎn)
微服務(wù)有哪些要點(diǎn)呢?第一張圖是SpringCloud的整個(gè)生態(tài)品嚣。
第二張圖是微服務(wù)的12要素以及在網(wǎng)易云的實(shí)踐炕倘。
第三張圖是構(gòu)建一個(gè)高并發(fā)的微服務(wù),需要考慮的所有的點(diǎn)翰撑。(打個(gè)廣告罩旋,這是一門課程,即將上線眶诈。)
接下來細(xì)說微服務(wù)的設(shè)計(jì)要點(diǎn)涨醋。
設(shè)計(jì)要點(diǎn)一:API網(wǎng)關(guān)。
在實(shí)施微服務(wù)的過程中逝撬,不免要面臨服務(wù)的聚合與拆分浴骂,當(dāng)后端服務(wù)的拆分相對(duì)比較頻繁的時(shí)候,作為手機(jī)App來講宪潮,往往需要一個(gè)統(tǒng)一的入口溯警,將不同的請(qǐng)求路由到不同的服務(wù),無論后面如何拆分與聚合狡相,對(duì)于手機(jī)端來講都是透明的梯轻。
有了API網(wǎng)關(guān)以后,簡單的數(shù)據(jù)聚合可以在網(wǎng)關(guān)層完成尽棕,這樣就不用在手機(jī)App端完成喳挑,從而手機(jī)App耗電量較小,用戶體驗(yàn)較好。
有了統(tǒng)一的API網(wǎng)關(guān)伊诵,還可以進(jìn)行統(tǒng)一的認(rèn)證和鑒權(quán)单绑,盡管服務(wù)之間的相互調(diào)用比較復(fù)雜,接口也會(huì)比較多日戈,API網(wǎng)關(guān)往往只暴露必須的對(duì)外接口询张,并且對(duì)接口進(jìn)行統(tǒng)一的認(rèn)證和鑒權(quán),使得內(nèi)部的服務(wù)相互訪問的時(shí)候浙炼,不用再進(jìn)行認(rèn)證和鑒權(quán)份氧,效率會(huì)比較高。
有了統(tǒng)一的API網(wǎng)關(guān)弯屈,可以在這一層設(shè)定一定的策略蜗帜,進(jìn)行A/B測試,藍(lán)綠發(fā)布资厉,預(yù)發(fā)環(huán)境導(dǎo)流等等厅缺。API網(wǎng)關(guān)往往是無狀態(tài)的,可以橫向擴(kuò)展宴偿,從而不會(huì)成為性能瓶頸湘捎。
設(shè)計(jì)要點(diǎn)二:無狀態(tài)化,區(qū)分有狀態(tài)的和無狀態(tài)的應(yīng)用窄刘。
影響應(yīng)用遷移和橫向擴(kuò)展的重要因素就是應(yīng)用的狀態(tài)窥妇,無狀態(tài)服務(wù),是要把這個(gè)狀態(tài)往外移娩践,將Session數(shù)據(jù)活翩,文件數(shù)據(jù),結(jié)構(gòu)化數(shù)據(jù)保存在后端統(tǒng)一的存儲(chǔ)中翻伺,從而應(yīng)用僅僅包含商務(wù)邏輯材泄。
狀態(tài)是不可避免的,例如ZooKeeper, DB吨岭,Cache等拉宗,把這些所有有狀態(tài)的東西收斂在一個(gè)非常集中的集群里面。
整個(gè)業(yè)務(wù)就分兩部分未妹,一個(gè)是無狀態(tài)的部分簿废,一個(gè)是有狀態(tài)的部分。
無狀態(tài)的部分能實(shí)現(xiàn)兩點(diǎn)络它,一是跨機(jī)房隨意地部署,也即遷移性歪赢,一是彈性伸縮化戳,很容易的進(jìn)行擴(kuò)容。
有狀態(tài)的部分,如DB点楼,Cache扫尖,ZooKeeper有自己的高可用機(jī)制,要利用到他們自己的高可用的機(jī)制來實(shí)現(xiàn)這個(gè)狀態(tài)的集群掠廓。
雖說無狀態(tài)化换怖,但是當(dāng)前處理的數(shù)據(jù),還是會(huì)在內(nèi)存里面的蟀瞧,當(dāng)前的進(jìn)程掛掉數(shù)據(jù)沉颂,肯定也是有一部分丟失的,為了實(shí)現(xiàn)這一點(diǎn)悦污,服務(wù)要有重試的機(jī)制铸屉,接口要有冪等的機(jī)制,通過服務(wù)發(fā)現(xiàn)機(jī)制切端,重新調(diào)用一次后端的服務(wù)的另一個(gè)實(shí)例就可以了彻坛。
設(shè)計(jì)要點(diǎn)三:數(shù)據(jù)庫的橫向擴(kuò)展。
數(shù)據(jù)庫是保存狀態(tài)踏枣,最重要的也是最容易出現(xiàn)瓶頸的昌屉。有了分布式數(shù)據(jù)庫可以使得數(shù)據(jù)庫的性能可以隨著節(jié)點(diǎn)的增加線性的增加。
分布式數(shù)據(jù)庫最最下面是RDS茵瀑,是主備的间驮,通過MySql的內(nèi)核開發(fā)能力,我們能夠?qū)崿F(xiàn)主備切換數(shù)據(jù)零丟失瘾婿,所以數(shù)據(jù)落在這個(gè)RDS里面蜻牢,是非常放心的,哪怕是掛了一個(gè)節(jié)點(diǎn)偏陪,切換完了以后抢呆,你的數(shù)據(jù)也是不會(huì)丟的。
再往上就是橫向怎么承載大的吞吐量的問題笛谦,上面有一個(gè)的負(fù)載均衡NLB抱虐,用LVS,HAProxy, Keepalived饥脑,下面接了一層Query Server恳邀。Query Server是可以根據(jù)監(jiān)控的數(shù)據(jù)進(jìn)行橫向的擴(kuò)展的,如果出現(xiàn)了故障灶轰,可以隨時(shí)進(jìn)行替換的修復(fù)的谣沸,對(duì)于業(yè)務(wù)層是沒有任何感知的。
另外一個(gè)就是雙機(jī)房的部署笋颤,DDB這面開發(fā)了一個(gè)數(shù)據(jù)運(yùn)河NDC的組件乳附,可以使得不同的DDB之間在不同的機(jī)房里面進(jìn)行同步,這時(shí)候不但在一個(gè)數(shù)據(jù)中心里面是分布式的,在多個(gè)數(shù)據(jù)中心里面也會(huì)有一個(gè)類似雙活的一個(gè)備份赋除,高可用性有非常好的保證阱缓。
設(shè)計(jì)要點(diǎn)四:緩存、緩存
在高并發(fā)場景下緩存是非常重要的举农。要有層次的緩存荆针,使得數(shù)據(jù)盡量靠近用戶。數(shù)據(jù)越靠近用戶能承載的并發(fā)量也越大颁糟,響應(yīng)時(shí)間越小航背。
在手機(jī)客戶端App上就應(yīng)該有一層緩存,不是所有的數(shù)據(jù)都每時(shí)每刻都從后端拿滚停,而是只拿重要的沃粗,關(guān)鍵的,時(shí)常變化的數(shù)據(jù)键畴。
尤其是對(duì)于靜態(tài)數(shù)據(jù)最盅,可以過一段時(shí)間去取一次,而且也沒必要到數(shù)據(jù)中心去取起惕,可以通過CDN涡贱,將數(shù)據(jù)緩存在距離客戶端最近的節(jié)點(diǎn)上,進(jìn)行就近的下載惹想。
有的時(shí)候CDN里面沒有问词,還是要回到數(shù)據(jù)中心去下載,稱為回源嘀粱,在數(shù)據(jù)中心的最外層激挪,我們稱為接入層,可以設(shè)置一層緩存锋叨,將大部分的請(qǐng)求攔截垄分,從而不會(huì)對(duì)后臺(tái)的數(shù)據(jù)庫造成壓力。
如果是動(dòng)態(tài)數(shù)據(jù)娃磺,還是需要訪問應(yīng)用薄湿,通過應(yīng)用中的商務(wù)邏輯生成,或者去數(shù)據(jù)庫中讀取偷卧,為了減輕數(shù)據(jù)庫的壓力豺瘤,應(yīng)用可以使用本地的緩存,也可以使用分布式緩存听诸,如Memcached或者Redis坐求,使得大部分的請(qǐng)求讀取緩存即可,不必訪問數(shù)據(jù)庫晌梨。
當(dāng)然動(dòng)態(tài)數(shù)據(jù)還可以做一定的靜態(tài)化瞻赶,也即降級(jí)成靜態(tài)數(shù)據(jù)赛糟,從而減少后端的壓力派任。
設(shè)計(jì)要點(diǎn)五式:服務(wù)拆分和服務(wù)發(fā)現(xiàn)砸逊。
當(dāng)系統(tǒng)扛不住,應(yīng)用變化快的時(shí)候掌逛,往往要考慮將比較大的服務(wù)拆分為一系列小的服務(wù)师逸。
這樣首先的好處就是開發(fā)比較獨(dú)立,當(dāng)非常多的人在維護(hù)同一個(gè)代碼倉庫的時(shí)候豆混,往往對(duì)代碼的修改就會(huì)相互影響篓像,常常會(huì)出現(xiàn),我沒改什么測試就不通過了皿伺,而且代碼提交的時(shí)候员辩,經(jīng)常會(huì)出現(xiàn)沖突,需要進(jìn)行代碼合并鸵鸥,大大降低了開發(fā)的效率奠滑。
另外一個(gè)好處就是上線獨(dú)立,物流模塊對(duì)接了一家新的快遞公司妒穴,需要連同下單一起上線宋税,這是非常不合理的行為,我沒改還要我重啟讼油,我沒改還讓我發(fā)布杰赛,我沒改還要我開會(huì),都是應(yīng)該拆分的時(shí)機(jī)矮台。
另外再就是高并發(fā)時(shí)段的擴(kuò)容乏屯,往往只有最關(guān)鍵的下單和支付流程是核心,只要將關(guān)鍵的交易鏈路進(jìn)行擴(kuò)容即可瘦赫,如果這時(shí)候附帶很多其他的服務(wù)辰晕,擴(kuò)容即使不經(jīng)濟(jì)的,也是很有風(fēng)險(xiǎn)的耸彪。
再就是容災(zāi)和降級(jí)伞芹,在大促的時(shí)候,可能需要犧牲一部分的邊角功能蝉娜,但是如果所有的代碼耦合在一起唱较,很難將邊角的部分功能進(jìn)行降級(jí)。
當(dāng)然拆分完畢以后召川,應(yīng)用之間的關(guān)系就更加復(fù)雜了南缓,因而需要服務(wù)發(fā)現(xiàn)的機(jī)制,來管理應(yīng)用相互的關(guān)系荧呐,實(shí)現(xiàn)自動(dòng)的修復(fù)汉形,自動(dòng)的關(guān)聯(lián)纸镊,自動(dòng)的負(fù)載均衡,自動(dòng)的容錯(cuò)切換概疆。
設(shè)計(jì)要點(diǎn)六:服務(wù)編排與彈性伸縮
當(dāng)服務(wù)拆分了逗威,進(jìn)程就會(huì)非常的多,因而需要服務(wù)編排岔冀,來管理服務(wù)之間的依賴關(guān)系凯旭,以及將服務(wù)的部署代碼化,也就是我們常說的基礎(chǔ)設(shè)施即代碼使套。這樣對(duì)于服務(wù)的發(fā)布罐呼,更新,回滾侦高,擴(kuò)容嫉柴,縮容,都可以通過修改編排文件來實(shí)現(xiàn)奉呛,從而增加了可追溯性计螺,易管理性,和自動(dòng)化的能力侧馅。
既然編排文件也可以用代碼倉庫進(jìn)行管理危尿,就可以實(shí)現(xiàn)一百個(gè)服務(wù)中,更新其中五個(gè)服務(wù)馁痴,只要修改編排文件中的五個(gè)服務(wù)的配置就可以谊娇,當(dāng)編排文件提交的時(shí)候,代碼倉庫自動(dòng)觸發(fā)自動(dòng)部署升級(jí)腳本罗晕,從而更新線上的環(huán)境济欢,當(dāng)發(fā)現(xiàn)新的環(huán)境有問題的時(shí)候,當(dāng)然希望將這五個(gè)服務(wù)原子性的回滾小渊,如果沒有編排文件法褥,需要人工記錄這次升級(jí)了哪五個(gè)服務(wù)。有了編排文件酬屉,只要在代碼倉庫里面revert半等,就回滾到上一個(gè)版本了。所有的操作在代碼倉庫里面都是可以看到的呐萨。
設(shè)計(jì)要點(diǎn)七:統(tǒng)一配置中心
服務(wù)拆分以后杀饵,服務(wù)的數(shù)量非常的多,如果所有的配置都以配置文件的方式谬擦,放在應(yīng)用本地的話切距,非常難以管理,可以想象當(dāng)有幾百上千個(gè)進(jìn)程中惨远,有一個(gè)配置出現(xiàn)了問題谜悟,你很難將它找出來话肖,因而需要有統(tǒng)一的配置中心,來管理所有的配置葡幸,進(jìn)行統(tǒng)一的配置下發(fā)最筒。
在微服務(wù)中,配置往往分為幾類礼患,一類是幾乎不變的配置是钥,這種配置可以直接打在容器鏡像里面,第二類是啟動(dòng)時(shí)就會(huì)確定的配置缅叠,這種配置往往通過環(huán)境變量,在容器啟動(dòng)的時(shí)候傳進(jìn)去虏冻,第三類就是統(tǒng)一的配置肤粱,需要通過配置中心進(jìn)行下發(fā),例如在大促的情況下厨相,有些功能需要降級(jí)领曼,哪些功能可以降級(jí),哪些功能不能降級(jí)蛮穿,都可以在配置文件中統(tǒng)一的配置庶骄。
設(shè)計(jì)要點(diǎn)八:統(tǒng)一的日志中心
同樣是進(jìn)程數(shù)目非常多的時(shí)候,很難對(duì)成千上百個(gè)容器践磅,一個(gè)一個(gè)登錄進(jìn)去查看日志单刁,所以需要統(tǒng)一的日志中心來收集日志,為了使收集到的日志容易分析府适,對(duì)于日志的規(guī)范羔飞,需要有一定的要求,當(dāng)所有的服務(wù)都遵守統(tǒng)一的日志規(guī)范的時(shí)候檐春,在日志中心就可以對(duì)一個(gè)交易流程進(jìn)行統(tǒng)一的追溯逻淌。例如在最后的日志搜索引擎中,搜索交易號(hào)疟暖,就能夠看到在哪個(gè)過程出現(xiàn)了錯(cuò)誤或者異常卡儒。
設(shè)計(jì)要點(diǎn)九:熔斷,限流俐巴,降級(jí)
服務(wù)要有熔斷骨望,限流,降級(jí)的能力窜骄,當(dāng)一個(gè)服務(wù)調(diào)用另外一個(gè)服務(wù)锦募,出現(xiàn)超時(shí)的時(shí)候,應(yīng)及時(shí)的返回邻遏,而非阻塞在那個(gè)地方糠亩,從而影響其他用戶的交易虐骑,可以返回默認(rèn)的托底數(shù)據(jù)。
當(dāng)一個(gè)服務(wù)發(fā)現(xiàn)被調(diào)用的服務(wù)赎线,因?yàn)檫^于繁忙廷没,線程池滿,連接池滿垂寥,或者總是出錯(cuò)颠黎,則應(yīng)該及時(shí)熔斷,防止因?yàn)橄乱粋€(gè)服務(wù)的錯(cuò)誤或繁忙滞项,導(dǎo)致本服務(wù)的不正常狭归,從而逐漸往前傳導(dǎo),導(dǎo)致整個(gè)應(yīng)用的雪崩文判。
當(dāng)發(fā)現(xiàn)整個(gè)系統(tǒng)的確負(fù)載過高的時(shí)候过椎,可以選擇降級(jí)某些功能或某些調(diào)用,保證最重要的交易流程的通過戏仓,以及最重要的資源全部用于保證最核心的流程疚宇。
還有一種手段就是限流,當(dāng)既設(shè)置了熔斷策略赏殃,也設(shè)置了降級(jí)策略敷待,通過全鏈路的壓力測試,應(yīng)該能夠知道整個(gè)系統(tǒng)的支撐能力仁热,因而就需要制定限流策略榜揖,保證系統(tǒng)在測試過的支撐能力范圍內(nèi)進(jìn)行服務(wù),超出支撐能力范圍的股耽,可拒絕服務(wù)根盒。當(dāng)你下單的時(shí)候,系統(tǒng)彈出對(duì)話框說“系統(tǒng)忙物蝙,請(qǐng)重試”炎滞,并不代表系統(tǒng)掛了,而是說明系統(tǒng)是正常工作的诬乞,只不過限流策略起到了作用册赛。
設(shè)計(jì)要點(diǎn)十:全方位的監(jiān)控
當(dāng)系統(tǒng)非常復(fù)雜的時(shí)候,要有統(tǒng)一的監(jiān)控震嫉,主要兩個(gè)方面森瘪,一個(gè)是是否健康,一個(gè)是性能瓶頸在哪里票堵。當(dāng)系統(tǒng)出現(xiàn)異常的時(shí)候扼睬,監(jiān)控系統(tǒng)可以配合告警系統(tǒng),及時(shí)的發(fā)現(xiàn)悴势,通知窗宇,干預(yù)措伐,從而保障系統(tǒng)的順利運(yùn)行。
當(dāng)壓力測試的時(shí)候军俊,往往會(huì)遭遇瓶頸侥加,也需要有全方位的監(jiān)控來找出瓶頸點(diǎn),同時(shí)能夠保留現(xiàn)場粪躬,從而可以追溯和分析担败,進(jìn)行全方位的優(yōu)化。
四镰官、Kubernetes本身就是微服務(wù)架構(gòu)
基于上面這十個(gè)設(shè)計(jì)要點(diǎn)提前,我們?cè)倩貋砜碖ubernetes,會(huì)發(fā)現(xiàn)越看越順眼朋魔。
首先Kubernetes本身就是微服務(wù)的架構(gòu)岖研,雖然看起來復(fù)雜,但是容易定制化警检,容易橫向擴(kuò)展。
如圖黑色的部分是Kubernetes原生的部分害淤,而藍(lán)色的部分是網(wǎng)易云為了支撐大規(guī)模高并發(fā)應(yīng)用而定制化的部分扇雕。
Kubernetes的API Server更像網(wǎng)關(guān),提供統(tǒng)一的鑒權(quán)和訪問接口窥摄。
眾所周知镶奉,Kubernetes的租戶管理相對(duì)比較弱,尤其是對(duì)于公有云場景崭放,復(fù)雜的租戶關(guān)系的管理哨苛,我們只要定制化API Server,對(duì)接Keystone币砂,就可以管理復(fù)雜的租戶關(guān)系建峭,而不用管其他的組件。
在Kubernetes中幾乎所有的組件都是無狀態(tài)化的决摧,狀態(tài)都保存在統(tǒng)一的etcd里面亿蒸,這使得擴(kuò)展性非常好,組件之間異步完成自己的任務(wù)掌桩,將結(jié)果放在etcd里面边锁,互相不耦合。
例如圖中pod的創(chuàng)建過程波岛,客戶端的創(chuàng)建僅僅是在etcd中生成一個(gè)記錄茅坛,而其他的組件監(jiān)聽到這個(gè)事件后,也相應(yīng)異步的做自己的事情则拷,并將處理的結(jié)果同樣放在etcd中贡蓖,同樣并不是哪一個(gè)組件遠(yuǎn)程調(diào)用kubelet曹鸠,命令他進(jìn)行容器的創(chuàng)建,而是發(fā)現(xiàn)etcd中摩梧,pod被綁定到了自己這里物延,方才拉起。
為了在公有云中實(shí)現(xiàn)租戶的隔離性仅父,我們的策略是不同的租戶叛薯,不共享節(jié)點(diǎn),這就需要Kubernetes對(duì)于IaaS層有所感知笙纤,因而需要實(shí)現(xiàn)自己的Controller耗溜,Kubernetes的設(shè)計(jì)使得我們可以獨(dú)立創(chuàng)建自己的Controller,而不是直接改代碼省容。
API-Server作為接入層抖拴,是有自己的緩存機(jī)制的,防止所有的請(qǐng)求的壓力直接到后端的數(shù)據(jù)庫上腥椒。但是當(dāng)仍然無法承載高并發(fā)請(qǐng)求的時(shí)候阿宅,瓶頸依然在后端的etcd存儲(chǔ)上,這和電商應(yīng)用一摸一樣笼蛛。當(dāng)然能夠想到的方式也是對(duì)etcd進(jìn)行分庫分表洒放,不同的租戶保存在不同的etcd集群中。
有了API Server做API網(wǎng)關(guān)滨砍,后端的服務(wù)進(jìn)行定制化往湿,對(duì)于client和kubelet是透明的。
如圖是定制化的容器創(chuàng)建流程惋戏,由于大促和非大促期間领追,節(jié)點(diǎn)的數(shù)目相差比較大,因而不能采用事先全部創(chuàng)建好節(jié)點(diǎn)的方式响逢,這樣會(huì)造成資源的浪費(fèi)绒窑,因而中間添加了網(wǎng)易云自己的模塊Controller和IaaS的管理層,使得當(dāng)創(chuàng)建容器資源不足的時(shí)候龄句,動(dòng)態(tài)調(diào)用IaaS的接口回论,動(dòng)態(tài)的創(chuàng)建資源。這一切對(duì)于客戶端和kubelet無感知分歇。
為了解決超過3萬個(gè)節(jié)點(diǎn)的規(guī)模問題傀蓉,網(wǎng)易云需要對(duì)各個(gè)模塊進(jìn)行優(yōu)化,由于每個(gè)子模塊僅僅完成自己的功能职抡,Scheduler只管調(diào)度葬燎,Proxy只管轉(zhuǎn)發(fā),而非耦合在一起,因而每個(gè)組件都可以進(jìn)行獨(dú)立的優(yōu)化谱净,這符合微服務(wù)中的獨(dú)立功能窑邦,獨(dú)立優(yōu)化,互不影響壕探。而且Kubernetes的所有組件的都是Go開發(fā)的冈钦,更加容易一些。所以Kubernetes上手慢李请,但是一旦需要定制化瞧筛,會(huì)發(fā)現(xiàn)更加容易。
五导盅、Kubernetes更加適合微服務(wù)和DevOps的設(shè)計(jì)
好了较幌,說了K8S本身,接下來說說K8S的理念設(shè)計(jì)白翻,為什么這么適合微服務(wù)朵诫。
前面微服務(wù)設(shè)計(jì)的十大模式藻糖,其中一個(gè)就是區(qū)分無狀態(tài)和有狀態(tài),在K8S中谦趣,無狀態(tài)對(duì)應(yīng)deployment掖看,有狀態(tài)對(duì)應(yīng)StatefulSet一罩。
deployment主要通過副本數(shù)瓤漏,解決橫向擴(kuò)展的問題扰付。
而StatefulSet通過一致的網(wǎng)絡(luò)ID,一致的存儲(chǔ)纯续,順序的升級(jí),擴(kuò)展灭袁,回滾等機(jī)制猬错,可以保證有狀態(tài)應(yīng)用,很好地利用自己的高可用機(jī)制茸歧。因?yàn)榇蠖鄶?shù)集群的高可用機(jī)制倦炒,都是可以容忍一個(gè)節(jié)點(diǎn)暫時(shí)掛掉的,但是不能容忍大多數(shù)節(jié)點(diǎn)同時(shí)掛掉软瞎。而且高可用機(jī)制雖然可以保證一個(gè)節(jié)點(diǎn)掛掉后回來逢唤,有一定的修復(fù)機(jī)制,但是需要知道剛才掛掉的到底是哪個(gè)節(jié)點(diǎn)涤浇,StatefulSet的機(jī)制可以讓容器里面的腳本有足夠的信息鳖藕,處理這些情況,實(shí)現(xiàn)哪怕是有狀態(tài)只锭,也能盡快修復(fù)著恩。
在微服務(wù)中,比較推薦使用云平臺(tái)的PaaS,例如數(shù)據(jù)庫喉誊,消息總線邀摆,緩存等。但是配置也是非常復(fù)雜的伍茄,因?yàn)椴煌沫h(huán)境需要連接不同的PaaS服務(wù)栋盹。
K8S里面的headless service是可以很好的解決這個(gè)問題的,只要給外部的服務(wù)創(chuàng)建一個(gè)headless service敷矫,指向相應(yīng)的PaaS服務(wù)例获,并且將服務(wù)名配置到應(yīng)用中。由于生產(chǎn)和測試環(huán)境分成Namespace沪饺,雖然配置了相同的服務(wù)名躏敢,但是不會(huì)錯(cuò)誤訪問,簡化了配置整葡。
微服務(wù)少不了服務(wù)發(fā)現(xiàn)件余,除了應(yīng)用層可以使用SpringCloud或者Dubbo進(jìn)行服務(wù)發(fā)現(xiàn),在容器平臺(tái)層當(dāng)然是用Service了遭居,可以實(shí)現(xiàn)負(fù)載均衡啼器,自修復(fù),自動(dòng)關(guān)聯(lián)俱萍。
服務(wù)編排端壳,本來K8S就是編排的標(biāo)準(zhǔn),可以將yml文件放到代碼倉庫中進(jìn)行管理枪蘑,而通過deployment的副本數(shù)损谦,可以實(shí)現(xiàn)彈性伸縮。
對(duì)于配置中心岳颇,K8S提供了configMap照捡,可以在容器啟動(dòng)的時(shí)候,將配置注入到環(huán)境變量或者Volume里面话侧。但是唯一的缺點(diǎn)是栗精,注入到環(huán)境變量中的配置不能動(dòng)態(tài)改變了,好在Volume里面的可以瞻鹏,只要容器中的進(jìn)程有reload機(jī)制悲立,就可以實(shí)現(xiàn)配置的動(dòng)態(tài)下發(fā)了。
統(tǒng)一日志和監(jiān)控往往需要在Node上部署Agent新博,來對(duì)日志和指標(biāo)進(jìn)行收集薪夕,當(dāng)然每個(gè)Node上都有,daemonset的設(shè)計(jì)叭披,使得更容易實(shí)現(xiàn)寥殖。
當(dāng)然目前最最火的Service Mesh玩讳,可以實(shí)現(xiàn)更加精細(xì)化的服務(wù)治理,進(jìn)行熔斷嚼贡,路由熏纯,降級(jí)等策略。Service Mesh的實(shí)現(xiàn)往往通過sidecar的方式粤策,攔截服務(wù)的流量樟澜,進(jìn)行治理。這也得力于Pod的理念叮盘,一個(gè)Pod可以有多個(gè)容器秩贰,如果當(dāng)初的設(shè)計(jì)沒有Pod,直接啟動(dòng)的就是容器柔吼,會(huì)非常的不方便毒费。
所以K8S的各種設(shè)計(jì),看起來非常的冗余和復(fù)雜愈魏,入門門檻比較高觅玻,但是一旦想實(shí)現(xiàn)真正的微服務(wù),K8S是可以給你各種可能的組合方式的培漏。實(shí)踐過微服務(wù)的人溪厘,往往會(huì)對(duì)這一點(diǎn)深有體會(huì)。
六牌柄、Kubernetes的常見的使用方式
下面我們來看一下畸悬,微服務(wù)化的不同階段,Kubernetes的使用方式珊佣。
第一階段:使用公有云虛擬機(jī)
也即沒有微服務(wù)化的階段蹋宦,基本上一個(gè)進(jìn)程就能搞定,兩個(gè)進(jìn)程做高可用咒锻,不需要使用容器妆档,虛擬機(jī)就非常好。
第二階段:容器作為持續(xù)集成工具
當(dāng)微服務(wù)開始拆分了虫碉,如何保證拆分后功能的一致性,需要持續(xù)集成作為保證胸梆,如前面的論述敦捧,容器是非常好的持續(xù)集成工具,是解決CI/CD中D的碰镜,所以一開始用host網(wǎng)絡(luò)就可以兢卵,這樣可以保證部署方式和原來兼容。
如果想用私有云進(jìn)行部署绪颖,直接部署在物理機(jī)上秽荤,在性能要求沒有很高甜奄,但是又要和其他物理機(jī)很好的通信的情況下,可以用bridge打平網(wǎng)絡(luò)的方式比較好窃款。通過創(chuàng)建網(wǎng)橋课兄,將物理網(wǎng)卡,容器網(wǎng)卡都連接到一個(gè)網(wǎng)橋上晨继,可以實(shí)現(xiàn)所有的容器和物理機(jī)在同樣的一個(gè)二層網(wǎng)絡(luò)里面烟阐。
如果性能要求比較高,例如要部署類似緩存紊扬,則可以使用sr-iov網(wǎng)卡蜒茄。
如果想實(shí)現(xiàn)租戶的簡單隔離,則往往使用各種Overlay的網(wǎng)絡(luò)模式餐屎,這是最常用的部署方式檀葛。圖中的數(shù)據(jù)來自網(wǎng)絡(luò)。Flannel腹缩,Calico都是非常好的網(wǎng)絡(luò)插件屿聋,雖然Flannel一開始使用用戶態(tài)的模式性能不好,后來使用內(nèi)核態(tài)庆聘,性能大大改善胜臊,使用gw模式后,和Calico性能相當(dāng)伙判。
網(wǎng)易云采用了Kubernetes和IaaS深度融合的方式象对,類似AWS的Fargate的模式,一方面可以使得原來使用虛擬機(jī)的用戶平滑地遷移到容器宴抚,另一方面可以實(shí)現(xiàn)公有云的租戶隔離勒魔。
如圖是融合的網(wǎng)易云容器服務(wù)的架構(gòu),這個(gè)管理OpenStack和Kubernetes的管理平臺(tái)菇曲,也是用的微服務(wù)架構(gòu)冠绢,有API網(wǎng)關(guān),熔斷限流功能常潮,拆分成不同的服務(wù)弟胀,部署在K8S上的,所以處處是微服務(wù)喊式。