一名運維創業者的思考:雲端計算時代的自動化運維走向
關於題目“雲端計算時代的自動化運維”,用通俗的話講,就是應用的自動化部署。
第一個關鍵詞是自動化,自動化代表高效率、低成本;第二個關鍵詞是應用部署。即,不涉及講物理基礎設施的運維(如機房基建、能源、消防、安保、佈線等等)。
假設一個企業要做一個電商網站,典型的運維流程是這樣:
1. 購買硬體裝置:伺服器、交換機。可能還有路由器、負載均衡器、防火牆,不一一窮舉了。
2. 在伺服器上安裝作業系統
3. 在伺服器上安裝配置基礎環境(資料庫、Web伺服器、搜尋引擎等)
4. 在伺服器上安裝配置應用軟體(用Java、PHP開發的電商軟體)
5. 把硬體裝置送進機房託管,開通公網訪問
6. 監控運維中的業務,並做日常備份、擴容/縮容、遷移、升級
如果是使用公有云,則沒有第1,2,5步,直接購買公有云的虛擬機器、容器、平臺服務(檔案儲存、關係資料庫、內容分發等)
應用環境和應用軟體部署是指第3步和第4步。
1 作業系統自動化部署
第2步是物理祼機的部署,現在市面上的主流伺服器,都支援IPMI管理,通電接上管理埠就可以完成BIOS設定,再輔以DHCP, TFTP, KickStart可以實現無人值守的自動化安裝作業系統。
目前虛擬化、私有云、公有云已經相當普及,除了一些對特殊硬體有要求的場合,和一些歷史遺留場合,其它大部分場合都可以用虛擬機器,物理機上安裝的是宿主作業系統,應用軟體裝在虛擬機器裡,這樣物理祼機就只需要安裝宿主作業系統,需求相對簡單,沒有應用部署那麼複雜。裝完之後不會經常去改動,執行穩定。
2 應用部署
與作業系統部署相比,應用部署複雜性高得多,主要表現在:
· 場景繁多
一個小型的B2C網站,有負載均衡器、Web伺服器、應用伺服器、快取伺服器、搜尋引擎、分散式檔案系統、監製中心、日誌中心、VPN伺服器等十多種伺服器角色
· 依賴複雜
軟體包之間有依賴,伺服器之間有通訊依賴
· 配置各異
除標準的ini,xml, yaml, json, properties檔案外,iptables, sysctl, nginx, haproxy, pptpd等都有自己獨特的配置檔案格式,多達上百種。文件描述和運維指令碼編寫都有相當大的難度。
3 應用部署技術發展歷程
下面以在CentOS上安裝nginx為例,回顧一下應用部署技術的發展歷程:
3.1 手工安裝配置
這是最古老的部署方式,直到今天也被廣大小規模團隊廣泛採用。部署過程往往會產生這樣一份文件供日後參考:
3.1.1 優點
3.1.1.1 靈活性高
可以安裝任何想要的版本,啟用任何想要的模組(包括自行開發的私有模組)
3.1.1.2 學習門檻低
文件是自然語言寫成,閱讀和書寫都很簡單,不需要額外學習其它技術語言。安裝配置用到的工具、命令也較少,主要是網路下載、解壓縮、編譯、文字編輯幾種,容易掌握。
3.1.2 缺點
作為最古老的部署技術,缺點也是顯而易見的:
3.1.2.1 文件不精確
由於文件是自然語言寫的,是寫給運維工程師閱讀的,而不是給機器執行的。文件寫的是什麼,跟機器上實際執行的是什麼,並不是100%一致的,需要人肉轉換。在長期版本變更、人員更替中極容易出現疏漏。當然,可以從行政管理上解決這類隱患。很多大公司都喜歡搞流程,用測試稽核流程來督促人少犯錯。然而,只要是這個文件是給人看而不是給機器執行的,這個文件就會一直面臨筆誤、表達不精確、更新不及時等隱患,要用流程來徹底杜絕這些隱患,成本很高。
3.1.2.2 效率低
上述5個步驟都是序列的,必須做完一步才能進行下一步。第1步和第3步是比較耗時的,若網速不快,或者編譯時間太長,運維工程師會浪費時間等待。
另一方面,若有多臺機器需要執行同樣的部署操作,也無法減少重複性操作。
3.2 自動化部署:shell指令碼
若伺服器稍有規模的團隊裡,上述手工部署就成了一個大問題。
人肉閱讀的文件急需轉換成機器執行的程式碼。最早也最廣泛運用的自動化部署技術便是shell指令碼。以bash為例,上述5步寫成bash shell就像這樣(示例程式碼,未經測試):
直接執行這個指令碼,就可以自動安裝配置好nginx了。
相比手工部署,使用shell指令碼的缺點只有兩點:一是寫程式碼需要一定學習門檻。二是維護的技術難度會略高。
3.2.1 優點
3.2.1.1 精確
由於shell指令碼是給機器執行的,shell指令碼自身就是一份精確的可執行的文件,所以,不存在筆誤、表達不精確、更新不及時的問題。
3.2.1.2 效率高
運維工程師只要把指令碼啟動起來就可以做別的工作了。
3.2.2 bash的缺點
Bash是幾乎所有linux發行版內建的,環境相容性好,簡潔易學。但它卻不是運維程式設計的終極之選。具體來說有兩大缺點:
3.2.2.1 缺少高階語言特性
Bash不是一門高階程式語言,和Perl/Python/Ruby/PHP這些同樣可以用作shell程式設計的語言相比,缺少很多高階語言特性,而這些特性在運維部署工作中會用到。
3.2.2.1 工具鏈不豐富
由於不支援OOP,因此沒有完整的單元測試框架。
開發框架、缺陷分析、效能分析工具也幾乎是一片空白。IDE支援雖有(JetBrains公司IntelliJ就有bash shell外掛),但功能不多。
3.3 自動化部署:運維DSL
得益於虛擬化和公有云的快速普及,高效高質量地完成應用部署不再是大公司專有的需求,也成了中小企業的剛需,前面分析過了,bash shell不能勝任大規模的、複雜的應用部署,自動化運維程式語言DSL(Domain Specific Language)被髮明出來,puppet, chef,ansible, saltstack是其中傑出的代表。
4 自動化運維技術發展趨勢展望
4.1 部署工作程式碼化
無論是使用bash / python shell,還是使用puppet、chef等DSL,都可以完成程式碼化這個過程。把手工操作變成程式碼。
使用程式碼自動化部署應用環境和應用,才能保證無論在辦公室測試環境,還是在機房生產環境,每次執行這個部署程式碼,都能得到相同的結果。這是一切自動化部署的基礎。
4.2 運維程式碼版本化
運維程式碼要和Java,PHP等應用程式碼一樣,納入SVN、GIT程式碼倉庫,執行嚴格的開發-測試-上線-回滾流程。
這樣便可利用svn/git的成熟SCM功能,用於這樣一些場景:
4.2.1 新建分支
運維程式碼由1.0升級到2.0,增加了快取層。則可以從1.0複製出一個分支出來,命名為2.0,然後再在2.0的基礎上修改。
4.2.2 差異比較
若要了解1.0和2.0的運維架構到底發生了什麼變化,執行svn和git的diff即可檢視每一行程式碼的變化。
4.2.3 歷史歸檔
1.0版穩定運行了半年,升級到2.0版本,此時1.0版凍結寫請求,歸檔留存。2.0上線執行一段時間,發現穩定性不夠。可以從歸檔中找出1.0版本的部署程式碼,回滾到1.0版本。
4.3 測試環境高保真
很多公司的測試和生產環境存在作業系統不一致、軟體版本不一致、配置項不一致的情況。這種不規範的運維有兩大後果:一是bug在測試環境未能測出,導致線上故障;二是線上出現異常時,測試環境不能復現。
一個應用至少有兩種環境:測試環境、生產環境。大一點的公司還會分成:開發環境、功能測試環境、效能測試環境、預發環境、生產環境。這麼多的環境的自動化部署程式碼,原則上應該是90%以上都相同,只有少數地方不一樣。
4.4 自動化測試
使用程式碼自動化部署完之後,伺服器是否立即可用,需要測試驗證。自動化測試能讓整個運維過程更加高效。
在應用開發領域,自動化測試、單元測試已經非常普及了,運維開發也可以做一些類似的自動化驗收測試工作:
4.4.1 終端應用測試
模擬一個客戶端訪問剛剛部署好的服務,例如:驗證其RESTfulAPI是否得到預期的結果。
優點是,最接近實際使用者,若此測試通過,則說明裝軟體、改配置、啟服務各項工作都正確。缺點是,若測試不通過,不能立即定位出哪裡出錯了。定位問題需藉助下面更底層的測試。
4.4.2 四層網路測試
使用nmap之類的工具檢測目標埠是否正常響應(包括防火牆是否放行)
4.4.3 本機測試
· 用yum,apt檢測包是否安裝
· 用service status檢測守護程序是否正常支援
· 用ps檢測程序是否正在執行
· 用ls檢測檔案是否存在
· 用grep檢查配置薦是否設定成了指定的值
自動化測試用例覆蓋足夠全面,我們便有可能實現一臺機器從祼機到上線服務全部自動化完成,無人值守。若沒有自動化測試,應用部署完成之後,仍然需要人工驗證是否滿足上線服務的要求。
4.5 工作流
運維程式碼從開發到上線發揮作用,也應該和應用程式碼一樣遵循下面的工作流:
這個流程圖只展示了最基本的要求:部署到生產環境前必須經過測試環境驗證。更復雜的還有程式碼reivew、效能測試環境驗證、漏洞掃描環境驗證、預發環境驗證,生產環境分批發布等環節。
很多公司的現狀是運維工程師開兩個ssh終端,一條命令,先在本地環境跑一下看看效果,成功就拿到線上去跑了。更有甚者,不經過本地驗證直接到線上操作了。這主要是因為運維工作沒有充分程式碼化,運維程式碼沒入svn、git倉庫。
4.6 圖形化介面和IDE
運維領域一直都缺少通用的、高效的圖形介面和IDE。這大約有兩個原因:
一是需求不強勁。運維程式設計的複雜度畢竟比應用程式設計簡單好幾個數量級。運維日常工作也沒有程式碼化,還有大量的人工操作,所以,運維程式碼通常像冰糖葫蘆一樣,一個個指令碼雖然串在一起,但大都是個獨立的個體,沒有那麼強的程式碼組織結構。
二是運維社群極客氛圍濃重。就連應用程式設計領域也只有Java、.NET等語言的使用者比較偏愛IDE。在PHP、Python、Perl社群,vim黨、emacs黨、sublime text黨、notepad++黨各領風騷。這些黨派崇拜的編輯器不同,但有一個共同信仰:不依賴IDE寫程式碼是一個優秀程式設計師的必備素質。
關於這個問題,我是這樣認為的,有高科技能提升程式設計生活質量,為什麼不用用?即使puppet、chef把運維程式設計體驗做到這麼好了,我仍然期待運維業界湧現一批Eclipse、AdobeFlash這樣的圖形介面、IDE。讓IDE的高效易用和運維的命令列操作相得益彰。
4.7 運維程式碼分治
運維界有一句祖訓:沒有折騰,就沒有故障。
但為了快速響應業務需求和提高資源利用率,運維又不得不頻繁折騰。有沒有什麼辦法能打破“折騰越多、故障越多”的魔咒?有,分而治之。
分治,就是把風險高的和風險低的分開、重要性高的和不高的分開、簡單的和複雜的分開、頻繁變動的和不頻繁的分開。應用程式設計領域,大家積極探索和實踐的各種架構、框架、模式,歸根到底都在做兩件事:封裝複雜度、隔離變化。
運維架構層的分治,在業界已經非常普遍了,比如應用伺服器和資料庫伺服器分離、交易資料庫和使用者資料庫分離;生產環境和測試環境隔絕。
4.7.1 配置項和邏輯程式碼分開
其實業界早就在這麼做了,puppet的hiera和saltstack的pillar都是做這個用的。
有些運維變更,可能只改變了配置項的值,而並沒改變運維程式碼裡的業務邏輯、流程控制。如果只改配置檔案,不改運維指令碼。釋出風險就低了很多,起碼不會導致語法錯誤。
4.7.2 會變動的配置項獨立
就像應用開發領域裡的模板引擎一樣,把配置檔案寫成模板,模板中包含變數,運維工具或者運維平臺解析模板內容,把變數替換成真實的值。
4.7.3 服務發現
將會變動的配置項獨立出來動態維護,還可以實現服務發現。以haproxy + etcd + confd為例:
confd就是一個模板引擎,類似Java裡有Velocity和Python裡的jinja。不同之處是:confd還有自動輪詢etcd的能力。使用confd解析和管理haproxy的配置檔案,摘錄如下:
跟原生的haproxy配置檔案不同,最後三行是confd模板。
etcd是一個KV儲存,類似memcached,不同之處是etcd生來就是分散式的,自帶高可用和負載均衡的基因,同時還有HTTPRESTful API,存取方便。使用etcd儲存後端伺服器列表。
當後端有一臺nginx服務啟動的時候,調etcd的api把這臺機器的ip地址寫入etcd上的列表。confd輪詢etcd時查到這臺新加入的機器,便會自己把它加進haproxy的backend server裡。
這樣便實現了負載均衡叢集自動化擴容,下線一臺nginx機器亦同此理,先調etcd的api刪除某臺機器,過一分鐘在這臺nginx上檢測不到流量了再把它下線。
擴容過程中沒有修改haproxy的配置,也沒有部署haproxy。只是呼叫了etcd的RESTfulAPI,這個風險就比修改haproxy配置檔案再部署上線小多了。
4.8 整合基礎設施API
所有的公有云廠商都提供了HTTPOpenAPI,包括國外的aws、azure、gce和國內的阿里雲、Ucloud、青雲。
市場佔有率排名靠前的虛擬化軟體商也都有HTTPOpenAPI,包括:VMware、Hyper-V、XenServer、OpenStack。
因此技術上有可能把基礎設施提供商的API整合進來,實現虛擬機器建立、啟動、安裝作業系統、聯網、執行命令、關機、銷燬全生命週期的自動化。
和應用部署指令碼不同,呼叫雲廠商的API不能由DSL指令碼完成,用bash shell來做也非常不方便。應該用PHP、Java之類的應用程式語言寫一個應用來做。
至此,虛擬機器和作業系統初始化、應用環境部署、應用軟體部署全部都實現了自動化,便可以從零建立一臺可上線服務的機器。
4.9 跨廠商跨城市故障轉移
實現了部署工作程式碼化和基礎設施API整合之後,便可以自由地跨廠商、跨城市遷移:在不同的機房維持兩份相同的資料,每分鐘同步。當基礎設施發生重大故障難以在短時間內恢復時,可以迅速在另外一個有資料的機房將整套應用自動化部署起來。
4.10 彈性伸縮
幾乎每一個給人類訪問的網站,其伺服器資源利用率都是存在明顯峰谷的:
· 有的尖峰是一年出現一次,典型的例子是阿里的雙十一。每年11月11日,電商狂歡。大賣家的進銷存系統、淘寶生態鏈上的SaaS服務商(如線上列印快遞單、傳送簡訊券碼、物流跟蹤)的系統壓力也跟著猛漲1-2個數量級。他們投資擴容的硬體裝置,只有這一天才能充分利用,平時利用率極低。
· 有的尖峰是一天出現一次或者多次,比如唯品會、聚划算的10點秒殺。基本每一個電商都一天多波次的秒殺、搶購。
· 更普遍的是白天高峰、凌晨到清晨低谷。
自動化運維(包括自動購買分配虛擬機器、自動部署應用環境、自動部署應用軟體、自動測試)使按需排程計算資源成為了可能。實時的彈性伸縮,意味著每天、甚至每分鐘都在做擴容、縮容,這必須要靠自動化運維實現。
4.10.1 公有云上的按需採購
主流的公有云計費粒度都已經細到小時(aws、阿里雲、Ucloud),有的做到了按分鐘(azure、gce),甚至還有按秒計費的(青雲)。
對出現頻率較低、計劃中的尖峰,人工干預,提前做好擴容和縮容預案,以雙十一為例,人工設定好11月10日購買一批按小時計費的機器(不是包年包月),到了11月15日釋放這些機器,廠商會停止計費。
對出現頻率高的尖峰,運維平臺智慧排程,比如每5秒取樣系統資源利用率,達到指定的擴容閾值就自動買機器並自動化部署、測試、上線服務,低於指定的回收閾值就自動下線伺服器、通知廠商停止計費。這種適用於部署上線時間極短的服務,特別是無狀態、無使用者資料的應用伺服器。若需要較長的預熱時間(如資料庫、快取、搜尋引擎),則需要提前擴容,這就要根據歷史性能曲線做智慧預測了。
按需購買對公有云廠商也有積極意義:
· 從巨集觀角度講,用多少買多少,杜絕浪費,提升了全球公有云資源池中的資源利用率,任何提升資源利用率的事情都是有積極正面的。
· 從經濟角度講,公有云按小時售賣的機器單價比包年的貴,如果兩種售賣方式都能100%把機器賣出去,按小時計費的總收入更高。
· 目前有的公有云廠商已經出現部分機房物理資源售罄的情況。如果提供實時服務(如電商、支付、新聞、社交)的客戶都按需採購,就有可能在閒時把資源釋放出來給實時性要求不高的客戶(如離線大資料處理、動畫渲染)使用。
4.10.2 私有云的業務間調配
已經投資購置大量硬體的企業,可以在不同內部業務之間排程,比如白天把大多數機器用來為消費者提供服務,晚上縮減承擔消費者請求的機器規模,釋放出來的計算資源用來做大資料處理。
5 自動化運維平臺
2012年,我剛在極其艱苦的環境下做了一個自營B2C,恰好看到12306故障頻頻,覺得自己能帶隊做一個比他們好的,於是試著去做資料庫建模,結果,就是有了《身為碼農,為12306說兩句公道話》這篇文章,那篇文章太火了,各種微博、微信、論壇累計轉發可能有幾十萬,還登上了《科技日報》、《南方都市報》、《新京報》等10餘家平面媒體,連12306的技術負責人(中國鐵科院計算所副所長)接受人民網採訪都引用我的觀點。後來微博上很多人轉發說“這兄弟生動地詮釋了:你行你上,不行別逼逼”。
2015年,我對運維做了這麼多展望,技癢難耐,決定再實踐一次“你行你上”,於是我自投資金百萬,做了“運維廚房”這樣一個自動化運維平臺。在這裡就不再多做闡述了。
原文出處:雲技術實踐(微信公眾號)
作者介紹:覃健祥
全球最先進自動化運維平臺【運維廚房】創始人,投身軟體開發和開源事業 16 年,歷任部落格中國CTO、雅虎高階技術專家、阿里巴巴高階技術專家、上市公司香江控股電商總經理。Segmentfault 社群享有聲望的答題專家和演講嘉賓。點選量上億的熱貼《身為碼農,為12306說兩句公道話》作者。