Our own, Mateusz Szostok has two sessions at KubeCon around K8s Service CatalogRead more

Mateusz Szostok, Piotr Kopczynski and Pawel Kosiec have several talks at San Diego Cloud Native MeetupRead more

Serverless

Overview

The term "serverless" refers to the Internet-based architecture. Application development that uses serverless technology relies solely on a combination of cloud-based, third-party services, client-side logic, and service-hosted remote procedure calls, also known as Functions as a Service (FaaS). Developers create this combination using lambda functions which connect third-party services and Kyma,replacing the common use of a server.

Using the serverless approach reduces the implementation and operation effort to the absolute minimum.

The serverless implementation of Kyma is based on Kubeless.

Architecture

The following diagram illustrates a generic serverless implementation.

General serverless architecture

The application flow takes place on the client side. Third parties handle the infrastructural logic. Custom logic can process updates and encapsulate databases. Authentication is an example of custom logic. Third parties can also handle business logic. A hosted database contains read-only data that the client reads. None of this functionality runs on a single, central server. Instead, the client relies on FaaS as its resource.

The following diagram shows an example of tasks that lambdas can perform in Kyma after a user invokes them.

Lambdas in Kyma

First, the user invokes the exposed lambda endpoint. Then, the lambda function can carry out a number of tasks, such as:

  • Retrieving cart information from Enterprise Commerce
  • Retrieving stock details
  • Updating a database

Open source components

Kyma is comprised of several open source technologies to provide extensive functionality.

Kubeless

Kubeless is the serverless framework integrated into Kyma that allows you to deploy lambda functions. These functions run in Pods inside the Kubeless controller on a node, which can be a virtual or hardware machine.

Kubeless also has a command line interface. Use Node.js to create lambda functions.

Istio

Istio is a third-party component that makes it possible to expose and consume services in Kyma. See the Istio documentation to learn more. Istio helps create a network of deployed services, called a service mesh.

In Kyma, functions run in Pods. Istio provides a proxy for specified pods that talk to a pilot. The pilot confirms whether access to the pod is permissible as per the request. In the diagram, Pod B requests access to Pod A. Pod A has an Istio proxy that contains a set of instructions on which services can access Pod A. The Istio proxy also notifies Pod A as to whether Pod B is a part of the service mesh. The Istio Proxy gets all of its information from the Pilot.

Istio architecture

NATS

The Event Bus in Kyma monitors business events and trigger functions based on those events. At the heart of the Event Bus is NATS, an open source, stand-alone messaging system. To learn more about NATS, visit the NATS website.

The following diagram demonstrates the Event Bus architecture.

Event Bus architecture

The Event Bus exposes an HTTP endpoint that the system can consume. An external event, such as a subscription, triggers the Event Bus. A lambda function works with a push notification, and the subscription handling of the Event Bus processes the notification.

Knative

Knative is a platform which manages serverless workloads inside Kubernetes environments. Due to its high versatility, Knative can manage the whole lifecycle of a lambda function, from building the source code to serving it.

Kyma bridges the gap between developers and Knative using its own Function Controller which uses the Function custom resource to facilitate the deployment of lambda functions.

For details, see the Knative project documentation.

Details

Kubeless Custom Resources

Kubeless uses Custom Resource Definitions (CRD) to:

  • Define the information required for the configuration of custom resources
  • Create functions
  • Create objects

The Function CRD ships by default with Kubeless.

See the content of the kubeless-crd.yaml file:

Click to copy
apiVersion: apiextensions.k8s.io/v1beta1
description: Kubernetes Native Serverless Framework
kind: CustomResourceDefinition
metadata:
name: {{ .Values.function.customResourceDefinition.metadata.name | quote }}
labels:
{{ include "labels.standard" . | indent 4 }}
spec:
group: {{ .Values.function.customResourceDefinition.spec.group | quote }}
names:
kind: {{ .Values.function.customResourceDefinition.names.kind | quote }}
plural: {{ .Values.function.customResourceDefinition.names.plural | quote }}
singular: {{ .Values.function.customResourceDefinition.names.singular | quote }}
scope: Namespaced
version: v1beta1

