Get started with fleet APIs

There are various commands you can use to interact with fleet. Fleet as you might recall, is the cluster manager from CoreOS. Service requests are sent to fleet and it decides which nodes from the cluster run the services. Since fleet has control of the cluster, it can automatically reshuffle service in case a node fails. This helps make sure your services run uninterrupted.

Coming back to fleet commands, there are cases when you’d rather like to automate the process, and let your code handle the cluster based on various logical situations. It is for such cases, fleet provides it’s own set of APIs available via HTTP. These APIs are not available by default, though. You’ll need to enable them before you can start using them.

In this post, I will explain the steps to setup and use fleet APIs. To get started, we need to enable fleet to listen for API calls on a network. As a pre-condition, you should have CoreOS ready to be installed on a cluster. I use AWS EC2 as the backend for my CoreOS cluster. Read more on how to install CoreOS on EC2 here. But don’t install it yet, you’ll need to tweak the cloud-config file to enable APIs over network. Let’s see how to do this.

Enable fleet API

fleet’s API is served using systemd socket activation. At service startup, systemd passes fleet a set of file descriptors, preventing fleet from having to care on which interfaces it’s serving the API. The configuration of these interfaces is managed through a systemd socket unit. CoreOS ships a socket unit for fleet (fleet.socket) which binds to a Unix domain socket, /var/run/fleet.sock.

So, to serve the fleet API over a network address, we simply need to extend or replace this socket unit. In this tutorial I will extend the socket unit in the cloud config file while installing CoreOS on AWS. This can be done during the first step of CoreOS installation. On the AWS CloudFormation page, just click the View in designer link next to specify an Amazon S3 template URL text box. This will open the page where you can edit the cloud config file. Here, search for the section units and add a drop in

“ — name: fleet.socket\n”,
“ command: start\n”,
“ drop-ins:\n”,
“ — name: 30-ListenStream.conf\n”,
“ content: |\n”,
“ [Socket]\n”,
“ ListenStream=48165\n”,

With this drop in we’re instructing fleet to listen on port 48165 for any API calls. After adding the drop in, the units section should look like this

“ units:\n”,
“ — name: etcd2.service\n”,
“ command: start\n”,
“ — name: fleet.socket\n”,
“ command: start\n”,
“ drop-ins:\n”,
“ — name: 30-ListenStream.conf\n”,
“ content: |\n”,
“ [Socket]\n”,
“ ListenStream=48165\n”,
“ — name: fleet.service\n”,
“ command: start\n”

Once added, proceed with CoreOS installation routine steps. If everything goes well, the nodes in cluster thus created will listen to API calls on port 48165. Lets now try to verify if fleet really is listening to your API calls. First connect to one of the nodes in your cluster and create a unit file. For example,

[Unit]
Description=MyApp
After=docker.service
Requires=docker.service
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill busybox1
ExecStartPre=-/usr/bin/docker rm busybox1
ExecStartPre=/usr/bin/docker pull busybox
ExecStart=/usr/bin/docker run — name busybox1 busybox /bin/sh -c “while true; do echo Hello World; sleep 1; done”
ExecStop=/usr/bin/docker stop busybox1

Save it as myapp.service. Then, execute the command

$ curl -w GET http://127.0.0.1:49153/fleet/v1/units

This should return a response with details about all the units the node has. Since we have only one unit, myapp.service it will be listed in the response. Here is how it looks

