有贊容器化實踐

有贊技術發表於2018-09-28

前言

容器化已經成為一種趨勢,它可以解決很多運維中的痛點,比如效率、成本、穩定性等問題,而接入容器的過程中往往也會碰到很多問題和不便。在有贊最開始做容器化是為了快速交付開發測試環境,在容器化的過程中,我們碰到過容器技術、運維體系適配、使用者使用習慣改變等各種問題,本文主要介紹有贊容器化過程中碰到的問題以及採取的方案。

有贊容器化的初衷

在有贊同時會有很多個專案、日常在並行開發,環境的搶佔問題嚴重影響了開發、測試和上線的效率,我們需要給每個專案提供一套開發聯調(daily)、測試環境(qa),並且隨著專案、日常的生命週期專案環境也會隨著建立和銷燬,我們最早的容器化需求就是怎麼解決環境快速交付的問題。

[有贊環境]

有贊容器化實踐

上面是有贊大致的研發流程,在標準流程中我們有四套穩定環境,分別是 Daily 環境、Qa 環境、預發環境和測試環境。我們的開發、測試、聯調工作一般並不會直接在穩定環境中進行,而是會拉一套獨立的專案環境出來,隨著程式碼經過開發、測試、預發驗收最終釋出到生產環境後再同步回 Daily/Qa 的穩定環境中。

[專案環境]

有贊容器化實踐

我們提供了一套以最小的資源投入滿足最大專案並行度的環境交付方案,在 Daily/Qa 穩定環境的基礎上,隔離出N個專案環境,在專案環境裡只需要建立該專案所涉及應用的計算資源,其它缺失的服務呼叫由穩定環境提供,在專案環境裡,我們大量使用了容器技術。

[持續交付]

有贊容器化實踐

後面我們又在專案環境快速交付的解決方案的基礎上實現了持續交付流水線,目前已經有超過 600 套專案/持續交付環境,加上 Daily/Qa 穩定環境,涉及計算例項四五千個,這些計算例項無論是 cpu 還是記憶體使用率都是非常低的,容器化可以非常好的解決環境交付的效率問題,以及提高資源使用率來節省成本的投入。

有贊容器化方案

我們的容器化方案基於 kubernetes(1.7.10)和 docker(1.12.6)、docker(1.13.1),下面介紹一下我們在各個方面遇到的問題以及解決方案。

網路

有贊後端主要是 java 應用,採用定製的 dubbo 服務化方案,過程中無法做到整個單元全量容器化,和原有叢集在網路路由上互通也就成了剛需,由於我們無法解決公有云上 overlay 網路和公有云網路的互通問題,所以一開始我們放棄了 overlay 網路方案,採用了託管網路下的 macvlan 方案,這樣既解決了網路互通的問題也不存在網路效能問題,但是也就享受不到公有云彈性資源的優勢了。隨著有贊多雲架構的發展以及越來越多的雲廠商支援容器 overlay 網路和 vpc 網路打通,彈性資源的問題才得到了緩解。

隔離性

容器的隔離主要利用核心的 namespace 和 cgroup 技術,在程式、cpu、記憶體、IO等資源隔離限制上有比較好的表現,但其他方面和虛擬機器相比存在著很多的不足,我們在使用過程中碰到最多的問題是容器裡看到的 cpu 數和記憶體大小不準確,因為/proc檔案系統無法隔離,導致容器裡的程式"看到"的是物理機的 cpu 數以及記憶體大小。

記憶體問題

我們的 java 應用會根據伺服器的記憶體大小來決定 jvm 引數應該怎麼配置,我們是採用 lxcfs 方案來規避的。

有贊容器化實踐

CPU 數的問題

因為我們有超賣的需求以及 kubernetes 預設也是採用 cpu share 來做 cpu 限制,雖然我們使用了 lxcfs,CPU 數還是不準的。jvm 以及很多 Java sdk 都會根據系統的 CPU 數來決定建立多少執行緒,導致 java 應用線上程數和記憶體使用上都比虛擬機器多的多,嚴重影響執行,其他型別的應用也有類似的問題。 我們會根據容器的規格內建一個環境變數 NUM_CPUS,然後比如 nodejs 應用就會按照這個變數來建立它的 worker 程式數。在解決 java 類應用的問題時,我們索性通過 LD_PRELOAD 將 JVM_ActiveProcessorCount 函式覆蓋掉,讓它直接返回 NUM_CPUS 的值[1]。

應用接入

在容器化之前,有讚的應用已經全部接入到釋出系統,在釋出系統裡已經標準化了應用的打包、釋出流程,所以在應用接入方面成本還是比較小的,業務方無需提供 Dockerfile。

  1. nodejs, python,php-soa 等用 supervisord 託管的應用,只需要在 git 倉庫裡提供 app.yaml 檔案定義執行需要的 runtime 和啟動命令即可。
    有贊容器化實踐
  2. java 標準化啟動的應用業務方無需改動
  3. java 非標準化的應用需要做標準化改造

映象整合

