當(dāng)我們談?wù)摬豢勺兓A(chǔ)設(shè)施時,我們在談?wù)撌裁?/h1>
作者 | 陳海波(漂石)
午夜時分,電話響起,線上告急。你從千呼萬釘中醒來,睡眼朦朧,手忙腳亂?;秀敝g,終于梳理清楚發(fā)生了什么,一個陳年老應(yīng)用突然停機(jī),消息堆積,系統(tǒng)停擺。而你就像一個下水道小工疏通馬桶一般,大力出奇跡,重啟機(jī)器,恢復(fù)服務(wù)。只見消息隊(duì)列中的堆積事件一瀉千里,警告消除。次日,你再也不想重現(xiàn)午夜兇鈴,決定對系統(tǒng)進(jìn)行永久性修復(fù):加一個定時重啟服務(wù)的腳本。斗轉(zhuǎn)星移,許多時日過去了,你也在不同的角落加了無數(shù)的腳本,也好久沒有半夜驚醒,甚至還能悠閑享受下午茶。但是,直到今天。今天,你們部門要降本增效,為了避免自己成為被砍掉的成本,你決定主動對線上的機(jī)器開刀:合并服務(wù),裁撤機(jī)器。雖然你對機(jī)器上都部署了什么應(yīng)用了然于胸,但是你已經(jīng)不記得都有哪些腳手架支撐著應(yīng)用的運(yùn)轉(zhuǎn)。重建環(huán)境難如登天,你又開始難眠了。
一、變化的基礎(chǔ)設(shè)施
復(fù)雜、神秘而神奇的線上環(huán)境承載了半部都市傳說,甚至有些公司的線上環(huán)境本身就是一本需要口耳相傳的上古神話。我雖然沒有看過沙漠下暴雨,但是看過沒人說的清楚上面有什么的環(huán)境。我雖然沒有看過大海親吻鯊魚,但是我看過重啟再也起不來的機(jī)器。如果你能說清楚任何一臺機(jī)器上都部署了什么應(yīng)用,以及機(jī)器上服務(wù)之間的依賴關(guān)系是什么樣子的,你已經(jīng)擊敗了八成的玩家。而造成這種局面的根本原因就是基礎(chǔ)設(shè)施的易變。
- 新增一個服務(wù)時:“我找臺機(jī)器部署一下”
- 某一個服務(wù)出問題時:“我上機(jī)器改一下”
- 需要對某個系統(tǒng)配置變更時:“我搞個腳本跑一跑”
看似常規(guī)運(yùn)維變更,有文檔記錄或者沒有文檔記錄,每一個環(huán)境都是如此的別致和獨(dú)一無二,再加上人員變動,造就了無數(shù)的“祖?zhèn)髅丶肌薄?/p>
1.什么是不可變的基礎(chǔ)設(shè)施
容器在被廣泛接受的同時,「不可變」也逐漸被潛移默化的接受。應(yīng)用容器消亡之后,容器內(nèi)的修改會隨著容器一起不復(fù)存在,不要在容器內(nèi)做修改就是最樸素的不可變理念。在程序啟動階段遇到問題,很少人還會把在容器內(nèi)修修補(bǔ)補(bǔ)作為正經(jīng)方案,而會回到最一開始的階段,從容器構(gòu)建階段解決問題。隨之帶來的就是大家對容器鏡像無盡的信任感,容器突然出現(xiàn)問題?重建試試。換個機(jī)器跑不起來?肯定是機(jī)器的問題。
2.容器帶來了什么
大家普遍認(rèn)同 Docker 或者說容器引發(fā)了一場革命。但是為何說容器是一場革命,到底革了什么的命?有一種說法是 Docker 簡化了服務(wù)的管理,停啟服務(wù)更加簡單,但是事實(shí)上 systemd 或者 supervisor 等老牌服務(wù)管理、運(yùn)維工具在這一點(diǎn)上不見得比 docker 難用多少。我認(rèn)為是鏡像技術(shù)引爆了革命,一個不可臨時修改的、固化的、自包含的交付物,真正的一次構(gòu)建到處運(yùn)行,一個可以快速鏟掉和快速部署的實(shí)體,再也沒有 「Works on my machine」,是如此的安心和可依賴。也正是因?yàn)槿萜鞯闹亟ㄊ侨绱说目旖?,使得我們有機(jī)會對「重啟試試」發(fā)揮到極致,出問題了,重建容器看看?你想嘗試使用 Docker,但是你的業(yè)務(wù)如此復(fù)雜,上機(jī)器重建容器和直接上機(jī)器重啟服務(wù)又有什么本質(zhì)差別呢。
二、Pet vs Cattle
隨之 Kubernetes 的到來,大規(guī)模的容器管理成為可能,而劃定大規(guī)模容器的管理最佳實(shí)踐也成為了熱門議題。
1.如何飼養(yǎng)一只貓
如果你得到了一只貓,你會如何飼養(yǎng)它?我記得我在領(lǐng)回一只貓之后,花了很長的時間和腦細(xì)胞用來商定一個我和它都能接受的名字。緊接著就是帶著我的小貓去醫(yī)院,制定疫苗計(jì)劃,來保證我的小貓未來的健康。后面便是日復(fù)一日的鏟屎和等著主子的眷顧。小王子告訴我:正因?yàn)槟銥槟愕呢埢ㄙM(fèi)了時間,這才使你的貓如此重要。經(jīng)典的運(yùn)維方式和貓的飼養(yǎng)是一樣的,我們可以稱之為寵物式運(yùn)維。你會對機(jī)器和應(yīng)用做詳盡的規(guī)劃,甚至為這個環(huán)境起一個名字,比如叫生產(chǎn)好了。你也會對這個環(huán)境悉心照料,定期看看監(jiān)控、做下升級保養(yǎng)。你為你的環(huán)境花費(fèi)了時間,你的環(huán)境如此重要。很難設(shè)想你的貓和你的環(huán)境突然間離你而去的場景,也許你會傷心的撕心裂肺和破產(chǎn)的撕心裂肺。
2.農(nóng)場主入門
在獲得了一只貓之后,你一不留神又獲得了一家牧場。但你可能無法像養(yǎng)一只貓一樣養(yǎng)幾千頭牛,因?yàn)閹浊€名字應(yīng)該是很難記住的。
你可能也不會依次帶著你的牛去醫(yī)院打疫苗,何不直接批發(fā)疫苗統(tǒng)一接種呢。如果有小牛犢存在嚴(yán)重的缺陷,也許你會陪在它身邊悉心照料,但更可能的是把它盡早的從流程中剔除,省的浪費(fèi)更多的飼料。從此你的生活便目無全牛,只要為牛群建立足夠多的保障設(shè)施,某一頭牛的狀態(tài)對整體又有什么影響呢。03
三、放牧式運(yùn)維
當(dāng)你已經(jīng)為上千頭牛建設(shè)了完善的飼養(yǎng)設(shè)施,你會驚奇的發(fā)現(xiàn),即使再加 100 頭牛,并不會增加太多的成本。而不像飼養(yǎng)貓,當(dāng)你有兩只貓的時候,最好能有 3 個貓砂盆,否則你將有機(jī)會體驗(yàn)到雞飛狗跳。你決心當(dāng)一個牧牛人運(yùn)維,再也不想給生產(chǎn)環(huán)境的主子們鏟屎了。擁抱 Kubernetes,像放牧一樣管理你的應(yīng)用。
1.牧養(yǎng)一群 Pod
你把生產(chǎn)環(huán)境的主子們裝進(jìn)集裝箱,通過容器鏡像對部署方式進(jìn)行標(biāo)準(zhǔn)化,誰也甭想做非標(biāo)的操作,再使用 Pod 對應(yīng)用進(jìn)行部署,再也不去關(guān)心應(yīng)用在哪個 Node 上啟動,這一切自有牧場(Kubernetes)自行處理。一個 Pod 異常了?沒關(guān)系,刪掉看看,下次起來又是一個全新的應(yīng)用。絲毫不會影響到牧場的正常運(yùn)轉(zhuǎn)。
一切絲般順滑,歲月靜好。午夜時分,電話響起,線上告急。你從千呼萬釘中醒來,睡眼朦朧,手忙腳亂。
恍惚之間,終于梳理清楚發(fā)生了什么,原來是不知何處流量涌現(xiàn),節(jié)點(diǎn)雪崩。而你就像一個下水道小工疏通馬桶一般,大力出奇跡,擴(kuò)容機(jī)器,恢復(fù)服務(wù)。pending Pod 消失不見,警告消除。次日,你再也不想重現(xiàn)午夜兇鈴,但陷入深思,身為牧場主的你,逐漸意識到一個燈下黑的問題。你可以輕松的同質(zhì)化對待每一頭牛,但你無法同質(zhì)化整個牧場。
2.牧養(yǎng)真正的基礎(chǔ)設(shè)施
幾番梳理,你找到了問題的關(guān)鍵:盡管可以放牧式管理 Pod,但是機(jī)器的運(yùn)維卻還是寵物式的。你依然會悉心照料每個機(jī)器:提前規(guī)劃、取一個名字、單獨(dú)控制規(guī)格、挑選操作系統(tǒng),甚至還有幾臺深得你愛,噓寒問暖,日夜?fàn)繏?,擁有單?dú)的內(nèi)部昵稱代號。作為業(yè)界領(lǐng)先的牧場主,你決心改造自己的牧場,如果能像管理 Pod 一樣管理 Node 是不是一個好主意?如果 Node 異常直接刪除 Node,等著彈出新的?還沒想完,你后背有些發(fā)涼,你還沒有像信任容器一樣信任虛機(jī),雖然你深知重啟可解決 90% 的故障,而重裝系統(tǒng)可以解決 99% 的故障。思來想去,你依然想做些嘗試,稍加思考,鎖定痛點(diǎn)有二:
- 機(jī)器按需快速彈縮,同質(zhì)管理
- OS 鏡像化:快速、安全、不可變
3.馴服虛機(jī)
經(jīng)過調(diào)研,你發(fā)現(xiàn)事情并不像原來設(shè)想的那樣深不可測,主流云廠商早就提供了野生工具,你只需要稍加馴服,便可以為自己的牧場服務(wù)。云廠商們很早便推出了彈性伸縮組,可以按照負(fù)載和期望維護(hù)虛擬機(jī)的數(shù)目。而阿里云也有自己的實(shí)現(xiàn)(ESS),可以無需人工干預(yù)的根據(jù)規(guī)則對 ECS 進(jìn)行擴(kuò)縮容。你看到了希望,這不就是 Node 的 Deployment 嗎?但是只是擴(kuò)容虛擬機(jī)對你來說并沒有什么價值,你深知需要的是牛圈,而不是木材,你需要對他們進(jìn)行馴服。這時,你轉(zhuǎn)頭看到了你的 Kubernetes 集群,靈感蹦出,為何要直面虛擬機(jī)呢,只要新擴(kuò)容出的機(jī)器能被納管到集群中不就解決了基本問題。說干就干,通過 AutoScaling 定義了啟動命令,開機(jī)后進(jìn)行標(biāo)準(zhǔn)化安裝和執(zhí)行 kube join 動作。當(dāng)機(jī)器開機(jī)不久,就可以出現(xiàn)在 Kubernetes 集群中。你感覺距離目標(biāo)進(jìn)了一步。
4.馴服 OS
很快,你又發(fā)現(xiàn)了一個新的問題,傳統(tǒng)的 OS 啟動和容器實(shí)在無法比擬,明明所有的依賴都在容器內(nèi)部,而且所有的應(yīng)用都已經(jīng)在容器內(nèi)運(yùn)行,但你還是不得不為 OS 內(nèi)置的、沒人使用的服務(wù)買單,這些服務(wù)拖慢了啟動速度,還引入了安全漏洞。而且,總是有人意識不到同質(zhì)化管理的好處,時不時有人上機(jī)器做一些不可知的修改,導(dǎo)致你每次想釋放虛機(jī)時需要去群里喊一喊,避免碰到什么神奇的 Bug。自尋煩惱,你苦笑道。你打算馴服 OS,對傳統(tǒng)的 OS 進(jìn)行剪裁,除了容器依賴的東西全部清理掉,說不好能大大加快機(jī)器的啟動速度。還有,最好能在啥地方加個告示,敬告大家不要在機(jī)器上做寫操作,避免釋放機(jī)器時文件的丟失。有天,你發(fā)現(xiàn)了阿里云的 ContainerOS,一個針對容器剪裁和優(yōu)化的操作系統(tǒng),你不需要親自動手剪裁了,甚至都不再需要加一個告示,因?yàn)?RootFS 都是只讀的,連 SSH 都不會默認(rèn)打開,從根本上杜絕了非標(biāo)操作。
你嘗試了一下,針對容器優(yōu)化的 OS 啟動賊快,點(diǎn)完彈出,一分鐘后你就可以把業(yè)務(wù)調(diào)度上去了。把 Node 當(dāng)做 Pod 管理,你看到了希望。
四、托管式放牧
但不久,你遇到了一個新的問題,創(chuàng)建機(jī)器一時爽,你的老板告訴你,你手里有一批機(jī)器存在一個要緊的 CVE 安全漏洞,需要抓緊時間搞一搞,你開始頭大了,因?yàn)槟阒?,除了存量的?jié)點(diǎn),現(xiàn)在只要創(chuàng)建新的機(jī)器就有安全漏洞。你有了一種若隱若現(xiàn)的感覺:你在走向深水區(qū)。
一番探尋后,你聽說有人提出應(yīng)該像自動駕駛一樣去托管一個集群,也看到了阿里云 ACK 的托管節(jié)點(diǎn)池。節(jié)點(diǎn)的擴(kuò)縮容、節(jié)點(diǎn)故障的自恢復(fù)、安全加固、OS 的托管,無不觸動著你。你意識到應(yīng)該從根本上解決問題:放手自建的 Kubernetes,全面擁抱托管。
擁抱托管后,你豁然開朗,原來事情本應(yīng)如此簡單,多年的摸索仿佛一顆種子,在看到托管節(jié)點(diǎn)池后瞬間發(fā)芽成果。從此,世界上又開始流傳了新三板斧傳統(tǒng):等等自愈看看?Pod 刪下看看?Node 刪下看看?樸實(shí)無華且有效。