歡迎光臨
每天分享高質量文章

瓜子雲平臺的實踐經驗

 

私有雲平臺的建設和公司在不同階段的需求是息息相關的,瓜子雲平臺從 2017 年啟動專案,到目前承載了公司上千個應用服務,每月服務釋出次數達上萬次。在公司業務爆發性增長的背景下,雲平臺團隊從 0 到 1 的完成了平臺搭建,初步實現了平臺產品化,也總結出了一些雲平臺建設的實踐和經驗。
這篇文章和大家分享下瓜子雲平臺的一些實踐經驗。瓜子是在 2017 年年中啟動雲平臺專案的,當時有如下背景:
  • 技術棧多樣化,PHP、Java、Go、Python 都有使用,但只有 PHP 建立了相對統一的部署流程

  • 業務迭代速度快,人員擴張速度快,再加上微服務化改造,專案數量激增,基於虛擬機器的運維壓力很大

  • 測試環境沒有統一管理,業務開發人員自行零散維護

基於此,我們的 0.x 版本,也是原型版本選擇瞭如下的切入點:
  • 在 CI/CD 層面,先定義出標準流程,但是並不涉及細節的規範化,便於使用者學習,快速將現有流程套進去

  • 同時支援 image 和 tar 包兩種產出,為雲上部署和虛擬機器部署做好構建路徑的相容,在將來遷移時這部分可以做到幾乎無縫

  • 先支援測試環境的部署,在驗證平臺穩定性的同時,不斷收集使用者需求進行快速迭代

 

叢集核心元件的技術選型

 

在服務編排和資源管理方面,Docker 和 Kubernetes 已經比較成熟了,基於容器的微服務化也是大勢,再加上我們對強隔離沒有訴求,所以跳過了 OpenStack,直接選擇了 Kubernetes 方案。
既然用了 Kubernetes 肯定就要解決跨節點的容器網路通訊問題,因為我們是自建機房,沒有公有雲在網路層面的限制,所以沒有考慮應用範圍更廣但是效能和可除錯性較差的 VXLAN 方案。最開始選擇的是 Macvlan + 自研 IPAM 的方式,之後轉向了方案完成度更高的基於 BGP 協議的 Project Calico。
Calico 的優點如下:
  • 基於 BGP 協議,轉發平面依靠主機路由表,不涉及任何封包解包操作,效能非常接近原生網絡卡,並且方便抓包除錯

  • 元件結構簡單,對 Kubernetes 支援很好

  • 可以和 IDC 路由器透過 BGP 協議打通,直接對外廣播容器 IP,讓叢集內外可以透過 IP 直連

  • 有 ACL 能力,類似 AWS 的 Security Group

當然肯定有缺點:
  • 節點間網路最好是二層可達,否則只能使用 IP-in-IP 這種隧道技術,那就失去大半意義了

  • 因為是基於三層轉發的,無法做到二層隔離,安全訴求高的場景不適用

  • 嚴重依賴 iptables,海量併發情況下 netfilter 本身可能成為瓶頸

 

編排和網路解決後,叢集就可以拉起來,接下來需要考慮的是流量如何進入,也就是負載均衡器的選型。在不想過多自己開發的前提下,使用 Kubernetes Ingress 是一個比較好的選擇,但是不同 Ingress 之間功能和成熟度差異都很大,我們也是嘗試了好幾種,從 Nginx 到 Linkerd,最終選擇了 Istio。我們在 0.2 版本開始用 Istio,初期它的不穩定帶來了很多困擾,不過在 1.x 版本釋出後相對穩定很多了。選擇 Istio 的另一個原因是為將來向 Service Mesh 方向演進積累經驗。
以上一個最小功能可用叢集就基本完備了,接下來在 CI/CD 這塊,我們封裝了一個命令列工具 med,它透過讀取專案中的 med.yml,自動生成 dockerfile 和 deployment.yml,之後呼叫 Docker 進行構建,並提交給 Kubernetes 叢集進行部署。
一個 med.yml 例子如下:

