Skip to content

Latest commit

 

History

History
442 lines (356 loc) · 18.7 KB

tutorial.md

File metadata and controls

442 lines (356 loc) · 18.7 KB

A Quick Tour of InfraKit

To illustrate the concept of working with Group, Flavor, and Instance plugins, we use a simple setup composed of

  • The default group plugin - to manage a collection of instances
  • The file instance plugin - to provision instances by writing files to disk
  • The vanilla flavor plugin - to provide context/ flavor to the configuration of the instances

For more information on plugins and how they work, please see the docs.

Building the binaries

First, build the plugins:

$ make binaries

Starting up InfraKit

InfraKit is made up of a collection of small microservice controllers that are commonly referred to as 'plugins'. 'Plugins' implement different Service Provider Interfaces in InfraKit:

  • The 'Instance' SPI is concerned with provisioning a resource
  • The 'Metadata' SPI provides a cluster-wide 'sysfs' where readable properties about the cluster are exposed and accessible as paths like a filesystem.
  • The 'Event' SPI allows the client to subscribe to topics (discoverable as paths) for events that are generated by the resources and controllers in the cluster. For example, you could have a topic called aws/ec2-instance/lost that you can subscribe to receive notification when ec2 instances are lost in the cluster due to crashes or terminations.

InfraKit can be run in different ways such as in Docker containers or as simple daemons. Here we are going with the simple daemons that are built from source. For a quick start with pre-built Docker containers, you can take a look at the Playbook.

There are many different plugins that InfraKit can use to provision resources. In this tutorial we use the very basic file plugin, which simply creates files on disk.

Start the default Group plugin

$ build/infrakit-group-default
INFO[0000] Listening at: ~/.infrakit/plugins/group

Start the file Instance plugin

$ mkdir -p tutorial
$ build/infrakit-instance-file --dir ./tutorial
INFO[0000] Listening at: ~/.infrakit/plugins/instance-file

Note the directory ./tutorial where the plugin will store the instances as they are provisioned. We can look at the files here to see what's being created and how they are configured.

Start the vanilla Flavor plugin

$ build/infrakit-flavor-vanilla
INFO[0000] Listening at: ~/.infrakit/plugins/flavor-vanilla

The CLI

As a user, you typically interact with the cluster and resources you provisioned via the infrakit CLI. The CLI can connect to local system as well as remote clusters (called 'remotes').

Which remote or local target to connect to is controlled by the INFRAKIT_HOST environment variable. When this variable is unset or not defined, infrakit CLI will look at local plugins which are discoverable on your localhost at $INFRAKIT_HOME/plugins.

To see, add or remove remotes, you would use the infrakit remote subcommand. For example:

$ build/infrakit remote ls
HOST                          	URL LIST
docker4mac                    	localhost:24864
if1                           	54.219.137.138:24864
swarm1                        	52.53.247.176:24864,54.215.167.235:24864,54.193.100.40:24864
test1                         	54.215.224.155:24864

Once a 'remote' has been added, you can change the target of the CLI by setting the INFRAKIT_HOST environment variable.

The infrakit CLI dynamically configures itself based on the set of plugins it has access to.

Show the plugins:

$ build/infrakit plugin ls
INTERFACE           LISTEN                                            NAME
Flavor/0.1.0        /Users/davidchung/.infrakit/plugins/flavor-vanillaflavor-vanilla
Group/0.1.0         /Users/davidchung/.infrakit/plugins/group         group
Metadata/0.1.0      /Users/davidchung/.infrakit/plugins/group         group
Instance/0.5.0      /Users/davidchung/.infrakit/plugins/instance-file instance-file

Doing a simple infrakit -h will show all the possible commands and options:

$ build/infrakit -h


infrakit command line interface

Usage:
  infrakit [command]

Available Commands:
  event          Access event exposed by infrakit plugins
  flavor-vanilla Access plugin flavor-vanilla which implements Flavor/0.1.0
  group          Access plugin group which implements Group/0.1.0,Metadata/0.1.0
  instance-file  Access plugin instance-file which implements Instance/0.5.0
  manager        Access the manager
  metadata       Access metadata exposed by infrakit plugins
  playbook       Manage playbooks
  plugin         Manage plugins
  remote         Manage remotes
  template       Render an infrakit template at given url.  If url is '-', read from stdin
  util           Utilties
  version        Print build version information
  x              Experimental features

Flags:
      --httptest.serve string   if non-empty, httptest.NewServer serves on this address and blocks
      --log int                 log level (default 4)
      --log-caller              include caller function (default true)
      --log-format string       log format: logfmt|term|json (default "term")
      --log-stack               include caller stack
      --log-stdout              log to stdout

