Abaco

Actor Based Co(mputing)ntainers: Functions-as-a-service using the Actor model.

DOI

Intro

Abaco is a web service and distributed system that combines the actor model of concurrent computation, Linux containers into a web services platform that provides functions-as-a-service. In Abaco, actor registered in the system is associated with a Docker image. Actor containers are executed in response to messages posted to their inbox which itself is given by a URI exposed via Abaco. In the process of executing the actor container, state, logs and execution statistics are collected. Many aspects of the system are configurable.

Quickstart

Usage Workflow

  1. Deploy a development version of the Abaco stack using docker-compose. First, change into the project root and export the following variable so that abaco containers know where to find the example configuration file

    $ export abaco_path=$(pwd)
    

    Then start the Abaco containers with the following two commands:

    $ docker-compose -f dc-all.yml up -d
    

    If all went well, the services will be running behind nginx on 8000. We assume the Docker Gateway is running on the default IP for Docker 1.9.1+ which is 172.17.0.1. If this is not the case for your setup, you will need to update the value of host within the store stanza of the all.conf file with the IP address of the Gateway. It also may take several seconds for the mongo db to be ready to accept connections.

  2. Register an actor – Initially, the Abaco system is empty with no actors defined which can be seen by making a GET request to the root collection:

    $ curl localhost:8000/actors
    

    Abaco will respond with a JSON message that looks something like:

    {
        "msg": "Actors retrieved successfully.",
        "result": [],
        "status": "success",
        "version": "0.01"
    }
    

    To define an actor, pass a name and an image available on the public Docker Hub.

    $ curl -X POST --data "image=jstubbs/abaco_test&name=foo" "localhost:8000/actors"
    

    Abaco responds in JSON. You should see something like this:

    {
        "msg": "Actor created successfully.",
        "result": {
            "default_environment": {},
            "description": "",
            "id": "e68ebbb7-4986-46ee-9332-a1f5cfc6a533",
            "image": "jstubbs/abaco_test",
            "name": "foo",
            "privileged": false,
            "stateless": false,
            "status": "SUBMITTED",
            "tenant": "dev_staging"
        },
        "status": "success",
        "version": "0.01"
    }
    

    Abaco assigned a uuid to the actor (in this case e68ebbb7-4986-46ee-9332-a1f5cfc6a533) and associated it with the image jstubbs/abaco_test which it began pulling from the public Docker hub.

  3. Notice that Abaco returned a status of SUBMITTED for the actor; behind the scenes, Abaco is starting a worker container to handle messages passed to this actor. The worker must initialize itself (download the image, etc) before the actor is ready. You can retrieve the details about an actor (including the status) by making a GET request to a specific actor using its uuid like so:

    $ curl localhost:8000/actors/e68ebbb7-4986-46ee-9332-a1f5cfc6a533
    

    When the actor’s worker is initialized, you will see a response like this:

    {
        "msg": "Actor retrieved successfully.",
        "result": {
            "default_environment": {},
            "description": "",
            "id": "e68ebbb7-4986-46ee-9332-a1f5cfc6a533",
            "image": "jstubbs/abaco_test",
            "name": "test",
            "privileged": false,
            "stateless": false,
            "status": "READY",
            "tenant": "dev_staging"
        },
        "status": "success",
        "version": "0.01"
    }
    

    A status of “READY” indicates that actor is capable of processing messages by launching containers from the image.

  4. We’re now ready to execute our actor. To do so, make a POST request to the messages collection for the actor and pass a message string as the payload.

    $ curl -X POST --data "message=execute yourself"  localhost:8000/actors/e68ebbb7-4986-46ee-9332-a1f5cfc6a533/messages
    

    abaco executes the image registered for e68ebbb7-4986-46ee-9332-a1f5cfc6a533, in this case, jstubbs/abaco_test, and passes in the string "execute yourself" as an environmental variable ($MSG). abaco will use the default command included in the image when executing the container. The response will look like this:

    {
        "msg": "The request was successful",
        "result": {
            "execution_id": "27326d48-7f00-4a45-a2f7-76fff8d685e6",
            "msg": "execute yourself"
        },
        "status": "success",
        "version": "0.01"
    }
    

    Note that the execution id (in this case, 27326d48-7f00-4a45-a2f7-76fff8d685e6) is returned in the response. This execution id can be used to retrieve information about the execution.

  5. An actor’s executions can be retrieved using the executions sub-collection.

    $ curl localhost:8000/actors/e68ebbb7-4986-46ee-9332-a1f5cfc6a533/executions
    

    The response will include summary statistics of all executions for the actor as well as the id’s of each execution. As expected, we see the execution id returned from the previous step.

    {
        "msg": "Actor executions retrieved successfully.",
        "result": {
            "ids": [
                "27326d48-7f00-4a45-a2f7-76fff8d685e6"
            ],
            "total_cpu": 144132228,
            "total_executions": 1,
            "total_io": 438,
            "total_runtime": 2
        },
        "status": "success",
        "version": "0.01"
    }
    

    The abaco_test image simply echo’s the environment and does a sleep for 5 seconds. We can query the executions collection with the execution id at any to get status information about the execution. When the execution finishes, its status will be returned as “COMPLETE” and details about the execution including runtime, cpu, and io usage will be available. For example:

    $ curl localhost:8000/actors/e68ebbb7-4986-46ee-9332-a1f5cfc6a533/executions/27326d48-7f00-4a45-a2f7-76fff8d685e6
    

    The response will look something like:

    {
        "msg": "Actor execution retrieved successfully.",
        "result": {
            "actor_id": "e68ebbb7-4986-46ee-9332-a1f5cfc6a533",
            "cpu": 144132228,
            "executor": "anonymous",
            "id": "27326d48-7f00-4a45-a2f7-76fff8d685e6",
            "io": 438,
            "runtime": 2,
            "status": "COMPLETE"
        },
        "status": "success",
        "version": "0.01"
    }
    
  6. You can also retrieve the logs (as in docker logs) for any execution:

    $ curl localhost:8000/actors/e68ebbb7-4986-46ee-9332-a1f5cfc6a533/executions/27326d48-7f00-4a45-a2f7-76fff8d685e6/logs
    

    Response:

    {
        "msg": "Logs retrieved successfully.",
        "result": "Contents of MSG: execute yourself\nEnvironment:\nHOSTNAME=f64b9adb8239\nSHLVL=1\nHOME=/root\n_abaco_api_server=https://dev.tenants.staging.agaveapi.co\nMSG=execute yourself\nPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\nPWD=/\n_abaco_username=anonymous\n",
        "status": "success",
        "version": "0.01"
    }
    

    As mentioned earlier, this test container simply echo’s the environment, and we see that from the logs. Notice that our MSG variable showed up, as well as a couple other variables: _abaco_api_server and _abaco_username. The username is showing up as “anonymous” since the development configuration is using no authentication; however, the abaco system has a configurable authentication mechanism for securing the services with standards such as JWT (https://tools.ietf.org/html/rfc7519), and when such authentication mechanisms are configured, the username will be populated.

Additional Features

The quick start introduced the basic features of abaco. Here we list some of the more advanced features.