Table des matières
SaltStack
- Tuto 3 :
Configurer le master
$ systemctl start salt-master $ systemctl enable salt-master
Configurer le minion
- Editer le fichier
/etc/salt/minion.d/master.conf
et indiquer lui votre master :
master: salt-master
- On démarre et active au boot le service :
$ systemctl start salt-minion $ systemctl enable salt-minion
- On voit apparaître portable.localdomain dans les liste des minions qui n'ont pas encore été acceptés :
salt-key -L a Accepted Keys: Denied Keys: Unaccepted Keys: portable.localdomain
- On génère une fingerprint pour ce minion sur le minion :
salt-call key.finger --local local: 14:e6:21:3b:0c:f9:0a:96:ea:5a:69:bb:2e:82:b4:c7:18:3c:4f:09:40:d2:46:8f:f9:09:e9:81:87:15:1a:0f
- On donne cette figerprint à portable.localdomain :
salt-key -f portable.localdomain Unaccepted Keys: portable.localdomain: 14:e6:21:3b:0c:f9:0a:96:ea:5a:69:bb:2e:82:b4:c7:18:3c:4f:09:40:d2:46:8f:f9:09:e9:81:87:15:1a:0f
- Puis on accepte la clé :
salt-key -a portable.localdomain The following keys are going to be accepted: Unaccepted Keys: portable.localdomain Proceed? [n/Y] Key for minion portable.localdomain accepted.
- On vérifie les clés :
salt-key -L a [sudo] Mot de passe de gigix : Accepted Keys: portable.localdomain Denied Keys: Unaccepted Keys: Rejected Keys:
- On vérifie le fonctionnement :
sudo salt 'portable.localdomain' test.ping portable.localdomain: True
- Sécurisons le minion avec la fingerprint du master. On récupère sa fingerprint publique :
salt-key -f master.pub Local Keys: master.pub: 1b:5e:6d:ae:20:65:dd:f1:62:0b:9b:85:eb:3a:38:8d:ec:d6:cf:98:06:3d:ca:65:fb:a7:dd:c6:86:15:bb:96
- On édite le fichier
/etc/salt/minion.d/master.conf
:
master: localhost master_finger: '1b:5e:6d:ae:20:65:dd:f1:62:0b:9b:85:eb:3a:38:8d:ec:d6:cf:98:06:3d:ca:65:fb:a7:dd:c6:86:15:bb:96'
- On restart le service :
systemctl restart salt-minion
- On teste à nouveau :
salt 'portable.localdomain' test.ping portable.localdomain: True
Afficher les clés
- La clé locale du minion:
salt-call key.finger --local local: 14:e6:21:3b:0c:f9:0a:96:ea:5a:69:bb:2e:82:b4:c7:18:3c:4f:09:40:d2:46:8f:f9:09:e9:81:87:15:1a:0f
- Les clés du master :
salt-key -F Local Keys: master.pem: 83:9f:f3:37:c6:6c:f8:55:5e:84:c7:60:4d:10:59:ce:a2:81:23:47:1a:bf:df:c1:6f:f1:3f:85:48:ee:8a:b0 master.pub: 1b:5e:6d:ae:20:65:dd:f1:62:0b:9b:85:eb:3a:38:8d:ec:d6:cf:98:06:3d:ca:65:fb:a7:dd:c6:86:15:bb:96 Accepted Keys: portable.localdomain: 14:e6:21:3b:0c:f9:0a:96:ea:5a:69:bb:2e:82:b4:c7:18:3c:4f:09:40:d2:46:8f:f9:09:e9:81:87:15:1a:0f
Rafraichir les Pillar / Grains / ..
Les pillars sont chargés quand le minion démarre, ou on peu le faire manuellement :
salt '*' saltutil.refresh_pillar salt '*' saltutil.refresh_grains
Tout resynchroniser :
salt '*' saltutil.sync_all
Exemples
Client en standalone (serverless) :
salt-call --local grains.items
Exécution sur le master :
salt-run test.foo
Exécution vers un cloud provider (https://docs.saltstack.com/en/latest/topics/cloud/index.html) :
salt-cloud
Client vers serveur :
salt-call grains.items
Serveur vers clients via SSH (agentless) :
salt-ssh -i --roster-file=./roster 'node1' test.ping
Exemple de fichier roster (toutes les options du fichier roster) :
node1: host: 192.168.122.1 user: root priv: /root/.ssh/id_rsa
Serveur vers clients via client salt :
salt '*' cmd.run 'ls -l /etc' salt '*' test.ping
Autres :
salt '*' cmd.run 'echo "Hello: $FIRST_NAME"' saltenv='{FIRST_NAME: "Joe"}'
salt myminion grains.item pythonpath --out=pprint
salt '*' cp.get_file salt://vimrc /etc/vimrc salt '*' cp.get_file "salt://{{grains.os}}/vimrc" /etc/vimrc template=jinja
salt '*' -b 10 test.ping salt -G 'os:RedHat' --batch-size 25% apache.signal restart
base: 'not webserv* and G@os:Debian or E@web-dc1-srv.* and ( ms-1 or G@id:ms-3 ) or J|@foo|bar|^foo:bar$': - match: compound - webserver
Documentation
States :
salt '*' sys.doc salt '*' sys.doc cmd salt '*' sys.doc cmd.run
Runner :
salt-run doc.runner
Structure d'un SLS
<Include Declaration>: - <Module Reference> - <Module Reference> <Extend Declaration>: <ID Declaration>: [<overrides>] # standard declaration <ID Declaration>: <State Module>: - <Function> - <Function Arg> - <Function Arg> - <Function Arg> - <Name>: <name> - <Requisite Declaration>: - <Requisite Reference> - <Requisite Reference> # inline function and names <ID Declaration>: <State Module>.<Function>: - <Function Arg> - <Function Arg> - <Function Arg> - <Names>: - <name> - <name> - <name> - <Requisite Declaration>: - <Requisite Reference> - <Requisite Reference> # multiple states for single id <ID Declaration>: <State Module>: - <Function> - <Function Arg> - <Name>: <name> - <Requisite Declaration>: - <Requisite Reference> <State Module>: - <Function> - <Function Arg> - <Names>: - <name> - <name> - <Requisite Declaration>: - <Requisite Reference>
- Corrrecte :
httpd: pkg.installed: []
Ou
httpd: pkg: - installed
httpd: pkg.installed: [] service.running: []
ius: pkgrepo.managed: - humanname: IUS Community Packages for Enterprise Linux 6 - $basearch - gpgcheck: 1 - baseurl: http://mirror.rackspace.com/ius/stable/CentOS/6/$basearch - gpgkey: http://dl.iuscommunity.org/pub/ius/IUS-COMMUNITY-GPG-KEY - names: - ius - ius-devel: - baseurl: http://mirror.rackspace.com/ius/development/CentOS/6/$basearch
- Incorrecte :
httpd: pkg.installed service.running
Exécution des sls
- Exécuter toutes les SLS :
salt '*' state.apply
- Exécuter la sls gigix :
salt '*' state.apply gigix
- Avec des paramètres et plusieurs sls :
salt '*' state.apply mysls1,mysls2 test=true saltenv=dev pillarenv=dev pillar='{"key": "val"}' exclude="[{'id': 'id_to_exclude'}, {'sls': 'sls_to_exclude'}]"
- Avec targetting par Pillar :
salt --pillar 'webserver_role:dev' state.apply
- Seulement un id d'une sls :
salt-call --local --file-root=$PWD state.sls_id this_state_will_return_changes test local: ---------- ID: this_state_will_return_changes Function: test.succeed_with_changes Result: True Comment: Success! Started: 00:38:08.528352 Duration: 0.287 ms Changes: ---------- testing: ---------- new: Something pretended to change old: Unchanged Summary for local ------------ Succeeded: 1 (changed=1) Failed: 0 ------------ Total states run: 1 Total run time: 0.287 ms
Targeting
https://docs.saltstack.com/en/latest/ref/states/top.html#advanced-minion-targeting
- globbing sur le nom des minions :
salt 'web[1-5]' test.ping salt 'web[1,3]' test.ping salt '*.example.*' test.ping salt 'web?.example.net' test.ping
base: 'web[1,3]': - match: glob - webserver
- regexp sur le nom des minions
salt -E 'web1-(prod|devel)' test.ping
base: 'web1-(prod|devel)': - match: pcre - webserver
- Liste de minion :
salt -L 'web1,web2,web3' test.ping
base: 'web1,web2,web3': - match: list - webserver
- Grain :
salt -G 'os:Fedora' test.ping
'node_type:webserver': - match: grain - webserver
- Grain avec regexp :
salt 'P@os:(RedHat|Fedora|CentOS)' test.ping
'os:Fedo.*': - match: grain_pcre - webserver
- Pillar exacte :
'cheese:foo': - match: pillar_exact - webserver
- Pillar globing :
salt -I 'somekey:specialvalue' test.ping salt -I 'foo:bar:baz*' test.ping
'cheese:foo:baz*': - match: pillar - webserver
- Pillar avec regexp :
salt 'J@pdata:^(foo|bar)$' test.ping
'cheese:(swiss|american)': - match: pillar_pcre - webserver
- Groupes (les nodesgroups sont à déclarer dans le fichier
/etc/salt/master
) :
nodegroups: group1: 'L@foo.domain.com,bar.domain.com,baz.domain.com and bl*.domain.com' group2: 'G@os:Debian and foo.domain.com' group3: 'G@os:Debian and N@group1'
base: group1: - match: nodegroup - webserver
- Network :
salt -S 192.168.40.20 test.ping salt -S 2001:db8::/64 test.ping
'172.16.0.0/12': - match: ipcidr - internal
- Multiples :
salt -C 'G@os:Debian and webser* or E@db.*' test.ping salt -C '* and not G@kernel:Darwin' test.ping salt -C '( ms-1 or G@id:ms-3 ) and G@id:ms-3' test.ping
base: 'webserv* and G@os:Debian or E@web-dc1-srv.*': - match: compound - webserver
- Range cluster (non supporté de base) :
salt 'R@%test:APPS' test.ping
CLUSTER: host1..100.test.com APPS: - frontend - backend - mysql
- data (avec le minion datastore) :
Désactiver un sls
salt '*' state.disable mysql
Pour lister ceux qui ont été désactivés :
salt '*' state.list_disabled
Réactiver un sls
salt '*' state.enable gigix
Voir les sls
salt '*' state.show_highstate salt '*' state.show_lowstate salt '*' state.show_low_sls foo saltenv=dev salt '*' state.show_sls core,edit.vim dev
Voir le contenu top sls des serveurs :
salt '*' state.show_top
Voir les sls en cours d'exécution
salt '*' state.running local: - The function "state.apply" is running as PID 13972 and was started at 2018, Mar 03 13:14:07.242163 with jid 20180303131407242163
Voir les statistiques d'exécution des sls
salt '*' state.show_state_usage
Récupérer une variable
- Récupérer un Pillar :
{{ salt['pillar.get']('foo:bar:baz', 'qux') }}
- Récupérer un Grain :
{{ salt['grains.get']('node_type', '') }}
Lister Pillar / Grains
- Grains :
salt '*' grains.items
- Pillar
salt '*' pillar.items
Définir une variable
- Définir une variable :
{% set the_node_type = salt['grains.get']('node_type', '') %}
{% set name = { 'RedHat': 'httpd', 'Debian': 'apache2', }.get(grains.os_family) %}
Executer un module
- Appeler un module :
{{ salt['module.function_name']('argument_1', 'argument_2') }} {{ salt['cmd.run']('pgrep -f redis-server') }}
Conditions
{% set ethhb = salt['pillar.get']('eth-hb', 'bond1') %} {% if grains['ip4_interfaces'][ethhb][0].startswith('192.168.1.') %} host.present: - ip: {{ grains['ip4_interfaces'][ethhb][0] }} - names: - {{ grains['host'] }}-hb {% else %} cmd.run: - name: "echo '{{ ethhb }} is not properly configured !'; exit 1" {% endif %}
Boucles
{% for user, uid in pillar.get('users', {}).items() %} {{user}}: user.present: - uid: {{uid}} {% endfor %}
Macro
La maccro est une sorte de fonction :
# macro message {% macro message(name, comment, changes=False, result=False, failhard=True) -%} pacemaker-{{ sls }}-{{ name }}: test.configurable_test_state: - name: pacemaker-{{ sls }}-{{ name }} - changes: {{ changes }} - result: {{ result }} - comment: {{ comment }} - failhard: {{ failhard }} {%- endmacro %} {{ message('error-test', 'mon erreur !!!', failhard=False) }}
Quitter lors d'une erreur
Avec l'option failhard :
/etc/yum.repos.d/company.repo: file.managed: - source: salt://company/yumrepo.conf - user: root - group: root - mode: 644 - order: 1 - failhard: True
Ordonnancement
L'ordonnancement est possible grâce à require ou require_in (sa dépendance inversée) :
httpd: pkg.installed: [] service.running: - require: - pkg: httpd - sls: network
vim: pkg.installed: - require_in: - file: /etc/vimrc /etc/vimrc: file.managed: - source: salt://edit/vimrc
On peu également faire appel à order
:
apache: pkg.installed: - name: httpd - order: 1
Pour désigner le dernier : order: last
ou order: -1
.
Exécution sur changement
L'exécution sur changement est possible grâce à onchanges ou onchanges_in (sa dépendance inversée). S'exécute seulement si le résultat de l'exécution cible est un succès et si la cible a des changements :
Deploy server package: file.managed: - name: /usr/local/share/myapp.tar.xz - source: salt://myapp.tar.xz Extract server package: archive.extracted: - name: /usr/local/share/myapp - source: /usr/local/share/myapp.tar.xz - archive_format: tar - onchanges: - file: Deploy server package
# (Archive arguments omitted for simplicity) # Match by ID declaration Extract server package: archive.extracted: - onchanges: - file: Deploy server package # Match by name parameter Extract server package: archive.extracted: - onchanges: - file: /usr/local/share/myapp.tar.xz
Cela se fait également avec watch et watch_in. watch agit comme require, mais ajoute un comportement supplémentaire (mod_watch). C'est à dire que si le module à une fonction mod_watchalors celle-ci sera appellée. Tous les modules n'ont pas de fonction mod_watch et s'exécuteront donc comme un simple require :
ntpd: service.running: - watch: - file: /etc/ntp.conf file.managed: - name: /etc/ntp.conf - source: salt://ntp/files/ntp.conf
On peu également le faire avec listen /listen_in.
Contrairement à watch et watch_in, listen et listen_in ne modifieront pas l'ordre des états et peuvent être utilisés pour s'assurer que vos états sont exécutés dans l'ordre dans lequel ils sont définis.
restart-apache2: service.running: - name: apache2 - listen: - file: /etc/apache2/apache2.conf configure-apache2: file.managed: - name: /etc/apache2/apache2.conf - source: salt://apache2/apache2.conf
restart-apache2: service.running: - name: apache2 configure-apache2: file.managed: - name: /etc/apache2/apache2.conf - source: salt://apache2/apache2.conf - listen_in: - service: apache2
Il y a aussi prereq et prereq_in expliqué ici.
Gestion des erreurs
La gestion des erreurs est possible grâce à onfail ou onfail_in (sa dépendance inverse).
primary_mount: mount.mounted: - name: /mnt/share - device: 10.0.0.45:/share - fstype: nfs backup_mount: mount.mounted: - name: /mnt/share - device: 192.168.40.34:/share - fstype: nfs - onfail: - mount: primary_mount
Héritage d'arguments
L'héritage est possible grâce à use ou use_in (sa dépendance inverse).
Dans cet exemple /etc/bar.conf
va prendre les même arguments que /etc/foo.conf
sauf pour la source
qu'il aura redéfini:
/etc/foo.conf: file.managed: - source: salt://foo.conf - template: jinja - mkdirs: True - user: apache - group: apache - mode: 755 /etc/bar.conf file.managed: - source: salt://bar.conf - use: - file: /etc/foo.conf
Exécuter en tant que
L'exécution en tant que est possible grâce à runas ou runas_in (sa dépendance inverse).
django: pip.installed: - name: django >= 1.6, <= 1.7 - runas: daniel - require: - pkg: python-pip run_script: cmd.run: - name: Powershell -NonInteractive -ExecutionPolicy Bypass -File C:\\Temp\\script.ps1 - runas: frank - runas_password: supersecret
unless / onlyif
unless et onlyif lance des commandes shell.
Dans l'exemple ci-dessous, vim sera installé quand toutes les conditions seront fausses :
vim: pkg.installed: - unless: - rpm -q vim-enhanced - ls /usr/bin/vim
onlyif est l'inverse qui signifie quand toutes les conditions serons vraies.
checkcmd
checkcmd permet de vérifier l'état attendu :
comment-repo: file.replace: - name: /etc/yum.repos.d/fedora.repo - pattern: ^enabled=0 - repl: enabled=1 - check_cmd: - ! grep 'enabled=0' /etc/yum.repos.d/fedora.repo
retry
L'option retry lui permet d'être exécuté plusieurs fois jusqu'à ce qu'un résultat souhaité soit obtenu ou que le nombre maximum de tentatives ait été atteint.
Le paramètre attemps contrôle le nombre maximum de fois que l'état sera exécuté. S'il n'est pas spécifié ou si une valeur non valide est spécifiée, la valeur par défaut sera 2.
Le paramètre until définit le résultat requis pour arrêter de réessayer l'état. Si non spécifié ou si une valeur non valide est spécifiée alors la valeur par défaut sera True.
Le paramètre interval définit la durée, en secondes, pendant laquelle le système attendra entre les tentatives. Si elle n'est pas spécifiée ou si une valeur non valide est spécifiée, la valeur par défaut sera 30.
Le paramètre splay permet d'étendre l'intervalle. Si elle n'est pas spécifiée ou si une valeur non valide est spécifiée, la valeur par défaut est 0 (c'est-à-dire qu'il n'y aura pas d'intervalle).
my_retried_state: pkg.installed: - name: nano - retry: attempts: 5 until: True interval: 60 splay: 10
install_nano: pkg.installed: - name: nano - retry: True
wait_for_file: file.exists: - name: /path/to/file - retry: attempts: 15 interval: 30
include / exclude
Fichier ssh/init.sls
:
openssh-client: pkg.installed /etc/ssh/ssh_config: file.managed: - user: root - group: root - mode: 644 - source: salt://ssh/ssh_config - require: - pkg: openssh-client
Fichier ssh/server.sls
:
include: - ssh openssh-server: pkg.installed sshd: service.running: - require: - pkg: openssh-client - pkg: openssh-server - file: /etc/ssh/banner - file: /etc/ssh/sshd_config /etc/ssh/sshd_config: file.managed: - user: root - group: root - mode: 644 - source: salt://ssh/sshd_config - require: - pkg: openssh-server /etc/ssh/banner: file: - managed - user: root - group: root - mode: 644 - source: salt://ssh/banner - require: - pkg: openssh-server
Fichier ssh/custom-server.sls
:
include: - ssh.server extend: /etc/ssh/banner: file: - source: salt://ssh/custom-banner
On peut également exclure un id ou un sls :
exclude: - sls: http - id: /etc/vimrc
provider
Il est de changer le comportement en spécifiant un provider. Par exemple systemd est le provider par défaut pour les services. Si on souhaite passer par init, on utilisera le provider service.
httpd: service.running: - enable: True - provider: service
emacs: pkg.installed: - provider: - cmd: customcmd
parallel
Tout est lancé en parallèle et prendra donc 10 secondes à la place de 15 :
sleep 10: cmd.run: - parallel: True nginx: service.running: - parallel: True - require: - cmd: sleep 10 sleep 5: cmd.run: - parallel: True
backup des changement des fichiers
Le fichier /etc/salt/minion
doit contenir la ligne suivant pour êtreactivé : backup_mode: minion
.
/etc/ssh/sshd_config: file.managed: - source: salt://ssh/sshd_config - backup: minion
- Pour lister les backups :
salt foo.bar.com file.list_backups /tmp/foo.txt foo.bar.com: ---------- 0: ---------- Backup Time: Sat Jul 27 2013 17:48:41.738027 Location: /var/cache/salt/minion/file_backup/tmp/foo.txt_Sat_Jul_27_17:48:41_738027_2013 Size: 13 1: ---------- Backup Time: Sat Jul 27 2013 17:48:28.369804 Location: /var/cache/salt/minion/file_backup/tmp/foo.txt_Sat_Jul_27_17:48:28_369804_2013 Size: 35
- Pour restaurer un backup :
salt foo.bar.com file.restore_backup /tmp/foo.txt 1
- Pour supprimer un backup :
salt foo.bar.com file.delete_backup /tmp/foo.txt 0
high / low state
- High :
Lors de la définition de formules salt dans YAML, les données représentées sont appelées High Data par le compilateur. Lorsque les données sont initialement chargées dans le compilateur, il s'agit d'un seul grand dictionnaire python, ce dictionnaire peut être vu en exécutant :
salt '*' state.show_highstate salt '*' state.show_highstate --out yaml salt '*' state.show_sls edit.vim --out pprint
- Low :
Cette structure “High Data” est ensuite compilée jusqu'au “Low Data”. Les données basses correspondent à ce qui est nécessaire pour créer des exécutions individuelles dans le système de gestion de la configuration de Salt. Les données faibles sont une liste ordonnée d'appels d'état unique à exécuter. Les données faibles sont une liste ordonnée d'appels à état unique à exécuter. Une fois que les données sont compilées, l'ordre d'évaluation peut être vu. Les lowstates peuvent être visualisées en exécutant:
salt '*' state.show_lowstate salt '*' state.low '{name: vim, state: pkg, fun: installed}'
Définir un Pillar
Les pillar sont à définir dans le fichier /srv/pillar/top.sls
.
Exemples :
{{ saltenv }}: '*': - common_pillar
base: '*': - apache dev: 'os:Debian': - match: grain - vim test: '* and not G@os: Debian': - match: compound - emacs
Fichier /srv/pillar/apache.sls
:
apache: lookup: name: httpd config: tmpl: salt://apache/files/httpd.conf
Exemple pour y faire appel :
{{ salt['pillar.get']('apache:lookup:name') }}
Gestion des états de retour
always-passes-with-any-kwarg: test.nop: - name: foo - something: else - foo: bar always-passes: test.succeed_without_changes: - name: foo always-fails: test.fail_without_changes: - name: foo always-changes-and-succeeds: test.succeed_with_changes: - name: foo always-changes-and-fails: test.fail_with_changes: - name: foo my-custom-combo: test.configurable_test_state: - name: foo - changes: True - result: False - comment: bar.baz is-pillar-foo-present-and-bar-is-int: test.check_pillar: - present: - foo - integer: - bar this_state_will_return_changes: test.succeed_with_changes this_state_will_NOT_return_changes: test.succeed_without_changes this_state_is_watching_another_state: test.succeed_without_changes: - comment: 'This is a custom comment' - watch: - test: this_state_will_return_changes - test: this_state_will_NOT_return_changes this_state_is_also_watching_another_state: test.succeed_without_changes: - watch: - test: this_state_will_NOT_return_changes
Gestion des environnements de configuration
Il prend le premier et s'il ne trouve pas il passe au suivant :
file_roots: base: - /srv/salt/prod qa: - /srv/salt/qa - /srv/salt/prod dev: - /srv/salt/dev - /srv/salt/qa - /srv/salt/prod
Jinja
map jinja
On appellera ces fichiers map.jinja.
{% set apache = salt['grains.filter_by']({ 'Debian': { 'server': 'apache2', 'service': 'apache2', 'conf': '/etc/apache2/apache.conf', }, 'RedHat': { 'server': 'httpd', 'service': 'httpd', 'conf': '/etc/httpd/httpd.conf', }, }, merge=salt['pillar.get']('apache:lookup')) %}
{% set htop = salt['grains.filter_by']({ 'Suse': { 'pattern': salt['grains.filter_by']({ '12.3': 'htop', 'default': 'htop', }, grain='osrelease'), }, 'default': { 'pattern': 'htop' }, }, grain='os') %}
On chargera par exemple le fichier apache/map.jinja
dans un fichier sls de la façon suivante :
{% from "apache/map.jinja" import apache with context %} apache: pkg.installed: - name: {{ apache.server }} service.running: - name: {{ apache.service }} - enable: True
runner
manage
- Status des minions :
$ salt-run manage.status down: - portable.localdomain up:
- Minions down :
$ salt-run manage.down - portable.localdomain
- Minions up :
$ salt-run manage.up - portable.localdomain
- Version du client salstack des minions :
$ salt-run manage.versions Master: 2017.7.3 Up to date: ---------- portable.localdomain: 2017.7.3
orchestrate
# /srv/salt/orch/cleanfoo.sls cmd.run: salt.function: - tgt: '*' - arg: - rm -rf /tmp/foo
salt-run state.orchestrate orch.cleanfoo
# /srv/salt/orch/webserver.sls install_nginx: salt.state: - tgt: 'web*' - sls: - nginx
salt-run state.orchestrate orch.webserver
# /srv/salt/orch/web_setup.sls webserver_setup: salt.state: - tgt: 'web*' - highstate: True
salt-run state.orchestrate orch.web_setup
# /srv/salt/orch/deploy.sls create_instance: salt.runner: - name: cloud.profile - prof: cloud-centos - provider: cloud - instances: - server1 - opts: minion: master: master1
# /srv/salt/orch/deploy.sls {% set servers = salt['pillar.get']('servers', 'test') %} {% set master = salt['pillar.get']('master', 'salt') %} create_instance: salt.runner: - name: cloud.profile - prof: cloud-centos - provider: cloud - instances: - {{ servers }} - opts: minion: master: {{ master }}
salt-run state.orchestrate orch.deploy pillar='{"servers": "newsystem1", "master": "mymaster"}'
bootstrap_servers: salt.function: - name: cmd.run - tgt: 10.0.0.0/24 - tgt_type: ipcidr - arg: - bootstrap storage_setup: salt.state: - tgt: 'role:storage' - tgt_type: grain - sls: ceph - require: - salt: webserver_setup webserver_setup: salt.state: - tgt: 'web*' - highstate: True
mine
https://docs.saltstack.com/en/latest/topics/mine/index.html
Une mine est identique à un grains mais moins statique. En effet celui-ci va être actualisé toutes les 60 minutes par défaut contrairement à un grains qui lui est actualisé seulement au démarrage du minion.
On peut changer dans la configuration du minion /etc/salt/minion
la variable mine_interval pour modifier le temps de collecte.
La mine se déclare comme un pillar avec la fonction mine_functions.
mine_functions: test.ping: [] network.ip_addrs: interface: eth0 cidr: '10.0.0.0/8'
Pour forcer la maj de toutes les mines :
salt '*' mine.update
beacons
https://docs.saltstack.com/en/latest/topics/beacons/index.html
Les beacons permettent de placer des hook sur des événements sur les minions.
Pour créer un beacons, créer le fichier /etc/salt/minion.d/beacons.conf
:
beacons: inotify: /etc/important_file: {} /opt: {}
Un autre exemple :
beacons: inotify: /etc/important_file: {} /opt: {} interval: 5 disable_during_state_run: True load: 1m: - 0.0 - 2.0 5m: - 0.0 - 1.5 15m: - 0.1 - 1.0 interval: 10
Par exemple si on modifie le fichier /etc/important_file
, cela va créer un event que l'on peu surveiller de cette façon sur le master :
salt-run state.event pretty=true
Ce qui affichera :
salt/beacon/larry/inotify//etc/important_file { "_stamp": "2015-09-09T15:59:37.972753", "data": { "change": "IN_IGNORED", "id": "larry", "path": "/etc/important_file" }, "tag": "salt/beacon/larry/inotify//etc/important_file" }
Un [#reactor] est la réponse du master à fournir à un minion lors d'un event sur un beacons.
reactor
https://docs.saltstack.com/en/latest/topics/reactor/index.html
Le reactor est la réponse à fournir aux beacons.
Sur le master, créer le fichier /srv/reactor/revert.sls
:
revert-file: local.state.apply: - tgt: {{ data['data']['id'] }} - arg: - maintain_important_file
Il faut maintenant indiquer au reactor d'exécuter le fichier revert sls, pour cela on édite le fichier /etc/salt/master.d/reactor.conf
:
reactor: - salt/beacon/*/inotify//etc/important_file: - /srv/reactor/revert.sls
Exemple de reactor :
reactor: # Master config section "reactor" - 'salt/minion/*/start': # Match tag "salt/minion/*/start" - /srv/reactor/start.sls # Things to do when a minion starts - /srv/reactor/monitor.sls # Other things to do - 'salt/cloud/*/destroyed': # Globs can be used to match tags - /srv/reactor/destroy/*.sls # Globs can be used to match file names - 'myco/custom/event/tag': # React to custom event tags - salt://reactor/mycustom.sls # Reactor files can come from the salt fileserver
Variables utiles
- Configuration du minion :
{{ opts['cachedir'] }}
- Pillar
{{ salt['pillar.get']('key', 'failover_value') }} {{ salt['pillar.get']('stuff:more:deeper') }}
- Grains:
{{ salt['grains.get']('os') }}
- environnement salt (base par défaut) :
{{ saltenv }}
- nom du sls courant :
{{ sls }}
- Chemin du sls :
{{ slspath }}
Copie de fichier
Copie un fichier du master vers les minions :
salt-cp '*' [ options ] SOURCE [SOURCE2 SOURCE3 ...] DEST
syndic
https://docs.saltstack.com/en/latest/topics/topology/syndic.html
salt-syndic permet de compartimenter les minions avec plusieurs masters. Chacun des master gèrent un groupe de minions.
Exemple :
# salt-key -L Accepted Keys: my_syndic Denied Keys: Unaccepted Keys: Rejected Keys: # salt '*' test.ping minion_1: True minion_2: True minion_4: True minion_3: True
proxy
https://docs.saltstack.com/en/latest/topics/proxyminion/index.html
salt-proxy permet de gérer des équipements où on ne peut pas installer de minion comme un switch réseau par exemple.
jobs
https://docs.saltstack.com/en/latest/topics/jobs/ https://docs.saltstack.com/en/latest/ref/runners/all/salt.runners.jobs.html
- Affiche les derniers jobs :
salt-run jobs.list_jobs
- Lancer un job :
On le stop avec Ctrl+c mais je job continue:
sudo salt '*' test.sleep 100 ^C Exiting gracefully on Ctrl-c This job's jid is: 20180304011226668249 The minions may not have all finished running and any remaining minions will return upon completion. To look up the return data for this job later, run the following command: salt-run jobs.lookup_jid 20180304011226668249:
- Savoir le status d'un jobs :
Le job n'a pas fini car il ne retourne rien :
sudo salt-run jobs.lookup_jid 20180304011226668249
Le job a terminé quand il retourne quelque chose :
salt-run jobs.lookup_jid 20180304011226668249 portable.localdomain: True
publish
https://docs.saltstack.com/en/latest/ref/peer.html https://docs.saltstack.com/en/latest/ref/modules/all/salt.modules.publish.html
Permet à un minion d'exécuter une commande sur un autre.
Créer le fichier /etc/salt/master.d/peer.conf
pour autoriser les master entre eux (cet exemple n'est pas sécurisé et est déconseillé) :
peer: .*: - .*
Redémarrer votre master et tester :
salt '*' publish.publish '*' test.ping portable.localdomain: ---------- portable.localdomain: True salt-call publish.publish '*' test.ping local: ---------- portable.localdomain: True
Commentaires
Pour commenter dans un sls il suffit d'utiliser le #
.
Pour commenter un block on peu passer en mode jinja avec {#
et #}
:
{# mon commentaire ligne1 mon commentaire ligne2 #}
Gestion des environnements avec gitfs
Editer le fichier de configuration /etc/salt/master.d/gitfs.conf
:
top_file_merging_strategy: same state_top_saltenv: base fileserver_backend: #- roots - git gitfs_provider: pygit2 gitfs_remotes: - https://github.com/gigi206/salt-test.git
roots correspond aux file_roots.
Chaque tag ou branche est accessible avec saltenv :
$ salt '*' state.apply saltenv=test $ salt '*' state.apply saltenv=base
Créer son propre module
Créer son propre state
Créer son propre grain
Client salt en python
Renderer en python
Vars selon context
auth: - __path__ (path to your module dir) modules: - __pillar__ - __salt__ - __opts__ - __context__ ({'systemd.sd_booted': True}) - __grains__ runners: - __pillar__ - __salt__ - __opts__ - __grains__ returners: - __salt__ - __opts__ - __pillar__ - __grains__ pillars: - __salt__ (modules) - __opts__ - __pillar__ - __grains__ # nothing tops: - ['__builtins__', '__file__', 'subprocess', 'yaml', '__name__', '__package__', '__doc__'] outputters: - __opts__ - __pillar__ - __grains__ states: - __pillar__ - __low__ (lowstate structure?) - __env__ - __running__ - __lowstate__ - __salt__ - __opts__ - __grains__ log_handlers: - __path__ renderers: - __salt__ - Execution functions (i.e. __salt__['test.echo']('foo')) - __grains__ - Grains (i.e. __grains__['os']) - __pillar__ - Pillar data (i.e. __pillar__['foo']) - __opts__ - Minion configuration options - __env__ - The effective salt fileserver environment (i.e. base). Also referred to as a "saltenv". __env__ should not be modified in a pure python SLS file. To use a different environment, the environment should be set when executing the state. This can be done in a couple different ways: Using the saltenv argument on the salt CLI (i.e. salt '*' state.sls foo.bar.baz saltenv=env_name). By adding a saltenv argument to an individual state within the SLS file. In other words, adding a line like this to the state's data structure: {'saltenv': 'env_name'} - __sls__ - The SLS path of the file. For example, if the root of the base environment is /srv/salt, and the SLS file is /srv/salt/foo/bar/baz.sls, then __sls__ in that file will be foo.bar.baz. grains: - __salt__ - __opts__ - __pillar__ - __grains__
Debug
- Option debug (-l debug) :
salt-call --local -l debug --file-root=$PWD state.apply test=True
- Tracer l'exécution de toutes les states :
salt-call --local --file-root=$PWD state.orchestrate test=True
- Voir tous les events :
salt-run state.event pretty=True