有贊容器化實踐
容器映象我們分了三層,依次為 stack 層(os),runtime 層(語言環境),應用層(業務程式碼和一些輔助agent),應用以及輔助 agent 由 runit 來啟動。由於我們的配置還沒有完全分離,在應用層目前還是每個環境獨立打包,映象裡除了業務程式碼之外,我們還會根據業務的語言型別放一些輔助的 agent。我們一開始也想將各種 agent 拆成多個映象,然後每個 pod 執行多個容器,後來因為解決不了 pod 裡容器的啟動順序(服務啟動有依賴)問題,就把所有服務都扔到一個容器裡去執行了。

有贊容器化實踐
我們的容器映象整合過程也是通過 kubernetes 來排程的(會排程到指定的打包節點上),在釋出任務發起時,管控系統會在叢集中建立一個打包的 pod,打包程式會根據應用型別等引數編譯程式碼、安裝依賴,並且生成 Dockerifile,然後在這個 pod 中使用 docker in docker 的方式來整合容器映象並推送到倉庫。 為了加速應用的打包速度,我們用 pvc 快取了 python 的 virtualenv,nodejs 的 node_modules,java 的 maven 包等檔案。另外就是 docker 早的版本里,Dockerfile ADD 指令是不支援指定檔案屬主和分組的,這樣會帶來一個問題就是需要指定檔案屬主時(我們的應用是以 app 賬號執行的)需要多執行一次 RUN chown,這樣映象也就多了一層資料,所以我們打包節點的 docker 版本採用了官方比較新的 ce 版本,因為新版本支援 ADD --chown 特性。

負載均衡(ingress)

有贊容器化實踐
有讚的應用內部呼叫有比較完善的服務化和 service mesh 方案,叢集內的訪問不用過多考慮,負載均衡只需要考慮使用者和系統訪問的 http 流量,在容器化之前我們已經自研了一套統一接入系統,所以在容器化負載均衡上我們並沒有完整按照 ingress 的機制來實現 controller,ingress 的資源配置是配在統一接入裡的,配置裡面轉發的 upstream 會和 kubernetes 裡的 service 關聯,我們只是做了一個 sync 程式 watch kube-api,感知 service 的變化來實時更新統一接入系統中 upstream 的伺服器列表資訊。

容器登入和除錯

有贊容器化實踐
在容器化接入過程中開發會反饋是控制檯比較難用,雖然我們優化了多次,和 iterm2 等的體驗還是有所不足,最終我們還是放開了專案/持續交付環境這種需要頻繁登陸除錯的 ssh 登陸許可權。 另外一個比較嚴重的問題是,當一個應用啟動後健康檢查有問題會導致 pod 一直在重新排程,而在開發過程中開發肯定是希望看到失敗現場的,我們提供了除錯釋出模式,讓容器不做健康檢查。

日誌

有贊容器化實踐
有贊有專門的日誌系統,我們內部叫天網,大部分日誌以及業務監控資料都是通過 sdk 直接打到天網裡去了,所以容器的標準輸出日誌僅僅作為一種輔助排查問題的手段。我們容器的日誌收集採用的是 fluentd,經過 fluentd 處理後按照天網約定的日誌格式打到 kafka,最終由天網處理進入 es 做儲存。

灰度釋出

我們涉及到灰度釋出的流量主要包含三部分:

  1. 使用者端的 http 訪問流量
  2. 應用之間的 http 呼叫
  3. 應用之間的 dubbo 呼叫 首先,我們在入口的統一接入上統一打上灰度需要用的各種維度的標籤(比如使用者、店鋪等),然後需要對統一接入、http client 以及 dubbo client 做改造,目的是讓這些標籤能夠在整個呼叫鏈上透傳。我們在做容器灰度釋出時,會發一個灰度的 deployment,然後在統一接入以及灰度配置中心配置灰度規則,整個鏈路上的呼叫方都會感知這些灰度規則來實現灰度釋出。

標準環境容器化

標準環境的出發點

  1. 和專案環境類似,標準穩定環境中的 daily,qa,pre 以及 prod 中超過一半執行在低水位的伺服器的資源非常浪費。
  2. 因為成本考慮 daily,qa,pre 裡都是以單臺虛擬機器執行的,這樣一旦需要釋出穩定環境將會造成標準穩定環境和專案環境的短暫不可用。
  3. 虛擬機器交付速度比較慢,使用虛擬機器做灰度釋出也比較複雜。
  4. 虛擬機器往往會存在幾年甚至更長的時間,執行過程中作業系統以及基礎軟體版本的收斂非常麻煩。

標準環境容器化推進

經過之前專案/持續交付的上線和迭代,大部分應用本身已經具備了容器化的條件。不過對於上線來說,需要整個運維體系來適配容器化,比如監控、釋出、日誌等等。目前我們生產環境容器化準備基本完成,生產網已經上了部分前端 nodejs 應用,其他應用也在陸續推動中,希望以後可以分享更多生產環境中的容器化經驗。

結束語

以上是有贊在容器化上的應用,以及在容器化過程中碰到的一些問題和解決方案,我們生產環境的容器化還處於開始階段,後面還會碰到各種個樣的問題,希望能夠和大家互相學習,後面能夠有更多的經驗分享給大家。

參考文獻

[1] github.com/fabianenard…

有贊容器化實踐

相關文章