Kubeless architecture

This doc covers the architectural design of Kubeless and directory structure of the repository.

Concepts

Kubeless is built around below core concepts:

  • Functions
  • Triggers
  • Runtime

Functions

A Function is representation of the code to be executed. Along with the code a Function contains metadata about its runtime dependencies, build instructions etc. A Function has a independent life-cycle. The following methods are supported:

  • Deploy - deploy function as function instances. This step may involve building the function image or re-use pre-generated image and deploying it on the cluster.
  • Execute - invoke a function directly i.e) not through any event source
  • Get - Returns the function metadata and spec
  • Update - Modify the function specification and its metadata
  • Delete - Deletes a function, and clean up any resource provisioned for the function from the cluster
  • List - Show the list of functions and their metadata
  • Logs - Return the logs generated by a function

Triggers

A Trigger represents an event source the functions associated to it. When an event occurs in the event source, Kubeless will ensure that the associated function are invoked at most once. A Trigger can be associated to a single function or to several ones depending on the event source type. They are decoupled from the life-cycle of functions and can be independently operated with the following methods:

  • Create - create a new trigger with details on event source and associated functions
  • Update - Modify the trigger specification
  • Delete - Deletes a trigger, and clean up any resource provisioned for the trigger
  • List - Show the list of trigger and their specification

Runtime

A Runtime represents language and runtime specific environment in which function will be executed. Please see runtimes for more details.

Design

Kubeless leverages multiple concepts of Kubernetes in order to support deploy functions on top of it. In details, we have been using:

  • A Custom Resource Definitions (CRD) is used to represent function
  • Each event source is modelled as a separate Trigger CRD object
  • Separate Custom Resource Definitions controller to handle CRUD operations corresponding to CRD object
  • Deployment / Pod to run the corresponding runtime.
  • Configmap to inject function's code to the runtime pod.
  • Init-container to load the dependencies that function might have.
  • Service to expose function.
  • Ingress resources to expose functions externally

Use of Kubernetes CRD's and CRD controllers forms the core design tenet of Kubeless. Use of separate CRD's for functions and triggers provides clear separation of concerns. Use of separate CRD controllers keeps the code decoupled and modular.

Functions

When you install kubeless, there is a CRD functions.kubeless.io created to represent Function:

$ kubectl get customresourcedefinition functions.kubeless.io -o yaml
apiVersion: v1
items:
- apiVersion: apiextensions.k8s.io/v1beta1
  kind: CustomResourceDefinition
  metadata:
    ...
    name: functions.kubeless.io
    ...
    selfLink: /apis/apiextensions.k8s.io/v1beta1/customresourcedefinitions/functions.kubeless.io
  spec:
    group: kubeless.io
    names:
      kind: Function
      listKind: FunctionList
      plural: functions
      singular: function
    scope: Namespaced
    version: v1beta1

Then function custom objects will be created under this CRD endpoint. A function object looks like this:

$ kubectl get function get-python -o yaml
apiVersion: kubeless.io/v1beta1
kind: Function
metadata:
  clusterName: ""
  creationTimestamp: 2018-03-25T19:13:07Z
  finalizers:
  - kubeless.io/function
  generation: 0
  labels:
    created-by: kubeless
    function: get-python
  name: get-python
  namespace: default
  resourceVersion: "9219"
  selfLink: /apis/kubeless.io/v1beta1/namespaces/default/functions/get-python
  uid: 8d25a793-3060-11e8-ad89-08002730c417
spec:
  checksum: sha256:d251999dcbfdeccec385606fd0aec385b214cfc74ede8b6c9e47af71728f6e9a
  deployment:
    metadata:
      creationTimestamp: null
    spec:
      strategy: {}
      template:
        metadata:
          creationTimestamp: null
        spec:
          containers:
          - name: ""
            resources: {}
    status: {}
  deps: ""
  function: |
    def foo(event, context):
        return "hello world"
  function-content-type: text
  handler: helloget.foo
  horizontalPodAutoscaler:
    metadata:
      creationTimestamp: null
    spec:
      maxReplicas: 0
      scaleTargetRef:
        kind: ""
        name: ""
    status:
      conditions: null
      currentMetrics: null
      currentReplicas: 0
      desiredReplicas: 0
  runtime: python2.7
  service:
    ports:
    - name: http-function-port
      port: 8080
      protocol: TCP
      targetPort: 8080
    selector:
      created-by: kubeless
      function: get-python
    type: ClusterIP
  timeout: "180"

function.spec contains function's details like code, handler, runtime and probably its dependency file etc.

Kubeless ships with a CRD controller named function-controller which continuously watch changes to function objects and react accordingly. By default function-controller is installed in kubeless-controller-manager deployment which is deployed into kubeless namespace. Function-controller watches for create events corresponding to creation of Function object. Function-controller creates a deployment for the function, and exposes the function as a clusterIP service. Both deployment and service resource created for the function can be controlled by the function creator by explicitly specifying deployment spec and service spec respectively in the function.spec.

Runtime image used for the function deployment could be chosen by one of the below options:

  • User explicitly specifies custom runtime image to be used for the function
  • Image artifact is generated on the fly by the function builder
  • A pre-built image is used for each language and version combination. A configmap is used to inject the function code from function.spec.function into the corresponding k8s runtime pod.

Function-controller on receiving Function CRD object deletion event, cleans up all the resources (deployment, service, configmap etc) provisioned.

