Scaleway serverless

Disclaimer: This walkthrough worked in the moment of the writing of this post and may be broken in the future.

I was very happy when Scaleway announced their "function as a service"-service. There is a need for more competition to AWS, Google or Azure.

To get a feeling for the complexity I want to describe how I deployed a function at scaleway. Their api documentation is better than I expected but the walkthrough is using serverless and nodejs.

I wanted to try this with Python 3, PyTorch and curl only. I failed with PyTorch because of an issue with a shared library in Alpine Linux.

So this walkthrough only uses numpy as an example. But this should work for all Python libraries that can run with Alpine Linux.

First you need your organization_id and a new token from your scaleway settings. This is described in the documentation.

Then you need a namespace:

curl -X POST "https://api.scaleway.com/functions/v1alpha2/regions/fr-par/namespaces" \
-H "accept: application/json" -H "X-Auth-Token: $TOKEN" -H "Content-Type: application/json" \
-d "{\"name\": \"hello-ns\", \"organization_id\": \"$ORGANIZATION_ID\"}"

To be sure everything worked, we list the namespaces:

curl "https://api.scaleway.com/functions/v1alpha2/regions/fr-par/namespaces" -H "accept: application/json" \
-H "X-Auth-Token: $TOKEN" -H "Content-Type: application/json"

Now the interesting part. We need the namespace_id created before. Create a function:

curl -X POST -H "X-Auth-Token: $TOKEN" \
"https://api.scaleway.com/functions/v1alpha2/regions/fr-par/functions" \
-d "{\"name\": \"hello\", \"namespace_id\": \"$NAMESPACE_ID\", \"memory_limit\": 128, \"min_scale\": 0, \"max_scale\": 1, \"runtime\": \"python3\"}"

In the response is an id we need next. For uploading the function we need to create a zip file with the name like this: function-$FUNCTION_ID.zip

The files we want to add to our zipfile are

  • handler.py

import numpy

def handle(event, context):
    return {
        "body": {
            "numpy": {
              "version": numpy.__version__,
        }},
        "statusCode": 200,
    }
  • packages

mkdir package
# install packages using the alpine image from scaleway for this
docker run --rm -v $(pwd):/home/app/function --workdir /home/app/function rg.fr-par.scw.cloud/scwfunctionsruntimes/python-dep3:v2.1.0 pip install numpy --target ./package

Generate zip and get size of zip:

# generate zip
zip -r function-$FUNCTION_ID.zip handler.py package
# get size of zip for upload calls
ls -l *zip

For my test the size of the zip file was 12003113 bytes.

get upload url (insert TOKEN, FUNCTION_ID and SIZE_OF_ZIP in bytes)

curl -X GET -H "X-Auth-Token: TOKEN" https://api.scaleway.com/functions/v1alpha2/regions/fr-par/functions/FUNCTION_ID/upload-url?content_length=SIZE_OF_ZIP

Upload using the url, zip-filename and zip-size from before:

export FUNCTION_ARCHIVE_URL=$(echo -n "<upload-url-from-before>")
curl -H "Content-Type: application/octet-stream" -H "Content-Length: SIZE_OF_ZIP" --upload-file FUNCTION_ARCHIVE_NAME $FUNCTION_ARCHIVE_URL

Now deploy the function from the uploaded storage:

curl -X POST -H "X-Auth-Token: $TOKEN" "https://api.scaleway.com/functions/v1alpha2/regions/fr-par/functions/$FUNCTION_ID/deploy" -d "{}"

The last call returns the url to invoke in the function. Use this url like this:

curl "<url-given-by-deploy>"

This should result in something like this:

{"numpy":{"version":"1.16.4"}}