項目背景
2019 年底,因為公司在業務研發的過程中,遇到了一些業務痛點,比如:公司的開發技術棧是 Java 相關的,而運維工程師擅長的則是 Shell 和 Python 腳本,無法直接對接;公司本身正處于快速增長期,開發工程師人力不足,無法支援日常的運維工作及運維平臺的開發;在現有的運維平臺中,使用了多種開源工具,而且沒有整合,較難管理。因此我發起了自動化運維平臺的項目,希望通過該運維平臺實現快速上手的開發模型,可以實現運維工程師自己開發業務,并進行快速的迭代服務。
基于 Spring Boot + MyBatis Plus + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能
為什么選擇 Apache APISIX
在進行網關選型時,我們進行了實際的測試。相對于其他網關,APISIX 基本上可以達到 NGINX 90% 的功能,并且支持了多種負載均衡策略以及支持多語言插件的機制,同時支持了軟 WAF,可以覆蓋我們95% 的安全業務場景。作為云原生 API 網關,APISIX 也提供了強大的日志功能,支持自定義日志格式,因此可以直接讓 access log 對接 ELK。由于 APISIX 也支持自定義插件的開發,可以根據我們的需求靈活擴展。得益于 APISIX 的基礎功能和強大的插件體系,可以有效降低開發成本。
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能
自動化運維平臺架構
自動化運維平臺整體架構圖如下:
存儲層:核心是 CMDB,主要功能是記錄和管理組織業務和 IT 資源的屬性,以及其它們之間的關系。不但負責所有業務變更的起始狀態查詢,而且所有的業務資源的變更都要反饋記錄在其中,實現業務標準規范的管控。存儲層也包含一些權限管理的數據、業務工單的流轉數據以及監控告警的時序數據;
公共基礎服務層:提供原子業務的 API,也可以認為是基礎中臺,復用了大量的開源工具;
業務編排層:需要根據實際業務進行設計,工程師的工作就是把原子業務 API 按需求進行報文適配、流程組合、數據讀寫,并打包成為接口供前端調用;
網關層:APISIX 所在的層,是后臺服務的業務邊界,負責負載均衡、服務注冊與發現、用戶鑒權、基礎網絡報文數據轉碼、內外交互日志的統一記錄、部分安全管控等等。與業務無關并且通用的服務統一放置到本層;
展示層:從用戶角度出發,設計便利的交互界面。此處使用了一個開源的前端全響應式 admin 網頁模板,即使開發者(運維)不熟悉 JavaScript ,也可以自己實現基本的表單和報表。
平臺使用的組件
核心網關 Apache APISIX:主要負責日志記錄、網絡安全以及負載均衡。另外我們不但通過自定義插件實現了高級業務網關的部分功能,而且還通過 API 能方便的和其他服務整合,快速實現各種指定功能,有效降低開發成本;
API 管理工具 YAPI:負責對接口的規范定義,測試用例編寫和作為 ACL 的數據源;
訪問控制組件 Casbin:輕量級、多模式、強范式的跨語言開源訪問控制框架,我們使用的是基于RESTful 的 PyCasbin;
數據存儲:MySQL 5.7;
自研 Web 框架 mug-skeleton:使用自研的 Web 框架,主要是為了更深層次的技術控制能力。
對接的第三方平臺相關組件
CMDB(自研):在開源的 CMDBuild 外包了一層 RESTful 的 API,方便交互;
OpenLDAP:用于用戶的賬號驗證,不負責鑒權;
工作流 Activiti:使用官方的 RestAPI 服務,由于是處于在網關后方,因此不需要考慮安全問題。
業務場景
用戶登錄及權限驗證
對于所有的 Web 框架,用戶登錄是一個必選項,接下來我將為大家介紹此場景。
首先,我們需要了解下場景中,我們的使用的相關組件,第一個就是訪問的前端,這個是在網關之外的,其次使用 APISIX 云原生 API 網關作為業務邊界。再之后的 Auth 服務,它是自定義開發的微服務,作用是校驗前端的 URL 請求和用戶登錄請求,并對通過認證的用戶發放 Token。LDAP 中存放的是公司內部的密碼信息。CMDB 存儲的是一些業務的相關信息,包括組織結構,可以訪問的權限的一些組織信息,最后是前端需要訪問的頁面。
了解完以上組件后,接下來,為大家介紹整體流程:
用戶登錄的時候,首先需要通過網關查詢,訪問的頁面是否在白名單中。因為部分頁面是不需要權限驗證的,比如:默認頁面或者一些錯誤頁面。如果訪問的頁面是需要驗證登錄的,那么這些請求就會通過相關插件,轉發到權限認證服務。
在權限認證中,鑒權服務會根據傳入的“用戶名”和“密碼”,從 LDAP 中查詢賬號是否正確。如果正確,就會通過 CMDB 查詢該用戶是屬于哪個組織、可以查看哪些功能模塊;得到結果后,使用 APISIX 的 JWT 插件,根據用戶信息生成一個 Token,并添加過期時間,返回給前端;用戶通過 Cookie 的方式進行Token存儲。該用戶后續如果繼續訪問,網關會從 Cookie 中把之前存儲的 Token 調出來,驗證當前用戶是否可以繼續訪問后面的頁面。
在這里,我們使用了 APISIX 的 consumer-restriction 插件,上述所講的權限認證,實際上就是通過 consumer-restriction 插件來完成的,不需要我們在后臺多次反復認證。
通過上述的描述,相信大家已經對正常的請求流程有了一定的理解,接下來將為大家介紹下如何判斷這些用戶權限不足的場景。在運維平臺中,如果有涉及到數據變更的操作,必須要攜帶 Token,當這個 Token 被 ACL 的接口驗證無權訪問后,就會直接返回一個禁止訪問的頁面,讓前端進行處理。以下是用戶登錄及權限驗證場景的具體流程和其中更使用的相關組件。
新業務微服務接入
在日常工作,我們經常會上線一些微服務,那么如何讓這個微服務接入自動化運維平臺呢?
我們內部會規定無論工程師使用哪種語言開發微服務,都需要使用 YAPI 對 API 進行定義。因此 YAPI 對我們所有可訪問的那些 URL 進行管控,統一一個入口在這邊。因為 YAPI 支持定義各種環境,所以我們在 YAPI 中定義了不同運行環境。最典型的示例就是:在生產環境中,我們會使用域名訪問;而在開發環境,就直接使用 127.0.0.1 進行訪問。完成 YAPI 的定義后,它就可以通過 mock 的方式,生成一系列請求用例,非常有利于后續進行生產環境的測試。所有的微服務接口,都可以通過 HTTP 請求的方式進行 mock 調用。
接下來,就是權限管理服務,這里所有的操作都是自動的:它會從 YAPI 中讀取 API 的定義,然后生成一系列的 ACL 規則。對于權限的管理,我們在平臺中使用了一個管理頁面:管理員可以通過該頁面管理 URL 的訪問規則,設置完成后,表單數據就會變更為一系列的 ACL 權限定義,存入數據庫中。在服務啟動的過程中,平臺使用的 cachebin 的訪問模型就會直接從數據庫中,把這些規則加載到內存里,然后生成一系列 APISIX 的 Consumer 的定義及路由表,寫入 APISIX 的 etcd 中。完成上述操作后,當用戶訪問的時候,平臺就可以直接通過 APISIX 進行一個權限管理。
該模型不但適用于自動化運維平臺,也同樣適用于各種中小型業務體系。
技術細節
通過上述的場景描述,相信大家已經對整套體系有了大概的認識,接下來為大家介紹下部分技術細節。
因為 APISIX 是基于 NGINX + Lua 實現的,所以部分功能需要通過 NGINX 的庫來實現。從上圖中,我們可以看到各種 Lua 腳本可以在哪些點切入到 NGINX 當中。在本文中,主要是為大家介紹 Rewrite/Access 以及 Content 階段可以進行的操作。
因為在 Rewrite/Access 階段,報文還沒有轉給 Upstream,所以可以在該階段進行各種各樣的數據預處理。從上圖中我們可以看到有個 access_by_lua,在該階段,可以使用 deny 命令進行權限的管理,包括接口權限以及 IP 準入白名單都可以在該階段實現。后文所介紹的 acl_plugin.lua 的插件就是在該階段實現的。
其次在 header_filter_by_lua 這個階段,常用于在請求訪問時,額外的在 HTTP 請求頭插入一些 key:value,供后續使用。例如,當需要我們線上灰度發布時,就可以在用戶的請求頭中加入標志位,通過這些標志位,就可以控制這些請求轉發哪些后端服務,從而實現灰度發布。當然我們也可以使用 APISIX 的 traffic-split 插件實現灰度發布。
最后就是 log_by_lua 階段,在該階段,我們可以把一些 trace 信息或者一些故障信息可以直接輸入到 log 文件中。同樣的,針對 Loggers,APISIX 也提供了非常多的插件,包括 skywalking-logger、kafka-logger、rocketmq-logger 等等。
自定義插件 acl-plugin.lua
acl-plugin.lua 插件的實現非常簡單。首先當用戶在請求的過程中,我們會給用戶添加相關的 JWT token 存儲在 cookie 里面,之后該用戶會從訪問的 cookie 中提取 JWT token,然后對該 token進行解碼并獲取用戶信息。
在 Rewrite 階段,通過使用用戶 ID、method及 URI,向后臺 ACL 接口發起請求進行權限驗證。如果通過了,就會把相關信息記錄到 log 中,供以后的安全認證使用。如果失敗了,就直接返回一個錯誤狀態碼并記錄到 error log 中。
在 APISIX 1.1 版本中,當時 cors 插件還沒有發布,因此對于跨域請求,我們也是通過該插件進行實現,當請求使用 GET 和 POST 的請求方法時,會進行相關的處理。如果是其他請求,則會直接通過,而現在可以直接使用 APISIX 的 cors 插件實現。APISIX 現在也可以使用多種語言進行插件的開發, 不僅僅是 Lua,詳細信息可參考:https://apisix.apache.org/zh/docs/apisix/plugin-develop%E3%80%82
Auth 服務
Auth 服務是與 acl-plugin.lua 插件配套的認證服務。該服務實現的功能非常簡單,主要是讀取請求報文中的信息,然后解碼出所需的認證元素,之后再把它轉發到相關的服務接口中。服務接口會根據認證信息返回相應的結果,APISIX 會根據結果拒絕或通過該請求。
Auth 服務中最核心的功能就是從數據庫中把 ACL 規則加載到內存里面。主要功能分為兩部分:
首先 account 接口。該接口主要作用就是:用戶訪問的時候,如果需要權限認證,則會通過向 LDAP 服務發送用戶的相關信息,進行認證。如果認證通過,則會從 CMDB 中查詢出用戶可訪問的相關信息,然后和用戶角色、過期時間等元素,一起組成 JWT Token,并生成一個 Cookie 返回給用戶,并且同時把該用戶信息在 APISIX 中注冊一個 Consumer 。該接口還實現了一個 acl_check 的功能,負責對用戶認證信息驗證,判斷該認證是成功還是失敗。
其次是 yapi 接口。該接口的主要作用是與 YAPI 進行交互。因為 YAPI 中有一個是供項目訪問的token,帶著這個 token,就可以讀取到這個項目所有的 API定義。因此該接口的主要功能,就是從 YAPI 中讀取 API 的 HTTP 接口定義,存儲到數據庫中,然后和權限管理的頁面進行一個表單交互,組合成 ACL 表,最后生成一系列 Casbin 的規則存到數據庫中。
總結
以上就是同程數科基于 Apache APISIX 的自動化運維平臺的架構及部分場景的介紹。現在,APISIX 的功能越來越強大,已經支持使用 Wasm 和 Python 進行插件開發。Apache APISIX 的生態也非常強大,如果大家有任何問題歡迎到社區中進行交流討論。
審核編輯:郭婷
-
JAVA
+關注
關注
19文章
2966瀏覽量
104707 -
python
+關注
關注
56文章
4793瀏覽量
84633
原文標題:基于 Apache APISIX 的自動化運維平臺
文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論