從上面這個例子能看到,我們將構建環節拆分成了 prepare 和 build 兩個部分,這個設計其實來源於 dockerfile 的一個最佳實踐:由於拉取依賴的環節往往較慢,所以我們習慣將依賴安裝和編譯過程放到不同的命令中,形成不同的 layer,便於下次復用,提高編譯速度。prepare 階段就是把這部分耗時但是變更不頻繁的操作提出來,透過 version 欄位控制,只要 version 值不變,prepare 部分就不會再重覆執行,而是直接利用之前已經生成好的 prepare 映象進行接下來的 build 環節。build 環節構建結束後將 image 提交到映象倉庫,等待使用者呼叫 deploy 命令進行部署。
在實際開發過程中使用者提出同一個程式碼倉庫構建多個產出的需求,比如一個 Java 專案同時構建出用於釋出的 Web Service 和提交到 Maven 的 jar 包。所以 build 和 deploy 階段都支援多個產出,透過 name 進行區分,引數方面則支援有限的模板變數替換。
最後,我們將 med.yml 和 GitLab CI 結合,一個 CI/CD 流程就出來了,使用者提交程式碼後自動觸發構建,上傳映象並部署到他的測試環境。

 

雲平臺產品化的一些思考

 

雲平臺 1.x
在測試環境跑了一段時間後,大家紛紛嘗到了甜頭,希望不只是在測試環境使用,生產環境也可以部署。這時簡易的客戶端工具就不滿足需求了,新增的主要訴求圍繞著許可權管理和灰度釋出,同時也希望有一個更加視覺化的平臺能看到實體執行的狀態,上線的進度和監控日誌等。需求細化如下:
  • 能直觀看到當前專案的執行狀態,部署狀態

  • 專案有許可權控制

  • 釋出系統支援預釋出和灰度部署

  • 日誌收集和監控報警能力

  • 配置管理能力

  • 定時任務支援

於是經過幾輪迭代後,視覺化的控制臺上線了:

這裡可以詳細展開下部署環節,為了滿足應用上線時的小流量測試需求,最開始是透過使用者換個名字手工部署一個新版本,然後靈活調整不同版本部署之間的流量百分比來實現。但是在執行一段時間後,發現太高的靈活度調整非常容易出錯,比如忘記了一個小流量部署,導致線上不正常,還很難 debug,並且整個操作過程也很繁瑣。於是我們收斂了功能,實現了流程釋出功能:

無論是流量調整還是流程釋出,Kubernetes 預設的滾動更新都是無法滿足需求的。我們是透過先建立一組新版本實體,然後再變更 Istio 的流量切換規則來實現的,示意圖如下:

同時為了既有專案平滑上雲,我們還提供了容器和虛擬機器部署的聯合部署,支援一個專案在一個釋出流程中同時部署到雲平臺和虛擬機器上。再配合外部 Nginx 權重的跳轉,就可以實現業務逐步將流量切換到雲上,最終完全去掉虛擬機器。
這裡有一個小插曲,由於基於 TCP 的 Dubbo 服務流量不經過 Istio 閘道器,而是透過註冊到 ZooKeeper 裡面的 IP 來進行流量調整的,上面的流程釋出和聯合部署對 Dubbo 服務沒有意義。我們在這個版本進行了一個網路調整,將叢集內部的 BGP 路由和外部打通,允許容器和虛擬機器直接通訊。由於 Calico 更換網段是要重新建立所有容器的,所以我們選擇拉起一個新叢集,將所有應用全部遷移過去,切換流量入口,再下掉舊叢集。這裡就體現了容器的便捷性了,數百個應用的遷移只花了十幾分鐘就再另一個叢集完全拉起,業務幾乎沒有感知。
配置管理方面,最開始是透過 env 管理,後來很多應用不太方便改成讀取 env 的方式,又增加了基於 ConfigMap 和配置中心的配置檔案註入能力。