Use the .yaml file to create the custom resource using the following command:

Click to copy
kubectl create -f <filename>

Kubeless creates a new namespaced endpoint that you can use to create and manage custom objects. Learn how to use CRDs to create objects in the Kubeless documentation on the Kubeless website.

Lambda functions

Lambda functions best serve integration purposes due to their ease of use. Lambda is a quick solution when the goal is to combine functionalities which are tightly coupled. In Kyma, lambdas run in a cost-efficient and scalable way using JavaScript in Node.js.

This is an example lambda function:

Click to copy
def myfunction (event, context):
print event
return event['data']

In Kyma, you can address the following scenarios:

  • Create and manage lambda functions.
  • Trigger functions based on business Events.
  • Expose functions through HTTP.
  • Consume services.
  • Provide customers with customized features.
  • Version lambda functions.
  • Chain multiple functions.

Kubernetes provides Kyma with labels that allow you to arrange lambda functions and group them. Labeling also makes it possible to filter lambdas functions. This functionality is particularly useful when a developer needs to manage a large set of lambda functions.

Behind the scenes, labeling takes place in the form of key-value pairs. Here is the example of code that enhances a function:

Click to copy
"labels": {
"key1" : "value1",
"key2" : "value2"
}

For more details on labels and selectors, visit the Kubernetes website.

The Node.js Runtime

Kyma supports Node.js 6 and 8. The function interface is the same for both versions. It is still best practice to start with Node.js 8, as it supports Promises out of the box. The result is less complicated code.

Please set the runtime version (Node.js 6 or 8) while creating a function.

In the next sections, we will describe how the system creates Node.js functions.

The Handler

The system uses module.exports to export Node.js handlers. A handler represents the function code executed during invocation. You have to define the handler using the command line. The Console UI only supports main as a handler name.

Click to copy
module.exports = { main: function (event, context) {
return
} }

Kyma supports two execution types: Request / Response (HTTP) and Events. In both types, a return identifies a successful execution of the function. For event types, the event is reinjected as long as the execution is not successful. Functions of the Request Response type can return data to the requesting entity. The following three options are available:

Return Content TypeHTTP StatusResponse
returnnone200 (OK)-
return "Hello World!"none200 (OK)Hello World!
return {foo: "BAR"}application/json200 (OK){"foo":"BAR"}

A failing function simply throws an error to tell the event service to reinject the event at a later point. An HTTP-based function returns an HTTP 500 status.

The Event Object and Context Object

The function retrieves two parameters: Event and Context.

Click to copy
event:
data: # Request body
foo: "bar" # The data is parsed as JSON when required
extensions: # Optional parameters
request: # Reference to the request received
query:
baz: "qux" # Query parameters
headers:
accept: "application/json" # Request headers
...
method: "POST" # HTTP method
...
response: ... # Reference to the response to send
# (specific properties will depend on the function language)
context:
function-name: "pubsub-nodejs"
timeout: "180"
runtime: "nodejs6"
memory-limit: "128M"

The Event contains the event payload as well as some request specific metadata. The request and response attributes are primarily responsible for providing control over http behavior.

Advanced Response Handling

To enable more advanced implementations, the system forwards Node.js Request and Response objects to the function. Access the objects using event.extensions.<request|response>.

In the example, a custom HTTP response is set.

Click to copy
module.exports = { main: function (event, context) {
console.log(event.extensions.request.originalUrl)
event.extensions.response.status(404).send("Arg....")
} }

The example code logs the original request url. The response is an HTTP 404. The body is Arg.....

Logging

Logging is based on standard Node.js functionality. console.log("Hello") sends "Hello" to the logs. As there is no graphical log tool available, use the command kubectl to display the logs.

Click to copy
kubectl logs -n {NAMESPACE} -l function=<function> -c {FUNCTION}

The logs for lambda Pods display the lambda code and the package.json file. In the code:

  • \n represents new line
  • \r represents Carriage return
  • \\ represents \

For example:

Click to copy
Lambda Code
module.exports = {\n main: function (event, context) {\n console.log("Hello World")\n\n} }
Lambda Code dependencies
{\n "end-of-stream": "^1.4.1",\n "from2": "^2.3.0",\n "lodash": "^4.17.5"\n}

