無服務器架構下的運維實踐
前言
在介紹運維之前,大家先來快速了解一下無服務器(serverless)的概念。由于筆者的實戰經驗是在AWS平臺上,本文中出現的無服務器均指使用AWS Lambda構建的serverless應用。Serverless的特點是用戶無需預配置或管理服務器,只需要部署功能代碼,服務會在需要的時候執行代碼并自動伸縮,從每天幾個請求到每秒數千個請求,輕松地實現FaaS(Function as a Service)。如下圖所示:
(圖片來自網絡)
在傳統的應用中,開發團隊除了需要編寫功能代碼,還要監控實時負載,并相應地對應用進行伸縮,還要處理一些因非功能性故障導致的停機(硬盤、內存等)。而無服務器架構則將開發團隊從服務器維護的工作中解放出來,繼而能更專注在功能代碼上(圖中的Function)。在實際的項目里,開發者只需將功能代碼打包上傳到AWS Lambda,再進行少量配置(環境變量,觸發條件,內存,超時時間等)即可將應用/服務上線。
以上是無服務器架構的基本概念。接下來,筆者將從日志,指標,監控及報警,災備這四個維度來介紹無服務器架構下的運維。
日志
默認情況下,應用運行時產生的日志會保存在應用服務器本機,在需要查看日志的時候,需要運維人員遠程登錄到這臺服務器獲取日志信息。這種方式操作起來稍顯繁瑣,而且當應用服務器的數量增多后,由于需要先找出產生錯誤信息的那臺服務器,會嚴重降低查找日志的效率。
一種解決辦法是ELK(ElasticSearch, Logstash, Kibana),這三個開源工具各司其職,Logstash負責日志的推送和轉換,ElasticSearch作為數據庫與搜索引擎,Kibana作為圖形界面。好處是搭建容易,良好的伸縮性,以及免費。但帶來的額外成本是,獨立出來的日志服務也需要做好全方位的監控(應用狀態,硬盤,網絡等),避免因為基礎服務的問題導致系統全面故障。
AWS無服務器架構中的日志是一個開箱即用的服務,所有日志自動采集到AWS CloudWatch Logs中,只要根據服務名稱找到對應的日志組,即可進行查詢搜索,不需要任何配置,也沒有任何維護成本。
指標
通常情況下,運維工作會包含采集線上應用的運行指標,來反映應用的健康狀況,故障率,性能,訪問量,訪問頻率等。這里以一個使用Spring Boot構建的API服務來舉例,Spring Boot中的Actuator扮演了采集指標的角色。默認配置下,對于每個API,Actuator會自動采集以下幾個指標:
- uri,例如/api/person/{id}
- method,例如GET或POST
- status,例如200或500
當然我們可以通過實現一些接口來擴展/自定義采集指標,這里就不展開了。有了指標數據,還需要對應的報表或儀表盤工具,以便更好地查詢和展示,可以選擇像Prometheus,Grafana這樣的工具。
那么AWS無服務器架構是否提供了類似的指標采集呢?答案是肯定的,AWS CloudWatch Metrics自動采集了Lambda function的以下四個指標:
- Invocations(實際調用量)
- Errors
- Duration(執行時間)
- Throttles(超過并行限制而被阻止的調用的數量)
Invocations和Errors取一段時間的總數,結合二者可以得出應用的錯誤率,如下
Duration則通過取平均數來反映一段時間的性能表現,在筆者的項目中Lambda function的耗時主要集中在SQL的查詢上,這個數字可以相應地反映技術人員對查詢優化的效果。當然,在實際情況中,這些檢驗都可以在預發布環境下進行,這個例子只是為了方便理解。
在筆者目前的項目中,Throttle并未被使用到,默認的并發限制是1000/秒,而用量***的Lambda function的調用頻率也不過每分鐘150次,距離超限差得很遠,不過這一數據對于并發高的應用有很重要的意義。
除了開箱即用的幾個指標以外,還可以結合CloudWatch metrics的API,在相應的功能代碼中埋點,定制化采集指標。例如,對于一個Lambda function,代碼里三個子task,默認提供的Duration只能反映總體的運行效率,如果需要統計每個task的消耗,就需要用到AWS CloudWatch metrics API。
監控&報警
監控的意義在于全面了解應用的資源使用率,性能和運行情況,這些數據可以用來幫助團隊及時作出調整,保證應用程序順暢運行。這通常包括CPU使用率,數據傳輸,磁盤使用等。在突發狀況導致系統不可用的時候,團隊的響應速度,往往取決于監控和報警的及時性,全面性和準確度。如果能在對歷史數據的分析之上對監控系統進行合理的配置,團隊甚至能預測不好的事情將要發生,提前做好防范,未雨綢繆。
同上,這里還是以一個Spring Boot應用為例,在上一小節指標數據的采集中提到過Actuator,事實上Actuator除了可以記錄上面提到的指標,還可以用來收集監控數據。這里我們只需要設置一個Spring Boot Admin應用,給需要進行監控的應用加上Spring Boot Admin client配置,監控數據就會通過Actuator暴露的API傳遞給Spring Boot Admin。
報警功能一般則要根據實際情況自行實現。Spring Boot Admin中實現了對Pagerduty,Slack等第三方工具的集成,如果只是需要簡單的郵件提醒,實現起來也不復雜,這里就不展開了。
隨著云上基礎設施的普及,上面提到的監控和報警早已是各個平臺的標準配置,根本輪不到開發者去操心如何實現及維護,運營團隊可以把更多的精力放在配置優化的工作中去。
AWS默認提供了非常完備的監控數據,也允許自定義監控dashboard,通過把一系列重要的指標添加到創建好的dashboard中,應用的運行狀況一目了然。
前面已經提到過,在出現錯誤,或性能底下時,根據某些關鍵指標的變動情況發送警告通知非常必要。筆者所在的項目的做法是使用AWS CloudWatch和AWS SNS提供的告警通知功能,只需要先選擇指標然后設定觸發閾值和檢查間隔時間即可,AWS SNS支持HTTP、SMS、Email等多種訂閱方式。下圖展示了如何設定當某個Lambda在過去5分鐘內發生了5次以上錯誤的時候發送通知。
災難備份&恢復
在系統鏡像,構建工具還有容器技術越來越普及的今天,災難備份的意義很大程度上是為了有效保護重要數據。通常的做法是設定一些定期任務,將數據傳輸到遠端的災備中心,從物理上抵御不可抗災難。如果數據量過大,出現網絡傳輸效率跟不上的情況,可以參考AWS用卡車拉數據的解決辦法。
真正需要用到災難備份的情況在筆者有限的經歷中還沒有發生過,但是如果不未雨綢繆,真正發生時的后果將難以設想。筆者項目中用到的AWS RDS默認啟用了以7天為周期的自動備份,這個配置可以手動調整也可以將配置寫入構建基礎設施的腳本中去。 如果災難真的發生,光有數據備份是不夠的,還需要能夠快速重建應用運行時的基礎設施。筆者所在的團隊(下文簡稱團隊)分別使用了AWS CloudFormation和Serverless framework,CloudFormation用來重建數據庫、網絡等基礎設施,Serverless framework用來重建Lambda function,在重建數據庫的時候,通過持續集成流水線,以環境變量的方式傳入最近一次數據備份快照的Id,15分鐘以內即可重建一套產品環境。
總結
筆者所在的團隊是10個人左右的配置,采用結對編程的方式,3對pair,包含web端、業務層、數據層。從產品原型確定到***次上線(MVP)耗時30天,每周至少發布一次新版本,story的平均交付時間(cycle time,從需求確定到上線)為8天。這樣的速度也許不能算快,但是如果沒有Serverless架構在運維端提供的支持,我們想要在交付速度上有更高的突破會困難得多。
***來談一下成本,俗話說拋開商業化談技術都是耍流氓,大部分人看到一個強大易用的工具都會下意識里覺得開銷會很大。實際上并不是這樣,我們做了一個粗算,選用雙核CPU,8G內存的M4型服務器,開銷是$72每月。dev,staging,prod三個環境都用同樣的配置就是$216每月,而實際上Lambda每個月的開銷包含所有環境在$20左右,需要注意的是Lambda的計費是根據使用量來的,我們的API訪問大約在150萬每月的量級??梢灶A見到當訪問達到一定數量的時候Lambda的開銷會和使用服務器的方案持平甚至更大,但是在量小的時候優勢明顯。
得益于強大的AWS生態,利用Lambda構建的無服務器應用經過少量甚至無需任何配置,即可以極低的價格獲得完整的運維功能和體驗。與自己利用開源工具進行搭建的方式相比,研發團隊可以從繁瑣的運維工作——特別是基礎工程搭建——中解脫出來,更加專注于產品本身,極大的提高軟件交付速度,可用性、可靠性和可擴展性也相當有保障。換來的代價是更高的遷移成本,某些功能的不可定制化可能成為瓶頸,以及對底層實現原理的屏蔽也可能對開發者的學習和成長有影響。
【本文是51CTO專欄作者“ThoughtWorks”的原創稿件,微信公眾號:思特沃克,轉載請聯系原作者】