日誌收集方面,最開始使用 ELK,只收集了容器的 stdout 和 stderr 輸出,後來對於放在指定位置的檔案日誌也納入了收集標的中。由於 Logstash 實在太耗資源,我們直接使用 ES 的 ingest 能力進行日誌格式化,去掉了中間的 Kafka 和 Logstash,從 Filebeat 直接輸出到 ES。當然 ingest pipeline 本身除錯起來比較複雜,如果有較多的日誌二次處理需求,不建議使用。日誌展示方面,Kibana 原生的日誌搜尋能力已經比較強大,不過很多人還是喜歡類似 tail -f 的那種檢視方法,我們使用了 Kibana 的第三方外掛 Logtrail 進行了模擬,提供了一鍵從控制檯跳轉到對應容器日誌檢視介面的能力。
監控收集和展示,也是標準的 Prometheus + Grafana,在收集 Kubernetes 暴露出來的效能指標的同時,也允許使用者配置自定義監控的 metric url,應用上線後會自動抓取。報警方面,因為 Prometheus 自帶的 Alert Manager 規則配置門檻比較高,所以我們開發了一個用於規則配置的專案 NieR,將常用規則由運維同學寫好後模板化,然後再提供給使用者訂閱,當然使用者也可以自行建立自己的模板。監控報警系統展開說能再寫一篇文章了,這裡就只放一下架構圖:

雲平臺 2.x
在 1.x 版本迭代的時候,我們發現,早期為了給使用者最大靈活性的 med.yml 在使用者量持續增長後帶來的培訓、運維成本越來越高。每一個第一次接觸平臺的同事都要花費半天的時間閱讀檔案,然後在後續的使用中還有很多檔案沒有描述清楚的地方要搞明白,變相提高了專案上雲的門檻。另外這種侵入使用者程式碼倉庫的方式,每次調整代價都非常大,服務端控制力度也太弱。
針對上述問題,我們在 2.x 版本徹底去掉了 med.yml,實現了全部 UI 化。這裡並不是說把之前的配置檔案丟到一個管理頁面上就算搞定了。拿構建來說,使用者希望的是每種語言有一個標準的構建流程,只需要稍微修改下構建命令就可以直接使用,於是我們定義了語言模板:

然後替使用者填好了大部分可以規範化的選項,當然也允許使用者自行編輯:

在部署層面,除了和構建產出聯動外,最大的變動是引數合理化佈局,讓新使用者基本不用看檔案就能明白各個引數的用途。

2.x 版本才剛剛起步,後續還有非常多在排期安排的事情,比如在功能方面:
  • 支援多叢集部署之後如何做到跨叢集排程

  • 如何方便的能讓使用者快速拉起一套測試環境,乃至於構建自己的內部應用市場

  • 監控系統能不能進一步抽象,直接透過 UI 的方式配置監控模板,能不能自動建議使用者合理的監控閾值

  • 給出各個業務的資源利用率和賬單

在基礎設施層面:
  • 能不能做到不超售但是還能達成合理的資源利用率

  • 離線計算能不能在低峰期復用線上叢集資源,但是不能影響業務

  • ServiceMesh 的進一步研究推廣

  • 有狀態服務的支援等等

等等
以上就是瓜子雲平臺的整體迭代路徑。在整個開發過程中,我們感觸最深的一點是,需要始終以產品化而不是做工具的思想去設計和實現。技術是為了需求服務的,而不是反過來,把一個使用者最痛的痛點打透比做一百個酷炫的功能有用的多。但打透說起來容易,做起來有很多臟活累活。
首先在需求分析階段,基礎設施的變更影響非常廣泛,在徵求大部分人意見的同時,如何引導大家往業界內更先進的路線上演進是要經過深思熟慮的。另外不同階段的需求也不盡相同,不要一窩蜂的追隨技術潮流,適合當前階段的才是最好的技術選型。
其次切入點最好是選擇共識基礎好,影響範圍大的需求點,阻力小,成果明顯。待做出成果後再一步步擴充套件到分歧比較嚴重的深水區。
最後落地的時候要做好技術運營,做好上線前的宣傳培訓,幫助使用者從舊系統儘量無痛的進行遷移。上線後的持續跟蹤,透過資料化的手段,比如前端埋點,核心指標報表等手段觀察使用者的使用情況,不斷調整策略。
上面這些在團隊小的時候可能都不是問題,一個溝通群裡直接就能聊清楚。但當團隊變大後,核心功能上一個不當的設計往往帶來的就是上千工時的白白消耗甚至造成線上事故,一個雲平臺產品能不能落地,技術架構和實現是一方面,上面這些產品和運營策略是否運用得當也是非常重要的。
Q&A;

 

