創業公司小團隊為什麼要使用Docker

即刻技術團隊發表於2017-04-06

以Docker為代表的容器技術已經持續成為話題好幾年了,本以為在沒有歷史包袱的創業公司中,Docker應該會成為生產環境上部署和管理服務的標準配置,然而最近發現一些友商在得知我們在生產上使用Docker和Kubernetes之後,居然表現出了一些驚訝。我想對於這些團隊沒有采納Docker而是繼續使用傳統運維方案,還是覺得即使多做一些繁瑣的運維工作,也希望對系統有更多的掌控度。

Docker所依賴的LXC容器技術,早在十多年前就被Google這類大廠使用了,國內的一些大廠也在很早開始投入研發和使用了,對他們來說,使用容器能夠充分利用計算資源,節省硬體開銷。然而對於小公司來說,把10臺伺服器壓縮到5臺伺服器並不能幫助公司活下去。

容器技術真正開始廣泛產生影響是從Docker的誕生開始,Docker剛出來的時候,官網上的slogan:“Build Ship Run”,準確的闡述了Docker的定位,從打包到部署,傳統運維的這一套流程,由於語言,環境,平臺的不同在各個公司千差萬別,幾乎每個公司都會開發一套自己的釋出系統。有了Docker之後,這些居然都可以標準化了,並且相對於笨重的虛擬機器,Docker幾乎就是一個程式簡單的包裝,只有很少的額外開銷,啟動速度也幾乎相當於直接啟動應用程式。

對於沒有專職運維的即刻團隊,很自然的從專案開始就使用Docker來做服務的釋出工具了:

第一階段:對映宿主機埠 + HAProxy轉發

由於一個Docker容器只是一個(或一組)程式的封裝,一個容器想要向宿主機之外的網路提供服務,就只能繫結宿主機的埠了,埠的管理也是一件大部分情況下都不希望人去操心的麻煩事,為了避免埠衝突,對於需要暴露埠的容器,Docker會隨機繫結一個宿主機埠,這個時候我們就需要服務發現機制來幫助不同機器上的服務來進行通訊了。

我們使用了一個簡單的方案,一套開源的工具:docker-discover和docker-register,它包含兩個元件:

  1. 每臺worker node虛擬機器上執行一個docker-register容器,用來掃描本地容器,把他們的服務名(用映象名作為服務名)和埠(包括容器內埠和宿主機埠)註冊到etcd上。

  2. 一個docker-discover容器用來做中心代理,它內部包含了一個HAProxy,每隔幾秒鐘掃描Etcd上的註冊服務,並生成配置檔案,重新整理HAProxy,生成backend配置的模版如下

{% for service in services %}
listen {{ service }}
    bind *:{{services[service].port}}
    {% for backend in services[service].backends %}
    server {{ backend.name }} {{ backend.addr }} check inter 2s rise 3 fall 2{% endfor %}
{% endfor %}複製程式碼

創業公司小團隊為什麼要使用Docker

這個方案給我們提供了一套系統的幾個基本功能:應用釋出,服務發現,負載均衡,程式守護,其中應用釋出是執行指令碼去各個worker node上拉取最新映象,程式守護則是由Docker daemon的restarts=always來提供。

除了提供一致的執行環境使服務的釋出和回滾比較可控,這套簡單的系統在釋出流程上還是像傳統運維一樣需要遠端執行指令碼,功能比較簡單,隨著我們後端系統成長起來,很快就不夠用了。

第二階段:Rancher

Docker本身只是提供了一個執行環境,除了把服務跑起來之外,要讓多個服務容器協同起來工作,我們還需要一個容器編排(Orchestration)系統,一般來說我們期望編排系統能幫我們實現幾個目的:

基本釋出自動化功能:

編排過程包含分配機器,拉取映象,啟動/停止/更新容器,存活監控,容器數量擴充套件和收縮

宣告式定義服務棧:

提供一種機制,可以用配置檔案來宣告服務的網路埠,映象及版本,在需要的時候通過配置可再現的建立出一整套服務。

服務發現:

提供DNS和負載均衡,一個容器啟動之後,需要其他服務能夠訪問到它,一個容器終止執行之後,需要保證流量不會再導向它。

狀態檢查:

需要持續監控系統是否符合配置中宣告的狀態,比如一臺宿主機掛了,需要把上面執行的容器在其他健康的節點上啟動起來,如果一個容器掛了,需要把它重新啟動。

從設計思路,社群活躍度等因素來看,Kubernetes無疑是編排工具最好的選擇,但由於元件較多,學習成本並不低,還有牆的因素,在國內甚至安裝都不是件容易的事。

這個時候我們發現Rancher正式釋出了,雖然沒有kubernetes那麼熱門,但它提供了所有我們需要的功能,還有一個簡單容易上手的Web UI。在早期我們的機器和服務數量都比較少,又急需一個編排工具好把有限精力都投入到開發上,所以迅速的把服務都遷移到Rancher上了。

