1. 程式人生 > >學習 Kubernetes 原生 Serverless 無服務架構 Kubeless

學習 Kubernetes 原生 Serverless 無服務架構 Kubeless

目錄

1、Serverless & Kubeless 介紹

1.1、Serverless

Serverless AWS 官方對 Serverless 的介紹:伺服器架構是基於網際網路的系統,應用開發不使用常規的服務程序,而是依賴於第三方服務,客戶端邏輯和服務託管遠端過程呼叫的組合。簡單的講,Serverless 就是指應用的開發不再需要考慮伺服器的硬體基礎設施,而是依賴於第三提供的後端服務(Baas)和應用邏輯執行容器(FaaS),但是並不是意味著沒有伺服器,而是伺服器以特定功能的第三方服務的形式存在。

Serverless 帶來的好處:

  • 降低了硬體基礎設施的部署和維護成本
  • 方便應用服務的擴充套件和監控,因為依賴的第三方執行平臺基本都支援動態擴充套件和服務監控。
  • 降低了由於應用服務訪問流量變化而帶來的硬體資源的浪費。
  • 方便開發者專注應用的開發,更快速的釋出應用,而不需要關注基礎架構的問題。

1.2、Kubeless

Kubeless 是 Kubernetes 原生無伺服器架構,目的是為了方便部署少量程式碼而不需要擔心底層基礎設施,它利用 Kubernetes 資源來提供自動縮放、API 路由、監控、故障排查等功能。Kubeless 利用 Kubernetes CRD (Custom Resource Definition)

來建立 functions 作為自定義 Kubernetes 資源型別,然後,執行一個叢集控制器來監視這些自定義資源並按需啟動執行,叢集控制器動態得將函式程式碼注入到執行環境中,並通過 Http 或者 PubSub 機制使其可以被呼叫。

Kubeless 是利用 CRD 自定義資源型別來實現其整個流程,上一篇文章 Kubernetes CRD (CustomResourceDefinition) 自定義資源型別 中我對 Kubernetes CRD 的工作原理和原始碼做了簡要的分析,可以先參考下該文章對其大概瞭解一下。

2、環境、軟體準備

本次演示環境,我是在本機 MAC OS 上操作,以下是安裝的軟體及版本:

  • Docker: 17.09.0-ce
  • Oracle VirtualBox: 5.1.20 r114628 (Qt5.6.2)
  • Minikube: v0.28.2
  • Kubernetes: v1.10.0
  • Kubeless: v1.0.0-alpha.8
  • Kubectl:
    • Client Version: v1.11.1
    • Server Version: v1.10.0

注意:這裡 Kubernetes 叢集搭建使用 Minikube 來完成,Minikube 啟動的單節點 k8s Node 例項是需要執行在本機的 VM 虛擬機器裡面,所以需要提前安裝好 VM,這裡我選擇 Oracle VirtualBox。k8s 執行底層使用 Docker 容器,所以本機需要安裝好 Docker 環境,這裡忽略 Docker、VirtualBox、Minikube、Kubectl 的安裝過程,可以參考之前文章 Minikube & kubectl 升級並配置, 這裡著重介紹下 Kubeless 安裝與部署。

3、kubeless cli 安裝

首先,我們需要下載一個類似 kubectl 工具的 kubeless cli 命令列客戶端,用來執行 kubeless 相關命令操作,可以從這裡 Github kubeless release page 選擇系統對應的版本安裝包,這裡我選擇 kubeless_darwin-amd64.zip 版本即可(這裡可以使用官網提供的適配指令碼,下載系統對應的安裝包)。