Note that in this case, we have three commands that are dynamically created for accessing the running flavor-vanilla, group, instance-file plugins:

  flavor-vanilla Access plugin flavor-vanilla which implements Flavor/0.1.0
  group          Access plugin group which implements Group/0.1.0,Metadata/0.1.0
  instance-file  Access plugin instance-file which implements Instance/0.5.0

For example:

$ build/infrakit instance-file -h


Access plugin instance-file which implements Instance/0.5.0

Usage:
  infrakit instance-file [command]

Available Commands:
  describe    Describe all managed instances across all groups, subject to filter
  destroy     Destroy the instance
  info        print plugin info
  provision   Provisions an instance.  Read from stdin if url is '-'
  validate    Validates an flavor config.  Read from stdin if url is '-'

The verbs as available commands are available based on the interface the plugin object implements.

To list all the 'file' instances we have managed by the instance-file plugin, we simply do this:

infrakit@ Wed May 24-16:24:09 demo % infrakit instance-file describe
ID                            	LOGICAL                       	TAGS

At this point, we have no instances under management. So let's provision some.

Provision a Group of Instances

Now we must create the JSON for a group. You will find that the JSON structures follow a pattern:

{
   "Plugin": "PluginName",
   "Properties": {
   }
}

This defines the name of the Plugin to use and the Properties to configure it with. The plugins are free to define their own configuration schema. Plugins in this repository follow a convention of using a Spec Go struct to define the Properties schema for each plugin. The group.Spec in the default Group plugin, and vanilla.Spec are examples of this pattern.

From listing the plugins earlier, we have two plugins running. instance-file is the name of the File Instance Plugin, and flavor-vanilla is the name of the Vanilla Flavor Plugin. So now we have the names of the plugins and their configurations.

Putting everything together, we have the configuration to give to the default Group plugin:

{
  "ID": "cattle",
  "Properties": {
    "Allocation": {
      "Size": 5
    },
    "Instance": {
      "Plugin": "instance-file",
      "Properties": {
        "Note": "Instance properties version 1.0"
      }
    },
    "Flavor": {
      "Plugin": "flavor-vanilla",
      "Properties": {
        "Init": [
          "docker pull nginx:alpine",
          "docker run -d -p 80:80 nginx-alpine"
        ],
        "Tags": {
          "tier": "web",
          "project": "infrakit"
        },
        "Attachments" :  [{"ID":"attachid", "Type": "attachtype"}]
      }
    }
  }
}

Save this as cattle.json

Note that we specify the number of instances via the Size parameter in the flavor-vanilla plugin. It's possible that a specialized Flavor plugin doesn't even accept a size for the group, but rather computes the optimal size based on some criteria.

Checking for the instances via the CLI:

$ build/infrakit instance-file describe
ID                              LOGICAL                         TAGS

Let's tell the group plugin to commit our group by providing the group plugin with the configuration:

$ build/infrakit group commit ./cattle.json
Committed cattle: Managing 5 instances

Checking with the group plugin, we should see a group called cattle:

$ build/infrakit group ls
ID
cattle

The group plugin is responsible for ensuring that the infrastructure state matches with your specifications. Since we started out with nothing, it will create 5 instances and maintain that state by monitoring the instances:

$ build/infrakit group describe cattle
ID                            	LOGICAL                       	TAGS
instance-4582464082013813178  	  -                           	infrakit.config_sha=x4nrsdaibscmj7awpkxzx5vvpt6pilw2,infrakit.group=cattle,project=infrakit,tier=web
instance-4657666275748037214  	  -                           	infrakit.config_sha=x4nrsdaibscmj7awpkxzx5vvpt6pilw2,infrakit.group=cattle,project=infrakit,tier=web
instance-5419344861148823408  	  -                           	infrakit.config_sha=x4nrsdaibscmj7awpkxzx5vvpt6pilw2,infrakit.group=cattle,project=infrakit,tier=web
instance-6391471917728203585  	  -                           	infrakit.config_sha=x4nrsdaibscmj7awpkxzx5vvpt6pilw2,infrakit.group=cattle,project=infrakit,tier=web
instance-7797144284686029457  	  -                           	infrakit.config_sha=x4nrsdaibscmj7awpkxzx5vvpt6pilw2,infrakit.group=cattle,project=infrakit,tier=web

The Instance Plugin can also report instances, it will report all instances across all groups (not just cattle).

