透過集群管理模式的發(fā)展歷程看穿Docker 的本質(zhì)
Docker很火很紅,簡直到了沒有道理的地步了。Docker為什么這么紅?因為它是一種可以用來掀桌子的技術(shù)。在部署自動化這條產(chǎn)業(yè)上的工人和機床制造商們,看家護院的 cmdb,分布式腳本執(zhí)行等所謂核心技術(shù)即便不會變成明日黃花,也會淪為二流技術(shù)。僅僅把 Docker 當(dāng)成一個輕量級 vmware 來使用,是沒法看穿其實質(zhì)的。要理解 Docker 的意義,不能從 Docker 是什么,能夠干什么說起。讓我們先來回憶一下集群管理模式的發(fā)展歷程,以及這些落后的模式的種種弊端。
手工管理時代
IP地址是放在 excel 表里的。管理是靠登陸跳板機,用 SSH 連接服務(wù)器。手工執(zhí)行命令做新的服務(wù)器部署,已有服務(wù)器的程序版本升級,以及各種配置刷新修改的工作。
弊端不言而喻,主要有這么幾點:
- 缺乏一致性,因為是手工操作所以服務(wù)器之間總是有一些差異
- 效率低下,一個人可以管理的服務(wù)器數(shù)量非常有限
自動化大躍進時代
業(yè)務(wù)數(shù)量的增長,很快使得機器的數(shù)量超過手工操作維護的極限。無論再爛的團隊, 只要業(yè)務(wù)長到這個份上了,必然會出現(xiàn)大量的自動化工具用腳本自動化執(zhí)行的方式快速地支撐業(yè)務(wù)。這個時代是一個黃金時代,運維真正長臉的時代。因為沒有自動 化的運維技術(shù),業(yè)務(wù)就會遇到瓶頸。自動化技術(shù)的引入,切實地體現(xiàn)成了業(yè)務(wù)的收益。
這時代的特征是兩個關(guān)鍵的系統(tǒng)
- 把本地 excel 表格里的 IP 地址用數(shù)據(jù)庫的方式管理起來,稱之為 CMDB
- 基于 SSH 或者 agent 的分布式腳本執(zhí)行平臺
效率低下了不再是主要問題,主要的弊端變?yōu)榱耍?/p>
大量的腳本,雜亂無章,內(nèi)容重復(fù),質(zhì)量難以保證,最終給故障留下隱患
沒有對現(xiàn)網(wǎng)預(yù)期狀態(tài)的定義和管理,所有的現(xiàn)網(wǎng)狀態(tài)都是腳本日積月累的產(chǎn)物,導(dǎo)致服務(wù)器狀態(tài)漂移,產(chǎn)生雪花服務(wù)器(每個機器都不一樣),進而給業(yè)務(wù)穩(wěn)定性留下隱患
這些弊端短期對業(yè)務(wù)來說并沒有立竿見影的傷害,屬于內(nèi)傷型的。而且很多隱患即便暴露了也會流于強調(diào)紀(jì)律,強調(diào)運維意識云云。很少會有人去追究背后的 運維理念的問題。結(jié)果就是大部分公司都停留在這個階段了。畢竟運維是一個足夠用即可的支撐領(lǐng)域。運維搞得再高科技,特高可用,未必和創(chuàng)業(yè)公司的成功有多少 直接聯(lián)系。
開發(fā)鬧革命時代
伴隨 DevOps 同時出現(xiàn)的是 infrastructure as code 的提法。簡單來說就是一幫開發(fā)殺到運維領(lǐng)域之后,看見這些運維居然是這樣去管理現(xiàn)網(wǎng)狀態(tài)的。于是他們把寫代碼的經(jīng)驗帶過來,將現(xiàn)網(wǎng)狀態(tài)建立成模型(所謂 code),把預(yù)期的狀態(tài)提交到版本控制中。就像寫代碼一樣,去管理服務(wù)器配置。
很多后臺開發(fā)主導(dǎo)的小創(chuàng)業(yè)公司直接跳過了上個時代,運維自動化體系從一開始就是基于 puppet 和 chef 來搞的。平心而論,用 puppet 的更多是缺少歷史包袱,而不是因為運維問題有多復(fù)雜。很多管理的機器數(shù)量不超過十臺,卻在如何使用 puppet/chef 上浪費大把時間的團隊也是有的。相反很多大公司因為有沉重的歷史包袱,和龐大的傳統(tǒng)運維團隊,這種開發(fā)鬧革命的路反而走不通。
這種做法主要是解決了腳本的管理問題,而且因為直接定義了現(xiàn)網(wǎng)狀態(tài),服務(wù)器之間的一致性也會好很多。但是光鮮亮麗的模型背后本質(zhì)上還是一堆腳本來驅(qū)動的。上個時代的弊端只是經(jīng)過了包裝和改良,并沒有辦法根除。
應(yīng)用預(yù)期狀態(tài)到現(xiàn)網(wǎng)依靠的還是跑腳本。而且與之前不同,現(xiàn)在更多的是跑別人寫的cookbook了,質(zhì)量也是良莠不齊的。
雖然定義了預(yù)期的現(xiàn)網(wǎng)狀態(tài),但是起點不同(比如從a=>c, b=>c)需要做的升級操作可能完全是不同的。要編寫一個面面俱到的升級腳本其實非常困難。
還有哪些問題?
一致性和穩(wěn)定性是最大的問題。服務(wù)器開機之后,常年是不重裝系統(tǒng)的。無數(shù)人在上面跑過腳本,執(zhí)行過命令,定位過問題。服務(wù)器實際的狀態(tài)是沒有辦法精確管控的。infrastructure as code 是一種改良,但是仍未根除這個問題。每一次在服務(wù)器上跑腳本其實就是一種賭博,因為沒有兩臺服務(wù)器是完全一樣的。在本地測試可行的腳本,未必在另外一臺上不會引起問題。這不是強調(diào)一下代碼里不能 rm * ,而要 rm path/* 就可以解決的問題。
版本管理其實一直是沒有的。做過開發(fā)的人,可能還會用 git/svn 來作為部署的基線,基本的版本都會提交到倉庫里。更多的一線運維用的還是 rsync 的模式。rsync 的意思就是要安裝一個新服務(wù)器,需要找一臺“與之最像”的服務(wù)器。然后把文件拷貝到新服務(wù)器上,把配置修改一下,啟動完事。攜程出事了,我個人猜測應(yīng)該與版本管理混亂有關(guān)系。
故障替換是非常困難的。先不說故障替換,就是故障機剔除就是一個頭疼的事情。比如ZooKeeper。各個客戶端都硬編碼三個 ip 地址。一旦其中一個 ip 掛掉了。zookeepr按照高可用協(xié)議可以保持正常,但是長期來說這個掛掉的ip還是要從各個使用方里剔除的。這個就且改了。一旦業(yè)務(wù)的高可用做得不好,需要運維來搞一些接告警之后替換故障機的事情,那就是各種腳本折騰各種配置文件的節(jié)奏了。
#p#
Docker 是如何掀桌子的
兩點神論,進入到 Docker 時代之后
- CMDB 不再至關(guān)重要了。CMDB 連同IP,以及服務(wù)器資源變成底層藍領(lǐng)工人關(guān)心的問題了。上層的后臺開發(fā)和業(yè)務(wù)運維不再需要也無法再以 IP 為中心的 CMDB 來管理配置。
- 分布式腳本執(zhí)行平臺從核心作業(yè)系統(tǒng)退居二線。很簡單,服務(wù)器不再需要變更了,常規(guī)的上新服務(wù)器,發(fā)布新版本都不再依賴腳本在一個已有的服務(wù)器上執(zhí)行去修改狀態(tài)。而是創(chuàng)建一個新的容器。
Docker的實質(zhì)是一個真正的版本管理工具。在 Docker 之前版本管理是各種拼湊的解決方案。什么是版本,服務(wù)器是由三部分組成:版本、配置、數(shù)據(jù)。所謂版本就是操作系統(tǒng),以及操作系統(tǒng)的配置。各種第三方包,開 發(fā)給的可執(zhí)行文件,和一部分配置文件。這些的集合是一個版本,其實就是一個完整的可執(zhí)行環(huán)境。除此之外一般就是一個數(shù)據(jù)庫,里面放了兩部分內(nèi)容,一部分是 管理員可以從頁面上修改的配置,一部分是業(yè)務(wù)數(shù)據(jù)。在 puppet 時代的版本,是一個申明文件。這個申明文件執(zhí)行的時候,需要先從某個 ISO 安裝出一個操作系統(tǒng),然后用 apt-get/yum 從某個鏡像源安裝一堆系統(tǒng)的包,然后用 pip/bundle 安裝一堆 python/ruby 語言層面的包,最后才是開發(fā)給你的 git/svn/某個不知名的tar.gz。你以為這些東西每次拼裝出來的東西都是同樣的版本么?其實未必。想當(dāng)年某墻干掉 github 的時候,不知道多少人無法做發(fā)布了。Docker 打包出的連系統(tǒng)在一起的鏡像,其實是對版本的最好闡述。
使用 Docker 之后不再需要修改現(xiàn)網(wǎng)的 container 了。一個 container 如果需要升級,那么就把它干掉,再把預(yù)先做好的新的鏡像發(fā)布成一個新的 container 替換上去。分布式腳本執(zhí)行,變成了分布式容器替換了。當(dāng)然這種標(biāo)準(zhǔn)化的操作,用 mesos marathon 已經(jīng)完美解決了。
使用 Docker 之后,無法再基于 IP 做管理了。倒不是給每個 container 分配一個 IP 分配不過來,而是 IP 代表的靜態(tài)模型無法跟上時代了?;?IP 管理,就意味你會基于 SSH 登陸這個 IP 來管理。這種思想從骨子里就是落后的了。進程,進程組,模塊,set 這些才是管理的粒度。至于進程是跑在哪個 IP 上的哪個容器里,不再重要了。一圖可以說明這個問題:
上面這個擴容的按鈕點完之后有讓你填 IP 嗎?沒有!你只需要告訴marathon,我要32個進程實例。它就會去找這些資源運行這 32 個實例。業(yè)務(wù)最終需要的是 32 個進程,而不是 32 個 IP。IP只是運行進程需要的資源而已。實際運行的時候進程可能是在一個IP上啟動了32個端口,也可能是隨機分配了5個IP,每個各跑了一些端口。當(dāng)然這些分配都是可以通過“約束”的方式表達的。而不是讓你去搞32個IP來,再跑個腳本去這些IP上部署這些進程。
The Missing Piece
拼圖游戲就差最后這一塊了。Docker 做為一個版本工具是絕對合格的。Marathon 以 Docker 的方式托管所有進程也是靠譜的。但是還不完整:
Docker鏡像作為版本發(fā)布到現(xiàn)網(wǎng)之后是無法運行的,因為任何一個應(yīng)用起碼都有好幾個服務(wù)要互相訪問。這些硬編碼在鏡像里的 IP 地址換了一個環(huán)境是無法執(zhí)行的。一個版本里任何配置都可以硬編碼,就是 IP 地址和端口是沒硬編碼的。
擴容縮容可以很容易創(chuàng)建和銷毀容器,但是引用了這個容器的服務(wù)器的其他容器怎么辦呢?
發(fā)布,故障替換都是同樣的問題
#p#
解決方案可以看這兩張圖:
方案其實非常簡單。把 app1 => app2 的網(wǎng)絡(luò)訪問關(guān)系,改成 app1 =local=> haproxy =network=> haproxy =local=> app2。通過在容器本地部署 haproxy “托管所有的端口”,也就是用 haproxy 在進程之間做聯(lián)線,而不是每個進程自己去負(fù)責(zé)連接網(wǎng)絡(luò)上的其他進程。
試想一下之前是在配置文件里硬編碼 10.0.0.1:3306 是某臺數(shù)據(jù)庫。硬編碼是不對的,是要打屁股的。所以我們把硬編碼的 ip 地址改成 127.0.0.1:10010。這一次我們不再硬編碼任何 IP 了,我們只硬編碼一個特殊的端口號。每個進程都有一堆特殊的本地端口號用于訪問自己需要的上下游服務(wù)。這個端口號背后的進程到底在哪個 IP,哪個 端口,哪個 container 里執(zhí)行。做為使用方不需要修改任何代碼(比如兼容什么 ZooKeeper/etcd 神馬的),也不用關(guān)心。甚至這個端口后面是多個遠程的IP構(gòu)成一個基于客戶端的高可用。代理甚至還可以做一些出錯換一個后端再重試的事情。
有了這種神器之后,擴容所容,發(fā)布變更,故障替換都很輕松了。容器隨便新增,隨便刪除。網(wǎng)絡(luò)結(jié)構(gòu)變化了之后,刷新各個地方的 haproxy 配置就是了。各種灰度,各種零停機替換方案都可以搞起。
名字服務(wù)與網(wǎng)絡(luò)
類似的方案有很多。最底層的方案是 SDN/IP 漂移,以及網(wǎng)絡(luò)的bonding。這種方案的特點是保持 IP 地址作為最傳統(tǒng)的名字服務(wù),妄圖延續(xù)其生命。
上層一點的方案是 DNS。再上層一些的方案是 ZooKeeper。
各種方案爭的就是服務(wù)如何注冊自己,如何彼此發(fā)現(xiàn)這個點。各種方案的優(yōu)缺點可以自己去讀:
btw,airbnb 在 13 年就把這套方案投入生產(chǎn)了。
最有意思的是把這種 haproxy 的方案與基于 SDN 的 IP 漂移方案做對比。haproxy 的就是替網(wǎng)絡(luò)做應(yīng)用層進程之間聯(lián)線的事情,通過引入 haproxy 讓這種聯(lián)線更具有靈活性。 而 SDN 的方案是說,你現(xiàn)在的業(yè)務(wù)進程之間是通過 IP 之間靜態(tài)鏈接的,這種連接不夠靈活沒關(guān)系,路由器幫你整。一個 IP 掛掉了,可以把IP漂移到另外一臺機器上去繼續(xù)使用。其實就是在一個場景下實現(xiàn)兩個進程的重新聯(lián)線,突破兩 IP 之間靜態(tài)互訪的限制,給基于 IP 的部署方案續(xù)命。
兩者底層的技術(shù)是相通的。所謂 IP 漂移最后靠的是現(xiàn)代牛逼的CPU,和軟件路由技術(shù)。最后玩的都是用戶態(tài)轉(zhuǎn)發(fā),dpdk神馬的。所以 haproxy 慢,轉(zhuǎn)發(fā)效率有問題神馬的,長期來看都不會是問題。用軟件來聯(lián)線,是趨勢。連路由器都開始這么玩了,連硬件廠商都開始賣軟件了。
The Final Battle
集群管理純粹變成進程管理,IP不再重要,狀態(tài)不再重要。CMDB會變得越來越邊緣化。
發(fā)布變更不再是去修改服務(wù)器,而是新建銷毀容器,以及更新進程間網(wǎng)絡(luò)聯(lián)線關(guān)系。分布式作業(yè)系統(tǒng)會越來越少用,跳板機就更加不允許使用了。
記住“immutable servers”這個提法吧,它終將會得到歷史的認(rèn)可。
原文鏈接:閑談集群管理模式