WAS IST DER ZWECK EINES TOOLS WIE SALTSTACK, UND DIE BESSERE FRAGE IST: WELCHES PROBLEM WIRD DAMIT GELÖST?
Die beiden Hauptzwecke von SaltStack sind Konfigurationsmanagement und Remote-Ausführung. Wahrscheinlich haben Sie schon einmal von einer der populäreren Alternativen zu SaltStack gehört oder diese verwendet - Ansible, Puppet oder Chef. Sie alle erreichen so ziemlich das gleiche Ziel. Ich mag Salt besonders, weil es in Python geschrieben ist und relativ leichtgewichtig ist. Es verwendet die Kommunikationsschicht von ZeroMQ, was es wirklich schnell macht, und es verwendet auch PyYAML für seine Konfigurationsmanagement-Rezepte (Zustände genannt).
Kurz gesagt, wenn Sie eine beliebige Anzahl von Servern verwalten und etwas auf ihnen tun müssen, müssten Sie sich bei jedem einzelnen anmelden und Ihre Aufgabe erledigen. Selbst wenn es sich um eine kleine Aufgabe handelt, wie den Neustart einer Instanz oder die Überprüfung der Betriebszeit, oder um eine größere Aufgabe, wie die Installation und Konfiguration von etwas, müssen Sie dies immer noch für jeden einzelnen Server tun. Wenn Sie viele Server verwalten, müssen Sie eine Menge manueller Arbeit leisten, um Ihre Aufgaben zu erledigen. Hier kann Salt Stack eingesetzt werden, um Ihre Arbeit zu automatisieren und die Möglichkeit zu bieten, Befehle auf einer beliebigen Anzahl von Rechnern aus der Ferne auszuführen.
Salt arbeitet entweder mit einem Master/Minion-Setup, bei dem Sie einen Master-Knoten haben, von dem aus Sie Befehle an die Minion-Knoten ausführen, oder mit salt-ssh, was so ziemlich das ist, wonach es klingt: Es ermöglicht Ihnen, alles, was Sie normalerweise an einen konfigurierten Minion auf einem beliebigen Rechner über ssh ausführen würden, unabhängig davon, ob Salt dort installiert ist.
ENTFERNTE AUSFÜHRUNG
Die Kommunikation zwischen dem Master-Knoten und seinen Untergebenen erfolgt über die Verschlüsselung mit öffentlichen Schlüsseln. Bei der Konfiguration der Unterknoten müssen Sie Ihrem Unterknoten zunächst mitteilen, wo sich der Master-Knoten befindet, und das geschieht über die Datei /etc/salt/minion conf. Es gibt eine Zeile, in der Sie den Standort des Master-Knotens mit dem Format - master - angeben können: 127.0.0.1.
Nachdem ein neuer Minion hinzugefügt wurde, müssen wir die Verschlüsselungsschlüssel dieses Minions auf dem Masterknoten akzeptieren.
Um zu sehen, welche Schlüssel verfügbar sind und zur Annahme anstehen, können wir verwenden:
# salt-key -L
Accepted Keys:
Denied Keys:
Unaccepted Keys:
new_minion
test_minion
test_minion2
Rejected Keys:
Dann nehmen wir die, die wir wollen, mit :
# salt-key -a <minion name>
Jetzt können wir mit diesem Befehl testen, ob die Kommunikation zwischen dem Master und den Untergebenen funktioniert:
# salt '*' test.ping
Webserver1: True
Webserver2: True
Webserver3: True
Auf die gleiche Weise können wir jeden beliebigen Befehl für jeden Untergebenen ausführen:
# salt '*' cmd.run "service httpd restart"
Und im Übrigen ist es mit salt-ssh genau dasselbe:
# salt-ssh '*' cmd.run "uptime"
Webserver1:
05:19am up 18 days 21:05, 1 user, load average: 0.03, 0.01, 0.00
Webserver2:
05:19am up 30 days 17:05, 1 user, load average: 0.05, 0.01, 0.00
Webserver3:
05:19am up 30 days 17:05, 1 user, load average: 0.04, 0.01, 0.00
Installation eines Pakets auf allen Zielservern:
# salt '*' pkg.install vim
Jeder einzelne Zielserver, auf dem Sie Befehle ausführen wollen, muss der Salt-Roster-Datei hinzugefügt werden, die sich im Verzeichnis /etc/salt/roster des Masters befindet. Sie sieht in etwa wie folgt aus:
# cat /etc/salt/roster
Webserver1:
host: webserver1.hostname.com
priv: /root/.ssh/id_rsa
Webserver2:
host: webserver1.hostname.com
priv: /root/.ssh/id_rsa
Webserver3:
host: webserver1.hostname.com
priv: /root/.ssh/id_rsa
Ich persönlich bevorzuge die Verwendung von salt-ssh für meine gesamte Konfigurationsverwaltung und Fernausführung, da ich nicht auf allen Servern Salt minion-Installationen unterhalten muss. Ich verwalte lediglich einen Masterknoten und eine Rasterdatei mit allen Zielservern, die ich verwalten möchte. Dann erstelle ich ein zentrales Repository für die Konfigurationsverwaltung und führe die Remote-Ausführung auf jedem beliebigen Server vom Master aus durch.
Hier sehen Sie eine Visualisierung der Remote-Ausführungsfunktion von Salt:

