容器化已經成爲一種趨勢,它能夠解決不少運維中的痛點,好比效率、成本、穩定性等問題,而接入容器的過程當中每每也會碰到不少問題和不便。在有贊最開始作容器化是爲了快速交付開發測試環境,在容器化的過程當中,咱們碰到過容器技術、運維體系適配、用戶使用習慣改變等各類問題,本文主要介紹有贊容器化過程當中碰到的問題以及採起的方案。php
在有贊同時會有不少個項目、平常在並行開發,環境的搶佔問題嚴重影響了開發、測試和上線的效率,咱們須要給每一個項目提供一套開發聯調(daily)、測試環境(qa),而且隨着項目、平常的生命週期項目環境也會隨着建立和銷燬,咱們最先的容器化需求就是怎麼解決環境快速交付的問題。前端
[有贊環境]java
上面是有贊大體的研發流程,在標準流程中咱們有四套穩定環境,分別是 Daily 環境、Qa 環境、預發環境和測試環境。咱們的開發、測試、聯調工做通常並不會直接在穩定環境中進行,而是會拉一套獨立的項目環境出來,隨着代碼通過開發、測試、預發驗收最終發佈到生產環境後再同步回 Daily/Qa 的穩定環境中。node
[項目環境]python
咱們提供了一套以最小的資源投入知足最大項目並行度的環境交付方案,在 Daily/Qa 穩定環境的基礎上,隔離出N個項目環境,在項目環境裏只須要建立該項目所涉及應用的計算資源,其它缺失的服務調用由穩定環境提供,在項目環境裏,咱們大量使用了容器技術。git
[持續交付]github
後面咱們又在項目環境快速交付的解決方案的基礎上實現了持續交付流水線,目前已經有超過 600 套項目/持續交付環境,加上 Daily/Qa 穩定環境,涉及計算實例四五千個,這些計算實例不管是 cpu 仍是內存使用率都是很是低的,容器化能夠很是好的解決環境交付的效率問題,以及提升資源使用率來節省成本的投入。docker
咱們的容器化方案基於 kubernetes(1.7.10)和 docker(1.12.6)、docker(1.13.1),下面介紹一下咱們在各個方面遇到的問題以及解決方案。後端
有贊後端主要是 java 應用,採用定製的 dubbo 服務化方案,過程當中沒法作到整個單元全量容器化,和原有集羣在網絡路由上互通也就成了剛需,因爲咱們沒法解決公有云上 overlay 網絡和公有云網絡的互通問題,因此一開始咱們放棄了 overlay 網絡方案,採用了託管網絡下的 macvlan 方案,這樣既解決了網絡互通的問題也不存在網絡性能問題,可是也就享受不到公有云彈性資源的優點了。隨着有贊多雲架構的發展以及愈來愈多的雲廠商支持容器 overlay 網絡和 vpc 網絡打通,彈性資源的問題才獲得了緩解。api
容器的隔離主要利用內核的 namespace 和 cgroup 技術,在進程、cpu、內存、IO等資源隔離限制上有比較好的表現,但其餘方面和虛擬機相比存在着不少的不足,咱們在使用過程當中碰到最多的問題是容器裏看到的 cpu 數和內存大小不許確,由於/proc文件系統沒法隔離,致使容器裏的進程"看到"的是物理機的 cpu 數以及內存大小。
咱們的 java 應用會根據服務器的內存大小來決定 jvm 參數應該怎麼配置,咱們是採用 lxcfs 方案來規避的。
由於咱們有超賣的需求以及 kubernetes 默認也是採用 cpu share 來作 cpu 限制,雖然咱們使用了 lxcfs,CPU 數仍是不許的。jvm 以及不少 Java sdk 都會根據系統的 CPU 數來決定建立多少線程,致使 java 應用在線程數和內存使用上都比虛擬機多的多,嚴重影響運行,其餘類型的應用也有相似的問題。 咱們會根據容器的規格內置一個環境變量 NUM_CPUS,而後好比 nodejs 應用就會按照這個變量來建立它的 worker 進程數。在解決 java 類應用的問題時,咱們索性經過 LD_PRELOAD 將 JVM_ActiveProcessorCount 函數覆蓋掉,讓它直接返回 NUM_CPUS 的值[1]。
在容器化以前,有讚的應用已經所有接入到發佈系統,在發佈系統裏已經標準化了應用的打包、發佈流程,因此在應用接入方面成本仍是比較小的,業務方無需提供 Dockerfile。
咱們涉及到灰度發佈的流量主要包含三部分:
通過以前項目/持續交付的上線和迭代,大部分應用自己已經具有了容器化的條件。不過對於上線來講,須要整個運維體系來適配容器化,好比監控、發佈、日誌等等。目前咱們生產環境容器化準備基本完成,生產網已經上了部分前端 nodejs 應用,其餘應用也在陸續推進中,但願之後能夠分享更多生產環境中的容器化經驗。
以上是有贊在容器化上的應用,以及在容器化過程當中碰到的一些問題和解決方案,咱們生產環境的容器化還處於開始階段,後面還會碰到各類個樣的問題,但願可以和你們互相學習,後面可以有更多的經驗分享給你們。