FaaSController
- A FaaSController is a business controller for handling Easegress and FaaS products integration purposes. It abstracts
FaasFunction
,FaaSStore
and,FaasProvider
. Currently, we only supportKnative
typeFaaSProvider
. TheFaaSFunction
describes the name, image URL, the resource, and autoscaling type of this FaaS function instance. TheFaaSStore
is covered by Easegress’ embed Etcd already. - FaaSController works closely with local
FaaSProvider
. Please make sure they are running in a communicable environment. Follow this knative doc to installKnative
[1]’s serving component in K8s. It’s better to have Easegress run in the same VM instances with K8s for saving communication costs.
Prerequisites
- K8s cluster : v1.23+
Knative
Serving : v1.3+ (with kourier type of network layer)
Configuration
Controller spec
One FaaSController will manage one shared HTTP traffic gate and multiple pipelines according to the functions it has.
The
httpserver
section in spec is the configuration for the shared HTTP traffic gate.The
Knative
section is forKnative
type ofFaaSProvider
. Depending your Kubernetes cluster, you can use either Magic DNS or Temporary DNS, see here. Here’s how you fill theKnative
section for each one of them:- Temporary DNS: The value of
networkLayerURL
can be found using the following command
$ kubectl get svc -n kourier-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kourier LoadBalancer 10.109.159.129 <pending> 80:31731/TCP,443:30571/TCP 250dk
The
CLUSTER-IP
with value10.109.159.129
is your kourier’s K8s service’s address. Use it as the value fornetworkLayerURL
in the YAML below.hostSuffix
’s value should beexample.com
[2], like described inKnative
serving’sTemporary DNS
.
- Temporary DNS: The value of
Magic DNS: For
networkLayerURL
, use theEXTERNAL-IP
of the loadbalancer:$ kubectl get svc -n kourier-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kourier LoadBalancer 1.2.3.4 some-external-ip-of-my-cloud-provider.com 80:31060/TCP,443:30384/TCP 12m
- For
hostSuffix
, usekn service list
to see the suffix of your functions: For urlhttp://demo.default.4.5.6.7.sslip.io
thehostSuffix
is4.5.6.7.sslip.io
(basically the IPx.x.x.x
+sslip.io
). Note: If you don’t have any functions yet deployed, you first use any value forhostSuffix
(for exampleexample.com
), then deploy a function and usekn service list
to find out the value ofhostSuffix
. Update it to your configuration and re-create FaaSController.
- For
name: faascontroller
kind: FaaSController
provider: knative # FaaS provider kind, currently we only support Knative
syncInterval: 10s
httpServer:
http3: false
port: 10083
keepAlive: true
keepAliveTimeout: 60s
https: false
certBase64:
keyBase64:
maxConnections: 10240
knative:
networkLayerURL: http://{knative_kourier_clusterIP} # or http://{knative_kourier_externalIP}
hostSuffix: example.com # or x.x.x.x.sslip.com for Magic DNS
FaaSFunction spec
- The FaaSFunction spec including
name
,image
, and other resource-related configurations. - The
image
is the HTTP microservice’s image URL. When upgrading the FaaSfFunction’s business logic. this field can be helpful. - The
resource
andautoscaling
fields are similar to K8s orKnative
’s resource management configuration.[3] - The
requestAdaptor
is for customizing the way how HTTP request content will be routed toKnative
’skourier
gateway.
name: "demo10"
image: "dev.local/colordeploy:17.0"
port: 8089
autoScaleType: "rps"
autoScaleValue: "111"
minReplica: 1
maxReplica: 3
limitCPU: "180m"
limitMemory: "100Mi"
requestCPU: "80m"
requestMemory: "20Mi"
requestAdaptor:
header:
set:
X-Func1: func-demo-10 # add one HTTP header
Lifecycle
There four types of function state: Initial, Active, InActive, and Failed[4]. Basically, they come from AWS Lambda’s status.
Initial
: Once the function has been created in Easegress, its original state isinitial
. After checking FaaSProvider(Knative)’s status successfully, it will becomeactive
automatically. And the function is ready for handling traffic.Active
: Easegress’s FaaSFunction will beactive
not matter there are requests or not. Easegress will only route ingress traffic to FaaSProvider when the function is in theactive
state.Inactive
: Stopping function execution by calling FaaSController’sstop
RESTful API and it will run intoinactive
. Updating function’s spec for image URL or other fields, or deleting function also need to stop it first.Failed
: The function will be turned intofailed
states during the runtime checking. If it’s about some configuration error, e.g., wrong docker image URL, we can detect this failure by function’sstatus
message and then update the function’s spec by calling RESTful API. If it’s about some temporal failure caused by FaaSProvider, the function will turn into theinitial
state after FaaSProvider is recovered.
Provision
│
│
│
┌─────▼──────┐ Start ┌────────────┐
│ │ Success │ │
┌────────┤ Initial ├────────────────► Active │
│ │ │ │ ├──────┐
│ └───┬───▲────┘ └────┬───▲───┘ │
│ │ │ │ │ │
│ │ │ │ │ │
│ Errors│ │ Update Stop │ │ Start │
│ │ ├───────────┐ │ │Success │
│ │ │ │ │ │ │
│ ┌───▼───┴────┐ │ ┌────▼───┴───┐ │
│ │ │ └─────────┤ │ │
Delete │ │ Failed │ │ Inactive │ │
│ │ ◄────────────────┤ │ │
│ └───┬───▲────┘ Start Failed └──────┬─────┘ │
│ │ │ │ │
│ │ │ Errors │ │
│ Delete │ └────────────────────────────┼────────────┘
│ │ │
│ │ │
│ ┌───▼────────┐ │
│ │ │ Delete │
└────────► Destory ◄───────────────────────┘
│ │
└────────────┘
Original State | Event | New State |
---|---|---|
initial | Checking the status in FaaSProvider by FaaSController automatically, and it’s ready | active |
initial | Checking the status in FaaSProvider by FaaSController automatically, and it’s has some faults | failed |
initial | Checking the status in FaaSProvider by FaaSController automatically, and it’s waiting on all resources to become ready | initial |
initial | Deleting the function by RESTful API | destroyed |
active | Checking the status of instance in FaaSProvider by FaaSController automatically, and it has some faults | failed |
active | Checking the status of instance in FaaSProvider by FaaSController automatically, and for something reason, some resources are missing or pending | failed |
active | Stoping the function by RESTful API | inactive |
active | Checking the status of instance in FaaSProvider by FaaSController automatically, and it’s healthy | active |
inactive | Updating the function by RESTful API | initial |
inactive | Deleting the function by RESTful API | destroyed |
inactive | Staring the function by RESTful API and after successfully checking the status in FaaSProvider by FaaSController automatically | active |
inactive | Staring the function by RESTful API but failing at checking status in FaaSProvider by FaaSController automatically | failed |
inactive | Staring the function by RESTful API, Checking the status of instance in FaaSProvider by FaaSController automatically, and for something reason, some resources are missing or pending | failed |
failed | Updating the function by RESTful API | initial |
failed | Deleting the function by RESTful API | destroyed |
failed | Checking the status in FaaSProvider by FaaSController automatically, and it’s ready again | initial |
failed | Checking the status of instance in FaaSProvider by FaaSController automatically, and for something reason, some resources are missing or pending | failed |
failed | Checking the status in FaaSProvider by FaaSController automatically, and it has some faults | failed |
RESTful APIs
The RESTful API path obey this design http://host/{version}/{namespace}/{scope}(optional)/{resource}/{action}
,
Operation | URL | Method | Body | Description |
---|---|---|---|---|
Create a function | http://eg-host/apis/v2/faas/{controller_name} | POST | function spec | When there is not such a function in Easegress |
Start a function | http://eg-host/apis/v2/faas/{controller_name}/{function_name}/start | PUT | empty | When function is in inactive state only, it will turn-on accepting traffic for this function |
Stop a function | http://eg-host/apis/v2/faas/{controller_name}/demo1/stop | PUT | empty | When function is in active state only, it will turn-off accpeting traffic for this function |
Update a function | http://eg-host/apis/v2/faas/{controller_name}/{function_name} | PUT | function spec | When function is in initial , inactive or failed state. It can used to update your function or fix your function’s deployment problem. |
Delete a function | http://eg-host/apis/v2/faas/{controller_name}/{function_name} | DELETE | empty | When function is in initial , inactive or failed states. |
Get a function | http://eg-host/apis/v2/faas/{controller_name}/{function_name} | GET | empty | No timing limitation. |
Get function list | http://eg-host/apis/v2/faas/{controller_name} | GET | empty | No timing limitation. |
Demoing
- Creating the FaasController in Easegress
$ cd ./easegress/example/primary-001 && ./start.sh
$ ./egctl.sh create -f ./faascontroller.yaml
$ ./egctl.sh get faas faascontroller
name: faascontroller
kind: FaaSController
provider: knative # FaaS provider kind, currently we only support Knative
syncInterval: 10s
httpServer:
http3: false
port: 10083
keepAlive: true
keepAliveTimeout: 60s
https: false
certBase64:
keyBase64:
maxConnections: 10240
knative:
networkLayerURL: http://10.109.159.129
hostSuffix: example.com
- Creating the function
$ curl --data-binary @./function.yaml -X POST -H 'Content-Type: text/vnd.yaml' http://127.0.0.1:12381/apis/v2/faas/faascontroller
- Waiting for the function provisioned successfully. Confirmed by using
Get
API for checking thestate
field
$ curl http://127.0.0.1:12381/apis/v2/faas/faascontroller/demo10
spec:
name: demo10
image: dev.local/colordeploy:17.0
port: 8089
autoScaleType: rps
autoScaleValue: "111"
minReplica: 1
maxReplica: 3
limitCPU: 180m
limitMemory: 100Mi
requestCPU: 80m
requestMemory: 20Mi
requestAdaptor:
host: ""
method: ""
header:
del: []
set:
X-Func: func-demo
X-Func1: func-demo-10
add: {}
body: ""
status:
name: demo10
state: active
event: ready
extData: {}
fsm: null
- Visiting function by HTTP traffic gate with
X-FaaS-Func-Name: demo10
in HTTP header.
$ curl http://127.0.0.1:10083/tomcat/job/api -H "X-FaaS-Func-Name: demo10" -X POST -d ‘{"megaease":"Hello Easegress+Knative"}’
V3 Body is
‘{megaease:Hello Easegress+Knative}’%
$ curl http://127.0.0.1:10083/tomcat/job/api -H "X-FaaS-Func-Name: demo10" -X POST -d ‘{"FaaS":"Cool"}’
V3 Body is
‘{FaaS:Cool}’%
The function’s API is serving in /tomcat/job/api
path and its logic is displaying “V3 body is” with the contents u post.
Reference
- knative website http://knative.dev
- Install knative serving via YAML https://knative.dev/docs/install/yaml-install/serving/install-serving-with-yaml/
- resource quota https://kubernetes.io/docs/concepts/policy/resource-quotas/
- AWS Lambda state https://aws.amazon.com/blogs/compute/tracking-the-state-of-lambda-functions/