$ build/infrakit instance-file describe
ID                            	LOGICAL                       	TAGS
instance-4582464082013813178  	  -                           	infrakit.config_sha=x4nrsdaibscmj7awpkxzx5vvpt6pilw2,infrakit.group=cattle,project=infrakit,tier=web
instance-4657666275748037214  	  -                           	infrakit.config_sha=x4nrsdaibscmj7awpkxzx5vvpt6pilw2,infrakit.group=cattle,project=infrakit,tier=web
instance-5419344861148823408  	  -                           	infrakit.config_sha=x4nrsdaibscmj7awpkxzx5vvpt6pilw2,infrakit.group=cattle,project=infrakit,tier=web
instance-6391471917728203585  	  -                           	infrakit.config_sha=x4nrsdaibscmj7awpkxzx5vvpt6pilw2,infrakit.group=cattle,project=infrakit,tier=web
instance-7797144284686029457  	  -                           	infrakit.config_sha=x4nrsdaibscmj7awpkxzx5vvpt6pilw2,infrakit.group=cattle,project=infrakit,tier=web

At any point you can safely free a group. This is a non-destructive action, which instructs InfraKit to cease active monitoring. No instances are affected, but InfraKit will no longer manage them.

$ build/infrakit group free cattle
Freed cattle

You can commit the group to start monitoring it again:

$ build/infrakit group commit cattle.json
Committed cattle: Managing 5 instances

Now let's update the configuration by changing the size of the group and a property of the instance. Save this file as cattle2.json:

{
  "ID": "cattle",
  "Properties": {
    "Allocation": {
      "Size": 10
    },
    "Instance": {
      "Plugin": "instance-file",
      "Properties": {
        "Note": "Instance properties version 2.0"
      }
    },
    "Flavor": {
      "Plugin": "flavor-vanilla",
      "Properties": {
        "Init": [
          "docker pull nginx:alpine",
          "docker run -d -p 80:80 nginx-alpine"
        ],
        "Tags": {
          "tier": "web",
          "project": "infrakit"
        },
        "Attachments" :  [{"ID":"attachid", "Type": "attachtype"}]
      }
    }
  }
}

Save this as cattle2.json

$ diff cattle.json cattle2.json 
7c7
<                 "Note": "Instance properties version 1.0"
---
>                 "Note": "Instance properties version 2.0"
13c13
<                 "Size": 5,
---
>                 "Size": 10,

Before we do an update, we can see what the proposed changes are:

$ build/infrakit group commit cattle2.json --pretend 
Committing cattle would involve: Performing a rolling update on 5 instances, then adding 5 instances to increase the group size to 10

So here 5 instances will be updated via rolling update, while 5 new instances at the new configuration will be created.

Let's apply the new config:

$ build/infrakit group commit cattle2.json 
Committed cattle: Performing a rolling update on 5 instances, then adding 5 instances to increase the group size to 10

If we poll the group, we can see state will converging until all instances have been updated:

$ build/infrakit group describe cattle
ID                            	LOGICAL                       	TAGS
instance-4857202356361893780  	  -                           	infrakit.config_sha=jpfedp4sefvncwye5b6yre5qoz2odtnd,infrakit.group=cattle,project=infrakit,tier=web
instance-5331231286773283071  	  -                           	infrakit.config_sha=jpfedp4sefvncwye5b6yre5qoz2odtnd,infrakit.group=cattle,project=infrakit,tier=web
instance-5527424552965675861  	  -                           	infrakit.config_sha=jpfedp4sefvncwye5b6yre5qoz2odtnd,infrakit.group=cattle,project=infrakit,tier=web
instance-6711510839918342232  	  -                           	infrakit.config_sha=jpfedp4sefvncwye5b6yre5qoz2odtnd,infrakit.group=cattle,project=infrakit,tier=web
instance-6870580757786415410  	  -                           	infrakit.config_sha=jpfedp4sefvncwye5b6yre5qoz2odtnd,infrakit.group=cattle,project=infrakit,tier=web
instance-7164654173522392740  	  -                           	infrakit.config_sha=jpfedp4sefvncwye5b6yre5qoz2odtnd,infrakit.group=cattle,project=infrakit,tier=web
instance-7416472420378252869  	  -                           	infrakit.config_sha=jpfedp4sefvncwye5b6yre5qoz2odtnd,infrakit.group=cattle,project=infrakit,tier=web
instance-7470730388550100679  	  -                           	infrakit.config_sha=jpfedp4sefvncwye5b6yre5qoz2odtnd,infrakit.group=cattle,project=infrakit,tier=web
instance-7585119672637883592  	  -                           	infrakit.config_sha=jpfedp4sefvncwye5b6yre5qoz2odtnd,infrakit.group=cattle,project=infrakit,tier=web
instance-8916238683700118734  	  -                           	infrakit.config_sha=jpfedp4sefvncwye5b6yre5qoz2odtnd,infrakit.group=cattle,project=infrakit,tier=web

