Running Functions in a Azure Function runtime with Knative
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
MyFunctionProj
MyFunctionProjWithDockerfile
func-in-docker
LICENSE
README.md
build-r00001.yaml
knative-build-template.yaml
route-r00001.yaml

README.md

Running Azure Functions in Knative

Azure functions are one of the serverless offerings available to users. Perhaps little known is that Azure functions can be easily packaged as Docker containers and that a tool called func is available to build and test functions locally. It has also been documented that Azure functions can easily run in Kubernetes since they can be packaged as containers.

This repository is a step by step tutorial to show you how to run functions that use the Azure function runtime in knative.

This sample is for JavaScript as function language.

Pre-requisites

For local testing you need:

On OSX for example, once you get the .NET core SDK you can get the Azure function core tools via brew:

brew tap azure/functions
brew install azure-functions-core-tools 

If you struggle to install .NET core and the Azure functions CLI, you can build it via Docker as shown in the next section.

Getting the Azure functions func CLI via Docker

First build the Docker image using the provided Dockerfile in the func-in-docker/ directory.

docker build -t azure-func func-in-docker/

You will then be able to run func from an interactive container.

docker run --rm --name azurefunc -w /workspace -v $(pwd):/workspace -p 7071:7071 -p 8080:8080 -ti azure-func
func@13a5ece9b783:/workspace$ which func
/usr/bin/func

Local function testing

You are now ready to start developing your function whether directly on your local machine or from within a container.

The following commands shows you the step by step process to start a function from scratch:

mkdir /tmp/functions
cd /tmp/functions
func init --worker-runtime=node
func new --name foobar --template "HTTP trigger"
sed -i 's/"authLevel": "function"/"authLevel": "anonymous"/' foobar/function.json
func start --port=8080

                  %%%%%%
                 %%%%%%
            @   %%%%%%    @
          @@   %%%%%%      @@
       @@@    %%%%%%%%%%%    @@@
     @@      %%%%%%%%%%        @@
       @@         %%%%       @@
         @@      %%%       @@
           @@    %%      @@
                %%
                %

Azure Functions Core Tools (2.1.725 Commit hash: 68f448fe6a60e1cade88c2004bf6491af7e5f1df)
Function Runtime Version: 2.0.12134.0
[10/19/2018 12:40:27] Building host: startup suppressed:False, configuration suppressed: False
[10/19/2018 12:40:27] Reading host configuration file '/tmp/functions/host.json'
[10/19/2018 12:40:27] Host configuration file read:
...

On another terminal do:

curl -w '\n\' http://localhost:8080/api/foobar?name=alice
Hello alice

If you reach this point you have successfully built a node.js function with the Azure Functions runtime. You can now move on to packaging that function as a container.

Preparing a Docker image

The simplest is to package your function within the azure-func Docker image with a Dockerfile like this:

FROM gcr.io/triggermesh/azure-func
RUN mkdir /tmp/funcroot
COPY . /tmp/funcroot
WORKDIR /tmp/funcroot
CMD ["func", "start", "--port", "8080"]

Build the image and run the container

docker build -t myfunc .
docker run -d -p 8080:8080 myfunc

You can now check the logs

docker logs -f myfunc

You are then ready to call the function.

curl -w '\n' http://localhost:8080/api/MyHttpTrigger?name=alice

Example: Create a Function with a Queue Trigger

First you need to create a queue on the Azure Queue Storage service and make note of your Storage connection string (aka your secret access key).

Let's assume you create a queue called fooqueue

Now initialize the function in an empty directory:

func init --worker-runtime=node

And create a new Queue trigger

func new -t "Queue trigger"  --name foobar

Specify your queue name in the file ./foobar/function.json which was just created.

Now build the function container with the following 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
RUN func extensions install --package Microsoft.Azure.Storage.Queue --version 9.4.0
CMD ["func", "start", "--port", "8080"]

And run it, with taking care to pass your connection string as an environment variable:

docker run -it --env AzureWebJobsStorage="...put in your Azure storage connection string ..." myfunc

Publish a message to your queue and watch it being consumed by your function.

Deploying Azure Functions in Knative

Please see the TriggerMesh nodejs runtime for complete instructions and explanations.

Knative leverages Kubernetes and Istio to provide automatic scaling and container image build steps. Knative can therefore package your functions in container images and run then with autoscaling turned on.

To build the container images that contain your Azure functions you need to deploy the Build template from this repo:

kubectl apply -f knative-build-template.yaml

And then as an example, create a Configuration object that will reference this build template and create what are called Knative revisions.

To get traffic to flow to your functions (assuming it is an HTTP Trigger type function you can create a Knative route object.

See the provided manifests:

kubectl apply -f build-r00001.yaml
kubectl apply -f route-r00001.yaml

To call your function you can use the debugging command below which lets your reach the function from within the cluster using the proper Host header.

kubectl run -it curl --image=gcr.io/cloud-builders/curl --restart=Never --rm -- \
  --connect-timeout 3 --retry 10 -vSL -w '\n' \
  -H 'Host: azure-runtime-example-function.default.example.com' \
  http://knative-ingressgateway.istio-system.svc.cluster.local/api/foobar?name=Hi%20Knative

Enjoy !

Add a runtime

Any of Azure's worker runtimes is likely supported. To add one, update the build template with Dockerfile content from func init --docker and the environment variable ASPNETCORE_URLS to set the port to 8080.

Support

We would love your feedback on this project so don't hesitate to let us know what is wrong and how we could improve it, just file an issue

Code of Conduct

This work is by no means part of CNCF but we abide by its code of conduct