$ export RELEASE=$(curl -s https://api.github.com/repos/kubeless/kubeless/releases/latest | grep tag_name | cut -d '"' -f 4)
$ export OS=$(uname -s| tr '[:upper:]' '[:lower:]')
$ curl -OL https://github.com/kubeless/kubeless/releases/download/$RELEASE/kubeless_$OS-amd64.zip && \
  unzip kubeless_$OS-amd64.zip && \
  sudo mv bundles/kubeless_$OS-amd64/kubeless /usr/local/bin/

安裝完畢,通過 kubeless -h 檢視該工具相關命令列引數說明。

$ kubeless -h
Serverless framework for Kubernetes

Usage:
  kubeless [command]

Available Commands:
  autoscale         manage autoscale to function on Kubeless
  completion        Output shell completion code for the specified shell.
  function          function specific operations
  get-server-config Print the current configuration of the controller
  help              Help about any command
  topic             manage message topics in Kubeless
  trigger           trigger specific operations
  version           Print the version of Kubeless

Flags:
  -h, --help   help for kubeless

Use "kubeless [command] --help" for more information about a command.

4、kubeless 部署

接下來,我們就可以部署 kubeless 了,首先可以建立一個新的 Namespace 來區分(預設 default),然後下載 kubeless yaml 檔案執行部署。這裡官網提供了三種方式的 yaml 部署檔案:

  • kubeless-$RELEASE.yaml:適用開啟 RBAC 認證的 Kubernetes 叢集
  • kubeless-non-rbac-$RELEASE.yaml:適用未開啟 RBAC 認證的 Kubernetes 叢集
  • kubeless-openshift-$RELEASE.yaml:適用部署 kubeless 到 openshift(1.5+)

因為我們使用的 Minikube 對應的 Kubernetes 版本開啟了 RBAC 認證,所以可以使用如下命令部署:

$ export RELEASE=$(curl -s https://api.github.com/repos/kubeless/kubeless/releases/latest | grep tag_name | cut -d '"' -f 4)
$ kubectl create ns kubeless
$ kubectl create -f https://github.com/kubeless/kubeless/releases/download/$RELEASE/kubeless-$RELEASE.yaml

$ kubectl get all -n kubeless
NAME                                               READY     STATUS    RESTARTS   AGE
pod/kubeless-controller-manager-5d7894857d-h4hr9   3/3       Running   0          1d

NAME                                          DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/kubeless-controller-manager   1         1         1            1           1d

NAME                                                     DESIRED   CURRENT   READY     AGE
replicaset.apps/kubeless-controller-manager-5d7894857d   1         1         1         1d

$ kubectl get crd
NAME                                    CREATED AT
cronjobtriggers.kubeless.io             2018-08-22T09:01:59Z
functions.kubeless.io                   2018-08-22T09:01:59Z
httptriggers.kubeless.io                2018-08-22T09:01:59Z

可以看到,部署完 kubeless 之後,預設建立了三個 CRD 資源型別,該服務依賴映象有三個:
kubeless/function-controller:v1.0.0-alpha.8 bitnami/http-trigger-controller:v1.0.0-alpha.9 bitnami/cronjob-trigger-controller:v1.0.0-alpha.9 還好,這次終於不需要翻牆啦!

接下來,我們來演示一下如何使用 kubeless 建立一個簡單的 function。

首先建立一個 Python 檔案 hello.py。

def hello(event, context):
  print event
  return event['data']

說明一下:

  • event 第一個引數,該引數包含關於事件源的所有資訊,下邊 event['data'] 中 key data 需要包含該方法請求的 body 體。
  • context 第二個引數,該引數包含該 function 的基本資訊。
  • 最後返回一個字串或 Object 物件給呼叫方。

接下來,通過 kubeless 部署該 function。

$ kubeless function deploy hello --runtime python2.7 --handler test.hello --from-file hello.py  -n kubeless
INFO[0000] Deploying function...
INFO[0000] Function hello submitted for deployment
INFO[0000] Check the deployment status executing 'kubeless function ls hello'

說明一下引數:

  • hello:這個是定義的要部署的 function 的名稱
  • --runtime python2.7:這個是執行該 function 的執行環境,因為我們要執行的是 python 檔案,所以得指定 python 執行環境,該版本 kubeless 預設支援的執行環境有:python2.7, python3.4, python3.6, nodejs6, nodejs8, nodejs_distroless8, ruby2.4, php7.2, go1.10, dotnetcore2.0, java1.8, ballerina0.981.0, jvm1.8,通過 kubeless get-server-config 可以檢視支援列表。
  • --handler test.hello:這個是用來接收請求時指定檔案暴漏的 function。例如,這裡我們指定了暴漏 test.py 檔案中的 hello 方法,當檔案有多個 function 時,指定要暴漏的那個即可。
  • --from-file hello.py:這個是指定包含 function 的檔案路徑,它也支援 zip 型別的檔案。

當然,它還支援其他很多引數,例如 --dependencies--label--port--schedule--secrets等等一系列引數,具體可以參考命令 kubeless function deploy --help

OK 稍等片刻,就部署好了,此時,我們通過 kubectl 命令檢視本次部署都部署了那些東西。

$ kubectl get all -n kubeless
NAME                                               READY     STATUS    RESTARTS   AGE
pod/hello-6f666c5bd-wmntj                          1/1       Running   0          1d
pod/kubeless-controller-manager-5d7894857d-h4hr9   3/3       Running   0          1d

NAME                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
service/hello           ClusterIP   10.102.190.186   <none>        8080/TCP         1d

NAME                                          DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/hello                         1         1         1            1           1d
deployment.apps/kubeless-controller-manager   1         1         1            1           1d

NAME                                                     DESIRED   CURRENT   READY     AGE
replicaset.apps/hello-6f666c5bd                          1         1         1         1d
replicaset.apps/kubeless-controller-manager-5d7894857d   1         1         1         1d

$ kubectl get functions -n kubeless
NAME            CREATED AT
hello           1d

可以看到,執行一次部署 function,後端 Kubernetes 中啟動了 replicasetdeploymentservicepodfunction 幾種資源,這裡就不詳細分析其執行過程了,下邊我會拿一個 java demo 分析一下其執行過程。通過 kubeless function ls hello 命令可以檢視該 function 的一些基本資訊,以及是否啟動成功。

$ kubeless function ls hello -n kubeless
NAME    NAMESPACE   HANDLER     RUNTIME     DEPENDENCIES    STATUS
hello   kubeless    test.hello  python2.7                   1/1 READY

最後,我們來直接呼叫該 hello function 試試看,看能否調通吧!

$ kubeless function call hello --data 'This is first time call this function.'
This is first time call this function.

可以得到預期返回結果,確實很方便呵。但是這種呼叫方式,並不能滿足我們日常需求,我們需要的是能夠通過 http 方式呼叫該方法,那有什麼辦法呢?這個方法有很多種。kubeless 提供了很多種方案供我們選擇,詳細參考文件 Expose and secure Kubeless functions 這裡,裡面介紹了使用 Kubernetes Ingress 方式暴漏該服務,通過部署一種型別的 Ingress,然後配合使用 kubeless trigger http 命令,自動建立 Router 規則,從而實現該服務暴漏外部訪問。

當然,本次測試我們可以簡單的使用 kubectl proxy 代理 APIserver URL 方式來訪問。

$ kubectl proxy -p 8080
$ curl -L --data 'Hello kubeless!' 127.0.0.1:8080/api/v1/namespaces/kubeless/services/hello:8080/proxy/
Hello kubeless!

這裡提一下,上邊 URL 地址中,kubeless 這個要指定對應的 Namespaces,hello:8080 這個要符合 <function-name>:<http-function-port> 方式,這裡因為我們部署時未指定 port,那麼就取預設埠號 8080

最後,如果想刪除該 function,可以使用命令如下:

$ kubeless function delete hello

5、kubeless java function 演示

下邊,我們新建一個 Java 型別程式碼,通過指定該執行環境為 java1.8,來看下通過 kubeless 部署一個此型別 function,底層容器到底執行了那些操作吧。

首先,新建一個簡單的 Java 檔案 HelloGet.java ,僅僅返回 Hello world! This is kubeless demo. 即可。

package io.kubeless;

import io.kubeless.Event;
import io.kubeless.Context;

public class Foo {
    public String foo(io.kubeless.Event event, io.kubeless.Context context) {
        return "Hello world! This is kubeless demo.";
    }
}

然後,部署該 function 並命名為 get-java

$ kubeless function deploy get-java --runtime java1.8 --handler Foo.foo --from-file HelloGet.java -n kubeless

部署完畢後,稍等片刻,如果正常的話,就會成功部署,通過 kubeless 命令檢視下。

$ kubeless function ls -n kubeless
NAME        NAMESPACE   HANDLER     RUNTIME     DEPENDENCIES    STATUS
get-java    kubeless    Foo.foo     java1.8                     1/1 READY
hello       kubeless    test.hello  python2.7                   1/1 READY

$ kubectl get functions  -n kubeless
NAME       CREATED AT
get-java   4m
hello      17h

接下來,呼叫一下該 function,看是否能夠成功返回。

$ kubeless function call get-java -n kubeless
Hello world! This is kubeless demo.

呼叫成功,說明部署沒有問題,通過 kubectl 命令檢視部署了那些資源。

$ kubectl get all -n kubeless
NAME                                               READY     STATUS    RESTARTS   AGE
pod/get-java-5ff45cd65d-2frkx                      1/1       Running   0          29m
pod/hello-6f666c5bd-wmntj                          1/1       Running   0          17h
pod/kubeless-controller-manager-5d7894857d-h4hr9   3/3       Running   0          18h

NAME               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/get-java   ClusterIP   10.110.56.131    <none>        8080/TCP   29m
service/hello      ClusterIP   10.102.190.186   <none>        8080/TCP   17h

NAME                                          DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/get-java                      1         1         1            1           29m
deployment.apps/hello                         1         1         1            1           17h
deployment.apps/kubeless-controller-manager   1         1         1            1           18h

NAME                                                     DESIRED   CURRENT   READY     AGE
replicaset.apps/get-java-5ff45cd65d                      1         1         1         29m
replicaset.apps/hello-6f666c5bd                          1         1         1         17h
replicaset.apps/kubeless-controller-manager-5d7894857d   1         1         1         18h

這裡,想必瞭解 K8s 的大家都知道 replicasetdeploymentservicepod這幾個資源型別都分別起什麼作用,這裡不再贅述了。接下來,咱們看下 pod/get-java-5ff45cd65d-2frkx 該 Pod 針對我們提供的 HelloGet.javajava1.8 執行環境,內部到底是如何處理的呢?

$ kubectl describe pod/get-java-5ff45cd65d-2frkx -n kubeless

Name:           get-java-5ff45cd65d-2frkx
Namespace:      kubeless
......
Init Containers:
  prepare:
    Container ID:  docker://bffe706d1f0c8e8f4ed0659bc5a46c2624512d7b51a1923cef3787a108c782f6
    Image:         kubeless/[email protected]:f162c062973cca05459834de6ed14c039d45df8cdb76097f50b028a1621b3697
    Image ID:      docker-pullable://kubeless/[email protected]:f162c062973cca05459834de6ed14c039d45df8cdb76097f50b028a1621b3697
    Port:          <none>
    Host Port:     <none>
    Command:
      sh
      -c
    Args:
      echo 'e5e99052dd50822d654c935dd2f5c893cf4062bfd304d7245503366c83cba93a  /src/Foo.java' > /tmp/func.sha256 && sha256sum -c /tmp/func.sha256 && cp /src/Foo.java /kubeless/Foo.java && cp /src/pom.xml /kubeless
    State:          Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Thu, 23 Aug 2018 10:36:38 +0800
      Finished:     Thu, 23 Aug 2018 10:36:38 +0800
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /kubeless from get-java (rw)
      /src from get-java-deps (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-5qprx (ro)
  compile:
    Container ID:  docker://e4bb9e2acbb35b014236e8242ee867acf8b668020cb9638d421587061f1cfa44
    Image:         kubeless/[email protected]:7e5e4376d3ab76c336d4830c9ed1b7f9407415feca49b8c2bf013e279256878f
    Image ID:      docker-pullable://kubeless/[email protected]:7e5e4376d3ab76c336d4830c9ed1b7f9407415feca49b8c2bf013e279256878f
    Port:          <none>
    Host Port:     <none>
    Command:
      sh
      -c
    Args:
      cp -r /usr/src/myapp/* /kubeless/ && cp /kubeless/*.java /kubeless/function/src/main/java/io/kubeless/ && cp /kubeless/function-pom.xml /kubeless/function/pom.xml 2>/dev/null || true && mvn package > /dev/termination-log 2>&1 && mvn install > /dev/termination-log 2>&1
    State:      Terminated
      Reason:   Completed
      Message:  dependent!

[INFO] skip non existing resourceDirectory /kubeless/function/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ function ---
......
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] kubeless ........................................... SUCCESS [02:05 min]
[INFO] params ............................................. SUCCESS [  0.499 s]
[INFO] function ........................................... SUCCESS [  0.031 s]
[INFO] handler ............................................ SUCCESS [  0.037 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 02:05 min
[INFO] Finished at: 2018-08-23T02:41:51Z
[INFO] Final Memory: 18M/192M
[INFO] ------------------------------------------------------------------------

      Exit Code:    0
      Started:      Thu, 23 Aug 2018 10:36:39 +0800
      Finished:     Thu, 23 Aug 2018 10:41:51 +0800
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /kubeless from get-java (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-5qprx (ro)
Containers:
  get-java:
    Container ID:   docker://0d1f5cfca8e3d7479ee48e938ca743563fca84221f71194bc460469b584b8ec5
    Image:          kubeless/[email protected]:debf9502545f4c0e955eb60fabb45748c5d98ed9365c4a508c07f38fc7fefaac
    Image ID:       docker-pullable://kubeless/[email protected]:debf9502545f4c0e955eb60fabb45748c5d98ed9365c4a508c07f38fc7fefaac
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Thu, 23 Aug 2018 10:41:54 +0800
    Ready:          True
    Restart Count:  0
    Liveness:       http-get http://:8080/healthz delay=3s timeout=1s period=30s #success=1 #failure=3
    Environment:
      FUNC_HANDLER:       foo
      MOD_NAME:           Foo
      FUNC_TIMEOUT:       180
      FUNC_RUNTIME:       java1.8
      FUNC_MEMORY_LIMIT:  0
      FUNC_PORT:          8080
    Mounts:
      /kubeless from get-java (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-5qprx (ro)
......
Events:
  Type    Reason                 Age   From               Message
  ----    ------                 ----  ----               -------
  Normal  Scheduled              30m   default-scheduler  Successfully assigned get-java-5ff45cd65d-2frkx to minikube
  Normal  SuccessfulMountVolume  30m   kubelet, minikube  MountVolume.SetUp succeeded for volume "get-java"
  Normal  SuccessfulMountVolume  30m   kubelet, minikube  MountVolume.SetUp succeeded for volume "get-java-deps"
  Normal  SuccessfulMountVolume  30m   kubelet, minikube  MountVolume.SetUp succeeded for volume "default-token-5qprx"
  Normal  Pulled                 30m   kubelet, minikube  Container image "kubeless/[email protected]:f162c062973cca05459834de6ed14c039d45df8cdb76097f50b028a1621b3697" already present on machine
  Normal  Created                30m   kubelet, minikube  Created container
  Normal  Started                30m   kubelet, minikube  Started container
  Normal  Pulled                 30m   kubelet, minikube  Container image "kubeless/[email protected]:7e5e4376d3ab76c336d4830c9ed1b7f9407415feca49b8c2bf013e279256878f" already present on machine
  Normal  Created                30m   kubelet, minikube  Created container
  Normal  Started                30m   kubelet, minikube  Started container
  Normal  Pulling                25m   kubelet, minikube  pulling image "kubeless/[email protected]:debf9502545f4c0e955eb60fabb45748c5d98ed9365c4a508c07f38fc7fefaac"
  Normal  Pulled                 25m   kubelet, minikube  Successfully pulled image "kubeless/[email protected]:debf9502545f4c0e955eb60fabb45748c5d98ed9365c4a508c07f38fc7fefaac"
  Normal  Created                25m   kubelet, minikube  Created container
  Normal  Started                25m   kubelet, minikube  Started container

從日誌輸出,我們可以看到,該 Pod 先後依賴了三個映象:kubeless/unzipkubeless/java-initkubeless/java, 這三個映象又分別幹了些什麼工作呢?

首先看下 kubeless/unzip 映象,它主要作用是將我們的原始檔掛載到容器指定位置,看啟動命令裡面主要乾了兩件事:一是 sha256 校驗檔案一致性,二是複製原始檔以及 pom.xml 到指定目錄。

echo 'e5e99052dd50822d654c935dd2f5c893cf4062bfd304d7245503366c83cba93a  /src/Foo.java' > /tmp/func.sha256 && sha256sum -c /tmp/func.sha256 && cp /src/Foo.java /kubeless/Foo.java && cp /src/pom.xml /kubeless

然後看下 kubeless/java-init 映象,主要執行一些初始化操作,看啟動命令主要乾了兩件事:一是複製指定檔案到指定目錄(這個指定的檔案下邊會講到),二是執行 mvn package & install 編譯操作。

cp -r /usr/src/myapp/* /kubeless/ && cp /kubeless/*.java /kubeless/function/src/main/java/io/kubeless/ && cp /kubeless/function-pom.xml /kubeless/function/pom.xml 2>/dev/null || true && mvn package > /dev/termination-log 2>&1 && mvn install > /dev/termination-log 2>&1

最後看下 kubeless/java 映象,雖然日誌上沒有顯示啟動命令,但是它非常關鍵,它的作用是在 Java 環境中啟動服務,呼叫我們指定的程式碼的類方法,來提供服務給外部呼叫。

我們進入到容器內部檢視下,具體該 function 執行的時候依賴了那些模組和 jar 包。

$ kubectl exec -it get-java-5ff45cd65d-2frkx -n kubeless /bin/sh

/ $ cd /kubeless/
/kubeless $ ls -alt
total 48
drwxr-xr-x    1 root     root          4096 Aug 23 02:41 ..
drwxrwsrwx    7 root     1000          4096 Aug 23 02:41 .
drwxr-sr-x    2 1000     1000          4096 Aug 23 02:41 lib
drwxr-xr-x    4 1000     1000          4096 Aug 23 02:39 handler
drwxr-xr-x    4 1000     1000          4096 Aug 23 02:39 function
drwxr-xr-x    4 1000     1000          4096 Aug 23 02:38 params
drwxr-sr-x    3 1000     1000          4096 Aug 23 02:36 ?
-rw-r--r--    1 1000     1000           202 Aug 23 02:36 Dockerfile
-rw-r--r--    1 1000     1000            79 Aug 23 02:36 Dockerfile.init
-rw-r--r--    1 1000     1000           303 Aug 23 02:36 Makefile
-rw-r--r--    1 1000     1000           876 Aug 23 02:36 pom.xml
-rw-r--r--    1 1000     1000           236 Aug 23 02:36 Foo.java

/kubeless 目錄為該 function 所在工作目錄,上邊提到複製指定檔案到指定目錄操作命令 cp -r /usr/src/myapp/* /kubeless/ && cp /kubeless/*.java /kubeless/function/src/main/java/io/kubeless/ && cp /kubeless/function-pom.xml /kubeless/function/pom.xml 這個,就是講映象中 /usr/src/myapp/ 目錄下的 handler、function、params 目錄複製到該目錄,同時將我們編寫的原始檔 Foo.java 複製到 function 目錄的指定位置以及將複製過來的 function-pom.xml 檔案複製到 function 根目錄去。那麼,這些操作主要是幹什麼用呢?我們可以從該目錄下 pom.xml 檔案以及 mvn package & install 日誌輸出可以得到答案。

/kubeless $ cat pom.xml
<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>io.kubeless</groupId>
    <artifactId>kubeless</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>kubeless</name>
    <url>http://maven.apache.org</url>
    <modules>
        <module>params</module>
        <module>function</module>
        <module>handler</module>
    </modules>
    <build>
    <plugins>
        <plugin>
        <artifactId>maven-dependency-plugin</artifactId>
        <executions>
            <execution>
            <phase>install</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <outputDirectory>/kubeless/lib</outputDirectory>
            </configuration>
            </execution>
        </executions>
        </plugin>
    </plugins>
    </build>
</project>

從該 pom 檔案中可以看到,該專案 io.kubeless.kubeless 專案下有三個子模組,就是上邊提到的複製過來的 params、function、handler 三個子專案。當執行 mvn install 時執行編譯,並將生成的 jar 包輸出到 /kubeless/lib 目錄去。我們在看下 function 模組下複製過去的 pom.xml 檔案。

$ cat function/pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <artifactId>function</artifactId>
  <name>function</name>
  <version>1.0-SNAPSHOT</version>
  <dependencies>
      <dependency>
          <groupId>io.kubeless</groupId>
          <artifactId>params</artifactId>
          <version>1.0-SNAPSHOT</version>
      </dependency>
  </dependencies>
  <parent>
    <groupId>io.kubeless</groupId>
    <artifactId>kubeless</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>
</project>

function 子模組是存放我們 Foo.java 檔案的模組,這也解釋了為什麼我們定義的 Foo.java 檔案 package 為 package io.kubeless; 開頭,因為 function 子模組的包定義結構就是如此:function/src/main/java/io/kubeless/Foo.java。從 pom 檔案中可以看到它繼承的父專案就是上邊的 io.kubeless.kubeless 同時依賴了 io.kubeless.params 子模組。

params 子模組比較簡單,裡面僅僅是兩個建構函式,也是我們 Foo.java 檔案中 import 的 Event 和 Context 所引入的類所在地方。

/kubeless $ cat params/src/main/java/io/kubeless/Context.java
package io.kubeless;

/**
 * Context includes information about the function environment
 */
public class Context {
    String functionName;
    String timeout;
    String runtime;
    String memoryLimit;

    public Context(String functionName, String timeout, String runtime, String memoryLimit) {
        this.functionName = functionName;
        this.timeout = timeout;
        this.runtime = runtime;
        this.memoryLimit = memoryLimit;
    }

/kubeless $ cat params/src/main/java/io/kubeless/Event.java  
public class Event {
    String Data;
    String EventID;
    String EventType;
    String EventTime;
    String EventNamespace;

    public Event(String data, String eventId, String eventType, String eventTime, String eventNamespace) {
        this.Data = data;
        this.EventID = eventId;
        this.EventType = eventType;
        this.EventTime = eventTime;
        this.EventNamespace = eventNamespace;
    }
}  

handler 子模組就厲害了,它是我們整個 function 執行提供外部呼叫並返回響應的控制的地方,它通過環境變數方式解析到我們部署 function 指定的 handler 類名方法名,以及 runtime、port 等引數,啟動一個 HttpServer 來提供兩個 context:一個為 /healthz 返回 200 狀態碼的 “OK” 字串給呼叫者,另一個為 / 它通過反射方式解析並呼叫我們 handler 定義的類名和方法名,並將方法執行結果返回給呼叫者。該子模組也繼承了 io.kubeless.kubeless 父專案,還依賴了 io.kubeless.paramsio.kubeless.function 模組,同時還依賴一些其他的 jar,例如 io.prometheus.simpleclientlog4j 等等。

/kubeless $ cat handler/src/main/java/io/kubeless/Handler.java
public class Handler {

    // 環境變數中取值,在部署時 Pod 中已經新增
    static String className   = System.getenv("MOD_NAME");
    static String methodName  = System.getenv("FUNC_HANDLER");
    static String timeout     = System.getenv("FUNC_TIMEOUT");
    static String runtime     = System.getenv("FUNC_RUNTIME");
    static String memoryLimit = System.getenv("FUNC_MEMORY_LIMIT");
    static Method method;
    static Object obj;
    
            
           

相關推薦

學習 Kubernetes 原生 Serverless 服務架構 Kubeless

目錄 1、Serverless & Kubeless 介紹 1.1、Serverless 1.2、Kubeless 2、環境、軟體準備 3、k

學習基於 KubernetesServerless 服務架構 Fission

目錄 1、Serverless & Fission 介紹 1.1、Serverless 1.2、Fission 2、環境、軟體準備

理解serverless服務架構原理(一)

閱讀目錄 一:什麼是serverless無服務? 二:與傳統模式架構區別? 三:serverless優缺點? 四:使用serverless的應用場景有哪些? 回到頂部 一:什麼是serverless無服務? serverless中文的含義是 "無伺服器",但是它真正的含義是開發者

Serverless服務應用架構縱橫談

https://www.cnblogs.com/windfic/p/7941998.html Serverless無服務應用架構縱橫談   一、Serverless是啥 自從網際網路興起以來,Server就成了網路的核心部件。所以圍繞Server的生意圈,也發展得如火如荼。

Serverless(伺服器架構)4大優點和缺點

Serverless核心概念在早期,術語無伺服器 是指依賴於第三方應用程式或服務來管理伺服器端邏輯的應用程式。 此類應用程式是基於雲的資料庫(如Google Firebase)或身份驗證服務(如Auth0或AWS Cognito)。 它們被稱為後端即服務(BaaS)服務。

91APP新零售平臺實踐分享:靠Kubernetes實現IT微服務架構_Kubernetes中文社群

儘管多數是.NET系統,91APP也積極擁抱輕量級容器技術,通過“鄉村包圍城市”的策略,新興系統先擁抱容器,下一步想轉型更高彈性的微服務架構,關鍵就是匯入Kubernetes來管理複雜的容器叢集 臺灣知名的新零售平臺供貨商91APP,已有超過1萬家品牌企業,通過91APP平臺經營電商生意。為了

AWS終於支援KubernetesServerless容器服務AWS Fargate同時釋出_Kubernetes中文社群

在之前文章 我們提到微軟、Google、IBM及甲骨文等主要雲服務廠商都支援Kubernetes,細心朋友會發現唯一少了AWS,幸運的是在本週(11/29)Amazon宣佈開始支援Kubernetes容器排程服務,推出 Amazon Elastic Container Service for

什麼是Serverless伺服器架構

Serverless不代表再也不需要伺服器了,而是說:開發者再也不用過多考慮伺服器的問題,計算資源作為服務而不是伺服器的概念出現。Serverless是一種構建和管理基於微服務架構的完整流程,允許你在服務部署級別而不是伺服器部署級別來管理你的應用部署,你甚至可以管理某個具

AWS終於支援KubernetesServerless容器服務AWS Fargate同時釋出

在之前文章 我們提到微軟、Google、IBM及甲骨文等主要雲服務廠商都支援Kubernetes,細心朋友會發現唯一少了AWS,幸運的是在本週(11/29)Amazon宣佈開始支援Kubernetes容器排程服務,推出 Amazon Elastic Container

原生伺服器架構是雲端計算的未來嗎?——雲端計算的演進

作為“十三五”重點規劃產業之一,雲端計算到底是什麼?又會怎樣發展?最近興起的雲原生(Cloud Native)和無伺服器架構(Serverless)又與雲端計算有什麼關係?本文將以雲端計算的發展為路線,為大家科普雲端計算的概念與現狀,無論讀者是開發、測試、抑或是產品、管理者都能在本文中有所收穫。 縱觀整個

Serverless伺服器架構詳解

> 本文對Serverless架構的基礎概念、具體產品、應用場景、工作原理進行詳細解析。 ## 基礎概念 **Serverless:** 無伺服器架構,即在無需管理伺服器等底層資源的情況下完成應用的開發和執行,是雲原生架構的核心組成部分。 通俗來說,如果將購買一臺物理伺服器比作**買車**,購

kubernetes學習記錄(5)——服務發現機制與Cluster DNS的安裝(CA認證版)

服務發現機制 Kubernetes提供了兩種發現Service的方法: 1.環境變數 當Pod執行的時候,Kubernetes會將之前存在的Service的資訊通過環境變數寫到Pod中。 這種方法要求Pod必須要在Service之後啟動。 在Ser

服務架構與實踐及雲原生等相關概念

定時 服務器端 body 內容 開放封閉原則 logs 方法 服務架構 binding 微服務架構與實踐 筆記:《微服務架構與實踐》 王磊 著 一 單塊架構   1 定義:對於這種功能集中、代碼和數據中心化、一個發布包、部署後運行在同一進程的應用程序,我們通常稱之為單塊架構

騰訊雲服務器雲函數架構精解

實時 可選 實的 適合 經驗 .com 核心 cloud 僅支持 歡迎大家前往騰訊雲技術社區,獲取更多騰訊海量技術實踐幹貨哦~ 分享人:陳傑,騰訊雲架構平臺部技術專家,10年雲計算經驗,現供職於騰訊架構平臺部,負責彈性計算及雲函數技術研發,致力於提供領先的基礎設施平臺以提

SpringCloud學習--微服務架構

registry org 什麽 moni ima red 都是 html 小團隊 目錄     微服務架構快速指南     SOA     Dubbo     Spring Cloud     Dubbo與SpringCloud對比 微服務(Microservi

5分鐘Serverless實踐 | 構建服務器圖片鑒黃Web應用

dem 結果 資源利用率 url 獲取 點擊 圖片 代碼包 image Serverless是什麽 Serverless中文譯為“無服務器”,最早可以追溯到2012年Ken Fromm發表的《Why The Future Of Software And Apps Is Se

5分鐘Serverless實踐 | 構建服務器的敏感詞過濾後端系統

trab 平臺 ase lac mps creat base pen 服務器架構 前言 在上一篇“5分鐘Serverless實踐”系列文章中,我們介紹了什麽是Serverless,以及如何構建一個無服務器的圖片鑒黃Web應用,本文將延續這個話題,以敏感詞過濾為例,介紹如何構

基於Spring Boot和Spring Cloud實現微服務架構學習

發的 附加 引入 所有應用 集中式 一個 操作 但是 onf Spring Cloud介紹 Spring Cloud是一個基於Spring Boot實現的雲應用開發工具,它為基於JVM的雲應用開發中的配置管理、服務發現、斷路器、智能路由、微代理、控制總線、全局鎖、決策競選、

基於Spring Boot和Spring Cloud實現微服務架構學習(四)

feign 方法調用 規則 實現 uri ati .com 阻止 無法 Spring Cloud介紹 Spring Cloud是一個基於Spring Boot實現的雲應用開發工具,它為基於JVM的雲應用開發中的配置管理、服務發現、斷路器、智能路由、微代理、控制總線、全局鎖、

Sprng Cloud學習筆記之單體架構和微服務架構

微服務架構 目前微服務是非常火的架構或者說概念,也是在構建大型網際網路專案時採用的架構方式。 單體架構 一個歸檔包(可以是JAR、WAR、EAR或其它歸檔格式)包含所有功能的應用程式,通常稱為單體應用。單體架構中,所有的業務模組都編寫在一個專案中,最終打成war包執行。 軟體設計