蘑菇街11.11:私有云平臺的Docker應用實踐
對于蘑菇街而言,每年的11.11已經成為一年中最大的考驗,考驗的是系統穩定性,容災能力,緊急故障處理,運維等各個方面的能力。蘑菇街的私有 云平臺,從無到有,已經經過了近一年的發展,生產環境上經歷了3次大促,穩定性方面得到了初步驗證。本文我將從架構、技術選型、應用等角度來談談蘑菇街的 私有云平臺。
另,ArchSummit全球架構師峰會北京站將于2015年12月18日~19日在北京國際會議中心召開,大會設置了《 揭秘雙十一背后的技術較量 》專題來深入解讀雙十一背后的技術故事,歡迎關注。
蘑菇街的私有云平臺(以下簡稱蘑菇街私有云)是蘑菇街面向內部上層業務提供的基礎性平臺。通過基礎設施的服務化和平臺化,可以使上層業務能夠更加 專注在業務自身,而不是關心底層運行環境的差異性。它通過基于Docker的CaaS層和KVM的IaaS層來為上層提供IaaS/PaaS層的云服務, 以提高物理資源的利用率,以及業務部署和交付的效率,并促進應用架構的拆分和微服務化。
在架構選型的時候,我們覺得Docker的輕量化,秒級啟動,標準化的打包/部署/運行的方案,鏡像的快速分發,基于鏡像的灰度發布等特性,都十 分適合我們的應用場景。而Docker自身的集群管理能力在當時條件下還很不成熟,因此我們沒有選擇剛出現的Swarm,而是用了業界最成熟的 OpenStack,這樣能同時管理Docker和KVM虛擬機。相對來說,Docker適合于無狀態,分布式的業務,KVM適合對安全性,隔離性要求更 高的業務。
對于上層業務來說,它不需要關心是運行在容器中,還是KVM虛擬機里。今后的思路是應用的微服務化,把上層的業務進行拆分,變成一個個微服務,從而對接PaaS基于容器的部署和灰度發布。
技術架構
在介紹雙十一的準備工作之前,我先簡單介紹一下蘑菇街私有云的技術架構。
我們采用的是OpenStack+novadocker+Docker的架構模式,novadocker是StackForge上一個開源項目, 它做為nova的一個插件,通過調用Docker的RESTful接口來控制容器的啟停等動作。每個Docker就是所謂的“胖容器”,它會有獨立的IP 地址,通過supervisord來管理容器內的子進程,常見的如SSHD、監控agent等進程。
我們在IaaS的基礎上自研了PaaS層的編排調度等組件,實現了應用的彈性伸縮、灰度升級,支持一定的調度策略。我們通過Docker和 Jenkins實現了持續集成(CI)。Git中的項目如果發生了git push等動作,便會觸發Jenkins Job進行自動構建,如果構建成功便會生成Docker Image并push到鏡像倉庫。基于CI生成的Docker Image,可以通過PaaS的API或界面,進行開發測試環境的實例更新,并最終進行生產環境的實例更新,從而實現持續集成和持續交付。
網絡方面,我們沒有采用Docker默認提供的NAT網絡模式,NAT會造成一定的性能損失。通過OpenStack,我們支持Linux bridge和openvswitch,不需要啟動iptables,Docker的性能接近物理機的95%。
準備工作
穩定性
迎戰雙11,最重要的當然是確保穩定性。通過近一年的產品化和實際使用,我們積累了豐富的提高穩定性的經驗。
對于那些已遇到過的問題,需要及時采用各種方式進行解決或者規避。
比如說,CentOS6.5對network namespace支持不好,在Docker容器內創建Linux bridge會導致內核crash,upstream在2.6.32-504中修復了這個bug,因此線上集群的內核版本,必須升級至 2.6.32-504或以上。
又比如,CentOS6.5自帶的device mapper存在dm-thin discard導致內核可能隨機crash,這個問題我們早在四月份的時候已經 發現并解決了 ,解決的辦法是關閉discard support,在docker配置中添加“--storage-opt dm.mountopt=nodiscard --storage-opt dm.blkdiscard=false”,并且嚴格禁止磁盤超配,因為磁盤超配可能會導致整個device mapper無法分配磁盤空間,而把整個文件系統變成只讀,從而引起嚴重問題。
監控
我們在雙11前重點加強的是針對容器的監控。
在此之前,我們已經自研了一套container tools。主要功能有兩個:一是能夠以容器為粒度計算load值,可以根據load值進行容器粒度的qps限流。二是替換了原有的top、free、 iostat、uptime等命令,確保運維在容器內使用常用命令時看到的是容器的值,而不是整個物理機的值。雙十一之后我們還會把lxcfs移植到我們 的平臺上來。
在宿主機上,我們增加了 多維度 的閾值監控和報警,包括對關鍵進程的存活性監控/語義監控,內核日志的監控,實時pid數量的監控,網絡連接跟蹤數的監控,容器oom的監控報警等等。
實時pid數量監控
為什么要監控實時的pid數量呢?因為目前的Linux內核對pid的隔離性支持是不完善的。還沒有任何Linux發行版能做到針對pid按照容器粒度進行pid_max限制。
曾經發生過一個真實的案例是:某個用戶寫的程序有bug,創建的線程沒有及時回收,容器中產生了大量的線程,最后在宿主機上都無法執行命令或者 ssh登陸,報的錯是"bash: fork: Cannot allocate memory",但是此時通過free命令看到空閑的內存卻是足夠的。
為什么會這樣呢?根本原因是內核中的pid_max(/proc/sys/kernel/pid_max)是全局共享的。當一個容器中的pid數 目達到上限32768,會導致宿主機和其他容器無法創建新的進程。最新的4.3-rc1才支持對每個容器進行pid_max的限制。
內存使用監控
值得一提的是,我們發現cgroup提供的內存使用值是不準確的,比真實使用的內存值要低。因為內核memcg無法回收slab cache,也不對dirty cache量進行限制,所以很難估算容器真實的內存使用情況。曾經發生過統計的內存使用率一到70-80%,就發生OOM的情況。為此,我們調整了容器內 存的計算算法,根據經驗值,將cache的40%算做rss,調整后的內存計算比之前精確了不少。
日志亂序
還有一個問題是跑Docker的宿主機內核日志中經常會產生字符亂序,這樣會導致日志監控無法取到正確的關鍵字進行報警。
經過分析發現,這個跟我們在宿主機和Docker容器中都跑了rsyslogd有關。由于內核中只有一個log_buf緩沖區,所有printk 打印的日志先放到這個緩沖區中,docker host以及container上的rsyslogd都會通過syslog從kernel的log_buf緩沖區中取日志,導致日志混亂。通過修改 container里的rsyslog配置,只讓宿主機去讀kernel日志,就能解決這個問題。
隔離開關
平時我們的容器是嚴格隔離的,我們做的隔離包括CPU、內存和磁盤IO,網絡IO等。但雙十一的業務量可能是平時的十幾倍或幾十倍。我們為雙十一 做了不少開關,在壓力大的情況下,我們可以為個別容器進行動態的CPU,內存等擴容或縮容,調整甚至放開磁盤iops限速和網絡的TC限速。
健康監測
我們還開發了定期的健康監測,定期的掃描線上可能存在的潛在風險,真正做到提前發現問題,解決問題。
災備和緊急故障處理
除了穩定性,災備能力也是必須的,我們做了大量的災備預案和技術準備。比如我們研究了不啟動Docker Daemon的情況下,離線恢復Docker中數據的方法。具體來說,是用dmsetup create命令創建一個臨時的dm設備,映射到Docker實例所用的dm設備號,通過mount這個臨時設備,就可以恢復出原來的數據。
我們還支持Docker容器的冷遷移。通過管理平臺的界面可以一鍵實現跨物理機的遷移。
與已有運維系統的對接
Docker集群必須能與現有的運維系統無縫對接,才能快速響應,真正做到秒級的彈性擴容/縮容。我們有統一的容器管理平臺,實現對多個Docker集群的管理,從下發指令到完成容器的創建可以在7秒內完成。
性能優化
我們從系統層面也對docker做了大量的優化,比如針對磁盤IO的性能瓶頸,我們調優了像 vm.dirty_expire_centisecs,vm.dirty_writeback_centisecs, vm.extra_free_kbytes這樣的內核參數。還引入了 非死book的開源軟件flashcache ,將SSD作為cache,顯著的提高docker容器的IO性能。
我們還通過合并鏡像層次來優化docker pull鏡像的時間。在docker pull時,每一層校驗的耗時很長,通過減小層數,不僅大小變小,docker pull時間也大幅縮短。
鏡像 |
文件層數 |
文件大小 |
docker pull時間 |
原鏡像 | 13 | 1.051 GB | 2m13 |
新鏡像 | 1 | 674.4 MB | 0m26 |
總結
總的來說,雙11是對蘑菇街私有云的一次年終大考,對此我們已有了充分的準備。隨著Docker集群部署的規模越來越大,我們還有很多技術難題有 待解決,包括容器本身的隔離性問題,集群的彈性調度問題等等。同時我們也很關注Docker相關的開源軟件Kubernetes、Mesos、 Hyper、criu、runC的發展,未來將引入容器的熱遷移,Docker Daemon的熱升級等特性。
如果大家想了解更多的話,可以關注我們的技術博客 http://mogu.io/ 。蘑菇街期待你的加入,一起來建設大規模的Docker集群。
作者介紹
郭嘉,蘑菇街平臺技術部架構師,虛擬化組負責人。2014年加入蘑菇街,目前主要專注于蘑菇街的私有云建設,關注Docker、KVM、OpenStack、Kubernetes等領域。郵箱:guojia@mogujie.com。