Purpose

This document describes a proposed integration between Apache OpenWhisk and Knative. Knative is a set of building blocks for serverless platforms running on top of Kubernetes. It is not a complete serverless platform and leaves the higher-level API concepts, CLIs, tooling, etc up to specific vendors to implement. OpenWhisk has some of these higher-level concepts and toolings - notably the notion of Actions, `wsk` and `wskdeploy`, composer and conductor, client libraries in multiple languages, integration with the serverless plugin, etc.

The aim of this proposal is to describe and prototype an OpenWhisk design that takes full advantage of Knative on top of Kubernetes while also retaining compatibility with most or all current OpenWhisk functions, integrations, user-facing tools and documentation, and overall ecosystem. This proposal does not consider non-Knative/Kubernetes platforms nor compatibility at a level other than the Controller API and function runtimes. In particular system requirements, installation steps, action execution guarantees, and other internal details will change.

This proposal is put forth by the serverless team at Red Hat for discussion with the broader Apache OpenWhisk community. If the community decides to move forward with some or all of this proposal, prototype code will be happily moved into official Apache repositories. Until that time, development will take place in the open but not under the Apache umbrella to allow for rapid iteration, prototyping, and design changes without confusing existing OpenWhisk users about the project's direction or impede progress towards graduating from Incubation.

Prototype Implementation

A rapidly evolving prototype of this proposal is available at https://github.com/projectodd/kwsk/.

There are also a number of asciicasts and screencasts available demoing some of the functionality, listed in order from oldest to newest:

The general goal of this prototype is to use Knative for as much of the implementation as possible. Right now there are two primary components to the prototype:

OpenWhisk-compatible client API

This is implemented as a small Golang server with large parts autogenerated from the upstream OpenWhisk OpenAPI spec. Existing OpenWhisk clients communicate with this API which translates all OpenWhisk API calls into the appropriate Kubernets and Knative API calls. It is tested by running the existing OpenWhisk API test suite against this new server. Many tests do not pass yet, and some may require slight changes to the test suite to be able to pass long-term. The goal is to use the OpenWhisk API test suite to validate compatibility and eventually document any known incompatibilities.

OpenWhisk-compatible runtime image shim

This is implemented as a small Golang server that gets bundled into repackaged container images for each OpenWhisk action kind. Knative expects to be able to POST events to the root path ("/") of running servers while OpenWhisk expects different semantics of an Invoker calling "/init" and "/run" of the action runtimes. This shim essentially acts like a mini-invoker, translating Knative event requests into ones the OpenWhisk runtimes expect.

This does mean that OpenWhisk container actions (ie blackbox actions) and other custom runtime images won't work out of the box without adding this shim. It is a later goal of this prototype to explore using Knative Build to automatically add the shim into arbitrary container images but that has not been implemented yet.


openwhisk_knative

Event flow on Knative

openwhisk_knative_eventing


Event → Knative Eventing → Knative Serving → Action Container Runtime Shim → Action Container OpenWhisk Runtime


Mapping between OpenWhisk and Knative objects

Actions

wsk action create myAction my_action.js

  • kwsk server

    • Kubernetes API server

      • create service.serving.knative.dev:myaction

        • create configuration.serving.knative.dev:myaction

          • create revision.serving.knative.dev:myaction-00001

        • create route.serving.knative.dev:myaction

wsk action get myAction

  • kwsk server
    • Kubernetes API server
      • get serving.serving.knative.dev:myaction

wsk action invoke myAction

  • kwsk server
    • POST -H "Host: myAction" knative-ingressgateway
      • if kwsk server is running inside the same Kubernetes cluster as Knative, this can directly hit the domainInternal of the Knative route instead of going via the ingress gateway w/ host header
      • the action parameters are passed as the POST body
      • the action runtime container images are the default upstream ones with the addition of a small golang binary added that proxies incoming POST requests and does the "/init" and "/run" handshake with the language-specific runtime

Triggers

wsk trigger create myTrigger

  • kwsk server
    • Kubernetes API server
      • create channel.channels.knative.dev:mytrigger

wsk trigger get myTrigger

  • kwsk server
    • Kubernetes API server
      • get channel.channels.knative.dev:mytrigger

wsk trigger fire myTrigger

  • kwsk server
    • POST mytrigger-channel.foo.svc.cluster.local

Rules

wsk rule create myRule myTrigger myAction

  • kwsk server
    • Kubernetes API server
      • create subscription.channels.knative.dev:myrule, specifying
              Channel of mytrigger and Subscriber of
              myaction.internal.dns.name
  • No labels