HTTP triggers

When you install kubeless, there is a CRD httptriggers.kubeless.io created to represent HTTP triggers:

$  kubectl get customresourcedefinition httptriggers.kubeless.io -o yaml
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: httptriggers.kubeless.io
  resourceVersion: "102"
  selfLink: /apis/apiextensions.k8s.io/v1beta1/customresourcedefinitions/httptriggers.kubeless.io
  uid: 0aa4a346-2ff4-11e8-ad89-08002730c417
spec:
  group: kubeless.io
  names:
    kind: HTTPTrigger
    listKind: HTTPTriggerList
    plural: httptriggers
    singular: httptrigger
  scope: Namespaced
  version: v1beta1

HTTP trigger custom objects will be created under httptriggers.kubeless.io CRD endpoint. An example HTTP trigger object looks like this:

$ kubectl get httptrigger get-python -o yaml
apiVersion: kubeless.io/v1beta1
kind: HTTPTrigger
metadata:
  labels:
    created-by: kubeless
  name: get-python
  namespace: default
spec:
  function-name: get-python
  host-name: get-python.192.168.99.100.nip.io
  ingress-enabled: true
  path: func
  tls: false

HTTP trigger object spec contains below fields:

  • function-name - name of the associated function that need to be invoked when URL corresponding to http trigger is accessed
  • host-name - name used for virtual hosting
  • path - route requests with this path to function service
  • tls - true if TLS is to be enabled

kubeless-controller-manager ships with http trigger CRD controller which watches for the HTTP trigger CRD objects and configures Kubernetes ingress accordingly.

Cronjob triggers

$ kubectl get customresourcedefinition cronjobtriggers.kubeless.io -o yaml
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: cronjobtriggers.kubeless.io
  selfLink: /apis/apiextensions.k8s.io/v1beta1/customresourcedefinitions/cronjobtriggers.kubeless.io
spec:
  group: kubeless.io
  names:
    kind: CronJobTrigger
    listKind: CronJobTriggerList
    plural: cronjobtriggers
    singular: cronjobtrigger
  scope: Namespaced
  version: v1beta1

Cronjob trigger custom objects will be created under cronjobtriggers.kubeless.io CRD endpoint. An example Cronjob trigger object looks like this:

$ kubectl get cronjobtrigger scheduled-get-python -o yaml
apiVersion: kubeless.io/v1beta1
kind: CronJobTrigger
metadata:
  labels:
    created-by: kubeless
    function: scheduled-get-python
  name: scheduled-get-python
  namespace: default
spec:
  function-name: scheduled-get-python
  schedule: '* * * * *'

Cronjob trigger object spec contains below fields:

  • function-name - name of the associated function that need to be invoked periodically as per specified
  • schedule - it takes a Cron format string, e.g. 0 * * * * or @hourly, as schedule time of its jobs to be created and executed.

kubeless-controller-manager ships with Cronjob trigger CRD controller which watches for the Cronjob trigger CRD objects and configures Kubernetes cronjobs to run the functions at scheduled intrerval time.

Kafka triggers

 kubectl get customresourcedefinition kafkatriggers.kubeless.io -o yaml
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: kafkatriggers.kubeless.io
  selfLink: /apis/apiextensions.k8s.io/v1beta1/customresourcedefinitions/kafkatriggers.kubeless.io
  uid: 0aa3988f-2ff4-11e8-ad89-08002730c417
spec:
  group: kubeless.io
  names:
    kind: KafkaTrigger
    listKind: KafkaTriggerList
    plural: kafkatriggers
    singular: kafkatrigger
  scope: Namespaced
  version: v1beta1

Kafka trigger custom objects will be created under kafkatriggers.kubeless.io CRD endpoint. An example Kafka trigger object looks like this:

 $ kubectl get kafkatrigger s3-python-kafka-trigger -o yaml
apiVersion: kubeless.io/v1beta1
kind: KafkaTrigger
metadata:
  labels:
    created-by: kubeless
  name: s3-python-kafka-trigger
  namespace: default
spec:
  functionSelector:
    matchLabels:
      created-by: kubeless
      topic: s3-python
  topic: s3-python

Kafka trigger object spec contains below fields:

  • functionSelector - label selector that selects list of matching function
  • topic - Kafka topic messages to which the functions associated must be invoked.

Kubeless command-line client

Together with kubeless-controller-manager, we provide kubeless cli which enables users to interact with Kubeless system. At this moment, Kubeless cli provides these below actions:

$ kubeless --help
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.

Implementation

Kubeless controller is written in Go programming language, and uses the Kubernetes client-go to interact with the Kubernetes apiserver.

Kubeless CLI is written in Go as well, using the popular cli library github.com/spf13/cobra. Basically it is a bundle of HTTP requests and kubectl commands. We send http requests to the Kubernetes apiserver in order to 'crud' CRD objects. Checkout the cmd folder for more details.

Directory structure

In order to help you getting a better feeling before you start diving into the project, we would give you the 10,000 foot view of the source code directory structure.

  • chart: chart to deploy Kubeless with Helm
  • cmd: contains kubeless cli implementation and kubeless-controller.
  • docker: contains artifacts for building the kubeless-controller and runtime images.
  • docs: contains documentations.
  • examples: contains some samples of running function with kubeless.
  • manifests: collection of manifests for additional features
  • pkg: contains shared packages.
  • script: contains build scripts.
  • vendor: contains dependencies packages.