{“units”:[{“currentState”:”launched”,”desiredState”:”launched”,”machineID”:”00e50df50b874296a33aa5627b492a93",”name”:”myapp.service”,”options”:[{“name”:”Description”,”section”:”Unit”,”value”:”MyApp”},{“name”:”After”,”section”:”Unit”,”value”:”docker.service”},{“name”:”Requires”,”section”:”Unit”,”value”:”docker.service”},{“name”:”TimeoutStartSec”,”section”:”Service”,”value”:”0"},{“name”:”ExecStartPre”,”section”:”Service”,”value”:”-/usr/bin/docker kill busybox1"},{“name”:”ExecStartPre”,”section”:”Service”,”value”:”-/usr/bin/docker rm busybox1"},{“name”:”ExecStartPre”,”section”:”Service”,”value”:”/usr/bin/docker pull busybox”},{“name”:”ExecStart”,”section”:”Service”,”value”:”/usr/bin/docker run — name busybox1 busybox /bin/sh -c \”while true; do echo Hello World; sleep 1; done\””},{“name”:”ExecStop”,”section”:”Service”,”value”:”/usr/bin/docker stop busybox1"}]}]}

Such response confirms that you can access fleet APIs via HTTP. Let us now see few of the commonly used fleet APIs and learn how and when to use them. But before that we need to understand the JSON request and response format that fleet APIs use.


We’re running a short developer survey to find issues with current software development methodologies. Fill the survey and get access to Devup beta!

https://devup1.typeform.com/to/QDiNFU


JSON Requests and Response format

Broadly, there are two entities that are used while communicating with fleet via APIs — Unit Entity and UnitState Entity. Unit entities are used to communicate to fleet the desired state of the cluster. Here are the various components of a unit entity.

  • currentState: (readonly) state the Unit is currently in (same possible values as desiredState)
  • desiredState: state the user wishes the Unit to be in (“inactive”, “loaded”, or “launched”)
  • machineID: ID of machine to which the Unit is scheduled
  • name: (readonly) unique identifier of entity
  • options: list of UnitOption entities

A UnitOption represents a single option in a systemd unit file.

  • name: name of option (e.g. “BindsTo”, “After”, “ExecStart”)
  • section: name of section that contains the option (e.g. “Unit”, “Service”, “Socket”)
  • value: value of option (e.g. “/usr/bin/docker run busybox /bin/sleep 1000”)

As you can see, the response we got from the GET API above exactly matches this format. UnitStates represent the current states of units actually running in the cluster. The information reported by UnitStates will not always align perfectly with the Units, as there is a delay between the declaration of desired state and the back-end system making all of the necessary changes. Here are the components of UnitState entity.

  • name: unique identifier of entity
  • hash: SHA1 hash of underlying unit file
  • machineID: ID of machine from which this state originated
  • systemdLoadState: load state as reported by systemd
  • systemdActiveState: active state as reported by systemd
  • systemdSubState: sub state as reported by systemd

Fleet APIs

Let us now take a look at few common fleet APIs.

Create a unit

To create a unit, you’ll need to pass a partial unit entity. Note that only the desiredState and options fields are required, rest of the fields can be ignored safely. Here is how the request looks like:

$ curl -w PUT http://127.0.0.1:49153/fleet/units/myapp1.service
{
“desiredState”:”launched”,
“Options”: [ {“section”:”Service”,”name”:”ExecStart”,”value”:”
/usr/bin/sleep 3000" } ]
}

Modify a unit

You can modify the state of an existing unit by passing just the desiredState.

$ curl -w PUT http://127.0.0.1:49153/fleet/units/myapp1.service
{
“desiredState”:”inactive”
}

List units

To list all the units currently on fleet, simply use

$ curl -w GET http://127.0.0.1:49153/fleet/units

Similarly, to get a specific unit’s details, you can use

$ curl -w GET http://127.0.0.1:49153/fleet/units/<unit_name>

Where <unit_name> is the name of unit whose details you’d like to get.

Delete unit

To completely remove a unit from fleet, use

$ curl -w DELETE http://127.0.0.1:49153/fleet/units/<unit_name>

Conclusion

In this post we learnt about setting up fleet to accept API calls by adding code drop-in, to CoreOS cloud config file. We also saw various JSON style request and response templates that fleet uses to interact via APIs. In the last section we took a look at few of the useful fleet APIs that can prove to be helpful while setting up or reconfiguring your fleet server.

Like what you read? Give Devup a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.