To illustrate the concept of working with Group, Flavor, and Instance plugins, we use a simple setup composed of
- The default
groupplugin - to manage a collection of instances - The
fileinstance plugin - to provision instances by writing files to disk - The
vanillaflavor plugin - to provide context/ flavor to the configuration of the instances
For more information on plugins and how they work, please see the docs.
First, build the plugins:
$ make binariesInfraKit 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/lostthat 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/groupStart the file Instance plugin
$ mkdir -p tutorial
$ build/infrakit-instance-file --dir ./tutorial
INFO[0000] Listening at: ~/.infrakit/plugins/instance-fileNote 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-vanillaAs 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:24864Once 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-fileDoing 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 stdoutNote 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 TAGSAt this point, we have no instances under management. So let's provision some.
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 TAGSLet'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 instancesChecking with the group plugin, we should see a group called cattle:
$ build/infrakit group ls
ID
cattleThe 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=webThe 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=webAt 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 cattleYou can commit the group to start monitoring it again:
$ build/infrakit group commit cattle.json
Committed cattle: Managing 5 instancesNow 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 10So 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 10If 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=webNote 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/nfrakit group describe cattle > before$ rm ./tutorial/instance-4857202356361893780 ./tutorial/instance-8916238683700118734After a few moments, let's capture the listing
$ build/nfrakit group describe cattle > afterA 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=webLet'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=webWe are back to 10 instances.
Finally, let's clean up:
$ build/infrakit group destroy cattleThis 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
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.