Skip to content

Structure

kako edited this page Apr 30, 2016 · 5 revisions

This document provides a brief explanation of SaltStack and reviews the structure of this repository.

Introduction

Salt delivers a dynamic communication bus for infrastructures that can be used for orchestration, remote execution, configuration management and much more.

In short, Salt works by allowing a master to tell minions to execute states with pillar as defined by the application of targeting rules against the minions' grains.

Some definitions might help:

  • Master: server that tells the minions to execute states
  • Minion: client that executes states as instructed by the master
  • State: command, procedure or check
  • Pillar: variable context of a minion used by states (eg, database connection parameters)
  • Grains: static attributes of a minion (eg, OS)
  • Targeting: definitions for application of pillars and states into minions

Now read that explanation again.

Pillar vs. Grain

Although at first sight the Pillar and Grain seem very similar, a grain value is determined once, when the minion service is started and generally remains the same forever, while a pillar's value is evaluated on every state execution.

This means that grains define general characteristics about a machine (such as its roles or environment), while pillar define specific parameters for salt states (database connection, branch name, etc).

Structure

The main structure of the repository is the following:

salt-config/
  cloud/
  pillar/
  salt/
  vagrant/

Cloud

This directory contains the configurations for Salt-Cloud, a system used to provision virtual machines on various public clouds via a cleanly controlled profile and mapping system.

It consists only of two files:

cloud/
  profiles.conf
  providers.conf

For more information on Salt-Cloud refer to Salt-Cloud.

Providers

Providers are used to abstract all the service-specific configurations away from profiles.

Since we only use AWS EC2 Ubuntu 14.04 machines, we have a single provider:

ec2-public-www:
  driver: ec2
  image: ami-d05e75b8
  minion:
    master: salt.pjtracker.com
...

Profiles

In our configuration, profiles only define the instance type (size) and grains, everything is defined by the provider.

For example, the demo instance has the following attributes:

pjtracker-demo:
  provider: ec2-public-www
  size: t2.micro
  grains:
    box_type: ec2
    app: pjtracker
    env: prod

Note that any attribute defined in an attribute can be overridden in a profile.

Pillar

Pillar allow us to parametrize state execution, by providing a context that is defined dynamically immediately before states are applied. The structure of this directory is the following:

pillar/
  auth/
    ec2.sls
    vagrant.sls
  pjtracker/
    dev.sls
    prod.sls
    shared.sls
    ...
  sonar.sls
  top.sls

Targeting

The targeting rules are defined in the file top.sls, always by using grains. In the following sample we use role, app, env and sub_env:

'G@roles:qua or G@roles:ci':
  - match: compound
  - sonar

'G@app:pjtracker and G@env:prod':
  - match: compound
  - pjtracker.prod

'G@app:pjtracker and G@sub_env:shared':
  - match: compoun
  - pjtracker.shared

Depending on the salt state targeting, some pillar data might be unnecessary for some boxes. In those cases it's good practice to be specific when targeting, to avoid cluttering the minions with useless information, which not only eases analysis but is more secure. That's why we only apply sonar information to qua and ci machines, since other machines would not use that pillar data.

Salt

This directory defines that states are applied to every machine. The structure is very similar to the pillar one:

salt/
  core/
    git.sls
    python.sls
    ...
  pjtracker/
    environment.sls
    repository.sls
    ...
  services/
    jenkins.sls
    postgresql.sls
    ...
  top.sls

Targeting

Targeting is also applied on grains, but since states are not environment-specific we never user env and sub_env. A sample from the file top.sls shows that:

'G@box_type:ec2':
  - match: compound
  - core.swap

'G@app:pjtracker':
  - match: compound
  - pjtracker.service
  - services.nginx

'G@roles:ci':
  - match: compound
  - services.jenkins
  - services.sonarqube.scanner

Pillar as Parameter

Since the salt targeting does not depend on environments, two machines with the same roles and application will execute exactly the same states regardless of environment. Any environment-specific difference is handled by pillar. For instance, the state to clone the repository for pjtracker, is heavily parametrized:

pjtracker-repo:
  git.latest:
    - name: {{ pillar['app']['repository']['url'] }}
    - target: {{ pillar['auth']['home'] }}/{{ pillar['app']['root'] }}
    - branch: {{ pillar['app']['repository']['branch'] }}
    - force_checkout: {{ pillar['app']['repository']['checkout'] }}
    - force_reset: {{ pillar['app']['repository']['checkout'] }}
    - user: {{ pillar['auth']['user'] }}
    - require:
      - file: ssh-config
      - ssh_known_hosts: ssh-github-host

Vagrant

This directory contains the configuration to use Vagrant:

vagrant/
  minion.example
  Vagrantfile

For more information refer to Deployment with Vagrant.

Clone this wiki locally