歡迎大家前往騰訊雲+社區,獲取更多騰訊海量技術實踐干貨哦~
本文由騰訊雲serverless團隊發表於雲+社區專欄
導讀:2018年7月6 - 7日,一年一度的技術圈盛會ArchSummit全球架構師峰會在深圳華僑城洲際酒店舉辦。100余位國內外技術專家齊聚深圳,分享各類技術架構最佳實踐。來自騰訊技術工程事業群架構平台部的jerome作了主題為《基於彈性計算的無服務器化實踐》的分享,以下為現場演講內容。
據Gartner和麥肯錫統計,全球的服務器CPU平均利用率只有6%到12%。國內阿里,騰訊等大型互聯網企業CPU平均利用率均10%出頭左右,這里主要是三種原因導致:
• 單一業務難以均衡利用各類資源導致99%情況下有資源閑置
• 在線服務的特點決定了有30%的時間段處於低負載
• 服務器流轉過程可能造成5%的時間段閑置
理想的情況是像Google那樣有公司級borg資源調度平台,各業務基於統一平台構建,共享資源池混搭調度,但基於BG分開運營的歷史現狀,公司運管聯合架平彈性計算及各BG運營部門聯合打造的共享算力平台,嘗試收集全公司的空閑資源,從現網中挖掘金礦,以docker容器的形式滿足計算類的需求。
經過一年的建設,當前已挖掘了約140w核,支持了億級的視頻轉碼,圖片壓縮以及騰訊圍棋,王者榮耀等游戲AI,手機瀏覽器等,但當前依然存在許多挑戰,比如:
比如業務接入門檻較高,需要業務理解多樣變化彈性的資源並做好適配,長尾業務接入困難;另外利用率也不受控,有些有狀態的業務利用率跑不高,且沒法自動擴縮容;小資源碎片,比如剩下1核1GB這種用不出去;最后平台沒法准確監控業務的運行狀態和質量,比如請求延時等,總結起來,當前困境根源還是我們只是提供資源層面的服務,而資源要用好確依賴很多業務層面的工作。回顧集群資源管理平台走過的歷程,從最開始使用物理機(Nothing-as-Service)到IaaS虛擬機服務,再到PaaS容器服務,其實每一步都在嘗試為業務做更多的事情,解放更多的生產力同時提升利用效率,下一步資源管理平台能否直接跳出資源服務層級,讓業務只需關系業務邏輯,按需付費便可以了呢?
答案是肯定的,它名字叫serverless,serverless不是指沒有服務器,而是指用戶無須關注服務器的存在,廣義上來講,現在的SaaS,BaaS,FaaS,PaaS都可以稱為serverless,區別是從下到上平台控制力越來越強,從左到右,平台通用性越來越好;但Serverless真正廣為人知,是因為以aws lambda為代表的FaaS函數即服務的出現,所以當前狹義上來講,Serverless一般指FaaS函數即服務,我們今天就用Serverless來指代函數即服務。
Serverless正好是解決我們當前問題的答案,業務接入門檻高,用serverelss可以不用關心資源,做到更快業務上線;利用率不受控,用serverless平台可以完全控制資源的分配,利用率不再受制於人;碎片資源用不出去,用serverless可以讓業務把計算切成函數更小粒度的函數級別;業務質量難以監控,用serverless我們感知業務的每次調用與返回,知道延時及返回結果。
於是我們基於現有的容器平台構建了serverless雲函數平台,主要包括:
• 構建函數管理模塊來管理函數的配置,包括元數據,代碼,權限,觸發方式等;
• 構建函數調用模塊來分發調用函數,解決負載均衡,故障容災,擴縮容等問題;
• 構建多語言的運行時環境,代理函數的網絡監聽請求,運行用戶函數代碼,監控函數運行過程,收集函數日志等;
• 構建函數觸發器等模塊,實現雲函數事件觸發式的自動調用;
新平台的構建有諸多考慮點,比如怎么做到足夠的易用,使得業務可以樂於嘗試;怎么做到足夠的穩定,來留住業務;如何做到比容器平台的成本更加節省,讓業務看到實實在在的好處;如何做到更快、更安全、能持續發展等,本文將一一分享。
足夠易用的關鍵在於能否讓用戶做更少的事情,在開發上,雲函數提煉業務邏輯之外的部分代為實現,比如網絡數據包收發,負載均衡,擴縮容,故障容災等,平台把龍畫好,只需要業務最后點睛即可上線;在運維上,托管代碼包管理,服務器故障處理,服務質量監控及容災、負載均衡、擴縮容等配置;甚至在應用上,提供文件上傳\刪除,定時器,主題的消息時等事件觸發式自動調用,雖然當前一些微服務平台也在做類似的事情,但依然以容器為維度,容器內部對平台而言是黑盒;雲函數參與了容器內部每一次用戶請求調用和返回的過程,可以獲取更多業務維度的信息,使得在資源調度和質量控制上可以更加的精准。
對比傳統的分布式系統,雲函數平台要做到足夠穩定還需要解決好函數調用流的問題,最簡單的調用流程是從雲api進來,走invoker做分發,再到計算節點執行,在同步調用一來一回的場景這樣沒問題,因為同步調用失敗時業務可以自行重試;但異步調用時不會返回調用結果給用戶,請求丟了用戶感知不到,所以需要有持久化方式保存所有的異步調用,以免丟失;另異步調用業務無法自行重試,當平台自動重試依然失敗時,需持久化保存便於問題追溯;重試本身也需要謹慎的設計,因為資源是調用請求到來時實時分配,重試可能會造成后台資源成倍增加,且在某些流式計算場景,計算有嚴格的時序要求,重試的時候還需要阻塞整個流的計算等。穩定性最常見的挑戰是熱更新能力,而Serverless雲函數平台天生支持熱更新,因為能獲知業務的每次請求和返回,且能控制業務請求的分發過程,做熱更新,其實就是簡單的禁掉節點,等待請求結束,更新后再重新啟用節點。
雲函數平台要比容器平台做到更低成本,需要盡量避免閑置及無效浪費的資源,在傳統的業務架構下,一個業務模塊最少需要1個實例,如果要容災,至少需要2個;而雲函數平台被設計為調用時實時分配資源,業務模塊最小實例數可以縮減到0,無負載時不保留資源,收到業務請求時再實時分配資源;業務申請資源時,會按照峰值指定cpu核心數,內存大小,磁盤容量,網絡帶寬等一系列資源參數,但絕大多數情況下用不完,所以雲函數平台一般只讓用戶配置內存大小,因為內存是不可壓縮資源,少了程序跑不起來,而對於cpu,帶寬等可壓縮資源,都由平台方根據內存大小及實際所需來配置且動態調整,以避免由於業務過量申請資源造成的浪費;另外雲函數有一個特殊點是支持事件觸發執行,但觸發配置不當可能造成無效循環造成資源浪費,比如配置文件上傳時執行某函數,但函數內又上傳了文件形成循環觸發,所以雲函數會監控函數調用流,發現無效循環,避免資源浪費。
由於雲函數的資源是收到請求后實時分配並初始化的,而用戶能容忍的等待時間一般不超過3s,故第一次請求的冷啟動的時間要足夠的快,而函數的初始化需要做很多的事情:先要申請資源,確定位置后要下載鏡像,下載函數代碼,啟動容器,初始化函數后才能執行函數,返回結果。其中鏡像下載的時間一般都超過3s,所以我們用了很多預處理,緩存和並行化的方式來提升性能,比如鏡像預分發到服務器避免實時下載,容器資源使用多級緩存以重利用,小到用指針代替內存拷貝來傳遞參數等,這里有個小問題,一個用戶函數用過的容器可以交給另一個用戶去使用嗎?並行化容器啟動與代碼下載流程,函數大參數傳遞使用共享內存指針方式傳遞等,最終將冷啟動的時間控制到200ms,熱啟動的時間控制到了5ms內,達到業界一流水准。
雲函數平台由於共享粒度更細,不可避免需要共享服務器內核,在安全方面挑戰會更大一些,所以我們在docker隔離的基礎上,額外做了一些安全措施,比如限制函數運行時環境只有/tmp目錄可寫,通過seccomp等內核特性限制端口監聽,端口掃描等敏感系統調用;但做安全的同時,也關注業務兼容性,比如大家習慣性的使用root來運行程序,禁止root可能會給用戶帶來一些額外的適配成本,所以我們使用root namespace技術把容器內的root映射成了容器外的普通用戶以控制權限,另外由於我們無法審核用戶代碼,而用戶技術上可以寫代碼去做嘗試做任何事情,比如收集運行環境信息,窺探管理服務器位置等,為了安全,對比開源的serverless平台,實現了函數運行環境和管理環境的分離,函數網絡包收發代理及日志收集等均放在容器外,容器內函數運行時環境不感知管理節點的的任何IP,端口信息及平台日志等信息。
由於業務除核心邏輯之外的非功能性需求都依托雲函數實現,對雲函數平台必然會有更多的需求,為支持業務可持續發展,跟上業務迭代速度,我們也做了一些優化,比如在過去一年,業務對我們平台提得最多的需求是支持各種編程語言,運行時環境安裝各種庫等,為了加快迭代效率,我們提煉了各類語言運行時環境的公共部分用C語言實現,因為各種高級語言均易實現對C庫的直接調用,這樣新增加一種語言支持能夠在1~2周內完成,在庫更新方面,我們把所有的運行時庫部署到母機上,通過目錄mount的方式掛進容器,使得庫的更新無須變更運行時環境鏡像。
匯總一下剛才的關鍵設計,我們通過讓用戶做得更少來提升易用性;謹慎的設計異步調用及重試來提升穩定性;消除閑置及過量申請來降低成本;利用緩存及並行來提升啟動速度;通過內核層技術及管理環境與運行環境隔離來提升安全性;通過提煉公共功能及避免重制鏡像來提升迭代速度,那實際效果怎樣呢?接下來給大家分享一下我們當前的一些用戶案例及經驗教訓。
當前雲函數平台在內部最大的用戶是游戲AI的特征提取,游戲AI在整個行業目前還處於摸索階段,算法變化很快,程序經常更新,計算量非常巨大,比如王者榮耀1天需執行上億錄像文件的特征提取。如果基於雲函數實現,只需要AI工程師用python寫兩個函數,一個腳本將從錄像文件中提取特征,生成HDF5文件,另一個函數將HDF5文件打散隨機化再推送到訓練平台進行訓練,算法更新時,提交新的函數即可,可以更專注於算法研究,無需再關心服務器的管理,計算的分布,擴縮容,故障容災等。除游戲AI之外,微信小程序的開發者工具也開始集成雲函數正在內測中,歡迎大家體驗。
回顧這1年多來的建設歷程,最大的教訓主要有2點:
• 前不久騰訊雲雲函數出現了一個安全漏洞,在雲函數的上下文通過bash反射,嘗試各種linux命令可獲知k8s的kubelet訪問地址,且由於k8s沒有配置鑒權,用戶可直接控制k8s去獲取其它容器內部數據,造成安全隱患,幸虧公司安全團隊及時發現未造成嚴重后果,這個問題的原因在於我們對k8s的安全機制缺乏了解,給我們的教訓是每引入一個開源組件,都需要吃透后再開放服務;
• 由於雲函數平台被設計為7*24不間斷工作,每次計算節點升級時需要經歷屏蔽,等待函數執行完,升級再啟用的過程,早年未做自動化,整個集群升級一次要耗費將近一周的時間,拖慢了版本迭代過程;
同時,我們覺得好的經驗主要有2點:
• 設計之初就考慮了平台的平滑升級,所以一年來變更了大大小小50來個版本,從未讓業務停過機;
• 另外我們重視了平台公共功能的提取,比如多語言支持方面,1~2周可搞定一種新編程語言,遠比其它serverless平台快;
在推廣serverless雲函數平台的過程中,我們發現對於無狀態微服務,負載波動大,對延時不敏感的場景,比較容易服務好,但對於有狀態的服務,需要業務自行保存狀態,對於持續高負載的業務,沒法發揮資源按需取用的優勢,對於延時敏感應用,由於中間函數的分發多了一層,延時有差不多5ms的損耗,對這些場景,serverless當前還不太適合。
但未來,serverless是可以期待的,當前serverless已經成了各大公有雲的標配,對於公有雲而言,serverless不僅僅是一種新形態的計算服務,更能充當整個雲平台的粘合劑,便於打包推廣其它雲服務,讓公有雲從各個分散的雲產品集合變成了有機的整體,成為用戶公共的雲后台;在開源社區,serverless平台也蓬勃發展,每隔一段時間都會出現新的值得關注學習的serverless平台;雖然當前serverless主要戰場在數據中心,但隨着IOT的發展,IOT邊緣設備可能成為serverless更大的戰場,因為邊緣設備的計算資源管理,軟件包發布更為復雜,更加有挑戰性,能解決好相當於雪中送炭。
武學修為對各路招數融匯貫通時,可以達到無招勝有招的境界,對於我們做集群資源調度的程序員來說,能把資源調度做到極致,讓業務根本感知不到服務器的存在,是我們最高的追求。
問答
Serverless:如何刪除一個函數?
相關閱讀
使用 SCF 無服務器雲函數定時撥測站點並郵件告警
使用 SCF 無服務器雲函數定時備份數據庫
使用 Serverless 進行 AI 預測推理
雲學院 · 課程推薦 | 騰訊專項技術測試組長,結合8年經驗為你細說冷熱分離法則
此文已由作者授權騰訊雲+社區發布,更多原文請點擊
搜索關注公眾號「雲加社區」,第一時間獲取技術干貨,關注后回復1024 送你一份技術課程大禮包!
海量技術實踐經驗,盡在雲加社區!