Flexibleres Targeting mit SaltStack

linux saltstack python

Saltstack bringt eigentlich schon einige Features mit um ein Targeting der verwalteten Server zu erleichtern. Am einfachsten ist natürlich der Aufruf salt '*' state.highstate, der einfach alle Server versorgt. Und auch die Unterscheidung zwischen Live und Testsystemen ist, entsprechende Benamung der Server vorausgesetzt, ein leichtes: salt 'prod.*' state.highstate bzw. salt 'test.*' state.highstate. Jetzt muss man ja nicht immer gleich einen Highstate werden und hier wird es dann schnell etwas schwieriger. Nicht jeder Produktivserver braucht jeden State. Wer welchen benötigt ist zwar in der top.sls von SaltStack festgelegt, aber das will man ja nicht jedes Mal händisch durchgehen. SaltStack bietet hier an Gruppen in der master-Konfiguration zu erzeugen.

bare:
  - 'proxy*'
  - 'web*'
  - 'storage*'
  - 'database*'
  - 'backup*'

Die Gruppen kann man dann mittels salt -N bare test.version ansteuern. Für feststehende, bzw. über den Namen der Server zuordbare, Gruppen ist das sehr praktisch. Ich habe aber ein paar Server, die zwar von der Namensvergabe her gleich sind, aber dennoch unterschiedliche States benötigen. Für diese lohnt es sich im Zweifel nicht auf Gruppen zurückzugreifen.

Daher habe ich mir ein kleines Script (salt_find.py) geschrieben:

#!/usr/bin/python

import yaml
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('state', help='State to execute')
parser.add_argument('-e', '--saltenv', default='base', help='saltenv to be used')
parser.add_argument('-c', '--config', default='/srv/salt/states/base/top.sls', help='Location of the main sls file')
parser.add_argument('-s', '--substitute', help='Substitute * in results')
args = parser.parse_args()

with open(args.config, 'r') as stream:
        try:
                yaml_data = yaml.safe_load(stream)
        except yaml.YAMLError as err:
                print(err)

for item in yaml_data[args.saltenv]:
        if args.state in yaml_data[args.saltenv][item]:
                if args.substitute:
                        item = item.replace("*", args.substitute)
                cmd = "salt '" + str(item) + "' state.sls " + str(args.state) + " saltenv=" + str(args.saltenv)
                print cmd

Das Script greift auf die top.sls von SaltStack zu, in der alle States den entsprechenden Servern zugewiesen sind. Server können hier unterschiedlichen Umgebungen (saltenv) zugewiesen sein, diese berücksichtigt das Script natürlich. In meiner top.sls werden einige Server mittels *.kundenname.internal zugeordnet. Dahinter verbergen sich dann meist prod.kundenname.internal und test.kundenname.internal. In der Regel möchte ich natürlich einen State zuerst nur auf den Testsystemen ausführen, daher kann man das Script anweisen * entsprechend zu ersetzen (substitute).

Das Script gibt dann die jeweils erforderlichen salt-Kommandos aus. Im Grunde könnte das Script diese natürlich auch direkt ausführen, ich finde es aber besser dies manuell zu machen, falls sich bei der Suche Überraschungen ergeben (man könnte natürlich auch einen --dry-run-Parameter einbauen).


Comments

Blog Comments powered by Disqus.

Previous Post