Fabric ist eine Python Bibliothek mit der Shell Befehle remote über SSH ausgeführt werden können.
Für die Implementierung des SSH-Protokolls wird automatisch Paramiko mit installiert.
Fabric zählt zu den Deployment Tools wie z.B.: Ansible, Chef, Puppet, SaltStack, etc.
Wer Python spricht, ist hier ganz weit vorne. (Ich kann’s leider nicht, geht aber auch ohne.)
Fabric ermöglicht es, mit nur einem Befehl, auf mehreren Servern Abläufe zu automatisieren, wie z.B.:
- Updates installieren
- Software installieren
- Dateien hoch- und runterladen
- Skripte ausführen
- Komplexe Umgebungen aufsetzen
Auf den Gegenstellen sollte ein separater Benutzer mit sudo Berechtigungen existieren oder ggf. angelegt werden.
# sudo installieren $ apt install sudo # Benutzer anlegen $ adduser username # den gewünschten user in die Gruppe sudo aufnehmen $ usermod -a -G sudo username
Will man nicht jedesmal das sudo Passwort eingeben, gibt man dem Benutzer die Berechtigung sudo ohne Passwort ausführen zu dürfen.
# sudo ohne Passwort, die /etc/sudoers editiert man mit $ visudo # am Ende der Datei den Eintrag hinzufügen username ALL=(ALL) NOPASSWD:ALL
Fabric installieren
Über die Paketverwaltung ist Fabric schnell installiert. (Debian Buster kommt mit Fabric 1.14.0 und Paramiko 2.4.2)
Läuft auch, Paramiko gibt aber einige CryptographyDeprecationWarning Meldungen aus. (nicht schön)
$ fab cmd:"uptime" [jack@server01] Executing task 'cmd' [jack@server02] Executing task 'cmd' [jack@server01] sudo: uptime [jack@server02] sudo: uptime /usr/lib/python2.7/dist-packages/paramiko/ecdsakey.py:164: CryptographyDeprecationWarning: \ Support for unsafe construction of public numbers from encoded data will be removed in a future version. Please use EllipticCurvePublicKey.from_encoded_point self.ecdsa_curve.curve_class(), pointinfo /usr/lib/python2.7/dist-packages/paramiko/kex_ecdh_nist.py:39: CryptographyDeprecationWarning: \ encode_point has been deprecated on EllipticCurvePublicNumbers and will be removed in a future version. Please use EllipticCurvePublicKey.public_bytes to obtain both compressed and uncompressed point encoding. m.add_string(self.Q_C.public_numbers().encode_point()) --- SNIP ---
Das lässt sich durch eine aktuellere Paramiko Version beheben. Dazu installiere ich Fabric 1 mit der Paketverwaltung von Python. (pip)
$ apt install --no-install-recommends python-pip $ pip install setuptools $ pip install 'fabric<2.0' Successfully installed fabric-1.14.1 paramiko-2.6.0
Fabfile (einfach)
Fabric sucht nach einer fabfile.py im aktuellen Verzeichnis. Die Datei mit folgendem Python Code erstellen. (einfaches Beispiel)
from fabric.api import * env.hosts = [ 'jack@server01', 'jack@server02', 'jack@server03', ] # password for ssh login (NOT RECOMMENDED) # env.password = 'password-for-jack' # ask for password to connect env.password = prompt("enter password to connect: ") @parallel def cmd(command): sudo(command)
Damit kann jetzt schon jeder Befehl, mit nur einem Kommando, auf allen eingetragenen hosts ausgeführt werden.
$ fab cmd:"uptime" [jack@server01] Executing task 'cmd' [jack@server02] Executing task 'cmd' [jack@server03] Executing task 'cmd' [jack@server01] sudo: uptime [jack@server02] sudo: uptime [jack@server03] sudo: uptime [jack@server01] out: sudo password: [jack@server01] out: 10:04:12 up 14 min, 1 user, load average: 0.62, 0.60, 0.69 [jack@server01] out: [jack@server02] out: sudo password: [jack@server02] out: 10:10:48 up 10 min, 1 user, load average: 0.65, 0.60, 0.65 [jack@server02] out: [jack@server03] out: sudo password: [jack@server03] out: 17:40:37 up 23 min, 1 user, load average: 0.77, 0.65, 0.84 [jack@server03] out: Done. Disconnecting from jack@server02... done. Disconnecting from jack@server03... done. Disconnecting from jack@server01... done.
Fabfile (erweitert)
Mit roledefs kann man Servergruppen und mit @task und def einzelnen Aufgabengruppen definieren.
from fabric.api import * # clear screen import os os.system('clear') # display message print(" _____ _ _ ") print(" | ___|_ _| |__ _ __(_) ___ ") print(" | |_ / _` | '_ \| '__| |/ __|") print(" | _| (_| | |_) | | | | (__ ") print(" |_| \__,_|_.__/|_| |_|\___|") print(" ") # group definitions env.roledefs = { 'raspis': ['pi@pi01', 'pi@pi02', 'pi@pi03', 'pi@pi04'], 'proxmox': ['root@pve01', 'root@pve02'], 'server': ['fab@db-srv01', 'fab@web-srv01', 'fab@web-srv02', 'fab@mail-srv01', 'fab@dns-srv01', ], } # some global envs env.colorize_errors = True @task # run any command, cmd:"command" def cmd(command): run(command) @task # update system def apt_update(): run('sudo apt-get update && sudo apt-get upgrade -y') @task # get uptime def uptime(): run('uptime') @task # get os version def os_version(): run('lsb_release -d') @task # upload a file def deploy_motd(): put('/etc/update-motd.d/00-server-motd', '/etc/update-motd.d/') @task # install a deb package def deploy_webmin(): run('wget http://prdownloads.sourceforge.net/webadmin/webmin_1.941_all.deb') run('sudo dpkg -i ~/webmin_1.941_all.deb') run('rm ~/webmin_1.941_all.deb')
Verfügbare Kommandos (Aufgabengruppen) des fabfiles ausgeben.
$ fab -l _____ _ _ | ___|_ _| |__ _ __(_) ___ | |_ / _` | '_ \| '__| |/ __| | _| (_| | |_) | | | | (__ |_| \__,_|_.__/|_| |_|\___| Available commands: apt_update cmd deploy_motd deploy_webmin uptime os_version
Von allen Proxmox Servern die PVE Version ausgeben.
$ fab -R proxmox cmd:"pveversion" _____ _ _ | ___|_ _| |__ _ __(_) ___ | |_ / _` | '_ \| '__| |/ __| | _| (_| | |_) | | | | (__ |_| \__,_|_.__/|_| |_|\___| [root@pve01] Executing task 'cmd' [root@pve01] run: pveversion [root@pve01] Login password for 'root': [root@pve01] out: pve-manager/6.1-3/37248ce6 (running kernel: 5.3.13-1-pve) [root@pve01] out: [root@pve02] Executing task 'cmd' [root@pve02] run: pveversion [root@pve02] out: pve-manager/6.1-3/37248ce6 (running kernel: 5.3.13-1-pve) [root@pve02] out: Done. Disconnecting from pve02... done. Disconnecting from pve01... done.
Von allen Raspberries die OS Version ausgeben.
$ fab -R raspis os_version _____ _ _ | ___|_ _| |__ _ __(_) ___ | |_ / _` | '_ \| '__| |/ __| | _| (_| | |_) | | | | (__ |_| \__,_|_.__/|_| |_|\___| [pi@pi01] Executing task 'os_version' [pi@pi01] run: lsb_release -d [pi@pi01] Login password for 'pi': [pi@pi01] out: Description: Raspbian GNU/Linux 10 (buster) [pi@pi01] out: [pi@pi02] Executing task 'os_version' [pi@pi02] run: lsb_release -d [pi@pi02] out: Description: Raspbian GNU/Linux 10 (buster) [pi@pi02] out: [pi@pi03] Executing task 'os_version' [pi@pi03] run: lsb_release -d [pi@pi03] out: Description: Raspbian GNU/Linux 10 (buster) [pi@pi03] out: [pi@pi04] Executing task 'os_version' [pi@pi04] run: lsb_release -d [pi@pi04] out: Description: Raspbian GNU/Linux 9.11 (stretch) [pi@pi04] out: Done. Disconnecting from pi@pi02... done. Disconnecting from pi@pi04... done. Disconnecting from pi@pi01... done. Disconnecting from pi@pi03... done.
Die langen Ausgaben von Fabric können auch etwas unterdrückt werden.
fab --hide=status,running -R raspis os_version _____ _ _ | ___|_ _| |__ _ __(_) ___ | |_ / _` | '_ \| '__| |/ __| | _| (_| | |_) | | | | (__ |_| \__,_|_.__/|_| |_|\___| [pi@pi01] Login password for 'pi': [pi@pi01] out: Description: Raspbian GNU/Linux 10 (buster) [pi@pi01] out: [pi@pi02] out: Description: Raspbian GNU/Linux 10 (buster) [pi@pi02] out: [pi@pi03] out: Description: Raspbian GNU/Linux 10 (buster) [pi@pi03] out: [pi@pi04] out: Description: Raspbian GNU/Linux 9.11 (stretch) [pi@pi04] out:
Einen Befehl auf einzelnen hosts ausführen.
fab --host=fab@web-srv02,fab@web-srv03 cmd:"uname -a" _____ _ _ | ___|_ _| |__ _ __(_) ___ | |_ / _` | '_ \| '__| |/ __| | _| (_| | |_) | | | | (__ |_| \__,_|_.__/|_| |_|\___| [fab@web-srv02] Executing task 'cmd' [fab@web-srv02] run: uname -a [fab@web-srv02] Login password for 'cmk': [fab@web-srv02] out: Linux wiki 5.4.44-2-pve #1 SMP PVE 5.4.44-2 (Wed, 01 Jul 2020 16:37:57 +0200) x86_64 GNU/Linux [fab@web-srv02] out: [fab@web-srv03] Executing task 'cmd' [fab@web-srv03] run: uname -a [fab@web-srv03] out: Linux lemp 5.4.44-2-pve #1 SMP PVE 5.4.44-2 (Wed, 01 Jul 2020 16:37:57 +0200) x86_64 GNU/Linux [fab@web-srv03] out: Done. Disconnecting from fab@web-srv03... done. Disconnecting from fab@web-srv03... done.
Fabric
Geniales Tool! Ich nutze nur einen Bruchteil von dem was Fabric alles leisten kann.
Es erleichtert mir damit aber schon ungemein die Administration und Pflege meiner einzelnen Linux Server.
Super Tipp! Danke sehr!
Freut mich! :)