Last time we launched a simple Mesos framework. Now let’s see how to interact with it.

Prequisite

Must complete all the steps from Part One

Accept an offer and launch a task

The next step is to accept the offer from the Mesos Master and launch a custom task on our running Mesos agent. This brings us into contact with another part of the Mesos architecture: an Executor. An Executor is the process on the Mesos agent which is used to launch and monitor a task. While it is possible to write a custom Executor, for this example we’ll just be using the Mesos provided one.

From the docs:

Mesos provides a simple executor that can execute shell commands and Docker containers on behalf of the framework scheduler; enough functionality for a wide variety of framework requirements.

To use the default executor, we simply need to include a command as a top-level field under task_infos. If we wanted to use a custom executor, we would nest command inside an executor node.

Command below. Remember to update the values for:

mesos-stream-id
framework_id
offer_ids
agent_id

In terminal 4:

(due to the size of this outrageous JSON blob I recommend dropping this command into POSTMAN to avoid weird copy/paste issues in a terminal)

curl -X POST \
  http://localhost:5050/api/v1/scheduler \
  -H 'content-type: application/json' \
  -H 'mesos-stream-id: 274bcc35-78db-42ac-8a10-b02944c5a6eb' \
  -d '{
    "framework_id": {
      "value": "089a7212-4aba-4aac-8425-7337161ece30-0000"
    },
    "type": "ACCEPT",
    "accept": {
      "offer_ids": [
        {
          "value": "089a7212-4aba-4aac-8425-7337161ece30-O0"
        }
      ],
      "operations": [
        {
          "type": "LAUNCH",
          "launch": {
            "task_infos": [
              {
                "name": "My Task",
                "task_id": {
                  "value": "shell hello world loop"
                },
                "agent_id": {
                  "value": "089a7212-4aba-4aac-8425-7337161ece30-S0"
                },
                "command": {
                  "shell": true,
                  "value": "echo starting; while [[ 1 -eq 1 ]]; do echo helloWorld; sleep 5; done"
                },
                "resources": [
                  {
                    "allocation_info": {
                      "role": "hello_world_role"
                    },
                    "name": "cpus",
                    "role": "*",
                    "type": "SCALAR",
                    "scalar": {
                      "value": 1
                    }
                  },
                  {
                    "allocation_info": {
                      "role": "hello_world_role"
                    },
                    "name": "mem",
                    "role": "*",
                    "type": "SCALAR",
                    "scalar": {
                      "value": 128
                    }
                  }
                ]
              }
            ]
          }
        }
      ],
      "filters": {
        "refuse_seconds": 5
      }
    }
  }'

Mesos responds with a 202 indicating that it Accepted the request but has not processed it. This is a good example of the Actor model, one-way communication implemented by Mesos.

Flipping thru the open terminals here is some interesting output:

Master node:

Status update TASK_RUNNING (UUID: 3abe8974-9d80-4374-9025-aae5d37cda1f) for task shell hello world loop of framework
Forwarding status update TASK_RUNNING (UUID: 3abe8974-9d80-4374-9025-aae5d37cda1f)

In our Framework terminal:

"type":"UPDATE" ... "state":"TASK_RUNNING" ...

Back in the browser at http://localhost:5050/#/, we should see the shell hello world loop task under active tasks! Clicking into the sandbox, then the stdout will reveal our looping terminal output.

We’ve just deployed a task! Are you feeling the cloud??

Acknowledge a status update from Mesos

To be a good citizen we need to acknowledge the status update from Mesos. (the Framework terminal will indicate that )

In Terminal 4:

curl -X POST \
  http://localhost:5050/api/v1/scheduler \
  -H 'content-type: application/json' \
  -H 'mesos-stream-id: 6c83f87e-e1d2-47c7-be1f-43f71d4794a6' \
  -d '{
    "framework_id": {
      "value": "f6480abb-914d-47e4-a802-b123c7925e7a-0000"
    },
    "type": "ACKNOWLEDGE",
    "acknowledge"     : {
      "agent_id"  :  {"value" : "f6480abb-914d-47e4-a802-b123c7925e7a-S0"},
      "task_id"   :  {"value" : "shell hello world loop"},
      "uuid"      :  "F+lGzCYnTam7KN0gWOq+6w=="
    }
  }'

Flipping to the Master node terminal:

Processing ACKNOWLEDGE call

Nice.

Launch a Docker container

Now scroll back up a bit and you will find another Offer from the Mesos master. Let’s accept that offer and launch a Docker task!

curl -X POST \
  http://localhost:5050/api/v1/scheduler \
  -H 'content-type: application/json' \
  -H 'mesos-stream-id: 274bcc35-78db-42ac-8a10-b02944c5a6eb' \
  -d '{
    "framework_id": {
      "value": "089a7212-4aba-4aac-8425-7337161ece30-0000"
    },
    "type": "ACCEPT",
    "accept": {
      "offer_ids": [
        {
          "value": "089a7212-4aba-4aac-8425-7337161ece30-O1"
        }
      ],
      "operations": [
        {
          "type": "LAUNCH",
          "launch": {
            "task_infos": [
              {
                "name": "nginx",
                "task_id": {
                  "value": "nginx"
                },
                "agent_id": {
                  "value": "089a7212-4aba-4aac-8425-7337161ece30-S0"
                },
                "command": {
                  "shell": true,
                  "value": "docker run --name mesos-nginx -p 8080:80 nginx"
                },
                "resources": [
                  {
                    "allocation_info": {
                      "role": "hello_world_role"
                    },
                    "name": "cpus",
                    "role": "*",
                    "type": "SCALAR",
                    "scalar": {
                      "value": 1
                    }
                  },
                  {
                    "allocation_info": {
                      "role": "hello_world_role"
                    },
                    "name": "mem",
                    "role": "*",
                    "type": "SCALAR",
                    "scalar": {
                      "value": 128
                    }
                  }
                ]
              }
            ]
          }
        }
      ],
      "filters": {
        "refuse_seconds": 5
      }
    }
  }'

Now http://localhost:8080/ will show nginx running on our system! Sweet.

Decline an offer

back in Terminal 4:

curl -X POST \
  http://localhost:5050/api/v1/scheduler \
  -H 'content-type: application/json' \
  -H 'mesos-stream-id: 274bcc35-78db-42ac-8a10-b02944c5a6eb' \
  -d '{
    "framework_id": {
      "value": "089a7212-4aba-4aac-8425-7337161ece30-0000"
    },
    "type": "DECLINE",
    "decline"         : {
      "offer_ids" : [
                      {"value" : "089a7212-4aba-4aac-8425-7337161ece30-O4"}
                    ],
      "filters"   : {"refuse_seconds" : 5.0}
    }
  }'

Kill a task

back in Terminal 4:

curl -X POST \
  http://localhost:5050/api/v1/scheduler \
  -H 'content-type: application/json' \
  -H 'mesos-stream-id: 274bcc35-78db-42ac-8a10-b02944c5a6eb' \
  -d '{
    "framework_id": {
      "value": "089a7212-4aba-4aac-8425-7337161ece30-0000"
    },
    "type": "KILL",
    "kill"            : {
      "task_id"   :  {"value" : "nginx"},
      "agent_id"  :  {"value" : "089a7212-4aba-4aac-8425-7337161ece30-S0"}
    }
  }'
Processing KILL call for task 'nginx'
Telling agent 089a7212-4aba-4aac-8425-7337161ece30-S0 at slave(1)@192.168.1.12:5051 (192.168.1.12) to kill task nginx

(note that the Task stays in “active” status in the UI, until we acknowledge the update from the Mesos master.)

fin