網易蜂巢基於萬節點Kubernetes(k8s)支撐大規模雲應用實踐_Kubernetes中文社群
本文整理自劉超在ArchSummit2016全球架構師峰會(北京站)的演講。
網易蜂巢是做容器Docker的,用Kubernetes來管理容器。現在蜂巢已經支撐了內部、外部很大規模的雲端計算應用,所以我們這個題目有兩個關鍵,一個是Kubernetes和容器,另外一個是大規模雲應用。
網易蜂巢的大規模容器平臺
上圖展示了蜂巢發展歷程。其實很早就開始做蜂巢了,一開始從私有云開始建設。發展分成兩層:應用層、平臺層。進行了四個方面的轉變,一是從虛擬機器進展到容器。因為虛擬機器僅僅是資源平臺的彈性,並沒有實現到應用級別的彈性,實現容器後對應用層要有一定的關心、改造、架構梳理。在應用層我們要做微服務化的改造以及開發流程DevOps的改造,我們還經歷了從私有云到公有云的轉化。2014年95%的應用移到平臺上來,2015年容器雲平臺才正式對外開放。很多應用都是我們自己支撐地比較好以後才作為容器雲平臺開放,對外進行服務。2016年主要是DevOps微服務幫助使用者真正改變流程,改進架構。
上圖是蜂巢上大規模的雲應用,從最早的郵箱,到後來網際網路應用產生了一個爆發的階段,很多logo大家都認識,比如說筆記、雲音樂、考拉海購等等。我們很驕傲的是,其中考拉海購和網易雲音樂都部署在蜂巢平臺上面,它們扛過了“雙十一”。雖然我們的音樂產品推出時間比較晚,但是使用者量很快激增,對整個架構也是一個很大的挑戰。
蜂巢大規模容器平臺整個架構如圖所示。我們原來做過私有云、IaaS平臺,IaaS平臺其實是比較費力的,尤其是對網路方面的優化和儲存方面的優化。到了容器平臺以後,容器本身對CPU隔離、記憶體隔離、應用隔離做得不錯,但是對跨主機網路隔離、統一儲存支援做得不夠,儘管有一些開源解決方案可以做這個事情,但我覺得對IaaS平臺做的一些優化是能夠幫助容器層來提供高效能的網路和儲存服務,所以我們的容器平臺和IaaS平臺有深度結合。在右圖的KVM,因為我們做的是公有云,最關注的就是安全問題。容器隔離性其實本身做得沒有那麼好,容器的許可權不知道開的高還是低,如果開的低用起來很彆扭,因為很多許可權沒有給它,但是開的高的話就可能在同一個主機上還有其他人的應用。 在公有云平臺上,採取的策略是不同的租戶不共享主機、不共享虛擬機器,這樣就能實現比較好的隔離性。
私有云平臺建設
這是私有云平臺資源彈性架構圖。網易資料中心開始建立起來時就是朝著五星級資料中心建立的,所以硬體層非常好,實現了全萬兆互聯、全SSD儲存。如果在蜂巢平臺上訂購一個容器,儲存都是SSD的,效能非常棒。計算虛擬化、網路虛擬化、儲存虛擬化,基本的OpenStack都會做這三層。把KVM作為計算儲存化、OpenVswitch作為網路儲存化、儲存虛擬化方面做了很多改進。基於OpenStack之上是PaaS平臺,PaaS平臺有資料庫、物件儲存、負載均衡、快取服務、CDN、安全服務。這些服務發展的整個歷程比雲平臺還要早,因為像資料庫、物件儲存、快取服務是在網易研究院一開始成立時,這方面的技術就已經開始積累了。
再往上是應用層。這是應用層的架構雛形,是一個電商網站。一般一開始應用層構建時都是單機模式的,這不能說架構師一開始設計時沒有設計好。其實現在網際網路的應用,我們遇到好多的客戶最想要的點就是上線速度快。現在有很多應用就是半年過一茬,如果趕不上這個風口,可能就飛不起來,就會被競爭對手落下,這樣架構再好也沒有用,所以一般不會一開始就把應用層拆得七零八落的。
虛擬機器層面部署方式一般會採取通過指令碼或者自動化配置的工具來進行應用的部署,這裡經常用的是Puppet Chef Ansible。虛擬機器能實現的資源層面比較彈性,比如說“雙十一”原來有5個節點,卡一下變成10個節點,很快可以部署出來,但是另外5個節點裡面是空的,怎麼辦呢?並不能很好實現應用彈性,所以就需要自動化的工具,除了調IaaS平臺把虛擬機器創建出來以外,還要進行部署。應用部署上去之後,如果變化比較慢是沒有任何問題的,指令碼是固定的只需要寫一次就可以了,但是現在應用變化非常快,需要不斷調整指令碼,運維成本還是相對比較大的。
隨著業務發展,應用層的架構就會越來越複雜。比如說使用者的管理,要不要給使用者做一些活動,使用者瀏覽時要不要提供搜尋推薦,要不要做積分,商戶要不要管理自己的供應商,和客戶有矛盾的話要不要有仲裁,支付需不需要對賬,商品配送要不要物流管理,包括對接銀聯、支付寶支付等等,所有的功能都加進來了。如果還是加到同樣一個應用裡的話,整個架構就太複雜了。這個時候架構就會面臨著三個方面的問題:
- 時間的靈活性。一個新的活動要上線的時候,能否儘快實現它的快速迭代。
- 空間的靈活性。能否實現非常快的彈性伸縮。
- 管理的靈活性。比如說有一個服務掛了,怎麼樣把它儘快接起來,和原來應用進行一定程度的關聯。
從虛擬機器到容器
接下來是一個從虛擬機器過渡到容器的時代。這個時代主要有以下幾個方面的不同:
- 原來以資源為核心,現在以應用為核心。運維人員不能再認為不關心應用,只要虛擬機器不掛就沒有問題。這個時候開發人員和運維人員已經不再是兩個獨立的實體,現在流行的概念就是DevOps。
- 有狀態容器。為什麼要支援有狀態容器?從虛擬機器到容器的演化過程,容器其實比較適用於部署一些無狀態的東西,最好是掛了以後再起,只有商務邏輯並沒有資料。雖然在哪個機器上重啟都是可以的,但是我們發現中間還是有很大溝壑的,用習慣虛擬機器的使用者不適應一旦切換到容器,應用就馬上進行無狀態,所以我們採取了一定的技術,下面也會分享如何實現有狀態的容器。
- 容器跨主機互聯和容器使用雲盤儲存。它對於計算的隔離比較好,但是對於網路互聯、共享雲盤,雖然業界有開源的方案,但是這種方案還是有問題的,一個是效能問題,一個是二次虛擬化的問題,一般採取公有云建立虛擬機器的時候,虛擬機器之間的互聯已經有了一個層次的虛擬化,這個時候容器之間的跨主機互聯還要再做一次虛擬化,這樣一層一層套效能就大幅度降低。雲盤儲存也是,如果要在IaaS層之外再做一層叢集,還是會有二次虛擬化,本來下面就是一個虛擬的儲存,創建出雲盤,雲盤再打出叢集,這種二次虛擬化儲存基本不可以使用了。
去狀態化
所謂的去狀態化,就是應用程式一開始會有很多的資料,比如有些資料是儲存在記憶體裡,像會話的資料,有的是儲存在本地檔案系統、本地庫裡,像照片。去狀態化做的事情沒有那麼難,把這些資料外接化就可以了,可以把會話放在快取裡,可以把使用者資料放在資料庫裡,可以把照片儲存在遠端的分散式儲存裡面。僅僅包括商務邏輯、演算法的應用擴充套件起來就非常方便,一變三、三變五,可以比較好地分擔整個應用。其他有狀態的事情就交給外面的快取、資料庫和分散式儲存來做。開源軟體和網際網路軟體發展到今天,外部的快取、資料庫和分散式儲存都已經有了自己的叢集模式,所以把它外接出來並不擔心丟失。
容器化
無狀態化以後,就可以進行容器化。有人說容器化就是微服務,微服務就是容器化,其實不完全。這裡我們用Kubernetes進行管理,把一個服務拆成了四個服務,服務A、B、C、D,它們之間互相關聯、互相調動。容器化並用Kubernetes管理以後,它的服務可以自發現、自修復。如果這時候中間的機器掛了,中間的B、C服務會自動遷移到另外兩臺機器上,重啟以後IP地址可能會是改變的,那麼服務A、D怎麼找到服務B、C呢?Kubernetes會自動管理,Kubernetes中每個服務都有一個服務名,A呼叫B,B就是一個服務名。A不用關心B的IP是什麼,也不用把IP配在配置檔案裡面,只需要把服務名配在配置檔案。無論B遷移到哪個機器,A要訪問B,Kubernetes會自動把服務名對映為B的IP地址訪問過去。這樣就會優雅地實現自修復以及負載均衡。如果發現B是瓶頸,原來B只有一個實體,現在B有三個實體,這三個實體還叫B,那麼A訪問時還是訪問B,但是A訪問時不用關心訪問的是這三個B裡面的哪一個,Kubernetes會幫我們選一個進行訪問,這樣就實現了負載均衡。
DevOps、可迭代
用這種方式,開發的整個流程會非常的順暢。因為容器的映象是不可變的,所以映象把OS、業務程式碼、執行環境、程式庫、目錄結構都包含在內,好處是映象無論放在測試、聯調、生產環境裡面,都能保證環境的一致性。其次,比如從1.0版本升級到1.1版本,發現1.1版本有點不對,要回滾到1.0版本時,也可以確認它就是當時的1.0版本。如果是自己手工調整的話,需要特別小心,過了一段時間可能會忘了自己做了哪些微調整從1.0版本升級到1.1版本。當然其中會有不一樣的地方,比如說環境的配置可能需要通過環境變數或者更穩健的方式來注入測試環境、聯調環境、生產環境。中間一個優雅的事情是,比如原來做一個程式往往會有三份配置檔案,打包時也會把不同的配置檔案放進去。如果以Kubernetes自發現的方式,把B的名字放到配置檔案裡就可以了。本地起一個開發環境,只要把B的名字設為127.0.0.1,在本地就可以相互訪問。到測試環境,A訪問B,配置檔案是不用變的,訪問的B就是測試環境裡面的B。到生產環境裡面一樣,配置檔案也不用變更,不用每次儲存多份配置檔案,開發流程也會非常順暢。
微服務架構
這是最初電商的架構,本來是單體的架構,後來拆分成很多很多的子服務,包括前端的、業務系統、基礎服務系統的,它們之間相互引用,利用Kubernetes相互發現。如果沒有自發現的系統,維護起來還是比較麻煩的。這其實是考拉海購抽象化的模型,整個架構比這個要複雜。巨大的優點是,比如“雙十一”來了,進行壓測可以發現裡面的瓶頸點,對瓶頸點可以進行彈性伸縮,對於非瓶頸點伸縮就相對小一點。大家不會在“雙十一”那天瘋狂的進行使用者註冊,但是下訂單壓力就比較大了。
從私有云到公有云
接下來,我們從私有云開始邁向公有云,開始對外進行服務。這還是有一些挑戰的:
第一,容器的安全問題。如果我們允許使用者共享主機,大家進容器是能看到這個機器上所有的CPU和MEMORY的,而不是僅僅只能看到兩盒。如果是一個黑客,完全可以把旁邊的容器黑掉,所以安全問題是一個非常關鍵的問題,安全問題一個解決思路就是KVM。
第二,容器啟動速度問題。申請容器時可以開一個相對比較大的KVM,第一個容器啟動會有KVM啟動時間,第二個容器啟動就沒有KVM啟動時間,你就會立刻體會到容器的好處。
第三,容器的規模問題。大家都開始使用公有云之後,容器規模會迅速擴大,也會導致整個Kubernetes叢集迅速擴大,從千節點現在已經到了15000節點。
第四,容器的租戶隔離問題。除了CPU、MEMORY的隔離,網路隔離、儲存隔離也是一個問題。
網易蜂巢平臺及優化
這是基於OpenStack上PaaS平臺再往上的容器和編排的平臺。在容器這一層我們提供了自己的映象倉庫,因為在國外訪問,由於防火牆的問題實在是太慢了,當然本地需要做一個cache,映象取下來的時間幾乎可以忽略不計。微服務場景下,必須要有日誌服務,把一個東西拆成了很多個東西以後如果出現了問題,日誌挨個看太多,所以日誌服務採取類似ELK的方式,把日誌收集起來,提供統一的搜尋引擎,這樣做之後交易的整個過程,哪個環節出了問題都一目瞭然。再往上就是編排,除了Kubernetes本身帶的彈性伸縮和服務發現能力之外,我們做了有狀態容器,彌補了從傳統的虛擬機器到最現代化的容器中間的過渡階段。還有排程優化,為什麼要做排程優化?當叢集規模特別大的時候,原來Kubernetes自己的排程機制已經不能滿足這麼多節點的排程效能。作為一個分散式系統最核心的就是排程系統,這就是為什麼很多大型的分散式系統最後都是在修改排程系統,比如OpenStack會把原來的排程系統分成很多的子服務,也是在做排程方面的優化。我們的多租戶是全方位的多租戶,不光是普通的隔離。
Kubernetes是有多租戶的想法和機制的,比如有Namespace,但沒有辦法隔離節點、網路,網路和儲存其實還是需要我們通過自己的機制來進行隔離的。節點的隔離是不同租戶是不會共享節點的,這時候需要有一個LABEL做控制。網路隔離是利用IaaS層的能力進行網路間的隔離,不同租戶會有自己的VXLAN ID。排程效能優化,Kubernetes本身是串型佇列優化,如果都是這個方式,當叢集大的時候任務佇列會特別多,會有很多人上來提交任務,這個時候一個佇列並不能解決問題,我們就改為了多個優先順序佇列解決問題,這樣就可以多執行緒的處理。叢集擴充套件性,Kubernetes會把資料放到ETCD裡,Agent節點會到裡面發現自己需要做哪些事情。我們後來發現叢集規模大了以後,單獨的一個ETCD叢集不能放下這麼多資料量,根據Pod、Node等資源,當一個使用者有一個操作時,我們知道這是屬於哪個使用者,進行負載量均衡的拆分。
這是虛擬機器啟動優化做的事情。我們發現虛擬機器啟動之所以在分鐘級就要分析一下,虛擬機器啟動用了多長時間,並不完全每一次都是一分鐘,有時候長有時候短。OpenStack會呼叫DHCPServer,根據上面拉下來的東西進行本地的初始化,初始化由於各種問題會導致時間非常不可控。其實IP是可以靜態化的,比如虛擬機器的啟動、容器的啟動,剛啟動的時候資料庫就可以給它分配一個IP,Agent就知道將要用哪個IP,就不需要再通過DHCP的方式再分配IP。網絡卡打到虛擬機器,虛擬機器裡的網絡卡會再放到Docker的Namespace裡面,這樣Docker訪問網絡卡就只有一層的虛擬化。有一些傳統應用,有些東西是放在虛擬機器裡的,新的應用是放在容器裡面的,它們之間的相互呼叫不希望用外部NAT方式,因為效能會下降。如果可以統一管理,就可以做到只有一層虛擬化,如果虛擬機器、容器裡面的應用屬於同一個租戶的話就可以相互互聯了。
蜂巢特色
蜂巢的特色首先就是聚焦應用,客戶只需要做好自己的微服務和DevOps就可以了。哪怕不能完全做好,下面有跨主機的二層網路、有狀態容器、外部統一儲存這三個,並沒有意識到用容器的方式和虛擬機器有太大差別。公用的監控、映象、彈性伸縮、持續整合的服務。下面有我們的PaaS層資料庫、分散式儲存,如果用蜂巢,不需要關心資料庫的資料會不會丟失,自己要不要起個數據庫,要不要起個DBA,這樣就避免了麻煩。你只需要關心微服務化和DevOps,儘快把自己的服務上線,站在風口上就可以了。
第二個特色,我們是全開源平臺。無論IaaS層用OpenStack,容器層用Kubernetes,資料庫用MySQL,快取使用Redis。雖然經過後臺一定優化,但是它們的介面是完全標準的,無論你用了MySQL任何私有的特性,遷上來都不會有不適應的地方。這樣一個全開源平臺對使用者嵌入是非常友好的。
作者介紹
劉超,愛程式碼,愛開源。網易雲解決方案總架構師,主要責任是把內部和外部很多雲應用搬到容器的蜂巢上來,目標是做到寫程式碼中最懂解決方案的,懂解決方案中的最會寫程式碼的。10年雲端計算領域研發及架構經驗,Open DC/OS貢獻者。長期專注於kubernetes、 OpenStack、Hadoop、Docker、Lucene、Mesos等開源軟體的企業級應用及產品化。曾出版《Lucene應用開發揭祕》。