[PYTHON] Ansible Übersicht

Ansible stolpert schnell, wenn er versucht, etwas anderes als das Beispiel in der Dokumentation zu tun. Ich vermute, dass diese Ansible-Wand darauf zurückzuführen ist, dass Sie nicht das ganze Bild sehen können. Wenn Sie es verwenden, sehen Sie nach und nach das gesamte Bild, aber es ist häufig der Fall, dass Sie es früher kennen müssen. Ich werde es als mein eigenes Memo belassen, beispielsweise als Struktur für eine Vogelperspektive des gesamten Bildes, aber ich hoffe, es wird anderen Menschen so viel wie möglich helfen.

  1. Ansible Einstellungsnotation
  2. Konfigurationsdatei ansible.cfg
  3. Inventar
  4. Playbook
  5. Verwenden Sie die Verzeichnisstruktur von Ansible
  6. Unterschied zwischen Import und Include
  7. Bonus: Machen Sie Raspberry Pi3 (Ubuntu Stretch 9) zum Kontrollhost

Wenn Sie mindestens 1. Ansibles Konfigurationsnotation, 2. Konfigurationsdatei ansible.cfg, 3. Inventar und 4. Playbook verstehen, sollten Sie in der Lage sein, ansible zu verwenden. Ich werde. (Es gibt Voraussetzungen wie SSH-Einstellungen.)

Während Sie es verwenden, können Sie mehrere Aufgaben gemeinsam verwalten und häufiger wiederverwenden. In Abschnitt 5 wird beschrieben, wie ansible mithilfe der Verzeichnisstruktur verwendet wird.

Abschließend werde ich beschreiben, wie man es mit Raspberry Pi3 als Bonus verwendet.

Ansible Einstellungsnotation

In den Ansible-Einstellungen YAML-Format und INI-Format Sie können E3% 82% A1% E3% 82% A4% E3% 83% AB verwenden (erweiterte INI-Notation, die "#" in Kommentaren zulässt). Sie können zwar flexibel schreiben, indem Sie beide schreiben können, es ist jedoch verwirrend, wenn Sie es zum ersten Mal verwenden, da es nicht einheitlich ist.

Es ist eine gute Idee, die folgenden Regeln zu beachten.

  1. * .cfg, Datei ohne Erweiterung ist im INI-Format
  2. * .yml und * .yaml sind im YAML-Format

Beispiel für ein INI-Format

Es besteht aus einem "Abschnittsnamen" in "[]" und einem "Parameter", der durch "=" beschrieben wird. Sie können Leerzeichen, TAB usw. vor und nach = setzen.

ini:./ansible.cfg


[defaults]
host_key_checking       = True

#Sie können Kommentare scharf schreiben
[privilege_escalation]
become_ask_pass         = True

;Sie können einen Kommentar mit einem Semikolon schreiben
[ssh_connection]
scp_if_ssh              = False

Nach = wird es mit Ausnahme der Booleschen Werte True / False und yes / no bis zum Ende der Zeile als "Zeichenfolge" behandelt. Wenn Sie es in "" usw. usw. einschließen, kann "" selbst als Teil der Zeichenfolge interpretiert werden.

Trennen Sie "Listen" (Arrays) durch Kommas (,).

Beispiel für ein YAML-Format

Die Aufzählung von "Namen", die durch ":" getrennt sind, wird "Skalar" genannt.

Skalar


name1:
name2:
:
nameN:

Wenn Sie ohne Präfix "-`" aufzählen, wird es "seriell" (einfache Aufzählung, "skalar").

Sie können den Wert nach : schreiben. Dies wird in YAML auch als "Mapping" bezeichnet.

Kartierung


name1: aaaa
name2: bbbb
:
nameN: cccc

Wenn Sie "-`" voranstellen, wird es zu einer Liste (Array). In YAML wird dies als "Sequenz" bezeichnet.

Reihenfolge


- name1:
- name2:

- nameN:

