Salt stack

Preview:

DESCRIPTION

An introduction about how to use salt-stack and how to improve it developing new modules and states with Python

Citation preview

salt-stack

Jose Ignacio Galarza @igalarzab

IndexWhy it’s so cool?

Developing for salt-stack

How to use it?

devops+

python

salt-stack

infrastructure management

master

not a polling model,

PUSHING

send instructions to the minions telling them what to do

PUB/SUB system on 4505

REP system on 4506

master

minion minionminion

SUB REPPUB

awesome diagram

MessagePack to serialize the messages

everything is

encrypted

it uses first public keys for authentication

master needs to know public keys of the minions

then, it uses AES for communication* (symmetric, faster)

how to accept minion keys?$ salt-key Unaccepted Keys: minion_1 !

$ salt-key -a minion_1

$ !

!

!

let’s go!salt ‘*’ test.pingminion_1:

True

minions

controlled machines

receive instructions via

PUB/SUB ZeroMQ

masterless configuration

* (salt-call)

modules

they provide the

functionality

aliases

pip

mysql

filenginxapache

aptssh

upstart

S3

quota

pamiptables mount

execute them with the cli!

$ salt ‘*’ state.highstate ...

$ salt ‘*’ cmd.run ‘ls /’ ...

states

what to manage or

configure in your

hosts

salt-stack states are just DATA

* usually in YAML

they usually map to module functions

!

!

!

!

!

!

!

!

!

/etc/init/nginx.conf:file:

- managed- template: jinja- user: root- require:

- pkg: nginx

understanding states

nginx:   pkg.installed:     - name: nginx   file:     - managed     - name: /etc/init/nginx.conf     - source: salt://nginx.conf     - require:       - pkg: nginx service:     - running     - enable: True - watch:       - file: /etc/nginx/nginx.conf

there are a lot of directives

require watch

includeextend

returners

where to save the

minion output

stdout

SQL DB

mongo

redis

renderers

language of the state

configuration

python

...

YAML

JSON

grains

configuration of the machine

* read-only data

** populated at the beginning

{% if grains['os'] == 'RedHat' %} httpd: pkg: - installed {% elif grains['os'] == 'Debian' %} apache2: pkg: - installed {% endif %}

using grains...

list the grains$ salt ‘*’ grains.ls ...

you can use them everywheredev: ‘os:Debian’: - match: grain - python_server

pillar

think of pillar as a

variable container

it’s data, just as same as the states

{% if grains['os'] == 'RedHat' %} apache: httpd git: git {% elif grains['os'] == 'Debian' %} apache: apache2 git: git-core {% endif %}

create a pillar of salt...

apache: pkg: - installed - name: {{ pillar['apache'] }}

and use it!

only salt-stack?

salt-vagrant

salt-cloud

halite

salt-bootstrap

developing for salt-stack

developing modules

it’s like developing a normal python module!

just create a file inside the _modules dir

every callable is exported*

* (with some exceptions)

import re!!import salt.utils!from salt.utils.decorators import memoize!!REVIEW_RE = re.compile(‘([\w\d_\-]+)==([\d\.]+) is available \(you have ([\d\.]+)\)’)!!!@memoize!def _detect_install():! return salt.utils.which('pip-review')!!!def __virtual__():! return 'piputils' if _detect_install() else False!

creating a module (for the pip-tools package)

!def review(autoinstall=False):! command_ret = __salt__['cmd.run'](! 'pip-review {0}'.format('-a' if autoinstall else '')! )!! packages = command_ret.split('\n')! updates = {}!! for package in packages:! match = REVIEW_RE.match(package)! if match:! name, old_v, new_v = match.groups()! updates[name] = (old_v, new_v)!! return updates!

creating a module (for the pip-tools package)

syncing the modules$ salt-call saltutil.sync_modules ...

and use it!$ salt-call piptools.review machine: ---------- Jinja2: - 2.7.1 - 2.6

useful variables like:

__salt__

__grains__

__outputter__

developing states

it’s (also) like developing a normal python module!

just create a file inside the _states dir

every callable is exported*

* (with some exceptions)

the renderer structure

maps directly to the state python module

def keep_updated(name, min_version=None, max_version=None):! updatable_packages = __salt__['piptools.review']()! pkg_info = updatable_packages.get(name, None)!! ret = {! 'name': name,! 'result': pkg_info is not None,! }!

creating a state (for the pip-tools package)

! if package_info:! ret['comment'] = 'Update {0} from {2} to {1}'.format(! name, *pkg_info! )! ret['changes'] = {!         name: {! 'old': package_info[1],! 'new': package_info[0]! }! }! else:! ret['comment'] = 'Inexistent package {0}'.format(name)!! if __opts__['test']:! ret['result'] = None!    else:! pass # Perform the update!! return ret!

creating a state (for the pip-tools package)

!Jinja2: # maps to "name" argument pip_package: # maps to pip_package state - keep_updated # maps to keep_updated funct - min_version: 1.0 # maps to min_version arg

mapping the file

and that’s all!

http://twitter.com/igalarzabhttp://github.com/igalarzab

questions?

thank you!

Recommended