garrison
garrison copied to clipboard
A kind of deployment tool thingy
garrison
Garrison is a simple tool I use for deploying docker containers to large amounts of servers, mostly on EC2.
The idea behind it is that most people just need a few bash scripts to be run on a lot of servers, and don't want to mess around with larger scale "Cloud" solutions.
If you're using auto-scaling or something like that, then this probably isn't for you. Garrison uses a push model, where you probably need a pull model. Consider just setting up your build scripts as "User Data"?
Requirements
- golang
- ssh
Installation
go get github.com/AndrewVos/garrison
Usage
Typically, you would create a garrison.json
file in your project root.
This describes what your infrastructure looks like.
You have configuration for each server, and tasks that can be run on each server.
Tasks
Tasks can only be scripts at the moment. They can be run in parallel, and can have environment variables.
When a set of parallel tasks are run, you won't see any output until the first tasks complete. Output from tasks will only show when each task completes.
{
"name": "your-task-name",
"script": "/some-local-file",
"parallel": false,
"environment": {
"ENV_VAR1": "value1",
"ENV_VAR2": "value2"
}
}
Task parameters
Sometimes you might need to pass an environment variable through to some task and you don't want to have to change your configuration every time. For example, you may be telling your build script which git branch you want to build.
You can specify parameters in your task like this:
{
"name": "build",
"parameters": ["BRANCH"],
"script": "build"
}
And then execute garrison as usual and it will use the BRANCH
environment variable:
BRANCH=some-branch garrison group:task
Example with Elasticsearch
Lets say we want to deploy andrewvos/docker-elasticsearch
. We need a task
to build (docker pull) the elasticsearch image on each server, and we need a task
to launch the container on each server.
This is what our garrison.json
file looks like:
[
{
"name": "elastic",
"servers": [
{ "address": "11.11.11.11", "user": "ubuntu" },
{ "address": "22.22.22.22", "user": "ubuntu" }
],
"tasks": [
{ "name": "build", "script": "deployment-scripts/build", "parallel": true },
{ "name": "launch", "script": "deployment-scripts/launch" }
]
}
]
Notice that parallel
is specified for the build
task. This is because we want this task to run
as fast as possible. Garrison will execute the build script on all servers at the same time.
For the launch
task we want to be sure that at least one elasticsearch server is up at a time, so we
don't execute this in parallel.
And we have a bash script for build
:
#!/bin/bash -e
docker pull andrewvos/docker-elasticsearch
And one for launch
:
#!/bin/bash
export CONTAINER=elasticsearch
docker stop $CONTAINER || :
docker rm $CONTAINER || :
docker run -d --name $CONTAINER -p 9200:9200 -p 9300:9300 -v /some/path:/var/lib/elasticsearch andrewvos/docker-elasticsearch
To launch the build
task just run garrison elastic:build
. Note that you can also single out a specific server by using
the address or the index in the task name:
garrison elastic:0:build
garrison elastic:11.11.11.11:build
ZSH Completion
Add the following to your .zprofile
.
fpath=($GOPATH/src/github.com/AndrewVos/garrison/zsh-completion $fpath)