Note the instances now have a new SHA jpfedp4sefvncwye5b6yre5qoz2odtnd while perviously we had x4nrsdaibscmj7awpkxzx5vvpt6pilw2.

To see that the Group plugin can enforce the size of the group, let's simulate an instance disappearing.

For comparison, we capture the listing before we destroy instances

$ build/infrakit group describe cattle > before
$ rm ./tutorial/instance-4857202356361893780 ./tutorial/instance-8916238683700118734

After a few moments, let's capture the listing

$ build/infrakit group describe cattle > after

A quick diff shows that 2 instances have been replaced:

$ diff before after
2c2,3
< instance-4857202356361893780  	  -                           	infrakit.config_sha=jpfedp4sefvncwye5b6yre5qoz2odtnd,infrakit.group=cattle,project=infrakit,tier=web
---
> instance-2554519562373330601  	  -                           	infrakit.config_sha=jpfedp4sefvncwye5b6yre5qoz2odtnd,infrakit.group=cattle,project=infrakit,tier=web
> instance-3947516675797073281  	  -                           	infrakit.config_sha=jpfedp4sefvncwye5b6yre5qoz2odtnd,infrakit.group=cattle,project=infrakit,tier=web
11d11
< instance-8916238683700118734  	  -                           	infrakit.config_sha=jpfedp4sefvncwye5b6yre5qoz2odtnd,infrakit.group=cattle,project=infrakit,tier=web

Let's look at the instances:

$ build/infrakit group describe cattle
ID                            	LOGICAL                       	TAGS
instance-2554519562373330601  	  -                           	infrakit.config_sha=jpfedp4sefvncwye5b6yre5qoz2odtnd,infrakit.group=cattle,project=infrakit,tier=web
instance-3947516675797073281  	  -                           	infrakit.config_sha=jpfedp4sefvncwye5b6yre5qoz2odtnd,infrakit.group=cattle,project=infrakit,tier=web
instance-5331231286773283071  	  -                           	infrakit.config_sha=jpfedp4sefvncwye5b6yre5qoz2odtnd,infrakit.group=cattle,project=infrakit,tier=web
instance-5527424552965675861  	  -                           	infrakit.config_sha=jpfedp4sefvncwye5b6yre5qoz2odtnd,infrakit.group=cattle,project=infrakit,tier=web
instance-6711510839918342232  	  -                           	infrakit.config_sha=jpfedp4sefvncwye5b6yre5qoz2odtnd,infrakit.group=cattle,project=infrakit,tier=web
instance-6870580757786415410  	  -                           	infrakit.config_sha=jpfedp4sefvncwye5b6yre5qoz2odtnd,infrakit.group=cattle,project=infrakit,tier=web
instance-7164654173522392740  	  -                           	infrakit.config_sha=jpfedp4sefvncwye5b6yre5qoz2odtnd,infrakit.group=cattle,project=infrakit,tier=web
instance-7416472420378252869  	  -                           	infrakit.config_sha=jpfedp4sefvncwye5b6yre5qoz2odtnd,infrakit.group=cattle,project=infrakit,tier=web
instance-7470730388550100679  	  -                           	infrakit.config_sha=jpfedp4sefvncwye5b6yre5qoz2odtnd,infrakit.group=cattle,project=infrakit,tier=web
instance-7585119672637883592  	  -                           	infrakit.config_sha=jpfedp4sefvncwye5b6yre5qoz2odtnd,infrakit.group=cattle,project=infrakit,tier=web

We are back to 10 instances.

Finally, let's clean up:

$ build/infrakit group destroy cattle

This concludes our quick tutorial. In this tutorial we:

  • Started the plugins and learned to access them
  • Created a configuration for a group we wanted to manage
  • Verified the instances created matched the specifications
  • Updated the configurations of the group and scaled up the group
  • Reviewed the proposed changes
  • Applied the update across the group
  • Removed some instances and observed that the group self-healed
  • Destroyed the group

Next Step

Now that you have completed the tutorial, it's time to explore the Playbooks. Playbooks are 'scripts' that can be shared and reused. Playbooks can drive the infrakit CLI by defining new commands and flags. A good one to start is the LinuxKit playbook, where we explore integration with LinuxKit.