Custom Resource

Function

The functions.serverless.kyma-project.io CustomResourceDefinition (CRD) is a detailed description of the kind of data and the format used to manage lambda functions within Kyma. To get the up-to-date CRD and show the output in the yaml format, run this command:

Click to copy
kubectl get crd functions.serverless.kyma-project.io -o yaml

Sample custom resource

The following Function object creates a lambda function which runs on the Node.js 8 runtime and responds to HTTP requests with "Hello World". It has low requirements in terms of compute resources and is therefore classified as size S.

Click to copy
apiVersion: serverless.kyma-project.io/v1alpha1
kind: Function
metadata:
name: hello-world
spec:
functionContentType: plaintext
size: S
runtime: nodejs8
function: |
module.exports = {
main: function(event, context) {
return 'Hello World'
}
}

Custom resource properties

This table lists all the possible properties of a given resource together with their descriptions:

PropertyRequiredDescription
metadata.nameYesSpecifies the name of the CR.
spec.functionYesProvides the source code of the lambda function.
spec.functionContentTypeYesSpecifies the content type of the function's code defined in the function property. The content type can be plaintext or base64-encoded.
spec.runtimeYesSpecifies the software runtime used to run the function's code.
spec.sizeYesSpecifies the compute requirement of the function expressed in size, such as S, M, L, or XL.
spec.depsNoSpecifies the dependencies of the lambda function.
spec.envNoSpecifies environment variables you need to export for the lambda function.
spec.timeoutNoSpecifies the duration in seconds after which the function execution is terminated. The default value is 180.

The Function custom resource relies on resources from Knative Serving and Knative Build.

ResourceDescription
BuildBuilds a container image containing the function code together with its configured runtime.
ServiceOrchestrates the deployment and availability of the function.

CLI reference

This section provides you with helpful command line examples used in Kyma.

Prerequisites

To develop, deploy, or run functions directly, download these tools additionally:

Set the cluster domain variable

The commands throughout this guide use URLs that require you to provide the domain of the cluster which you are using. To complete this configuration, set the variable yourClusterDomain to the domain of your cluster.

For example, if your cluster's domain is demo.cluster.kyma.cx, run the following command:

Click to copy
export yourClusterDomain='demo.cluster.kyma.cx'

Details

Use the command line to create, call, deploy, expose, and bind a function.

Deploy a function using a yaml file and kubectl

You can use the Kubeless CLI to deploy functions in Kyma.

Click to copy
kubectl apply -f https://raw.githubusercontent.com/kyma-project/examples/master/gateway/lambda/deployment.yaml

Check if the function is available:

Click to copy
kubeless function list hello

Deploy a function using a JS file and the Kubeless CLI

You can deploy a function using the Kubernetes and Kubeless CLI. See the following example:

Click to copy
kubeless function deploy hello --label app=hello --runtime nodejs8 --handler hello.main --from-file https://raw.githubusercontent.com/kyma-project/examples/master/event-subscription/lambda/js/hello-with-data.js --trigger-http

Call a function using the CLI

Use the CLI to call a function:

Click to copy
kubeless function call hello

Expose a function without authentication

Use the CLI to create an API for your function:

Click to copy
kubectl apply -f https://raw.githubusercontent.com/kyma-project/examples/master/gateway/lambda/api-without-auth.yaml

Expose a function with authentication enabled

If your function is deployed to a cluster, run:

Click to copy
curl -k https://github.com/kyma-project/examples/blob/master/gateway/lambda/api-with-auth.yaml | sed "s/.kyma.local/.$yourClusterDomain/" | kubectl apply -f -

If Kyma is running locally, add hello.kyma.local mapped to minikube ip to /etc/hosts.

Click to copy
echo "$(minikube ip) hello.kyma.local" | sudo tee -a /etc/hosts

Create the API for your function:

Click to copy
kubectl apply -f https://github.com/kyma-project/examples/blob/master/gateway/lambda/api-with-auth.yaml

Bind a function to events

You can bind the function to Kyma and to third-party services. For details, refer to the Service Catalog-related documentation.