實踐 | 一個案例思考容器落地的山高路遠坑深
背景:某銀行數據中心計劃搭建一個基於容器的PaaS平台
持續集成
持續集成是容器一個繞不過去的話題,無論哪家容器廠商都一定會談到,數人云關於持續集成,最開始用的是drone,一個小眾的持續集成工具,將drone內置在平台上,通過平台的持續集成功能可以方便的實現持續集成的配置和管理。
drone 的坑
- 一開始我們覺得這是一個很好的工具,但是後來發現其實沒有想像中的那麼美好,它的問題:對SVN的支持不好
- 容易出問題,因為數人云平台所有的組件都是容器化的,所以若使用drone,則需要使用docker-in-docker技術,但是該技術已經是一個不再被維護的技術了,所以繼續使用的風險很大。
Jenkins是個好工具
Jenkins是一個好工具,功能強大且穩定,基於Jenkins實現的持續集成基本沒有花費什麼開發的時間,通過腳本將代碼構建和平台連接在一起即可輕鬆實現CI/CD。
總結
往往用戶需要的並不是那些看起來很酷的功能,真正需要的是能夠實際解決問題的方案,即使這個方案很普通。
配置管理
在我看來,容器是一個革命性的產物,改變了軟體交付的方式,它開箱即用的特性消滅了程序員常說的一句話 「在我這裡運行時正常的啊!」; 它快速部署,環境無關的特性幫助運維人員提高了工作效率,但是任何事情都有其兩面性,它的開箱即用,環境無關帶來好處的同時,也帶來了問題——配置文件。
傳統應用在容器時代面臨的第一個問題
一般而言,每個程序都會有一個或多個配置文件,裡邊記錄著DB地址、賬號、密碼、緩存地址等信息,在容器時代之前,應用程序一般的流轉方式是「從開發->測試->生產」:
- 開發同學交付一個編譯之後的二進位文件,源文件(解釋執行)或者代碼倉庫中某一個tag,同時附帶一個release notes;
- 測試同學拿到開發同學交付的內容後,就將其部署在自己的測試環境中,如果release notes中說明了有配置信息需要更新或依賴文件版本需要升級,會依照文件進行調整;
- 如果測試通過,確定可以投產,那麼就將其交付給運維同學進行生產部署。
此時有一個問題,開發、測試、運維每個環節都會自己維護配置文件,如果使用了容器,那麼配置文件管理就是很麻煩的問題了,因為配置文件被放到了容器里,若想修改配置文件就不是那麼簡單的事情了,所以這就是傳統應用在容器化時面臨的第一個問題,當然這個問題也不是不能解決,一般而言,有以下幾種解決方案:
- 掛盤,將配置文件放到外部存儲中,然後將該目錄掛到容器中;
- 生成新的鏡像,基於Docker文件系統的特性,使用測試環境的配置文件覆蓋開發環境的鏡像,從而得到測試環境的鏡像,同理,使用生產環境的配置文件覆蓋開發環境的配置文件得到生產環境的鏡像,使用該方案會導致每個環境都有一個鏡像。
容器時代配置管理的正確打開方式
以上分析了傳統應用容器化基本都會遇到的一個問題,而且也沒有給出很好的解決方案,下面我們來談下容器化時代配置管理的正確打開方式。
其實通過上面問題的描述,我們可以很容易的找到問題的根本原因:配置文件本身是一個本地存儲狀態,要對其做無狀態改造,對於配置管理的無狀態改造一般是通過配置中心來完成的,即應用通過配置中心獲取配置信息,無需讀取本地配置文件,但是這個問題更麻煩,要解決這個問題需要首先解決兩個問題:- 要先有個配置中心
- 要改代碼,使其可以適配配置中心
隨著容器的普及,未來配置中心肯定會逐漸成為程序的標配。
最終選擇的解決方案
關於容器時代配置文件的問題,上邊大概提到了3種方案,在最終落地的時候選擇的是哪一種呢?答案是第二種——生成新的鏡像。這是一個很保守的方案,為什麼沒有選擇另外兩種呢? 我們來解釋下原因:
- 方案一[掛盤], 這個方案會給容器產生另外一個狀態,外部文件,不符合cloud 的思想,pass;
- 方案三[配置中心],成本太高,周期太長,而且需要改代碼,往往之前的應用已經被維護了很多年,修改其配置介面,風險太大。
總結
雖然這個選擇從技術上來看很保守,但是個人認為,使用一個不太優雅的方案幫助一個新技術快速落地,然後推動其快速前進,比一直糾結於方案是否高大上,是否優雅等,而導致新的技術一直被懸在空中更好,就像大家一直在爭論Mesos、Kubernetes、Swarm究竟哪個更好,現在也沒有一個結論,與其爭論這麼多虛的,不如仔細想一下自己的問題是什麼,究竟哪個技術更適合自己。
日誌
目前使用ELK作為日誌方案。
傳統應用的坑
一般而言,傳統的應用都是把日誌寫到一個指定的路徑下,然後通過Logstash採集日誌並送入Elasticsearch進行存儲,但是這種應用如果直接容器化之後就會帶來一個問題——應用的日誌文件應該如何存儲。
- 方案一:放到容器里
- 方案二:掛盤,寫到外部存儲上
兩種方案都有一些問題:
- 放到容器里,邏輯上最簡單,不需要做任何改動,但是它的問題是,怎麼從容器中把日誌取出來。
- 通過掛盤,把容器日誌寫到外部存儲,然後沿用傳統的Logstash + ES 的方式處理日誌,聽起來很美好,但是如何建立容器和日誌的對應關係?
容器時代日誌的正確打開方式
按照之前的慣例,我們先提出在容器時代,日誌的正確處理方式,如果應用使用Docker進行交付,不建議寫日誌文件,直接將日誌寫入標準輸出即可,然後Logstash通過Docker的log-driver捕獲日誌,這樣日誌文件既不需要落盤,也使日誌文件擺脫了狀態,可以更容易的橫向擴縮。
最終選擇的解決方案
最終我們實現的是方案三,因為用戶在我們的建議下,選擇了將日誌輸出到標準輸出。
新的問題
寫日誌的目的是為了看的,這是一個無比正確的廢話,但是如何實時的看到需要的日誌卻成了我們面臨的一個新問題。在容器時代之前,我們一般是通過tail來實時的看日誌或者通過Kibana來分析日誌。
在容器的時代,通過Kibana看日誌的方式沒什麼變化,但是看實時日誌就有了一些問題,在用戶採取了我們的建議將日誌寫入標準輸出後可以比較優雅的處理日誌了,但是另外一個問題出現了,實時日誌沒有了,因為日誌已經被log-driver收走了,怎麼辦?雖然依然可以從ES中找到日誌,但是由於ELK本身的機制,不能通過ELK看到實時日誌。新的解決辦法
新的問題,需要新的辦法來解決,如何解決,其實說穿了也簡單,實現了一個log-agent的功能,可以將日誌送到兩個地方,Logstash和實時日誌。
總結
事情就是這樣,我們以為解決了一個問題的時候,往往一個新的問題又擺在前面,像容器落地這種事情,對傳統應用的整體工作方式和流程都有很大的衝擊,所以一定也會遇到同等規模的問題需要解決。
監控
銀行對監控是非常重視的,尤其是運維部門,所以為了滿足客戶的需求,我們實現了:
- 平台自身監控
- 宿主機監控
- 中間件監控
監控本身是我們平台很重要的一個部分,但是在實際實施過程中發現,客戶其實不是很在意做的監控頁面,儀錶盤等監控數據,他們自身有健全的監控平台,其實我們需要做的事情就是將我們的數據吐到他的平台上即可。
總結
世事難料,你永遠不知道下一塊巧克力什麼味道,這個我們自身投入了很大精力和時間來實現的功能在用戶那裡就變成了一個對接的任務。
彈性擴縮
彈性擴縮一直是容器廠家喜歡談的一個口號,曾經有一度我們認為基於Docker的特性來實行彈性擴縮是一件很容易的事情,但是後來發現,這裡其實有一個大坑。
擴很容易,縮很難
彈性擴容是一件比較容易的事情,我們只要對接監控數據,然後配置一些規則,即可觸發應用容器個數增加,實現擴容,但是縮容就會面臨幾個問題:
- 什麼時候縮容?
- 如何安全的縮容?
什麼時候縮容,這個問題相對來說還不是特別麻煩,可以設定一個指標,比如CPU,內存,IO等指標來觸發縮容,這裡只要做一些帶有緩衝的規則,避免由於規則簡單而導致的擴縮抖動即可。
如何安全的縮容相當麻煩,縮容在本質上是要停掉一些容器的,如何判斷這個容器是可以停止的,如果一個容器沒有流量了,那麼應該是可以被停止的,如何讓一個容器的流量停止?可以通過前端負載進行控制,不往這個容器分發流量,那麼前端的負載是如何判斷應該如何往後端分發流量呢?這個有多重因素:自身演算法
應用程序本身是有狀態的,需要保持會話
從以上簡單的分析中我們可以發現,縮容不是簡單的條件符合了就可以做的事情,要想在不影響業務的情況下實現縮容,是一件非常麻煩的事情,它與平台架構,運行的程序的業務邏輯有很深的耦合。
總結
要實現自動的擴縮容,不是一件簡單的事情,而是一個系統的工程。
以上內容是基於數人云在某銀行實施過程中總結出來的一些感悟,如果能給大家一些幫助,我們非常高興,如果有問題,請指出來,我們共同提高,Docker到現在大概有3年多的歷史,個人看來它距離真正落地還有很大一段路程要走,我們必須不停的摸索。
歡迎關注同名專欄
掃碼關注公眾號,獲得更多姿勢
aHR0cDovL3dlaXhpbi5xcS5jb20vci9nMHpidzlERWRvMEpyWlNnOXhtUg== (二維碼自動識別)
推薦閱讀:
※Docker市場看好,小白也能進級成大神!
※你眼中的#Kubernetes 2017年度十大新聞事件#
※密碼1212@KubeCon北美峰會幹貨直播培訓課
※使用Node.js+Docker+GraphQL+MongoDB構建服務