準確的說,Rancher是一套容器管理打包方案,支援三種編排引擎:Kubernetes,Swarm,還有Rancher自己開發的Cattle(最近好像換成了Mesos)。從功能的完整性和易用性來看,Rancher甚至可以算得上一個商業軟體了,部署極其簡單,這也是我們選擇它作為入門級容器管理平臺的原因。

Rancher元件圖,中小企業常用的軟體功能都能找到:

創業公司小團隊為什麼要使用Docker

後來圍繞Rancher,也使用了一些Catalog裡提供的服務棧,我們逐步搭建起來了一套完整的容器運維繫統,包含了日誌收集,效能監控,配合AWS的Auto Scaling Group,應用擴充套件也是很方便的事情。

第三階段:Kubernetes

雖然Rancher非常的易用,但隨著我們後端機器和專案數量的增加,它的一些問題也暴露出來了,UI卡頓,釋出速度越來越慢,1.3之後甚至經常出現服務的預期狀態(容器數量,版本)無法被保證,卡在釋出中或者完成中狀態,真正讓我們下定決心要遷移的是一次重大故障,疑似網路雪崩引起,叢集所有機器都在重複斷開連線,本來按一般編排系統的設計,worker node上的容器之間通過overlay網路通訊,node和Rancher server的連線即使斷開也不會影響已經啟動的容器執行。但在1.3之後的Rancher中,不知是有意設計還是bug,worker node重新連線上Rancher server之後,節點上所有的容器會被重新schedule,這就導致叢集中所有容器都不斷的被銷燬又重新建立。

在Rancher上碰到大大小小的問題,我們發現大部分都很難找到社群提供的解決方案,我們很可能是不幸比較早踩坑的人,雖然Rancher是開源的,但技術上的文件相比使用文件明顯欠缺很多,想通過了解他的實現來排查問題比較困難,也很少有Rancher公司之外的contributor,這點是和Kubernetes很明顯不同的。

和Rancher提供了一整套解決方案不一樣,Kubernetes提供的是一個框架,對於Rancher,即使不熟悉其中各個元件,也可以直接用預設的配置安裝,拿來當一個釋出工具使用,Kubernetes則要求使用者對他的元件有一定程度瞭解,社群提供了很多幫助部署的installer,但使用前都需要不少配置工作。

DevOps同事畫的Kubernetes架構圖:

創業公司小團隊為什麼要使用Docker

在Rancher上積累了一些容器編排的經驗之後,我們對使用Kubernetes做編排也有了一些信心,於是開始遷移到效能更好,社群更活躍的kubernetes上。

我們將線上服務一點點從Rancher上把流量切換到Kubernetes叢集,起初發現流量稍微增漲便丟包嚴重,定位到問題是DNS解析緩慢,觀察kernel log發現宿主機conntrack count到達上限,出現丟包。

這裡解釋一下iptable裡的conntrack:我們在使用iptable做面向連線的防火牆時,要允許與一個ip地址建立特定連線,除了讓該連線下的包能進來,還要讓回覆的包能出去,由於ip是個無狀態協議,這個時候就需要一個session表來記錄有狀態的連線,conntrack就是用來記錄這些session的。在微服務下,服務間呼叫頻繁,會產生大量DNS查詢,linux預設的conntrack_max很容易突破限制,所以在部署有DNS service的機器上設定一個較高的conntrack_max值基本上是必須的。

容器生態

前面介紹了我們使用容器來做服務編排,除了這些,相對於傳統架構,使用容器我們還獲得了一整套日誌和監控的解決方案,比如日誌採集,部署在容器中的日誌可以直接列印到標準輸出中,Docker本身支援多種logging driver,可以將日誌直接發到Graylog,AWS CloudWatch等日誌平臺,也可以讓Fluentd等日誌採集工具來採集Docker預設輸出的json-file,相比之下傳統架構可能需要在應用中使用專門配置的logger輸出到收集系統,或者配置專門的採集器去採集不同的日誌檔案。

小公司對基礎設施的投入不足,一般沒有專人去熟悉Kubernetes這種大型開源專案,但即刻算是一個對技術持開放態度,願意讓工程師去踩坑、嘗試的公司。相對於採用傳統架構,因為容器編排系統都是以提高本身的複雜性來覆蓋繁瑣的配置和指令碼編寫工作,本身複雜了就會導致出現問題的時候會比較難排查。但做過運維工作的應該瞭解,一般自己編寫的指令碼很難具有通用性,很可能環境稍有改變就不能使用了,運維是比較枯燥的工作,有了編排系統幫助處理這些,我們可以把更多的精力放到更有意義的工作上。

題圖By:蒙天放

參考:

jasonwilder.com/blog/2014/0…

thenewstack.io/containers-…

rancher.com/rancher/

conntrack-tools.netfilter.org/manual.html

相關文章