Q:請問瓜子私有雲是一朵獨立的雲還是多雲部署?如果是多雲部署,雲間網路是採用的什麼技術?如何打通多雲之間的網路的?謝謝
A:我們在設計之初就考慮多叢集 / 多 IDC 部署的,這也是選擇 Calico 的一個原因。透過 BGP 協議將容器 IP 廣播出去後,雲間互聯和普通虛擬機器互聯沒有區別,當然這需要網路裝置支援。
Q:新版本實體釋出的時候怎麼切Istio才能保障灰度的流量不丟失呢?
A:在流程釋出裡面,我們相當於先新建一組新的實體,在它們的 Readiness 檢查透過後,切換 Istio 規則指向新實體做到的。
Q:穩定性方面有沒有出現過比較大的問題,怎麼解決的?
A:有兩個時期穩定性故障較多,一個是 Istio 版本比較低的時候,這個只能說一路趟坑趟過來,我們甚至自己改過 Istio 程式碼,現在的版本已經沒出過問題了;一個是叢集用的太狠,當叢集接近滿載時,Kubernetes 會出現很多連鎖問題,這個主要是靠監控來做及時擴容。
Q:自建機房的話為什麼不接著使用 Macvlan + IPAM 方案呢?是為了之後上公有雲做準備嗎?
A:當時面臨一個本機 Macvlan 容器互相不通的問題,再加上有熟悉的團隊已經在生產跑了很久 Calico 了,所以就直接換到了 Calico。
Q:請問幾秒的時延對一些高效的服務來講也是不可接受的。咱們有想過透過何種方式去避免灰度的流量損失問題麼?
A:還真沒遇到過這個需求。我理解如果有一個服務如此關鍵,那麼在整個流量變更環節(從機房入口開始)到灰度策略上都得仔細考慮。如果接受不了 Istio 這個延時,一個思路是完全拋棄 Istio Ingress,直接使用一個切換迅速的負載均衡器。因為容器 IP 是直通的,完全可以從叢集外直接連進來,只要解決服務發現的問題就行。
Q:應用服務追蹤怎麼處理的?對接Istio?
A:語言棧比較多的情況下這是個痛點,目前我們也是在嘗試,即使是 Sidecar 也不能完全對業務沒侵入。公司內部 Java 技術棧更喜歡 Skywalking 這種完全無侵入的方式。
Q:使用 Istio 時,怎麼解決效能損壞問題的?
A:目前還沒有啟用 Mixer 這些對效能影響比較大的元件,所以目前效能損耗還是比較小的。如果對效能有嚴格的要求,我們會建議他使用 service name 做直連。
Q:為什麼 Kubernetes 預設的滾動更新不能滿足要求?哪裡有問題?
A:沒辦法精細控制灰度粒度,比如部署了 4 個實體,我要求切 10% 的流量灰度,這就做不到了。另外,滾動更新回滾也比較慢。
Q:目前支撐的生產應用服務規模和雲平臺的規模能介紹下?包括一些指標,比如多少應用進行灰度更新耗時?
A:應用規模的話目前超過 1000 了,每個月釋出次數超過 10000。灰度更新是使用者自行控制整個釋出進度的,所以耗時不太有參考意義。

已同步到看一看
贊(0)

分享創造快樂