本文是根據 KubeSphere 雲原生 Meetup 杭州站講師祁寧分享內容整理而成。php
SegmentFault 是一家綜合性技術社區,因爲它的內容跟編程技術緊密相關,所以訪問量的波動也和這一羣體的做息時間深度綁定。一般狀況下 web 頁面的請求量峯值在 800 QPS 左右,但咱們還作了先後端分離,因此 API 網關的峯值 QPS 是請求量峯值的好幾倍。node
SegmentFault 做爲一個技術社區的系統架構變化,裏面有些東西仍是頗有意思的。react
緊接着,咱們遇到了很多挑戰,促使使咱們不得不往 K8s 架構上遷移。web
首先,雖然咱們是一家小公司,可是業務線卻很是複雜,整個公司只有 30 人左右,技術人員只佔其中三分之一左右,因此承載這麼大的業務量負擔仍是很重的。並且創業公司的業務線調整很是頻繁,臨時性工做也比較多,傳統的系統架構在應對這種伸縮性要求比較高的場景是比較吃力的。數據庫
其次,複雜的場景引起了複雜的配置管理,不一樣的業務要用到不一樣的服務,不一樣的版本,即便用自動化腳本效率也不高。編程
另外,咱們內部人員不足,因此沒有專職運維,如今 OPS 的工做是由後端開發人員輪值的。但後端開發人員還有本身本職工做要作,因此對咱們最理想的場景是能把運維工做所有自動化。segmentfault
最後也是最重要的一點就是咱們要控制成本,這是高情商的說法,低情商就是一個字「窮」(笑)。固然,若是資金充足,以上的問題都不是問題,可是對於創業公司(特別是像咱們這種訪問量比較大,可是又不像電商,金融那些掙錢的公司)來講,咱們必將處於且長期處於這個階段。所以可否控制好成本,是一個很是重要的問題。後端
2020 年之前,SegmentFault 的網站仍是很是傳統的後端渲染頁面的方法,因此服務端的架構也很是簡單。服務端將瀏覽器的 http 請求轉發到後端的 php 服務,php 服務渲染好頁面後再返回給瀏覽器。這種架構用原有的部署方法還能支撐,也就是在各個實例上部署 php 服務,再加一層負載均衡就基本知足需求了。瀏覽器
然而隨着業務的持續發展,後端渲染的方式已經不適合咱們的項目規模了,所以咱們在 2020 年作了架構調整,準備將先後端分離。先後端分離的技術特色我在這裏就不贅述了,這裏主要講它給咱們帶來了哪些系統架構上的挑戰。一個是入口增多,由於先後端分離不只涉及到客戶端渲染(CSR),還涉及到服務端渲染(SSR),因此響應請求的服務就從單一的服務變成了兩類服務,一類是基於 node.js 的 react server 服務(用來作服務端渲染),另外一類是 基於 php 寫的 API 服務(用來給客戶端渲染提供數據)。而服務端渲染自己還要調用 API,而咱們爲了優化服務端渲染的鏈接和請求響應速度,還專門啓用了了使用專有通信協議的內部 API 服務。緩存
因此實際上咱們的 WEB SERVER 有三類服務,每種服務的環境各不相同,所需的資源不一樣,協議不一樣,各自之間可能還有相互鏈接的關係,還須要負載均衡來保障高可用。在快速迭代的開發節奏下,使用傳統的系統架構很難再去適應這樣的結構。
咱們迫切須要一種可以快速應用的,方便部署各類異構服務的成熟解決方案。
首先是開箱即用,理論上來講這應該是 KubeSphere 的優勢,咱們直接點一點鼠標就能夠打造一個高可用的 K8s 集羣。這一點對咱們這種沒有專職運維的中小團隊來講很重要。根據個人親身經歷,要從零開始搭建一個高可用的 K8s 集羣仍是有點門檻的,沒有接觸過這方面的運維人員,一時半會是搞不定的,其中的坑也很是多。
若是雲廠商能提供這種服務是最好的,咱們不用在服務搭建與系統優化上花費太多時間,能夠把更多的精力放到業務上去。以前咱們還本身搭建數據庫,緩存,搜索集羣,後來所有都使用雲服務了。這也讓咱們的觀念有了轉變,雲時代的基礎服務,應該把它視爲基礎設施的一部分加以利用。
若是能把運維工做所有用代碼來管理,那就再理想不過了。而目前 K8s 確實給咱們提供了這樣一個能力,如今咱們每一個項目都有一個 Docker 目錄,裏面放置了不一樣環境下的 Dockerfile,K8s 配置文件等等。不一樣的項目,不一樣的環境,不一樣的部署,一切均可以在代碼中描述出來加以管理。
好比咱們以前提到的一樣的 API 服務,使用兩種協議,變成了兩個服務。在這如今的架構下,就能夠實現後端代碼一次書寫,分開部署。其實這些文件就代替了不少部署操做,咱們須要作的只是定義好之後執行命令把它們推送到集羣。
而一旦將這些運維工做代碼化之後,咱們就能夠利用現有的代碼管理工具,像寫代碼同樣來調整線上服務。更關鍵的一點是,代碼化以後無形中又增長了版本管理功能,這離咱們理想中的全自動化運維又更近了一步。
持續集成標準化了代碼發佈流程,若是能將持續集成和 K8s 的部署能力結合起來,無疑能大大加快項目迭代速度。而在使用 K8s 以前咱們就一直用 GitLab 做爲版本管理工具,它的持續集成功能對咱們來講也比較適用。在作了一些腳本改造以後,咱們發現它也能很好地服務於現有的 K8s 架構,因此也沒有使用 K8s 上諸如 Jenkins 這樣的服務來作持續集成。
步驟其實也很簡單,作好安全配置就沒什麼問題。咱們本地跑完單元測試以後,會自動上線到本地的測試環境。在代碼合併到上線分支後,由管理員點擊確認進行上線步驟。而後在本地 build 一個鏡像推送到鏡像服務器,通知 K8s 集羣去拉取這個鏡像執行上線,最後執行一個腳原本檢查上線結果。整個流程都是可視化可追蹤的,並且在代碼管理界面就能夠完成,方便開發者查看上線進度。
目前咱們用一個專門的倉庫來管理這些基礎鏡像,這可使開發人員擁有與線上一致的開發環境,並且後續的版本升級也能夠在基礎鏡像中統一完成。
除了將 Dockerfile 文件統一管理之外,咱們還將鏡像 build 服務與持續集成結合起來。每一個 Dockerfile 文件都有一個所屬的 VERSION 文件,每次修改裏面的版本號並提交,系統都會自動 build 一個相應的鏡像並推送到倉庫。基礎鏡像的管理工做徹底自動化了,大大減小了人爲操做帶來的錯誤與混亂。
最後是一點感想:當作完容器化後,會發現應用在集羣裏運行的時候並不須要佔用那麼多臺服務器。這是由於下降了資源的粒度,因此能夠作更多的精細化規劃,所以使用效率也提升了。
本文由博客一文多發平臺 OpenWrite 發佈!