Ansible Tutorial
Wir können Ansible mit Python pip installieren oder aber wie hier beschrieben aus den Debian Paketen.
sudo apt -y update
sudo apt -y install ansible
Nach der Installation können wir testen, ob Ansible erfolgreich installiert wurde.
ansible --version
ansible 2.9.6
config file = /etc/ansible/ansible.cfg
configured module search path = ['/home/mschulz/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3/dist-packages/ansible
executable location = /usr/bin/ansible
python version = 3.8.10 (default, Nov 14 2022, 12:59:47) [GCC 9.4.0]
Als nächstes erstellen wir einen SSH Key für Ansible mit ssh-keygen. Da dies ein Maschinen SSH Key wird, geben wir keine Passphrase ein.
ssh-keygen -t rsa -b 2048 -f ~/.ssh/ansible
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/tux/.ssh/ansible
Your public key has been saved in /home/tux/.ssh/ansible.pub
The key fingerprint is:
SHA256:qJIaMNOHebagIblGeKdSvb2NihH5sHwnIANb12g6Qng tux@earth
The key's randomart image is:
+---[RSA 2048]----+
| |
|. o |
|o.E + . |
|+* O . |
|&.# * . S |
|+& / = |
|=.B B o |
|.+ = o + |
|. . ..o . |
+----[SHA256]-----+
Nun kopieren wir den SSH Public key auf die entfernten Maschinen, welche von Ansible verwaltet werden sollen.
ssh-copy-id -i ~/.ssh/ansible.pub ansible@<SERVER>
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/tux/.ssh/ansible.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'ansible@<SERVER>'"
and check to make sure that only the key(s) you wanted were added.
Jetzt erstellen wir uns ein Git Repository für unser Ansible, wo wir die Konfiguration, wie auch die Playbooks speichern.
mkdir -p ~/ansible
cd ~/ansible/
git init
Nun erstellen wir eine inventory Datei, in dem wir die von Ansible verwalteten Maschinen eintragen.
vi inventory
192.168.0.3
Die Änderungen commiten wir nun in unseren Git Repository.
git add inventory
git commit -m "first version of the inventory file"
git push origin master
Nun testen wir unsere Ansible Konfiguration und setzen auf allen in der Inventory definierten Maschinen einen Ping ab.
ansible all --key-file ~/.ssh/ansible -i inventory -m ping
[WARNING]: Platform linux on host 192.168.0.3 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could change this. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information.
192.168.0.3 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
Der ping war erfolgreich, aber wir bekommen eine Warnung angezeigt. Um diese Warnung nicht mehr anzuzeigen, erstellen wir uns eine ansible.cfg
im Git Repository und tragen unter [defaults]
folgendes ein.
vi ansible.cfg
[defaults]
# See: https://stackoverflow.com/questions/70202432/getting-a-python-warning-when-running-playbook-ec2-inventory
interpreter_python = auto_silent
Nun aktualisieren wir unser Git Repository und testen die Konfiguration erneut.
git add ansible.cfg
git commit -m "ansible configuration added"
git push origin master
Nun prüfen wir die neue Konfiguration erneut.
ansible all --key-file ~/.ssh/ansible -i inventory -m ping
192.168.0.3 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
Damit wir nicht jedes mal den Pfad zum Key wie auch zum Inventory angeben müssen, tragen wir auch dies in die ansible.cfg
Konfiguration unter [defaults]
ein.
vi ansible.cfg
[defaults]
# See: https://stackoverflow.com/questions/70202432/getting-a-python-warning-when-running-playbook-ec2-inventory
interpreter_python = auto_silent
inventory = inventory
private_key_file = ~/.ssh/ansible
Nun aktualisieren wir unser Git Repository und testen die Konfiguration erneut.
git add ansible.cfg
git commit -m "ansible configuration extended"
git push origin master
Die neue Konfiguration werden wir wie folgt testen. Dabei müssen wir nun nicht mehr den SSH Key, wie auch das Inventory angeben.
ansible all -m ping
192.168.0.3 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
Mit folgenden Befehl zeigen wir alle Maschinen aus der Inventory an.
ansible all --list-hosts
hosts (1):
192.168.0.3
Mit dem Modul gather_facts (-m gather_facts
) können wir details aus den Maschinen des Invetroy anzeigen lassen. Mit --limit
grenzen wir die Ausgabe auf den definierten Maschinen ein (Ausgab stark verkürzt).
ansible all -m gather_facts --limit 192.168.0.3
192.168.0.3 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"172.26.0.1",
"192.168.0.3",
.....
},
"changed": false,
"deprecations": [],
"warnings": []
}
Jetzt werden wir auf all unseren Maschinen mit dem Apt Befehl den Repository Index aktualisieren. Damit Ansible auch den Index aktualisieren kann, müssen wir das Sudo Password eingeben. Damit ansible dies auch abfragt, geben wir die Argumente --become --ask-become-pass
mit an.
ansible all -m apt -a update_cache=true --become --ask-become-pass
BECOME password:
PLAY [all] ************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************************************************************************************************
ok: [192.168.0.3]
TASK [update repository index] ****************************************************************************************************************************************************************************************************************
changed: [192.168.0.3]
TASK [install apache2 package] ****************************************************************************************************************************************************************************************************************
ok: [192.168.0.3]
PLAY RECAP ************************************************************************************************************************************************************************************************************************************
192.168.0.3 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Nun installieren wir auf allen Maschinen vim
und mit dem Argument state=latest
sorgen wir dafür, das auch wenn vim schon installiert ist, vim auf die aktuellese Version gehalten wird.
ansible all -m apt -a "name=vim state=latest" --become --ask-become-pass
BECOME password:
192.168.0.3 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"cache_update_time": 1672069465,
"cache_updated": false,
"changed": false
}
In diesem Fall ist auf allen Maschinen bereits vim
installiert und auf dem neusten Stand.
Mit folgendem Befehl upgrade=dist
halten wir die Maschinen auf den aktuellsten Stand.
ansible all -m apt -a "upgrade=dist" --become --ask-become-pass
BECOME password:
192.168.0.3 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"msg": "Reading package lists...\nBuilding dependency tree...\nReading state information...\nCalculating upgrade...\n0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.\n",
"stderr": "",
"stderr_lines": [],
"stdout": "Reading package lists...\nBuilding dependency tree...\nReading state information...\nCalculating upgrade...\n0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.\n",
"stdout_lines": [
"Reading package lists...",
"Building dependency tree...",
"Reading state information...",
"Calculating upgrade...",
"0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded."
]
}
Damit wir nicht alles in der Befehlszeile eingeben müssen, erstellen wir uns unser ersten Playbook. In diesem definieren wir, dass der Packet Index aktualisiert wird und apache2
auf dem Server installiert wird, bzw. apache2
auf den neusten Stand gehalten wird. Die Notation wird im YAML Format erstellt.
vi install_apache2.yml
---
- hosts: all
become: true
tasks:
- name: update repository index
apt:
update_cache: yes
when: ansible_distribution in ["Debian", "Ubuntu"]
- name: install apache2 package
apt:
name: apache2
state: latest
when: ansible_distribution in ["Debian", "Ubuntu"]
Möchte man den apache2
deinstallieren, können wir folgendes Playbook erstellen.
vi remove_apache2.yml
---
- hosts: all
become: true
tasks:
- name: update repository index
apt:
update_cache: yes
when: ansible_distribution in ["Debian", "Ubuntu"]
- name: remove apache2 package
apt:
name: apache2
state: absent
when: ansible_distribution in ["Debian", "Ubuntu"]
Nun aktualisieren wir unser Git Repository und testen die Konfiguration erneut.
git add .
git commit -m "added install/remove playbooks for apache2"
git push origin master
Nun testen wir unser ersten Playbook, zum installieren des apache2
.
ansible-playbook --ask-become-pass install_apache2.yml
BECOME password:
PLAY [all] ************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************************************************************************************************
ok: [192.168.0.3]
TASK [update repository index] ****************************************************************************************************************************************************************************************************************
ok: [192.168.0.3]
TASK [install apache2 package] ****************************************************************************************************************************************************************************************************************
ok: [192.168.0.3]
PLAY RECAP ************************************************************************************************************************************************************************************************************************************
192.168.0.3 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Nun haben wir viele Abhängigkeiten und viel Code im Playbook. Wir werden daher das Playbook generisch abändern. Wir nutzen dann statt das apt
Modul, das package
Modul und statt der Package Namen wie apache2, verwenden wir Variablen, die wir im Inventory definieren werden. Somit kann das Playbook auch für z.B. CentOS verwendet werden.
Als erstes ändern wir unser Playbook wie folg ab.
vi install_apache2.yml
---
- hosts: all
become: true
tasks:
- name: install apache and fcgid packages
package:
name:
- "{{ apache_package }}"
- "{{ fcgid_package }}"
state: latest
update_cache: yes
Die Variablen für die Package Namen definieren wir in unser inventory.
vi inventory
192.168.0.3 apache_package=apache2 fcgid_package=libapache2-mod-fcgid
Nun testen wir unsere Konfiguration.
ansible-playbook --ask-become-pass install_apache2.yml
BECOME password:
PLAY [all] ************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************************************************************************************************
ok: [192.168.0.3]
TASK [install apache and fcgid packages] ******************************************************************************************************************************************************************************************************
ok: [192.168.0.3]
PLAY RECAP ************************************************************************************************************************************************************************************************************************************
192.168.0.3 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Würden wir im inventory z.B. ein RedHat definiert haben, würde dieses Playbook auch dafür funktionieren. Wir müssten nur apache2
mit httpd
und libapache2-mod-fcgid
mit mod_fcgid
ändern bzw. im inventory definieren.
Nun aktualisieren wir unser Git Repository damit dieses wieder auf dem neusten Stand ist.
git add .
git commit -m "refactoring the playbook/inventory"
git push origin master
Nun werden wir in unseren inventory Gruppen hinzufügen. Ein Server kann auch in mehrere Gruppen sein, wie dies in meinem Fall ist.
vi inventroy
[web_servers]
192.168.0.3 apache_package=apache2 fcgid_package=libapache2-mod-fcgid
[db_servers]
192.168.0.3 mysql_package=default-mysql-server
Ausserdem haben wir in unserem Playbook noch tags gesetzt.
vi site.yml
---
- hosts: all
become: true
pre_tasks:
- name: install updates (Debian)
tags: always
apt:
upgrade: dist
update_cache: yes
when: ansible_distribution == "Debian"
- hosts: web_servers
become: true
tasks:
- name: install apache and fcgid packages
tags: apache,apache2
package:
name:
- "{{ apache_package }}"
- "{{ fcgid_package }}"
state: latest
- hosts: db_servers
become: true
tasks:
- name: install mysql-server packages
tags: mysql,mariadb
package:
name:
- "{{ mysql_package }}"
state: latest
Mit dem nun folgenden Befehl, können wir uns alle Tags des jeweiligen Playbook anzeigen lassen.
ansible-playbook --list-tags site.yml
playbook: site.yml
play #1 (all): all TAGS: []
TASK TAGS: [always]
play #2 (web_servers): web_servers TAGS: []
TASK TAGS: [apache, apache2]
play #3 (db_servers): db_servers TAGS: []
TASK TAGS: [mariadb, mysql]
Nun wird es Zeit, das neue Playbook mit zwei tags zu testen.
ansible-playbook --tags "apache2,mysql" --ask-become-pass site.yml
BECOME password:
PLAY [all] ************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************************************************************************************************
ok: [192.168.0.3]
TASK [install updates (Debian)] ***************************************************************************************************************************************************************************************************************
ok: [192.168.0.3]
PLAY [web_servers] ****************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************************************************************************************************
ok: [192.168.0.3]
TASK [install apache and fcgid packages] ******************************************************************************************************************************************************************************************************
ok: [192.168.0.3]
PLAY [db_servers] *****************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************************************************************************************************
ok: [192.168.0.3]
TASK [install mysql-server packages] **********************************************************************************************************************************************************************************************************
ok: [192.168.0.3]
PLAY RECAP ************************************************************************************************************************************************************************************************************************************
192.168.0.3 : ok=6 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0