KONFIGURATIONSMANAGEMENT
Salt verwendet Vorlagenkonfigurationsdateien mit der Endung .sls, die normalerweise im YAML-Format geschrieben sind, aber auch viele andere Formate sind verfügbar.
Hier ist ein sehr einfaches Beispiel für einen Salt-State, der einfach ein Paket auf einem beliebigen Betriebssystem installiert (Salt bestimmt den Paketmanager, der für die Installation benötigt wird).
Möchten Sie wissen, was wir sonst noch tun?
Entdecken Sie unser Know-how!
mariadb-client:
pkg:
- installed
Eine Basisinstallation von Apache sieht folgendermaßen aus:
apache:
pkg.installed: []
service.running:
- watch:
- pkg: apache
- file: /etc/httpd/conf/httpd.conf
- user: apache
user.present:
- uid: 87
- gid: 87
- home: /var/www/html
- shell: /bin/nologin
- require:
- group: apache
group.present:
- gid: 87
- require:
- pkg: apache
/etc/httpd/conf/httpd.conf:
file.managed:
- source: salt://apache/httpd.conf
- user: root
- group: root
- mode: 644
Vollständige Installation von Apache
Ganz unten in diesem Artikel werde ich ein komplizierteres Beispiel anführen (da es relativ lang ist), in dem wir die komplette Installation von Apache automatisieren und bestimmte Änderungen an seiner Konfiguration vornehmen, wie z.B. das Kopieren einer virtuellen Hostvorlage, das Vornehmen einiger Umgebungsänderungen, das Ändern des Ports, das Starten des Webservers und das Ausführen einiger Smoke-Tests, um sicherzustellen, dass der konfigurierte virtuelle Host funktioniert.
Einen Salt-Status auf einen beliebigen Server anzuwenden, ist so einfach wie:
# salt-ssh Webserver1 state.apply apache2/apache2
Zur Fehlersuche können Sie auch einen Testlauf durchführen, um zu sehen, was die Software tut, bevor sie tatsächlich etwas tut:
# salt-ssh Webserver1 state.apply apache2/apache2 test=True -l debug
Wenn Sie alle Ihre Zustände auf einen neuen Untergebenen anwenden müssen, können Sie einfach den Befehl hightstate ausführen, der Ihre Sammlung von .sls-Dateien (einen sogenannten Zustandsbaum) auf den neuen Untergebenen anwendet.
# salt 'Webserver3' state.highstate
Und hier ist das längere Beispiel für die Apache-Installation und -Konfiguration, das ich bereits erwähnt habe:
# Set variables for your environment
{% set envString = 'prod' %}
# Vhost configuration
{% set vhostFileName = 'itgix_vhost.conf' %}
{% set vhostServerName = 'itgix.com' %}
# Paths
{% set dataPath = '/opt/data/itgix/HTTPServer' %}
{% set logPath = '/opt/logs/itgix/HTTPServer' %}
{% set apacheInstallDir = '/opt/app/HTTPServer/prod/conf' %}
# Get server IP of eth0 interface - used in Smoke Tests only
{% set serverIPAddress = salt['network.interfaces']()['eth0']['inet'][0]['address'] %}
# Get hostname
{% set serverHostname = salt['grains.get']('host') %}
# Set ENVIRONMENT variable
setEnvVariable:
environ.setenv:
- name: ENVIRONMENT
- value: {{ envString }}
- update_minion: True
# Install apache
#apache2:
# pkg:
# - name: apache2
# - installed
# Add Group equivalent to - groupadd -g 5000 itgix0000
webserverGroup:
group.present:
- name: itgix0000
- gid: 5000
- addusers:
- itgix0000
# Add User equivalent to - itgix0000:x:5000:5000::/home/ihs00000:/bin/false
webserverUser:
user.present:
- name: itgix0000
- shell: /bin/false
- home: /home/itgix0000
- uid: 5000
- gid: 5000
- groups:
- itgix0000
# Create env dir
envDir:
file.directory:
- name: {{ dataPath }}/{{ envString }}/htdocs/infra
- user: root
- group: root
- dir_mode: 755
- file_mode: 644
- makedirs: True
- recurse:
- user
- group
- mode
# Create logs dir
logPath:
file.directory:
- name: {{ logPath }}/{{ envString }}
- user: ihs00000
- group: ihs00000
- dir_mode: 755
- file_mode: 644
- makedirs: True
- recurse:
- user
- group
- mode
# Create or replace uid.conf with itgix0000 user and group name
uid.conf:
file.managed:
- name: {{ apacheInstallDir }}/uid.conf
- user: root
- group: root
- replace: True
- contents:
- User itgix0000
- Group itgix0000
# Create or replace lbtestfile.html with: environment - hostname
lbtestfile.html:
file.managed:
- name: {{ dataPath }}/{{ envString }}/htdocs/infra/lbtestfile.html
- user: root
- group: root
- replace: True
- contents: |
<html>
<head>
<title> {{ envString }} - {{ serverHostname }} </title>
</head>
<body>
<pre>
{{ envString }} - {{ serverHostname }}
Status: OK
</pre>
</body>
</html>
# Create or replace WhereAmI.Info with env - hostname
WhereAmI.info:
file.managed:
- name: {{ dataPath }}/{{ envString }}/htdocs/infra/WhereAmI.info
- user: root
- group: root
- replace: True
- contents:
- {{ envString }} - {{ serverHostname }}
# Create or replace listen.conf - Listen port
listen.conf:
file.managed:
- name: {{ apacheInstallDir }}/listen.conf
- user: root
- group: root
- replace: True
- contents:
- Listen {{ serverIPAddress }}:40200
# Copy Virtual host - itgix_vhost.conf (force: True is used to overwrite file if exists)
meapp.conf:
file.managed:
- name: {{ apacheInstallDir }}/vhosts.d/{{ vhostFileName }}
- source: salt://apache2_4/files/{{ vhostFileName }}
- force: True
- makedirs: True
- user: root
- group: root
- mode: 644
# Copy Virtual host - 00_default (force: True is used to overwrite file if exists)
00_default.conf:
file.managed:
- name: {{ apacheInstallDir }}/vhosts.d/00_default.conf
- source: salt://apache2_4/files/00_default.conf
- force: True
- user: root
- group: root
- mode: 644
# Find and replace all occurances of <env> with the current environment
replaceEnvInVhost:
file.replace:
- name: {{ apacheInstallDir }}/vhosts.d/{{ vhostFileName }}
- backup: original
- pattern: <env>
- repl: {{ envString }}
# Find and replace all occurances of <env> with the current environment
replaceEnvInDefaultVhost:
file.replace:
- name: {{ apacheInstallDir }}/vhosts.d/00_default.conf
- backup: original
- pattern: <env>
- repl: {{ envString }}
# Add ServerName to vhost
replaceSrvNameInVhost:
file.replace:
- name: {{ apacheInstallDir }}/vhosts.d/{{ vhostFileName }}
- backup: original
- pattern: <server_name>
- repl: {{ vhostServerName }}
# Enable apache2 service to be started at runtime and start apache2 now.
#enableAndStartApache:
# service.running:
# - name: apache2
# - enable: True
# Get IP of eth0 and execute smoke tests towards it
smokeTestWithIP:
cmd.run:
- name: curl -v http://{{ serverIPAddress }}:40200/infra/lbtestfile.html
smokeTestWithHostAndIP:
cmd.run:
- name: curl -v -H "host:itgix.com" http://{{ serverIPAddress }}:40200/infra/lbtestfile.html

