Running Knative Functions with the Azure Functions Runtime

Sebastien Goasguen

Sebastien Goasguen

Nov 13, 2018
Running Knative Functions with the Azure Functions Runtime
Running Knative Functions with the Azure Functions Runtime

Azure has established itself has real competition to AWS in the last few years. Their new commitment to Open-source software has been impressive and their Kubernetes team is a major contributor in the community.

When talking Serverless, AWS Lambda is definitely leading the pack, but Azure functions are very often talked about. I had a look at Azure functions recently and I have to say that I was quite impressed: Azure functions are cool

Interestingly, while we have had to rely on a third-party reverse-engineering of Lambda to get a look at the function runtime. Azure itself released its runtime in the shape of Azure function core tool: func.

With func you can create a function, load the extensions that are needed to configure the event binding that you need and then create a container image from it.

There have been several blogs over the last few months about running Azure functions in Kubernetes.

However, with the advent of Knative (which gives us auto-scaling, internal build system and additional eventing), it begs to wonder: “Can I run my functions in the Azure function runtime within knative?”

The answer is a resounding Yes and here is how:

Build Your Function with func

This is a summary, for the full step by step please check out the main repository and definitely we would love the help to make it better.

> As a sign of how times have changed I will know talk about a MSFT tool and even tell you to install .NET. That said, I learned basic at 10 years old and my first computers were all running MS-DOS. Close the Aparte.

Microsoft has developed a tool to help Azure users write Azure functions, at the CLI it is called func and you get it by installing the Azure function core tools which has .NET dependency.

The .NET bit might be a bit challenging on some OS, so we prepared a Docker image for you gcr.io/triggermesh/azure-func

To start developing your function create an empty directory and start our image in interactive mode:


mkdir newfunc
docker run --rm --name azure-func-w /workspace -v $(pwd):/workspace -p 7071:7071 -p 8080:8080 -ti gcr.io/triggermesh/azure-func
func@13a5ece9b783:/workspace$ which func
/usr/bin/func

You can then initialize your function, create an HTTP trigger and start it:

func init --worker-runtime=node
func new --name foobar --template "HTTP trigger"
func start --port=8080

There might be a few gotchas but that’s really all there is to it.

Deploy in Knative or TriggerMesh Cloud

Since you created this function within a Docker container, you can easily package it as a Docker image and hence run it in knative.

For the impatient, the TLDR CLI commands to do it will look like this:

tm deploy buildtemplate --from-file knative-build-template.yaml
tm deploy service --from-source /URL_OF_YOUR_SOURCE/ --build-template azure-runtime

For the longer version, check the full repository. Here is a summary:

We have prepared a Knative build-template for it. The core of it is a kaniko based container build using the Docker image that we created with func. First, we write a Dockerfile in the workspace and then we do the build and publish the image to a registry.


steps:
  - name: dockerfile
    image: gcr.io/kaniko-project/executor:debug
    command:
    - /busybox/sh
    args:
    - -c
    - |
      cd /workspace/${DIRECTORY}
      [ -f "Dockerfile" ] && echo "Dockerfile found (from init --docker presumably)" && exit 0
      # TBD how to handle npm ci (see nodejs-runtime)
      cat <> Dockerfile
      FROM gcr.io/triggermesh/azure-func
      USER root
      COPY . /home/func
      RUN chown -R func:func /home/func
      ENV ASPNETCORE_URLS=http://+:8080
      USER func:func
      WORKDIR /home/func
      CMD ["func", "start", "--port", "8080"]      
      EOF
      pwd
      ls -l
      cat Dockerfile
  - name: export
    image: gcr.io/kaniko-project/executor
    args:
    - --context=/workspace/${DIRECTORY}
    - --dockerfile=/workspace/${DIRECTORY}/Dockerfile
    - --destination=${IMAGE}:${TAG}
    - --skip-tls-verify=${SKIP_TLS_VERIFY}

Create this template in your TriggerMesh account (or your own knative environment):


kubectl apply -f knative-build-template.yaml

With a Build template called azure-runtime deployed you can create your function using a Configuration object, here is an example from a personal test.


apiVersion: serving.knative.dev/v1alpha1
kind: Configuration
metadata:
  name: azure-runtime-example-function
spec:
  build:
    source:
      git:
        url: https://github.com/sebgoa/azure-queue-func.git
        revision: master
    template:
      name: azure-runtime
      arguments:
      - name: SKIP_TLS_VERIFY
        value: "true"
      - name: TAG
        value: 0.0.1
      - name: IMAGE
        value: unauthenticated.registry.svc.cluster.local/sebgoa/queue
  revisionTemplate:
    spec:
      container:
        image: unauthenticated.registry.svc.cluster.local/sebgoa/queue:0.0.1
        env:
        - name: AzureWebJobsStorage
          valueFrom:
            secretKeyRef:
              name: azurequeue
              key: connection
    metadata:
      labels:
        knative.dev/type: "function"

And Voila ! Just like that, you have created a Node.js function using the Azure function runtime and you are now running it in Knative.

Create your first event flow in under 5 minutes