markround.com

DevOps, Sound Engineering and other things of interest...

Tiller 0.3.0 and New Defaults Datasource

| Comments

Tiller v0.3.0 has just been released, which brings a couple of changes. The first is that the ordering of plugins specified in common.yaml is now significant. Tiller will run these plugins in the order that they are specified; this is important as before the order was effectively random, so your templates may change with this release if you rely on merging values from different sources (hence the major version bump indicating a breaking change).

The reason for this (apart from making Tiller’s behaviour more deterministic) is that there is now a DefaultsDataSource, which allows you to specify global and per-template values in a defaults.yaml (or in separate YAML files under /etc/tiller/defaults.d/) and then over-ride these with other data sources later.

You’ll hopefully find this useful if you have a lot of environments you want to deploy your Docker containers into (Development, Integration, Staging, NFT, Production, etc.) but only a few values change between each one.

Examples

Note : If you’re new to Tiller, I recommend reading the documentation and my other articles on this blog.

Note 2 : Tiller v0.7.0 and later support a new configuration system, where you can place most configuration blocks in one file, instead of splitting it out over different environment files. However, this article still refers to the old “one file per environment” approach as it’s still supported and won’t be removed.

The following is a simple example of how you might use the new DefaultsDataSource to generate a fictional application configuration file. Here’s what your common.yaml might look like :

/etc/tiller/common.yaml
1
2
3
4
5
6
7
8
9
exec: /usr/local/bin/myapp

data_sources:
  - defaults
  - file
  - environment_json

template_sources:
  - file

As mentioned above, the order you load data and template sources is significant. Tiller will use each one in the order it is listed, from top to bottom so you now have control over which module has priority. If you wanted to change it so the file module over-rides values from the environment_json module (see see http://www.markround.com/blog/2014/10/17/building-dynamic-docker-images-with-json-and-tiller-0-dot-1-4/), you’d swap the order above :

data_sources:
  - defaults
  - environment_json
  - file

Now, here’s our example template configuration file that we want to ship with our Docker container :

/etc/tiller/templates/app.conf.erb
1
2
3
4
5
6
7
8
9
[http]
http.port=<%= port %>
http.hostname=<%= environment %>.<%= domain_name %>

[smtp]
mail.domain_name=<%= domain_name %>

[db]
db.host=<%= database %>

In this, you can see that there’s a few dynamic values defined, but we probably don’t want to have to specify them in all our environment files if they’re the same for most of our environments. For example, the domain_name is used in a couple of places, and we’ll also assume that for all our environments the HTTP port will remain the same apart from the staging environment. You can see that if we had a lot of templates to generate, being able to specify the domain_name and other shared variables in a single place will now be much neater.

Let’s now fill in the defaults for our templates. This is done by creating the new defaults.yaml file in your Tiller configuration directory, which is usually /etc/tiller :

/etc/tiller/defaults.yaml
1
2
3
4
5
global:
  domain_name: 'example.com'

app.conf.erb:
  port: '8080'

Now, for all our environments, we only need to provide the values that will change, or that we want to over-ride. Let’s take our “production” environment first – the only thing we want to specify in this example is the database name:

/etc/tiller/environments/production.yaml
1
2
3
4
app.conf.erb:
  target: /tmp/app.conf
  config:
    database: 'prd-db-1.example.com'

Now run Tiller to generate the file :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ tiller -n
tiller v0.3.0 (https://github.com/markround/tiller) <github@markround.com>
Template generation completed

$ cat /tmp/app.conf
[http]
http.port=8080
http.hostname=production.example.com

[smtp]
mail.domain_name=example.com

[db]
db.host=prd-db-1.example.com

Let’s now create a new “staging” environment, and demonstrate over-riding the port as well as setting the database; notice how we’re only setting the values that have changed for this environment :

/etc/tiller/environments/staging.yaml
1
2
3
4
5
app.conf.erb:
  target: /tmp/app.conf
  config:
    port: '8081'
    database: 'stg-db-1.dev.example.com'

And now run Tiller to create our config file for this environment:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ tiller -e staging -n
tiller v0.3.0 (https://github.com/markround/tiller) <github@markround.com>
Warning, merging duplicate data values.
port => '8080' being replaced by : '8081' from FileDataSource
Template generation completed

$ cat /tmp/app.conf
[http]
http.port=8081
http.hostname=staging.example.com

[smtp]
mail.domain_name=example.com

[db]
db.host=stg-db-1.dev.example.com

You’ll notice that Tiller warned you about the value from the DefaultsDataSource being replaced with one from the FileDataSource; you can see here how the ordering of plugins loaded in common.yaml is important.

And there you have it. A short example (and I’ve omitted the creation of the other example environments and templates), but you can see how this new behaviour will make life much easier when you use Tiller as the CMD or ENTRYPOINT in your container. Hopefully this will mean more efficient Tiller configs and will help you create more flexible Docker images. Any feedback or queries, just leave them in the comments section below, or report a bug/request a new feature on the Github issue tracker.

Comments