--- title: 【Survey】OpenWhisk 折騰安裝部署筆記 01 date: 2020-12-31 22:48 is_modified: false disqus: cynthiahackmd categories: - "雲端網路 › 雲端運算" - "資訊科技 › 開發與輔助工具" tags: - "Fass/Serverless" - "OpenWhisk" - "Linux/Unix" - "網站與雲端平台" - "工具安裝與部署" --- {%hackmd @CynthiaChuang/Github-Page-Theme %} <br> 下這個標題的意思不是我折騰 OpenWhisk,而是...OpenWhisk 在折騰我 Orz 之前在[了解 Serverless 的概念與 FaaS 服務](/@CynthiaChuang/Serverless-Use-Cases-Study-Notes-Contents)時,就有過想要自己架設 OpenWhisk 來玩玩的打算。剛好最近進來個工作,要我評估 Openwhisk 是否符合需求建議書(RFP)的需求。 <!--more--> ## 前置閱讀 與 Openwhisk 最相關的條目就是 ==Fass/Serverless==,因此在開始前可以先看看 [IBM 微講堂系列 - 《Serverless 應用案例賞析》](/@CynthiaChuang/Serverless-Use-Cases-Study-Notes),複習下 Fass/Serverless 的概念場景。可以的話,順便玩玩 [IBM Cloud Functions](https://cloud.ibm.com/functions/),這套是以 Apache OpenWhisk 為基礎所架設 FaaS 平台,可以透過操作 IBM Cloud Functions 對 OpenWhisk 的功能有個概念。 <br> :::info :information_source: **Fass/Serverless 補充說明** - [Serverless应用场景_Serverless_通用解决方案-阿里云](https://help.aliyun.com/document_detail/65565.html) - [Serverless 架构:用服务代替服务器 - HackerVirus - 博客园](https://www.cnblogs.com/Leo_wl/p/6055252.html) ::: ## 簡介 [Apache OpenWhisk](https://openwhisk.apache.org/) 是由 IBM 和 Adobe 驅動的開源項目,由 IBM 在 2016 年 2 月將此項目貢獻給 Apache 基金會([GitHub](https://github.com/apache/openwhisk)),並在 2019 年 7 月從孵化器畢業,晉升為 Apache 的頂級項目。 <p class="illustration"> <img src="https://i.imgur.com/dhrBgsq.jpg" alt="OpenWhisk"> OpenWhisk 晉升 Apache 的頂級項目(圖片來源: <a href="https://www.infoq.cn/article/MMwF9fbx-XaAGwwhtT8L">赵钰莹 | infoq</a>) </p> 有人說 AWS Lambda 是 Serverless 的代名詞,我想這不可否認,畢竟 AWS 是最早推出 Serverless,各廠商推出 Serverless 時的競品絕對有它。但它畢竟不是開源的,因此我們無法直接使用並架設在我們自己的環境。 若說到開源的 Serverless 平台,則是 ==OpenWhisk== 與 ==Kubeless== 天下。OpenWhisk 較為成熟且有許多活躍開發者的支持,但相較之下 OpenWhisk 也比 Kubeless 複雜許多、也重複實現了些 Kubernetes 中已經存在的特性(比如自動擴展機制)。 :::info :information_source: **開源的 Serverless 平台比較** - [【译】Kubernetes Serverless 框架的全面对比(OpennFaas,OpenWhisk,Fission,Kubeless 等)](https://juejin.im/post/5d1abf09f265da1bc8544227) ::: <br> 與 AWS Lambda 相同,OpenWhisk 是一個==事件驅動==的無狀態的計算模型。==理論上==它可以支持任何程式語言,使用者僅需上傳程式碼到 OpenWhisk 中,並設定相對應的觸發事件與處理數據流即可,OpenWhisk 負責處理計算資源的擴展。 ## 程式編輯模型 先來看看 OpenWhisk 程式編輯模型,前面提過它是==事件驅動==模型。所謂的事件驅動,顧名思義就是,事件來了才去做一件事情。當事件源觸動觸發器後進入系統,然後在系統中通過規則的匹配去決定要觸發的動作,最終產生所需的結果。 <p class="illustration"> <img src="https://i.imgur.com/a5Wgs5M.png?1" alt="apache OpenWhisk理念"> Apache OpenWhisk理念(圖片來源: <a href="https://github.com/dWChina/ibm-opentech-ma/blob/master/serverless-use-cases/Serverless-00.pdf">課程講義</a>) </p> 在這樣的程式編輯模型中,會有幾個重要的角色: 1. **觸發器(Trigger)** 2. **動作(Action)** 3. **規則(Rule)** 5. **資訊來源/訂閱源 (Feed)** <p class="illustration"> <img src="https://i.imgur.com/lZP3G5P.png" alt="Apache OpenWhisk 程式編輯模型"> Apache OpenWhisk 程式編輯模型(圖片來源: <a href="https://github.com/dWChina/ibm-opentech-ma/blob/master/serverless-use-cases/Serverless-00.pdf">課程講義</a>) </p> 下面就各角色進行說明: ### 觸發器 (Trigger) 而在事件驅動模型中,最先對事件做出反應的是 Trigger,它會對如資料庫的增刪查改、 GitHub 推送新的 commit...等外部事件源進行對應的反應。 不過在 OpenWhisk 中 Trigger 僅是某類別事件的具名頻道,也就是說僅僅是==一個名字==。可以說它是對所要反應特定類型事件的變數宣告,實際上必須透過 Feed 來呼叫 Trigger。關於 Feed 我們等等在說,這邊僅需要先知道 OpenWhisk 中 Trigger 其實只是類似一個函數,它必須經由他人呼叫,才能向下執行。 以資料庫更新為例,在 OpenWhisk 之外會有一個 Event provider,由它監聽資料庫。當 provider 監聽到更新事件時,再由它通知 Trigger 資料更新了。 <p class="illustration"> <img src="https://i.imgur.com/XznGAql.png" alt="Trigger"> Trigger(圖片來源: <a href="https://github.com/dWChina/ibm-opentech-ma/blob/master/serverless-use-cases/Serverless-00.pdf">課程講義</a>) </p> ### 規則 (Rule) 而當事件源觸動 Trigger 後進入系統流程後,通過 Rule 的匹配去決定要觸發的 Action,最為對 Trigger 的響應。 <p class="illustration"> <img src="https://i.imgur.com/hJtcgqJ.png" alt="Rule"> Rule(圖片來源: <a href="https://github.com/dWChina/ibm-opentech-ma/blob/master/serverless-use-cases/Serverless-00.pdf">課程講義</a>) </p> 一般來說 Trigger 與 Rule 的對應關係是一對多,單一 Trigger 事件可以綁定一或多個 Rule 進而呼叫多個 Action,單一個 Action 也可以回應多個 Rule,但每個 Rule 只能綁定一個 Action: <p class="illustration"> <img src="https://i.imgur.com/HPLO4vM.png" alt="Rule"> </p> ### 動作 (Action) 當 Rule 觸發相對應的 Action 後,最終會執行 Action 產生所需的結果。 在 OpenWhisk 中,Action 所指的是執行某個行為的一段程式碼,這些行為可以是計算、資料格式轉換、資料抽取、第三方 API 調用...等,一般來說它輸入與輸出的的資料格式都是 Json。 <p class="illustration"> <img src="https://i.imgur.com/URsL9hc.png" alt="Action"> Action(圖片來源: <a href="https://github.com/dWChina/ibm-opentech-ma/blob/master/serverless-use-cases/Serverless-00.pdf">課程講義</a>) </p> 前面提到過==理論上== OpenWhisk 可以支持任何程式語言,但會什麼會說是理論上呢?因為 OpenWhisk 其實是有明確列出所能直接支援的語言,包含:[.Net](hhttps://github.com/apache/openwhisk-runtime-dotnet)、 [Go](https://github.com/apache/openwhisk-runtime-go)、 [Java](https://github.com/apache/openwhisk-runtime-java)、 [JavaScript](https://github.com/apache/openwhisk-runtime-nodejs)、 [PHP](https://github.com/apache/openwhisk-runtime-php)、 [Python](https://github.com/apache/openwhisk-runtime-python)、 [Ruby](https://github.com/apache/openwhisk-runtime-ruby)、 [Swift](https://github.com/apache/openwhisk-runtime-swift) 與尚在實驗階段的 [Ballerina](https://github.com/apache/openwhisk-runtime-ballerina) 和 [Rust](https://github.com/apache/openwhisk-runtime-rust)。而未列出的語言,如需求建議書中要求的 C++ ,並無直接支援。 但若細看這些語言的支援方式,會發現它其實是採用不同的 [Docker 映像檔](https://hub.docker.com/u/openwhisk)來進行。因此若所慣用的語言不在明列的支援清單中,其實也可以直接提供[自定義 Docker 映像檔](https://github.com/apache/openwhisk-runtime-docker)來達成對該語言使用。 雖說程式碼裡面只要你寫的出來什麼都能塞。但有兩點必須注意的是: 1. **無狀態** FaaS 中是無狀態的,不應該存在狀態的紀錄。 2. **短時運行** 在 OpenWhisk 中是有預設最長執行時間的,因此若超過此限制則不建議使用 Faas 執行,或是需要在切成更小的粒度分開執行。 若真需要將 Action 切成更小的粒度,則可以使用**動作序列 / 動作串 (Action Sequence,簡稱 Sequence)**,把一系列的動作鏈結來。顧名思義,它就是一連串的動作,在此序列中的動作會被按順序呼叫,並將一個動作的輸出會傳遞為下一個動作的輸入。如此一來不僅能達到切分的目的,也可讓 Action 被重複使用。 ### 事件源(Event Sources)/ 事件(Event)/ 訂閱源(Feed) 剛剛一直說到事件驅動,在這邊事件其實存在著三個概念: 1. **事件源(Event Sources)** 就是產生事件的==來源==,如:資料庫、 IoT 設備...等。 2. **事件(Event)** 事件源所==產生的事件==。例如資料庫的增刪查改、IoT 感應器超出特定溫度、GitHub 推送新的 commit,或是簡單 HTTP 要求...等。 3. **訂閱源(Feed)** 前面提到 Trigger 時提到過,在 OpenWhisk 之外會有一個 ==Event provider==,由它監聽事件,並通知 Trigger。 而在 OpenWhisk 整個系統中扮演 Event provider 角色的是 Feed。前面提過 Trigger 其實是類似一個函數,外部事件的變動與 OpenWhisk 無關,如果 OpenWhisk 想知道這些變動,必須依賴 Feed 來捕獲這些事件並呼叫,才能得知。 Feed 主要負責從外部事件源來接收事件,不管所接收事件原本的資料結構、格式、傳輸協定為何,它會轉換成 OpenWhisk 所需的協議與格式。更詳細來說,Feed 它是管理外部事件觸發 Trigger 這件事,包括了創建 Trigger、刪除 Trigger、暫停觸發與取消暫停...等生命週期的動作事件。 <p class="illustration"> <img src="https://i.imgur.com/1g4VI6S.png" alt="Feed"> Feed (圖片來源: <a href="https://github.com/dWChina/ibm-opentech-ma/blob/master/serverless-use-cases/Serverless-02.pdf">課程講義</a>) </p> 而 Feed 的可以透過下列三種體系結構模式來創建,詳細的說明,可以看看[這篇](/@CynthiaChuang/Serverless-Use-Cases-Study-Notes-03#簡介): 1. **Hook** 2. **輪詢(Polling)** 3. **連接(Connections)** <br><br> 最後來貼張漂亮的流程圖: <p class="illustration"> <img src="https://i.imgur.com/LWt3hjl.png" alt="OpenWhisk 流程示例"> OpenWhisk 流程示例(圖片來源: <a href="https://www.cnblogs.com/junjiang3/p/9613698.html">junjiang3 | 博客园</a>) </p> 簡單複述一下架構,由 Event Sources 產生 Event,而這些 Event 會被 Feed 所捕獲,而當後 Feed 捕獲 Event 後會觸發 Trigger。一個 Trigger 會綁定一到多個 Rules,而符合條件 Rule 會觸發相對應的 Action 或 Action Sequence 都會被執行,而這些 Action 在執行時,依照需求可能會呼叫第三方程式。Action 除了被 Trigger 觸發外,也可以透過 REST 直接呼叫,當成 API 使用。 <br> 貼下另外一張我也很喜歡的流程圖: <p class="illustration"> <img src="https://i.imgur.com/JwrVcR4.png" alt="OpenWhisk 流程示例"> OpenWhisk 流程示例(圖片來源: <a href="https://www.oreilly.com/library/view/learning-apache-openwhisk/9781492046158/ch01.html">Oreilly</a>) </p> ## 系統架構 前面提到是屬於資料流動的部份,接下來看看系統架構的部份: <p class="illustration"> <img src="https://i.imgur.com/P4oYa39.png?1" alt="OpenWhisk 系統架構"> OpenWhisk 系統架構 </p> 會說 OpenWhisk 比 Kubeless 複雜的原因在於,它利用了 CouchDB、 Kafka、 Nginx、 Redis 和 Zookeeper 等許多底層元件,雖說這可以讓使用者清晰地關注於可伸縮和彈性的服務(!?),但這也迫使使用者與開發者必須具備些工具的相關知識,拉高了學習曲線。 附上找到的另外一張流程圖,這張有較為清楚的步驟標號,但有些元件被省略或是被特定指出: <p class="illustration"> <img src="https://i.imgur.com/qhjWCWy.png?1" alt="OpenWhisk 系統架構流程圖"> OpenWhisk 系統架構(圖片來源: <a href="https://www.adobe.io/apis/experienceplatform/runtime/docs.html#!adobedocs/adobeio-runtime/master/overview/howitworks.md">Adobe I/O</a>) </p> 回頭來看看 OpenWhisk 組成元件扮演著怎樣的角色: ### Step1: Nginx & Redis Nginx(音:engine X [:speaker:](https://translate.google.com/?hl=zh-TW#view=home&op=translate&sl=en&tl=zh-TW&text=Nginx))是套是免費的開源軟體,通常用於作為非同步框架的網頁伺服器,也可以用作反向代理、負載平衡器和HTTP快取。 在 OpenWhisk 中是 Nginx 是作為 API Gateway,整體遵守 Restful 設計的架構。當每個進入 OpenWhisk 請求,都會經由它接收後,並將處理後的請求後轉發給 Controller。另外 Nginx 會使用 Redis 來儲存黑名單列表。 ### Step2: Controller Controller 可以視為真正處理請求的地方。當通過 Nginx 後,會轉而觸發 Controller,由它來為每個請求進行身份驗證與授權,並將操作指派給 Invoker。 另外有看到資料寫到 Controller 是使用 Scala 語言編寫的 rest api,並基於 Akka 運行時環境和 Spray REST / HTTP 工具箱構建,用於對 OpenWhisk 內部對象的增刪查改(CRUD)和 Action 的調用。 ### Step3、4、8: CouchDB CouchDB 用於儲存一些系統狀態,憑證、namespace、Action、Trigger、Rule 等定義皆存儲在於此。而這邊除了使用 CouchDB 外,根據[文件](https://github.com/apache/openwhisk-deploy-kube/blob/master/docs/configurationChoices.md#using-an-external-database)也可以使用 [Cloudant](https://www.ibm.com/tw-zh/cloud/cloudant)。只是若是使用 Cloudant 就必須跟 IBM 綁在一起可能會不太適合。 在整個 OpenWhisk 架構中,CouchDB 被用在了三個地方: 1. **身份驗證與授權** 當 Nginx 請求轉發給 OpenWhisk 後,Controller 會從 CouchDB 讀取使用者的身份資料,當確認驗證無誤後,Controller 會再進行下一步處理。 2. **取回 Action** 身份驗證通過後,Controller 會從 CouchDB 中加載 Action、 Code...等。 3. **儲存結果** Action 的執行結果也會存回 CouchDB,就是圖中線 8 的部份。 <p class="illustration"> <img src="https://i.imgur.com/FXuX36T.png?1" alt="Lean OpenWhisk Architecture"> Lean OpenWhisk Architecture(圖片來源: <a href="https://medium.com/openwhisk/lean-openwhisk-open-source-faas-for-edge-computing-fb823c6bbb9b">Medium</a>) </p> ### Step5: Consul 當 Controller 並將資料指派給 Invoker 前,它會先與 Consul 確認。Consul 擁有可用的 Invoker 及其健康狀況清單。Controller 會決定重新使用現有的「熱」容器(Container),或啟動一個暫停的「暖」容器,或啟動一個新的「冷」容器進行新的調用。 ### Step6: Kafka Apache Kafka 通常用於構建即時資料管道和 Streaming 應用程式。 OpenWhisk 利用 Kafka 連接 Controller 和 Invoker,所有 Controller 發布的 Action,都會轉換成消息在 Kafka 中排隊等待執行。當 Controller 得到 Kafka 的收到請求的確認消息後,會直接向發出請求的使用者回傳 ActivationId,當使用者收到 ActivationId 後可視為請求已經成功存入 Kafka,在之後可以藉由 ActivationId 向 OpenWhisk 取回運行結果。 ### Step7: Invoker Invoker 算是 OpenWhisk 的最後階段,Invoker 也是用 Scala 實做的,它會執行 Action 的程式碼。 當 Invoker 從 Kafka 中接受了 Controller 傳來的請求後,會生成 Docker Container, 接著從 CouchDB 複製 Action 原始碼並注入容器中。一旦執行完成後,執行結果會被存回 CouchDB 中。 ### Step8:CouchDB 上一階段中的 Invoker 會回傳執行結果到 CouchDB 中儲存。可以藉由在第六階段中取回的 ActivationId 來向 CouchDB 取得結果,看起來會類似這樣: ```bash= { "activationId": "31809ddca6f64cfc9de2937ebd44fbb9", "response": { "statusCode": 0, "result": { "hello": "world" } }, "end": 1474459415621, "logs": [ "2016-09-21T12:03:35.619234386Z stdout: Hello World" ], "start": 1474459415595, } ``` ### 其他架構圖 在找資料的時候從,其實還有找到其他幾張 OpenWhisk 的架構圖,只是我在前面的敘述,找不到適合的地方插入這幾個張圖,所以這邊就把它列出來: <p class="illustration"> <img src="https://i.imgur.com/njWWU1M.png" alt="OpenWhisk 系統架構流程圖"> OpenWhisk 系統架構(圖片來源: <a href="https://events19.lfasiallc.com/wp-content/uploads/2017/11/Apache-OpenWhisk-Kubernetes-A-Perfect-Match-for-Your-Serverless-Platform_Ying-Chun-Guo-_-Zhou-Xing.pdf">Apache OpenWhisk + Kubernetes</a>) </p> <p class="illustration"> <img src="https://i.imgur.com/uzB1iBF.png?1" alt="OpenWhisk 系統架構流程圖"> OpenWhisk 系統架構(圖片來源: <a href="https://www.oreilly.com/library/view/learning-apache-openwhisk/9781492046158/ch01.html#serverless_and_openwhisk_architecture">Oreilly</a>) </p> ## 系統限制 OpenWhisk 有一些系統限制,包括一個 Action 可以使用多少記憶體、 Trigger 每分鐘的觸發頻率之類的。 <p class="illustration"> <img src="https://i.imgur.com/5YGKaoY.png?3" alt="OpenWhisk action execution constraints"> OpenWhisk action execution constraints(圖片來源: <a href="https://www.oreilly.com/library/view/learning-apache-openwhisk/9781492046158/ch01.html#serverless_and_openwhisk_architecture">Oreilly</a>) </p> ### Actions <p class="illustration"> <img src="https://i.imgur.com/MgQ7u6y.png" alt="Default Limits for Actions"> Default Limits for Actions(圖片來源: <a href="https://github.com/apache/openwhisk/blob/master/docs/reference.md#actions">apache/openwhisk|GitHub</a>) </p> 其中 ==timeout/memory/logs==,這三個參數使用者可以自行調整。 ### Triggers <p class="illustration"> <img src="https://i.imgur.com/MC6VDH5.png" alt="Default Limits for Triggers"> Default Limits for Triggers(圖片來源: <a href="Default Limits for Triggers">apache/openwhisk | GitHub</a>) </p> ## 小結 系統的介紹先到這邊好了,下一章節我在試著安裝 OpenWhisk 並評估建議書的需求。 ## 參考資料 1. [Apache OpenWhisk Documentation](https://openwhisk.apache.org/documentation.html) 。檢自 cheneydc|简书 (2020-04-08)。 2. cheneydc (2017-08-06)。[折腾Openwhisk - 本地ubuntu部署openwhisk](https://www.jianshu.com/p/8e3a77c28532) 。檢自 cheneydc|简书 (2020-04-08)。 3. junjiang3 (2018-09-09)。[Apache Openwhisk学习(一)](https://www.cnblogs.com/junjiang3/p/9613698.html) 。檢自 博客园 (2020-07-14)。 4. 零空科技 (2017-06-09)。[Apache OpenWhisk架構概述](https://kknews.cc/zh-tw/tech/j6egn8y.html) 。檢自 每日頭條 (2020-07-14)。 5. 赵钰莹 (2019-07-29)。[无服务器平台Apache OpenWhisk晋升为顶级项目](https://www.infoq.cn/article/MMwF9fbx-XaAGwwhtT8L) 。檢自 InfoQ (2020-07-14)。 6. 腾讯IVWEB团队 (2019-07-02)。[【译】Kubernetes Serverless 框架的全面对比(OpennFaas,OpenWhisk,Fission,Kubeless 等)](https://juejin.im/post/5d1abf09f265da1bc8544227) 。檢自 掘金 (2020-07-14)。 7. Glynn Bird (2016-07-12)。[OpenWhisk 简介:轻松创建微服务](https://developer.ibm.com/zh/articles/os-introducing-openwhisk-microservices-made-easy/) 。檢自 IBM Developer (2020-09-28)。 8. 協同撰寫。[Nginx](https://zh.wikipedia.org/wiki/Nginx) 。檢自 維基百科 (2020-09-28)。 9. 深圳清华大学研究院下一代互联网研发中心 (2019-08-19)。[Openwhisk 概览](https://zhuanlan.zhihu.com/p/78766357) 。檢自 知乎 (2020-09-28)。 10. [How Adobe I/O Runtime Works](https://www.adobe.io/apis/experienceplatform/runtime/docs.html#!adobedocs/adobeio-runtime/master/overview/howitworks.md)。檢自 Adobe I/O (2020-09-28)。 11. Michele Sciabarrà。 [Chapter 1. Serverless and OpenWhisk Architecture](https://www..com/library/view/learning-apache-openwhisk/9781492046158/ch01.html#serverless_and_openwhisk_architecture)。檢自 Learning Apache OpenWhisk (2020-09-29)。 12. 協同撰寫(2019-02-14)。 [Apache/openwhisk reference.md](https://github.com/apache/openwhisk/blob/master/docs/reference.md#system-limits)。檢自 apache/openwhisk | Github (2020-09-29)。 ## 更新紀錄 :::spoiler 最後更新日期:2020-12-31 - 2020-12-31 發布 - 2020-09-29 完稿 - 2020-04-08 起稿 ::: <br><br> > **本文作者**: 辛西亞.Cynthia > **本文連結**: [辛西亞的技能樹](https://cynthiachuang.github.io/Installation-and-Deployment-Notes-of-OpenWhisk-01/) / [hackmd 版本](https://hackmd.io/@CynthiaChuang/Installation-and-Deployment-Notes-of-OpenWhisk-01) > **版權聲明**: 部落格中所有文章,均採用 [姓名標示-非商業性-相同方式分享 4.0 國際](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en) (CC BY-NC-SA 4.0) 許可協議。轉載請標明作者、連結與出處!