Einrückung stellt eine Hierarchie dar, die als "Sammlung" bezeichnet wird. Verwenden Sie zum Einrücken Leerzeichen. Bitte beachten Sie, dass die Verwendung von TAB zu einem Fehler führt. (Wenn Sie vi / vim verwenden, wird durch Setzen von set expandtab TAB durch Leerzeichen ersetzt.)

Beispiel-playbook-samle1.yml


- name: the 1st Example
  hosts: 172.17.0.2
  tasks:
    - name: Hello, World!
      debug:
    - name: Next debug
      debug: msg="Hello, Ansible!"

In diesem Beispiel sind "Name: das erste Beispiel", "Hosts: 172.17.0.2", "Aufgaben:" die gleichen skalaren (parallelen (sequentiellen)) Einstellungen, "-name: Hallo, ansible", "-name: Next". Der Debug-Teil ist die Sequenz (Liste (Array)). Es ist eine Zuordnung mit jeweils einem Wert. Aufgaben ist eine Sammlung.

Ich sehe oft das YAML-Format mit --- (drei Bindestriche) am Anfang. Dies liegt daran, dass die Struktur von YAML einen Definitionsblock mit "---" beginnen und mit "..." (drei Punkte) enden soll. Sie können mehrere Blöcke mit --- in eine Datei schreiben, aber im Allgemeinen verwendet ansible keine solche Struktur. Sie können denken, dass es sicher ist, "---" hinzuzufügen. Das Umschreiben des obigen playbook-samle1.yml führt zu folgendem Ergebnis.

playbook-samle1.yml


---
- name: the 1st Example
  hosts: 172.17.0.2
  tasks:
    - name: Hello, World!
      debug:
    - name: Next debug
      debug: msg="Hello, Ansible!"

Konfigurationsdatei ansible.cfg

