--- title: 【Survey】OpenWhisk 折騰安裝部署筆記 02 date: 2020-12-21 23:21 is_modified: false disqus: cynthiahackmd categories: - "雲端網路 › 雲端運算" - "資訊科技 › 開發與輔助工具" tags: - "Fass/Serverless" - "OpenWhisk" - "Linux/Unix" - "網站與雲端平台" - "工具安裝與部署" --- {%hackmd @CynthiaChuang/Github-Page-Theme %} <br> 繼續被 OpenWhisk 折騰... orz [前一篇](/@CynthiaChuang/Installation-and-Deployment-Notes-of-OpenWhisk-01)大概看了下基本的系統架構與限制後,這篇開始試著安裝 OpenWhisk。 <!--more--> ## Deploys anywhere 從 [Openwhisk 官網](http://openwhisk.incubator.apache.org/)上看到,OpenWhisk 可以利用一些常見的 Container 框架,例如: Kubernetes and OpenShift, Mesos and Compose 快速部署。 <p class="illustration"> <img src="http://openwhisk.apache.org/images/illustrations/OW-Deployments.png" alt="The Learning Model"> Deploys anywhere(圖片來源: <a href="http://openwhisk.apache.org/" >Openwhisk</a>) </p> 從 Apache 的 [Githib](https://github.com/apache) 上,找到了幾份部署的教學: - [Kubernetes](https://github.com/apache/openwhisk-deploy-kube) - [Openshift](https://github.com/apache/openwhisk-deploy-openshift) - [Mesos](https://github.com/apache/openwhisk-deploy-mesos) - [Compose](https://github.com/apache/openwhisk-devtools/tree/master/docker-compose) 研究了一下安裝難度與實際需要部署的環境考量,最終決定挑 Kubernetes 來快速部署。 ## 前置安裝 既然決定要利用 [Kubernetes](https://kubernetes.io/),那當然需要先將它部署起來。另外為了簡化 Kubernetes 叢集的部署管理,也安裝了 [Helm](https://helm.sh/)。 ### Kubernetes & kind 要弄出測試用的 Kubernetes 小型叢集,最簡單的方法是使用 ==Docker-in-Docker==,直接在 Docker 上運行 Kubernetes。這邊為了迅速上手使用 ==kind== 這套工具,可以快速架設多節點的 Kubernetes 叢集環境。 對了,在 OpenWhisk 中配置的 Docker 預設須具備至少 4 GB 記憶體和 2 個 virtual CPUs。 <p class="illustration"> <img src="https://i.imgur.com/Ncg5fgi.png" alt="kind"> kind(圖片來源: <a href="https://github.com/kubernetes-sigs/kind">kind|GitHub</a>) </p> #### Step 1、安裝 kind 按照 [kind 安裝文件](https://github.com/kubernetes-sigs/kind)的說明,安裝 kind 的方法有二: 1. `GO111MODULE` 2. 直接下載原始碼來配置路徑 考慮到我的電腦有裝過 [Golang](https://www.runoob.com/go/go-environment.html) 所以決定用 `GO111MODULE` 來安裝,不過還是先用指令檢查下 Golang 版本: ``` bash= $ go version go version go1.14 linux/amd64 ``` 可以看到版本為 `1.14` 符合文件中 `1.13` 以上的要求。確定版本後,就可以可以用 go module 來安裝: ```bash= $ GO111MODULE="on" go get sigs.k8s.io/kind@v0.7.0 ``` #### Step 2、建立 Kubernetes 安裝完 kind 後,就可以進行叢集的配置。這個的配置難度不高,基本上按照[設置文件](https://github.com/apache/openwhisk-deploy-kube/blob/master/docs/k8s-kind.md)就可以完成。 首先先建立一個 yaml 檔,並取名為 `kind-cluster.yaml`: ```yaml= kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane - role: worker extraPortMappings: - hostPort: 31001 containerPort: 31001 - role: worker ``` <br> 完成 ymal 檔撰寫後,就可以使用 kind 指令開始配置 Cluster,其中指令中的 `--name` 如果沒有指定,預設會是 `kind`: ```bash= $ kind create cluster --config kind-cluster.yaml --name kind-cluster Creating cluster "kind-cluster" ... ✓ Ensuring node image (kindest/node:v1.17.0) 🖼 ✓ Preparing nodes 📦 📦 📦 ✓ Writing configuration 📜 ✓ Starting control-plane 🕹️ ✓ Installing CNI 🔌 ✓ Installing StorageClass 💾 ✓ Joining worker nodes 🚜 Set kubectl context to "kind-kind-cluster" You can now use your cluster with: kubectl cluster-info --context kind-kind-cluster Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community 🙂 ``` #### Step 3、 Kubernetes 叢集確認 安裝完成後,可以用 `get clusters` 指令來確定剛剛所建立的叢集: ```bash= $ kind get clusters kind-cluster ``` <br> 如果用 `docker ps` 來觀察目前啟動的 container,也會發現多了 3 個。另外,試試看 `create` 指令中最後一個步驟的提示,可以看到一些詳細資料: ```bash= $ kubectl cluster-info --context kind-kind-cluster Kubernetes master is running at https://127.0.0.1:32778 KubeDNS is running at https://127.0.0.1:32778/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy ``` <br> 在網路上找尋安裝資訊的時候,看到有些指令提示中會多出 `export KUBECONFIG` 的指令, ```bash= $ kind create cluster --name moelove Creating cluster "moelove" ... ✓ Ensuring node image (kindest/node:v1.13.4) 🖼 ✓ Preparing nodes 📦 ✓ Creating kubeadm config 📜 ✓ Starting control-plane 🕹️ Cluster creation complete. You can now use the cluster with: export KUBECONFIG="$(kind get kubeconfig-path --name="moelove")" kubectl cluster-info ``` 看[文字說明](https://kubernetes.io/docs/tasks/tools/install-kubectl/#verifying-kubectl-configuration),這條指令像是配置 kubectl 使用的。我這邊指令提示中沒出現這行,我有點不確定是因為 kind 版本的關係,或者是因為之前同仁在這台機台有配置過 kubectl? <br> 除了上述資訊外,還有一個 `kubectl config view`,也可以用來查看配置結果: ```bash= $ kubectl config view apiVersion: v1 clusters: - cluster: certificate-authority-data: DATA+OMITTED server: https://127.0.0.1:32778 name: kind-kind-cluster contexts: - context: cluster: kind-kind-cluster user: kind-kind-cluster name: kind-kind-cluster current-context: kind-kind-cluster kind: Config preferences: {} users: - name: kind-kind-cluster user: client-certificate-data: REDACTED client-key-data: REDACTED ``` <br> 小插曲,第一次建立的時候,我發現我 cluster 拼錯成 cluste,只好把錯的叢集刪掉重新建立: ```bash= $ kind delete cluster --name kind-cluste ``` ### Helm <p class="illustration"> <img src="https://i.imgur.com/hR6ZGds.png?1" alt="Helm"> Helm(圖片來源: <a href="https://medium.com/@C.W.Hu/kubernetes-helm-chart-tutorial-fbdad62a8b61f">Cheng-Wei Hu|Medium</a>) </p> 另外一個需要先安裝的工具是 [Helm](https://github.com/helm/helm),它是一個管理設定檔的工具,可以簡化 Kubernetes 叢集上應用程式的部署和管理。此外 OpenWhisk 中的 Helm chart 也需要 Helm 3。 Helm 所提供的安裝方式還不少,有直接下載 [binary file](https://github.com/helm/helm/releases) 、使用 Snap(Linux) 以及 shell script 的方式,就是安裝時要稍微注意一下版本,按文件要求必須安裝 Helm v3.0.1 以上的版本,安裝可以參考這份[教學](https://whmzsu.github.io/helm-doc-zh-cn/quickstart/install-zh_cn.html#%E5%AE%89%E8%A3%85-helm-%E5%AE%A2%E6%88%B7%E7%AB%AF)。 安裝後,試著使用 `helm help` 來確認是否安裝成功: ```bash= $ helm help The Kubernetes package manager Common actions for Helm: - helm search: search for charts - helm pull: download a chart to your local directory to view - helm install: upload the chart to Kubernetes - helm list: list releases of charts Environment variables: ...(略) ``` ## 部署 有了 K8S 叢集與 Helm 後,就可以使用 Helm 將 OpenWhisk 部署到 K8S 叢集上了,這邊依照文件的四個部署動作來進行: ### Step 1. 初始化叢集設定 在[前置配置 Kubernetes 叢集](#Step-2、建立-Kubernetes-叢集)時,我們在 `kind-cluster.yaml` 中宣告了三個節點,其中一個節點作為 control-plane,另外兩個節點作為 worker: ```yaml= - role: control-plane - role: worker extraPortMappings: - hostPort: 31001 containerPort: 31001 - role: worker ``` 這步驟中,我們要標記 Kubernetes 中每個 worker 的預計用途,按文件說明這邊將一個節點保留給 invoker,另一個用運行 OpenWhisk 系統: ```bash= $ kubectl label node {name}-worker openwhisk-role=core node/{name}-worker labeled $ kubectl label node {name}-worker2 openwhisk-role=invoker node/{name}-worker2 labeled ``` <br> :warning: 注意,請把指令中 `{name}` 換成建立叢集所取的名字,以上面的例子來說就是 `kind-cluster`,如果在建立叢集時沒特別命名,則會是預設 `kind`。名字打錯的話,它會跟你說 ==NotFound== 喔! ```bash= $ kubectl label node kind-worker openwhisk-role=core Error from server (NotFound): nodes "kind-worker" not found ``` ### Step 2. 定義 yaml 要配置 OpenWhisk,首先需要定義一個 `mycluster.yaml` 來指定一些入口訊息和其他的系統配置。不過,在此之前需要先用下列指令確定輔助節點的 internalIP: ```bash= $ kubectl describe node kind-cluster-worker | grep InternalIP: | awk '{print $2}' 172.17.0.4 ``` 得到一個實際的 <INTERNAL_IP> ,這個 IP 稍後會用於 `mycluster.yaml`。 ```bash= whisk: ingress: type: NodePort apiHostName: <INTERNAL_IP> apiHostPort: 31001 invoker: containerFactory: impl: "kubernetes" nginx: httpsNodePort: 31001 ``` ### Step 3. 使用 Helm Chart 配置 準備好 `mycluster.yaml` 後,就可以使用 Helm 來將 OpenWhisk 部署到 Kubernetes 集群。在開始前,先建立個 namespace 名為 `openwhisk`: ```bash= $ kubectl create namespace openwhisk namespace/openwhisk created ``` <br> 然後[下載 openwhisk-deploy-kube](https://github.com/apache/openwhisk-deploy-kube.git),並確認專案中資料夾 `helm/openwhisk` 是否存在。若存在,就可以直接透過指令安裝 OpenWhisk 的 Chart。其中指令中的 `owdev` 是 release name,`openwhisk` 則是我們上一個步驟中所建立的 namespace: ```bash= $ helm install owdev ./helm/openwhisk -n openwhisk -f mycluster.yaml NAME: owdev LAST DEPLOYED: Fri Apr 10 15:32:13 2020 NAMESPACE: openwhisk STATUS: deployed REVISION: 1 NOTES: Apache OpenWhisk Copyright 2016-2018 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). To configure your wsk cli to connect to it, set the apihost property using the command below: $ wsk property set --apihost <whisk.ingress.apiHostName>:<whisk.ingress.apiHostPort> Your release is named owdev. To learn more about the release, try: $ helm status owdev [--tls] $ helm get owdev [--tls] Once the 'owdev-install-packages' Pod is in the Completed state, your OpenWhisk deployment is ready to be used. Once the deployment is ready, you can verify it using: $ helm test owdev [--tls] --cleanup ``` <br> 過程中,需要稍微留意下安裝過程中所出現的 `<whisk.ingress.apiHostName>:<whisk.ingress.apiHostPort>` ,這組 HostName 與 HostPort 稍後會到用。但如果沒注意到也沒關係,可藉由下列指令再看一次: ```bash= $ helm status owdev -n openwhisk ``` 不過,其實這兩個值是在 `mycluster.yaml` 中所定義的 `apiHostName` 與 `apiHostPort`。 ### Step 4. 配置 wsk CLI. 配置完 Helm Chart 後,就可以通過設置 auth 和 apihost 配置 wsk,以告訴 wsk CLI 如何連接到 OpenWhisk。不過開始配置前要先安裝完 [wsk CLI](https://github.com/apache/openwhisk-cli)。 ```bash= $ wsk property set --apihost <whisk.ingress.apiHostName>:<whisk.ingress.apiHostPort> ok: whisk API host set to 172.17.0.4:31001 $ wsk property set --auth 23bc46b1-71f6-4ed5-8c54-816aa4f8c502:123zO3xZCLrMN6v2BKK1dXYFpXlPkccOFqm12CdAsMgRU4VrNZ9lyGVCGuMDGIwP ok: whisk auth set. Run 'wsk property get --auth' to see the new value. ``` ### Step 5. 驗證 OpenWhisk 部署 安裝完成後,就可以進行驗證了: ```bash= $ helm test owdev -n openwhisk Pod owdev-tests-package-checker pending Pod owdev-tests-package-checker pending Pod owdev-tests-package-checker pending Pod owdev-tests-package-checker running Pod owdev-tests-package-checker succeeded Pod owdev-tests-smoketest pending Pod owdev-tests-smoketest pending Pod owdev-tests-smoketest pending Pod owdev-tests-smoketest running Pod owdev-tests-smoketest succeeded NAME: owdev LAST DEPLOYED: Fri Apr 10 15:32:13 2020 NAMESPACE: openwhisk STATUS: deployed REVISION: 1 TEST SUITE: owdev-tests-package-checker Last Started: Fri Apr 10 15:42:58 2020 Last Completed: Fri Apr 10 15:43:02 2020 Phase: Succeeded TEST SUITE: owdev-tests-smoketest Last Started: Fri Apr 10 15:43:02 2020 Last Completed: Fri Apr 10 15:43:07 2020 Phase: Succeeded NOTES: Apache OpenWhisk Copyright 2016-2018 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). To configure your wsk cli to connect to it, set the apihost property using the command below: $ wsk property set --apihost <whisk.ingress.apiHostName>:<whisk.ingress.apiHostPort> Your release is named owdev. To learn more about the release, try: $ helm status owdev [--tls] $ helm get owdev [--tls] Once the 'owdev-install-packages' Pod is in the Completed state, your OpenWhisk deployment is ready to be used. Once the deployment is ready, you can verify it using: $ helm test owdev [--tls] --cleanup ``` <br> 另外一個相對應的刪除指令,可以用來刪除所有已部署的 OpenWhisk 組件: ```bash= $ helm uninstall owdev -n openwhisk ``` <br> 把整個 [Openwhisk](https://github.com/apache/openwhisk) 全弄來好了後,就可測試是否安裝成功,下列指令中 `WHISK_SERVER` 和 `WHISK_AUTH` ,可以使用 `wsk property get --apihost` and `wsk property get --auth` 來查訊: ```bash= cd openwhisk $ ./gradlew :tests:testSystemBasic -Dwhisk.auth=$WHISK_AUTH -Dwhisk.server=https://$WHISK_SERVER -Dopenwhisk.home=`pwd` ``` <br> 它會給出一個測試結果: <p class="illustration"> <img src="https://i.imgur.com/47SoEgK.png" alt="測試結果"> </p> ## 測試 這邊試著建立觸發器(Trigger)、動作(Action)與規則(Rule)。 ### action 1. **action with python** 這邊先準備一個用 python 所撰寫的 action,取名為 `catapi.py` XDDD,不過我懶的實做 function,所以我直接把傳進來的參數,直接丟回去: ```python= def main(args): name = args.get("name", "stranger") color = args.get("color", "white") command = "INSERT INTO catdb VALUES( {} , {} )".format(name,color) print(command) return {"command":command} ``` <br> 準備好程式碼後,就使用指令建立 action,其中下列指令中的: 1. `catapi` ;是指 ACTION_NAME。 2. `catapi.py` :則是對應的 action code。 3. `kind` :的 flag 則是指定 action code 所撰寫的語言。 4. `web` :則是告知你的 action 是否允許通過 url 溝通。 5. `-i` :則是 skip 掉憑證檢查,因為我是在 local 端測試所以就跳掉憑證檢查。如果是正式上線產品,才會需要加憑證功能,我看大家都用 openssl 去生成。 ```shell= $ wsk action create catapi catapi.py --kind python:3 --web true -i $ wsk action create catapi catapi.py --kind python:3 --web true -i ok: created action catapi ``` <br> 建立了後,就可以透過 invoke 來呼叫這些 action,會顯示一組回傳結果: ```shell= $ wsk action invoke catapi --blocking -r --param name Cynthia --param color black -i { "command": "INSERT INTO catdb VALUES( Cynthia , black )" } ``` 另外,也可以透過 activation list 來看到 action 的活動情況: ```bash= $ wsk -i activation list catapiDatetime Activation ID Kind Start Duration Status Entity 2020-04-13 11:05:55 3eb4e20951ed4194b4e20951ed919498 python:3 cold 11ms success guest/catapi:0.0.1 ``` <br> 因為我剛剛 `web` 設置為 true,允許使用 url 調用這個 action。這邊先將其建立為 api 並取得其 api path: ```bash= $ wsk -i api create /catapi /insert post catapi --response-type json ok: created API /catapi/insert POST for action /_/catapi https://172.17.0.4:31001/api/23bc46b1-71f6-4ed5-8c54-816aa4f8c502/catapi/insert $ curl --request POST \ --url https://172.17.0.4:31001/api/23bc46b1-71f6-4ed5-8c54-816aa4f8c502/catapi/insert \ --header "Content-Type: application/json" \ --data '{"name":"CC", "color":"black"}' \ -k { "command": "INSERT INTO catdb VALUES( CC , black )" } ``` <br> 2. **action with bash** 這邊試著建立一個 bash 的 action,雖然[明面上所支援的語言](/@CynthiaChuang/Installation-and-Deployment-Notes-of-OpenWhisk-01#動作-Action)並不包括 bash,但在 [GitHub 的討論](https://github.com/apache/openwhisk/issues/2927)中發現,有人提到默認的 docker 框架實際上是可以執行 bash 腳本的,因此這邊按照[這篇網誌](https://medium.com/openwhisk/serverless-functions-in-your-favorite-language-with-openwhisk-f7c447558f42)試著來建立 bash 的 action。 在開始之前,先準備一個名為 `flip.sh` 的程式碼,它是用來擲硬幣 N 次並返回拋擲硬幣的結果。 ```bash= #!/bin/bash # install jq if it does not exist # openwhisk 提供的docker 有裝 if [ ! -f /usr/bin/jq ]; then apk update && apk add jq # 取決於環境, 但 openwhisk 提供的環境應該用上面那條指令 # apt-get update && apt-get install jq fi # determine number of flips N=`echo "$@" | jq '."n"'` # total count of heads and tails HEADS=0 TAILS=0 for i in `seq 1 $N`; do echo -n "flipping coin..." if [ $(( RANDOM % 2 )) == 0 ]; then echo "HEADS"; HEADS=$(( HEADS + 1 )) else echo "TAILS"; TAILS=$(( TAILS + 1 )) fi done echo "{\"trials\": $N, \"heads\": $HEADS, \"tails\": $TAILS}" ``` 按照網誌中的指示,使用 native actions 來建立。 ```bash= $ wsk -i action create flip --native flip.sh --web true ok: created action flip $ wsk -i action invoke flip --result --param n 100 { "heads": 47, "tails": 53, "trials": 100 } ``` 除了使用 action create 來執行 bash 外,在下方也有看到[大神的回覆](https://github.com/apache/openwhisk/issues/2927#issuecomment-347018584),表示可以透過修改 [runtime manifest](https://github.com/apache/openwhisk/blob/master/ansible/group_vars/all#L38) 的 [方式](https://github.com/apache/openwhisk/blob/master/docs/actions-new.md) 來將 bash 加入 kind 的候選列中。 P.S. 我在後來找不到 runtime manifest,它好像變成 [runtimes.json](https://github.com/apache/openwhisk/blob/556cd3d7e2fb12a3419555411b181bc1c080af8a/ansible/files/runtimes.json)? <br> 3. **action with C** 再來根據[文件](https://github.com/apache/openwhisk/blob/master/docs/actions-docker.md#example-static-c-binary)的敘述試著建立 C 語言的 action。 先準備一個 C 的程式碼取名叫做 `main.c`: ```cpp= #include <stdio.h> int main(int argc, char *argv[]) { printf("This is an example log message from an arbitrary C program!\n"); printf("{ \"msg\": \"Hello from arbitrary C program!\", \"args\": %s }", (argc == 1) ? "undefined" : argv[1]); } ``` 並使用 gcc 對原始碼進行編譯後,將編譯結果打包壓縮檔案: ```shell $ gcc main.c -o exec $ zip -r action.zip exec ``` 最後一樣選擇使用 native actions,並傳入打包好的壓縮。 ```bash= $ wsk -i action create c-binary action.zip --native ok: created action c-binary $ wsk -i action invoke c-binary --result --param name James { "args": { "name": "James" }, "msg": "Hello from arbitrary C program!" } ``` <br> 4. **action with C++** 最後試著建立一個 C++ 的 action,這邊預期可以像 C 一樣,先進行編譯後使用 native 建立 action。所以還是先準備一個原始碼 `helloworld.cpp` ```cpp= #include <iostream> using namespace std; int main(){ cout << "{ \"msg\": \"Hello from arbitrary C++ program!\"}" ; } ``` 接下來將原始碼進行編譯後打包: ```shell= $ g++ helloworld.cpp -o exec $ zip -r action.zip exec ``` 最後建立並試著調用 action,看來沒辦法用相同的辦法 ```shell= $ wsk -i action create cplus action.zip --native ok: created action cplus $ wsk -i action invoke cplus3 --result { "error": "The action did not return a dictionary." } ``` 試著印出 log 看能不能有點頭緒: ```shell= wsk activation logs -i 1518db43520746e098db43520756e036 2020-04-14T09:55:03.774174764Z stdout: Error loading shared library libstdc++.so.6: No such file or directory (needed by /action/exec) 2020-04-14T09:55:03.774207363Z stdout: Error relocating /action/exec: _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc: symbol not found 2020-04-14T09:55:03.774216897Z stdout: Error relocating /action/exec: _ZNSt8ios_base4InitC1Ev: symbol not found 2020-04-14T09:55:03.774225361Z stdout: Error relocating /action/exec: _ZNSt8ios_base4InitD1Ev: symbol not found 2020-04-14T09:55:03.774232412Z stdout: Error relocating /action/exec: _ZSt4cout: symbol not found 2020-04-14T09:55:03.774244895Z stdout: 2020-04-14T09:55:03.776577246Z stderr: The action did not initialize or run as expected. Log data might be missing. ``` 可以發現錯誤訊息顯示沒有 libstdc++ 的函式庫。拜了下大神,[發現](https://github.com/kohlschutter/junixsocket/issues/33#issuecomment-273255073) openwhisk/dockerskeleton 是 alpine 體系的 docker ,本身**不含 libstdc++.so.6**,所以我如果想執行 C++,必須 build 新的 image 了。 至於如何如何用 docker 建立 action 可以參考[這份教學](https://github.com/apache/openwhisk/blob/master/docs/actions-docker.md),這邊紀錄一下 dockerfile: ```dockerfile= # Dockerfile for example whisk docker action FROM openwhisk/dockerskeleton ENV FLASK_PROXY_PORT 8080 ### Add source file(s) ADD cpp_code/helloworld.cpp /action/helloworld.cpp RUN export http_proxy=http://87.xx.xx.120:8080 && \ export https_proxy=http://87.xx.xx.120:8080 && \ apk add --no-cache --virtual .build-deps \ bzip2-dev \ g++ \ libc-dev \ ### Compile source file(s) && cd /action; g++ -o exec helloworld.cpp \ CMD ["/bin/bash", "-c", "cd actionProxy && python -u actionproxy.py"] ``` <br> 5. **action with other** 至於其他與研究不一一嘗試嘗試了,可以直接從 [Openwhisk 官方文件](https://openwhisk.apache.org/documentation.html#actions-creating-and-invoking)中了解其他內建語言的基礎用法。 ### 第三方函式庫 忽然想到如果有相依函式庫的怎麼辦?如果是編譯語言應該連同相依函式庫一起傳入應該可行,但是直譯語言就必須來找找了。還好最後有找到[文件](https://github.com/apache/openwhisk/blob/master/docs/actions-python.md#packaging-python-actions-with-a-virtual-environment-in-zip-files)。 一樣準備一支原始碼 `__main__.py` ,根據我看到資料好像一定要叫這個? ```python= import numpy; def main(args): return {"version":numpy.version.version} ``` 另外根據你所使用的函式庫,提供一份 `requirements.txt`,並將兩者把包成壓縮檔。 ```typescript= numpy ``` 最後接著試著建立與調用。 ```shell= $ wsk action create numpytext --kind python:3 helloPython.zip -i ok: created action numpytext $ wsk -i action invoke numpytext --result { "version": "1.18.2" } ``` ## 其他 ### CouchDB 在上一章 Survey [整體系統架構](/@CynthiaChuang/Installation-and-Deployment-Notes-of-OpenWhisk-01#系統架構)時,有提到 CouchDB,不過啟動過程中完全沒有看到它的蹤影。 就[文件](https://github.com/apache/openwhisk-deploy-kube/blob/master/docs/configurationChoices.md#using-an-external-database)上來看,CouchDB 需要[額外配置並進行設定](https://github.com/apache/openwhisk/blob/master/tools/db/README.md#using-couchdb),不然 CouchDB 的生命週期會與 OpenWhisk 的生命週期綁在一起,不利於錯誤修復與備援。 是說在文件中有提到,如果不想用 CouchDB,另一個選擇則是 Cloudant。但沒記錯的話 Cloudant 是 IBM 家的產品?所以其實等於沒有選擇... ### Redis 另外因為目前配置沒有設定 [Redis](https://github.com/apache/openwhisk-deploy-kube/blob/master/docs/configurationChoices.md#using-an-external-redis),是用在 API Gateway 也就是 NGINX 會使用到它,不過現階段沒有特別去處理它,如果真要上限,這部分也要額外配置。 ## 評估 1. **需支援不同的程式語言,包含:Go、Java、Python、C++、C、C# 與 Bash** 前面[測試](/@CynthiaChuang/Installation-and-Deployment-Notes-of-OpenWhisk-02#action)的時候有嘗試過,上述語言都可以完成支援。其中Go、Java、Python、C# 為[內建支援](/@CynthiaChuang/Installation-and-Deployment-Notes-of-OpenWhisk-01#動作-Action)的語言,而 C 與 Bash 可透過建立 native actions 來實現,但 C++ 就必須提供 docker image。 2. **確認如何支援第三方Library,以及是否有檔案大小的限制** 1. 以 [python 為例](https://github.com/apache/openwhisk/blob/master/docs/actions-python.md#packaging-python-actions-with-a-virtual-environment-in-zip-files),若是有第三方套件,則將所需的 requirements.txt 與程式碼包成 zip 後上傳。 2. 否,有檔案大小的限制。 在之前的 Survey [系統限制](/@CynthiaChuang/Installation-and-Deployment-Notes-of-OpenWhisk-01#Actions)時,說明有列出檔案大小僅支援 48MB,因此若壓縮檔超出檔案大小限制,則須改用 docker。 <br> 3. **支援的編譯語言要能在平台上進行編譯,並能選擇編譯的環境,例如 Java 選擇 JDK 版本,Golang 選擇 Golang 版本** 1. 目前各個平台都無法在直接在平台上進行編譯,create action 時必須提供編譯好的結果或是直譯式的原始碼。這段真要做需要 UI 配合。 2. 如要不同的語言版本必須提供不同版本的 runtime docker,並修改 runtimes.json。 P.S. 是說文件中有看到, 可以用[直譯的方式](https://openwhisk.apache.org/documentation.html#actions-creating-and-invoking),直接使用原始碼來建立 action 來執行程式 Golang,但也可以[先行編譯](https://github.com/apache/openwhisk/blob/master/docs/actions-go.md#precompiling-go-sources-offline)。 4. **直譯式語言要能夠選擇 runtime 版本** 同上,如要不同的語言版本必須提供不同版本的 runtime docker,並修改 runtimes.json。 5. **針對功能呼叫次數與使用資源進行計費** 可以參考 IBM 的計費機制,畢竟 IBM 底層也是 OpenWhisk。 IBM 是根據每秒每個 GB 的記憶體收費的,每秒的執行對每個 GB 的配置記憶體收費為 0.000017,所以在設定 action 時,可以配置執行工作所需的最大記憶體,就可以進一步降低成本。 在這邊可以利用相關指令,分別取得每次的執行時間與 limit 資訊: ```shell= $ wsk activation list -i $ wsk action get [action_name] -i ``` 6. **每個函數設定不同的資源用量限制,例如:RAM 或是 CPU** 在 `wsk action create` 的參數中,有些相關的 flag 可以用: ```shell= $ wsk action create --help create a new action Usage: wsk action create ACTION_NAME ACTION [flags] Flags: -m, --memory LIMIT the maximum memory LIMIT in MB for the action (default 256) -t, --timeout LIMIT the timeout LIMIT in milliseconds after which the action is terminated (default 60000) -l, --logsize LIMIT the maximum log size LIMIT in MB for the action (default 10) ``` 7. **每個相關功能進行監控** <p class="illustration"> <img src="https://i.imgur.com/LGWTKrb.png" alt="監控"> </p> 這是 IBM 的 UI 界面,界面中的活動摘要、活動時間都可以從 `wsk activation list` 取得 ```shell= $ wsk activation list hello -i Datetime Activation ID Kind Start Duration Status Entity 2020-04-10 16:48:19 327771e4092449fcb771e4092439fcac nodejs:10 cold 48ms success guest/hello:0.0.1 2020-04-10 15:44:16 2ee94a612f684db2a94a612f68edb26b nodejs:10 warm 3ms success guest/hello:0.0.1 2020-04-10 15:44:16 0bd20f54c7e54718920f54c7e50718c5 nodejs:10 warm 3ms success guest/hello:0.0.1 2020-04-10 15:44:16 ad69c9ee77aa4be9a9c9ee77aacbe929 nodejs:10 warm 4ms success guest/hello:0.0.1 2020-04-10 15:43:06 7a1fb66a583e404e9fb66a583e704e9c nodejs:10 warm 5ms success guest/hello:0.0.1 2020-04-10 15:43:04 9f38e9c4706143c2b8e9c47061c3c23c nodejs:10 warm 4ms success guest/hello:0.0.1 2020-04-10 15:43:04 e94847e0d77b4f058847e0d77b3f05fb nodejs:10 cold 49ms success guest/hello:0.0.1 ``` 而 log 與返回的 action 結果,也可以藉由下列指令取得: ```shell= $ wsk activation logs [Activation ID] -i $ wsk activation result [Activation ID ] -i ``` ```shell= $ wsk activation poll ``` 8. **提供管理網頁介面讓每個用戶對每個功能進行管理,包括線上編寫函數程式碼、建立、刪除、監控函數。** 管理網頁介面需要由 UI 實做,不過各功能可以藉由 cli 完成: - action - **create**:create a new action - **update**:update an existing action, or create an action if it does not exist - **invoke**:invoke action - **get**:get action - **delete**:delete action - **list**:list all actions in a namespace or actions contained in a package 除了更新的功能,但是編譯語言的更新還是需要重新編譯。 ## 小結 媽呀!終於告一段落! 雖然沒有寫得很詳細,很多東西沒有寫到,不過算是告一個段落了。 ## 參考資料 1. [Openwhisk 官網](http://openwhisk.incubator.apache.org/) 。檢自 Openwhisk (2020-09-29)。 2. 協同撰寫。[OpenWhisk Deployment on Kubernetes](https://github.com/apache/openwhisk-deploy-kube/blob/master/README.md)。檢自 openwhisk-deploy-kube|GitHub (2020-09-30)。 3. 協同撰寫。[Deploying OpenWhisk on kind](https://github.com/apache/openwhisk-deploy-kube/blob/master/docs/k8s-kind.md)。檢自 openwhisk-deploy-kube|GitHub (2020-09-30)。 4. 张晋涛。[Kubernetes 从上手到实践](https://juejin.im/book/6844733753063915533/section/6844733753126813709)。檢自 掘金小册 (2020-10-22)。 5. (2020-09-22)。[Install and Set Up kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/)。檢自 Kubernetesb (2020-10-22)。 6. 胡程維|Cheng-Wei Hu (2019-07-20)。[Kubernetes 基礎教學(三)Helm 介紹與建立 Chart](https://medium.com/@C.W.Hu/kubernetes-helm-chart-tutorial-fbdad62a8b61)。檢自 Medium (2020-10-22)。 7. Mingo (2019-02-27)。[安装 · Helm用户与开发者指南](https://whmzsu.github.io/helm-doc-zh-cn/quickstart/install-zh_cn.html)。檢自 github (2020-10-22)。 8. rodric rabbah (2018-01-23)。[Serverless functions in your favorite language with OpenWhisk | by | Apache OpenWhisk](https://medium.com/openwhisk/serverless-functions-in-your-favorite-language-with-openwhisk-f7c447558f42)。檢自 Medium (2020-11-16)。 9. style95 (2017-11-06)。[bash kind action · Issue #2927 · apache/openwhisk](https://github.com/apache/openwhisk/issues/2927)。檢自 apache/openwhisk | GitHub (2020-11-16)。 10. 協同撰寫。[openwhisk/actions-docker.md](https://github.com/apache/openwhisk/blob/master/docs/actions-docker.md)。檢自 apache/openwhisk | GitHub (2020-11-16)。 11. pierredavidbelanger (2017-01-08)。[Error loading shared library libstdc++.so.6 · Issue #33](https://github.com/kohlschutter/junixsocket/issues/33)。kohlschutter/junixsocket | GitHub (2020-11-16)。 12. [Documentation](https://openwhisk.apache.org/documentation.html#actions-creating-and-invoking)。Openwhisk (2020-11-16)。 13. 協同撰寫。[openwhisk/actions-python.md](https://github.com/apache/openwhisk/blob/master/docs/actions-python.md#packaging-python-actions-with-a-virtual-environment-in-zip-files)。檢自 apache/openwhisk | GitHub (2020-11-16)。 14. 協同撰寫。[openwhisk-deploy-kube/configurationChoices.md](https://github.com/apache/openwhisk-deploy-kube/blob/master/docs/configurationChoices.md#using-an-external-database)。檢自 apache/openwhisk-deploy-kube | GitHub (2020-11-16)。 15. 協同撰寫。[openwhisk/README.md](https://github.com/apache/openwhisk/blob/master/tools/db/README.md#using-couchdb)。檢自 apache/openwhisk | GitHub (2020-11-16)。 16. Chanwit Kaewkasi [Docker for Serverless Applications: Containerize and orchestrate functions using OpenFaas, OpenWhisk, and Fn](https://books.google.com.tw/books?id=_d5YDwAAQBAJ&pg=PA120&lpg=PA120&dq=openwhisk+apigateway+redis&source=bl&ots=nT2aTGxuu-&sig=ACfU3U0NiWTKbgNqf4hqsvrP4iN3e94Gig&hl=zh-TW&sa=X&ved=2ahUKEwjuxYLdtPboAhWIbN4KHTfHC8YQ6AEwBHoECAsQPw#v=onepage&q=openwhisk%20apigateway%20redis&f=false)。檢自 Google 圖書 (2020-11-16)。 ## 更新紀錄 :::spoiler 最後更新日期:2020-11-17 - 2020-11-17 完稿 - 2020-09-29 起稿 ::: <br><br> > **本文作者**: 辛西亞.Cynthia > **本文連結**: [辛西亞的技能樹](https://cynthiachuang.github.io/Installation-and-Deployment-Notes-of-OpenWhisk-02/) / [hackmd 版本](https://hackmd.io/@CynthiaChuang/Installation-and-Deployment-Notes-of-OpenWhisk-02) > **版權聲明**: 部落格中所有文章,均採用 [姓名標示-非商業性-相同方式分享 4.0 國際](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en) (CC BY-NC-SA 4.0) 許可協議。轉載請標明作者、連結與出處!