Siehe auch: Ansible-Konfigurationseinstellungen - Ansible-Dokumentation (https://docs.ansible.com/ansible/latest/reference_appendices/config.html) Da die Erweiterung der Konfigurationsdatei ".cfg" lautet, beschreiben Sie sie im INI-Format. Ansible-bezogene Befehle suchen in der folgenden Reihenfolge nach Konfigurationsdateien, und die erste gefundene Konfigurationsdatei wird verwendet.

  1. Datei, die durch die Umgebungsvariable "ANSIBLE_CONFIG" angegeben wird
  2. ansible.cfg (. / Ansible.cfg) im aktuellen Verzeichnis
  3. Ausgangsverzeichnis .ansible.cfg ( ~ / .ansible.cfg oder `$ HOME / .ansible.cfg)
  4. /etc/ansible/ansible.cfg

Ansible.cfg Beispiel

ansible.cfg


[defaults]
inventory		= ./inventory
interpreter_python	= /usr/bin/python3
#deprecation_warnings	= False

[privilege_escalation]
become_ask_pass		= yes

[ssh_connection]
scp_if_ssh		= False

Inventar

Siehe: So erstellen Sie Ihr Inventar - Ansible Documentation Um den ansible-Befehl auszuführen und das später beschriebene Playbook zu bedienen, muss eine Datei namens Inventory vorbereitet werden, die den zu bedienenden Host beschreibt. Kurz gesagt, es ist wie eine Sammlung von / etc / hosts-Dateien.

Inventarbeispiel

myhost1


172.17.0.2

Die kleinste Inventardatei enthält nur eine IP-Adresse (Host).

myhost2


172.17.0.2
172.17.0.3

[group1]
172.17.0.2
172.17.0.3

[group2]
172.17.0.[3:7]

[my_all:children]
group1
group2

Spielbuch

Geben Sie anstelle der Ad-hoc-Modulspezifikation (= Single-Shot) und der Operation "ansible-m ping host pattern" eine Konfigurationsdatei an, die als Playbook bezeichnet wird, um eine Reihe von Operationen auszuführen. Das Format des Playbooks ist im Allgemeinen das YAML-Format.

Playbook Beispiel

playbook-sample1.yml


- name: the 1st Example
  hosts: 172.17.0.2
  tasks:
#Die Aufgabe ist eine Liste(Reihenfolge)Geben Sie mit an.
#Zeigen Sie die Standardmeldung im Debug an.
    - name: Hello, World
      debug:
#Zeigen Sie die angegebene Nachricht im Debug an.
    - name: Next debug
      debug: msg="Hello, Ansible!"

Um das Playbook ausführen zu können, müssen Sie eine Inventardatei angeben.

myhosts1


172.17.0.2
$ ansible-playbook -i myhosts1 playbook-sample1.yml

PLAY [the 1st Example] *************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************
ok: [172.17.0.2]

TASK [Hello, World] ****************************************************************************************************
ok: [172.17.0.2] => {
    "msg": "Hello world!"
}

TASK [Next debug] ******************************************************************************************************
ok: [172.17.0.2] => {
    "msg": "Hello, Ansible!"
}

PLAY RECAP *************************************************************************************************************
172.17.0.2                 : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Ansible Verzeichnisstruktur

Siehe: Rollen - Ansible-Dokumentation Durch die Verwendung der folgenden Verzeichnisstruktur ist es einfacher, Dateien und Aufgaben anzugeben.

./
├─ ansible.cfg  ……………………………… (1)Konfigurationsdatei. Umgebungsvariable ANSIBLE_In KONFIG
│ Fester Name, sofern nicht ausdrücklich angegeben.
├─ playbook.yml ……………………………… (2)Playbook Beliebiger Dateiname. Das YAML-Format ist üblich.
│
├─ inventory/ …………………………………… (3)Inventarverzeichnis. Muss angegeben werden,
│ │ Beliebiger Name. Als Option angeben.
│    ├─ hosts …………………………………… (4)Jeder Name. INI-Format ohne Erweiterung,
│    ├─ hosts2.yml-Erweiterung.YAML-Format für yml.
│    ├─ : 
│    └─ hostsN
├─ group_vars/ ………………………………… (5)Variablen, die für die "Zielhostgruppe" der angegebenen Aufgabe gelten
│ │ Das zu speichernde Verzeichnis. Fester Name.
│    ├─ groupname1 ……………………… (6)Setzen Sie den Namen "Zielhostgruppe" auf den Dateinamen. INI-Format ohne Erweiterung,
│    ├─ groupname2.Wenn es im yml YAML-Format ist, die Erweiterung.Mach es yml.
│    ├─ : 
│    └─ groupnameN
├─ host_vars/ …………………………………… (7)Variablen, die für den "Zielhost" der angegebenen Aufgabe gelten
│ │ Das zu speichernde Verzeichnis. Fester Name.
│    ├─ hostname1 ………………………… (8)Setzen Sie den Namen "Zielhost" auf den Dateinamen. INI-Format ohne Erweiterung,
│    ├─ hostname2.Wenn es im yml YAML-Format ist, die Erweiterung.Mach es yml.
│    ├─ : 
│    └─ hostnameN
├─ files/ ……………………………………………… (9)Dateispeicher zum Kopieren und Übertragen. Fester Name.
│    ├─ file1 ……………………………………(10)Beliebiger Dateiname.
│    ├─ file1
│    ├─ :
│    └─ fileN
└─ roles/ ………………………………………………(11)Einstellungsverzeichnis für die Verwendung von Rollen in Playbooks. Fester Name.
    ├─ role1/ ……………………………………(12)Setzen Sie den Namen "Zielrolle" auf den Verzeichnisnamen.
    ├─ role2/
    ├─ :
    └─ roleN/
         ├─ defaults …………………(13)Das Verzeichnis, in dem die Standardvariableneinstellungen gespeichert sind. Fester Name.
         │   └── main.yml ……(14)Die zuerst geladene Variableneinstellungsdatei. Fester Name.
         │                       import_Wie vars wird es geladen, wenn das Playbook analysiert wird.
         ├─ vars ……………………………(15)Ein Verzeichnis, in dem variable Einstellungen gespeichert werden. Fester Name.
│ │ Basisverzeichnis bei Angabe einer Datei mit einem relativen Pfad.
         │    ├─ varfile1 ……(16)Beliebiger Dateiname. INI-Format ohne Erweiterung,
         │    ├─ varfile2.Wenn es im yml YAML-Format vorliegt, fügen Sie die Erweiterung hinzu.Mach es yml.
         │    ├─ :
         │    └─ varfileN
         └─ tasks …………………………(17)Verzeichnis zum Speichern von Aufgaben. Fester Name.
             └── main.yml ……(18)Die erste auszuführende Task-Konfigurationsdatei. Fester Name.
Wenn Sie die Verarbeitung abhängig vom Betriebssystem des Zielhosts ändern möchten,
                                 main.Import aus yml/Lesen Sie mit include.

Es gibt andere Rollen in Verzeichnissen wie "Handler /", "Vorlagen /" und "Meta /", aber wenn Sie die obige Verzeichnisstruktur verstehen, ist es vorerst einfacher, auch andere Verzeichnisse zu verstehen. ..

Weitere Informationen finden Sie unter "Rollen - Ansible-Dokumentation". Es gibt auch ein Beispiel in "Best Practices: Verzeichnislayout - Ansible Documentation".

Unterschied zwischen Import und Include

Siehe: Einschließen und Importieren - Ansible-Dokumentation Sowohl Import * als auch Include * sind beim Lesen von Dateien gleich, werden jedoch zu unterschiedlichen Zeiten gelesen.

  • All import* statements are pre-processed at the time playbooks are parsed.
  • All include* statements are processed as they are encountered during the execution of the playbook.

Von besonderer Bedeutung ist die Verarbeitung von Variablen (z. B. Vorlage {{samplevarname}}) mit der Vorlage JINJA2 und die Zuweisung von Variablen.

Wenn Sie import * verwenden, wird es erweitert, bevor die Aufgabe ausgeführt wird, sodass die eingebettete Vorlage durch den tatsächlichen Wert ersetzt wird und die Aufgabe ausgeführt wird, nachdem die Zuordnung zur Variablen abgeschlossen ist.

Wenn Sie dagegen include * verwenden, wird es beim Ausführen der Aufgabe erweitert. Wenn es also geladen und ausgeführt wird, wird die Vorlage durch den tatsächlichen Wert ersetzt und die Zuweisung erfolgt.

Bonus: Machen Sie Raspberry Pi3 (Ubuntu Stretch 9) zum Kontrollhost

Ansible wird in der Python-Umgebung verwendet. Wenn Sie jedoch das Betriebssystem-basierte Ansibule (apt / apt-get install) unter Ubuntu (Stretch 9) von Raspberry Pi3 installieren, wird Version 2.2 von Ansible installiert (geschrieben am 13. Januar 2020). Ab dem Datum).

Die neuesten Funktionen sind in Version 2.2 nicht verfügbar, was etwas unpraktisch ist. Sie können daher die neueste Version von Ansible (die neueste Version 2.2 zum Zeitpunkt des Schreibens) verwenden, indem Sie sie in einer virtuellen Umgebung von Python installieren (pip install). (Die Version von Python3 für Raspberry Pi3 / Ubuntu ist 3.5)

$ cat /etc/os-release
PRETTY_NAME="Raspbian GNU/Linux 9 (stretch)"
NAME="Raspbian GNU/Linux"
VERSION_ID="9"
VERSION="9 (stretch)"
VERSION_CODENAME=stretch
ID=raspbian
ID_LIKE=debian
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"
$ python3 --version
Python 3.5.3

Die Installation in der virtuellen Python-Umgebung ist wie folgt.

$ python3 -m venv ansible
$ source ansible/bin/activate
$ pip install -U pip
$ pip install ansible

Die * ansible * nach python3 -m venv und die * ansible *, die im Befehl source angegeben sind, sind identisch, und Sie können selbst entscheiden. Das in "pip install" angegebene "ansible" ist das zu installierende Paket. Führen Sie es also so aus, wie es ist, ohne es zu ändern.

Verwendung von: point_up: alias

Wenn Sie bash verwenden, ist es praktisch, die folgenden Einstellungen in ~ / .bashrc vorzunehmen.

bash:~/.bashrc Oder ~/.bash_aliases Eine solche


alias ansibleenv='type deactivate > /dev/null 2>&1 && deactivate; cd ~/work/Ansible.d/; source ~/work/Python.d/envs/ansible/bin/activate'

Wenn es im Teil "Typ deaktivieren> / dev / null 2> & 1 && deaktivieren" in einer anderen Umgebung aktiviert wurde, deaktivieren Sie es. Wechseln Sie mit cd ~ / work / Ansible.d in Ihr Arbeitsverzeichnis. Die Umgebung von ansible wird durch "source ~ / work / Python.d / envs / ansible / bin / enabled" aktiviert. Einmal eingestellt, können Sie es mit "ansibleenv" aufrufen.

: point_up: Fehlerbehebung bei Weakref.py

Auf Raspberry Pi kann der folgende Fehler auftreten, selbst wenn ansible selbst erfolgreich ausgeführt wurde.

:
PLAY RECAP *************************************************************************************************************
172.17.0.2                 : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Exception ignored in: <function WeakValueDictionary.__init__.<locals>.remove at 0x75c7fdf8>
Traceback (most recent call last):
  File "/usr/lib/python3.5/weakref.py", line 117, in remove
TypeError: 'NoneType' object is not callable
Exception ignored in: <function WeakValueDictionary.__init__.<locals>.remove at 0x75c7fdf8>
Traceback (most recent call last):
  File "/usr/lib/python3.5/weakref.py", line 117, in remove
TypeError: 'NoneType' object is not callable
    :
    :
Exception ignored in: <function WeakValueDictionary.__init__.<locals>.remove at 0x75c7fdf8>
Traceback (most recent call last):
  File "/usr/lib/python3.5/weakref.py", line 117, in remove
TypeError: 'NoneType' object is not callable

Dies ist ein Fehler, der durch die undefinierte Variable `` `/ usr / lib / python3.5 / schwachref.py``` (Typ" None ") verursacht wird. Die zugrunde liegende Lösung sollte vom Anrufer in Betracht gezogen werden, kann jedoch durch Anwenden des folgenden Patches vorläufig vermieden werden: (Obwohl es ziemlich rau ist)

diff:weakref.py.patch


*** weakref.py.bak      2018-09-28 02:25:39.000000000 +0900
--- weakref.py  2020-01-03 18:44:49.190027705 +0900
***************
*** 114,120 ****
                  else:
                      # Atomic removal is necessary since this function
                      # can be called asynchronously by the GC
!                     _remove_dead_weakref(d, wr.key)
          self._remove = remove
          # A list of keys to be removed
          self._pending_removals = []
--- 114,121 ----
                  else:
                      # Atomic removal is necessary since this function
                      # can be called asynchronously by the GC
!                     if type(_remove_dead_weakref) is not type(None) and type(d) is not type(None) and type(wr) is not type(None):
!                         _remove_dead_weakref(d, wr.key)
          self._remove = remove
          # A list of keys to be removed
          self._pending_removals = []

Patchen:

$ sudo patch -c -b /usr/lib/python3.5/weakref.py weakref.py.patch

-c ist eine Patch-Option vom Kontexttyp und -b ist eine Option zum Erstellen von Backups.

Recommended Posts

Ansible Übersicht
Linux Übersicht
Installation von Ansible
Ansible Note
Cloud Datalab Übersicht
Cloud-native Serviceübersicht