Auf dieser Seite möchte ich mir einen kleinen Merkzettel zum Thema Ansible anlegen, da ich immer wieder mal wichtige Dinge dazu vergesse. Ich mach das hier in Stichpunkten und ergänze es jeden Tag mal. Dies ist keine Dokumentation sondern ein kleines Notizbuch dazu.
- Die ansible.cfg kann in folgenden Verzeichnis gezogen werden. Im aktuellen Verzeichnis, mit der Variable ANSIBLE_CONFIG, im Homeverzeichnis (~/.ansible.cfg) oder im /etc/ansible Folder. Der einfachste Aufbau kann wie folgt ausehen im aktuellen Verzeichnis.
[defaults]
inventory = inventories/devel/inventory
private_key_file = ~/.ssh/ansible
remote_user = ansible
log_path = log/ansible.log
vault_identity_list = save@/home/jonnybravo/bin/vault-keyring-client.pl, security@/home/jonnybravo/bin/vault-keyring-client.pl
force_handlers = true
nocows = true
retry_files_enabled = true
retry_files_save_path = retry-fils
#Cachen on facts erlauben
gathering = smart
#roles_path = ./roles
fact_caching = jsonfile
fact_caching_connection = fact_cache
fact_caching_timeout = 86400
[ssh_connection]
pipelining = true
- Retry Files kann wie folgt gestartet werden “
ansible-playbook playbooks/command.yaml --limit @error/retry-fils/command.retry“ Ein einfaches Inventory. :
[test]
debian ansible_host=xxx
ubuntu ansible_host=xxx
[test:vars]
ansible_python_interpreter=/usr/bin/python3
ansible_ssh_common_args='-o StrictHostKeyChecking=no'
[debian_hosts]
debian
[debian_hosts:vars]
ansible_user=ansible
ansible_become=true
ansible_become_pass=ansible
[ubuntu_hosts]
ubuntu
[ubuntu_hosts:vars]
ansible_user=ansible
ansible_become=true
- Ansible bietet eine Menge von Adoc Kommandos Hier eine kleine Liste von möglichen einsätzen -m ist das module
| Befehl | Beschreibung |
| ansible all -a „ls lisa /home“ | Dieses ist ein einfacher Shell aufruf auf allen Zielsystemen |
| ansible all -m ping | Ist ein Ping mit der Namensauflösung aus dem Inventory |
| ansible all -m command -a „df -h“ | Das Module Command um eine Komandozeile auszuführen. Das ist das selbe wie -a |
- Ein simples Beispiel für einen Command Aufruf über einen Task. Register speichert denn Aufruf in eine variable und Output stdout_lines oder stdout geben dann den output aus.
---
- hosts: all
gather_facts: true
tasks:
- name: Platzbedarf
command: df -h /
changed_when: false
register: df_cmd
- debug:
msg: '{{df_cmd.stdout_lines}}'
- Jeden Task kann man Tags geben, das hat den vorteil das man nicht immer alles aufrufen muss. Hier ein einfaches Beispiel mit dem entsprechenden Aufruf.
---
- hosts: all
gather_facts: true
tasks:
- name: yes
debug:
msg: "yes"
tags:
- "yes"
- name: no
debug:
msg: "no"
tags:
- "no"
- "nein"
ansible-playbook playbooks/tag-beispiel.yml -t "nein"
- Mit dem Command ansibe-playbook werden die Plays ausgeführt. Es gibt drei wichtige Optionen die ich immer wieder vergesse
| start-at-task | ansible-playbock <Play.yml –start-at-task „Name des Tasks *“ | führt das Playbook ab einem Task aus |
| check und diff | ansible-playbook <Play-yml> –check –diff | checkt und zeigt die änderung an die bei einem Play ausgeführt wird. |
| vard | ansible-playbook <Play.yaml> -e var=wert | Übergeben eine Variable |
- Ab der Version 2.2 ist es möglich bei den handlers listen zu definieren.
- Es gibt auch vars prompt abfrage einer varibale
---
- hosts: localhost
gather_facts: false
vars_prompt:
- name: "name"
prompt: "Wie ist dein Name"
default: "Meister Lampe"
private: false
- name: "passwort"
prompt: "dein neues Passwort"
private: true
tasks:
- debug:
msg: "Deine Name ist {{name}} und dein Passwort {{passwort}}"
ansible-playbook playbooks/vars_prompt.yml -e name=Daniel -e passwort=Start1234!
- Mit dem task assert kann man prüfen ob alle variablen im Play vorhanden sind
hosts: debian
gather_facts: no tasks:
assert:
that:
hostname is defined and hostname != ''
fail_msg: Die Variable hostname ist nicht vorhanden oder leer
name: Hostname setzen
hostname:
name: "{{ hostname }}"
- Es gibt varibalen die immer da sind unabhängig vom fact.
| inventory_hostname | der Name des Hosts im Inventory |
| inventory_hostname_short | der Name ohne FQDN |
| groups | Inventory Gruppe |
| hostvars | Hostvariablen aller Hosts (inkl. facts) |
| playbook_dir | Verzeichnis in dem das aktuelle Playbook liegt |
| inventory_dir,inventory_file | Verzeichnis bzw. File vom Inventory |
| role_path,role_name | Datei bzw. Name der aktuellen Rolle |
| ansible_version | Version von ansible |
- Man kann eigne facts anlegen wenn man auf dem Zielhost in dem Verzeichnis /etc/ansible/facts.d/ Datein mit der endung .facts anlegt im json Format. Ausführungsrechte müssen vorhanden sein chmod -x <datei.fact>
{
"Name" : "Mein fact"
}
ansible debian -m setup -a 'filter=ansible_local'
{{ansible_local.preferences.MeineName}}
- when kann ein größer kleiner und gleich. Der Aufruf kann ie folgt aussehen. ansible_distribution_version is version(‚19.10‘, ‚>=‘) Hier noch ein Beispiel.
vars:
apache:
Debian:
package_name: apache2
service_name: apache2
RedHat:
package_name: httpd
service_name: httpd
tasks:
- name: Apache installieren
package:
name: "{{apache[ansible_os_family].package_name}}"
- name: Dienst starten und in Bootprozess integrieren
service:
name: "{{apache[ansible_os_family].service_name}}"
state: started
enabled: yes
oder per include
tasks:
- include_vars: apache_{{ansible_os_family}}.yml
- name: Apache installieren
package:
name: "{{apache_package_name}}"
- name: Dienst starten und in Bootprozess integrieren
service:
name: "{{apache_service_name}}"
state: started
enabled: yes
- Ansible kann schleifen in mehreren Variationen. Hier ein paar Beispiele.
vars:
Comic:
- Spiderman
- Hulk
- IronMan
tasks:
- name: Schleife über Liste
debug: msg="Marvel comic {{ item }}!"
with_items: "{{Comic}}"
vars:
tiere:
- [Spiderman, Hulk, IronMan]
- [SuperSchlaubi, Dumbo]
tasks:
- name: Schleife über verschachtelte Liste
debug: msg="Marvel comic {{ item }}!"
with_items: "{{tiere}}"
vars:
tiere:
Hund: Wuff
Katze: Miau
Maus: Fiep
tasks:
- name: Schleife über Map
debug: msg="{{ item.key }} macht {{ item.value }}."
with_dict: "{{tiere}}"
tasks:
- name: Schleife über eine Folge
debug: msg="{{item}}"
with_sequence: start=6 end=12 stride=2 format=Ich_bin_die_Zahl_%02d
tasks:
- name: Würfeln
shell: "echo $(( $RANDOM % 6 + 1))"
register: wurf
args:
executable: /bin/bash
until: "'6' in wurf.stdout"
retries: 10
delay: 1
- debug: msg="Eine 6 wurde gewürfelt!"
vars:
users:
- name: testuser
home: /home/testuser
pass: Test
- name: schlaubi
shell: /bin/bash
pass: supergeheim
tasks:
- name: Benutzer anlegen
user:
name: '{{item.name}}'
shell: '{{item.shell | default("/bin/bash")}}'
home: '{{item.home | default(omit)}}'
password: '{{item.pass | password_hash("sha512") }}'
update_password: on_create
with_items: '{{users}}'
#loop_control mit label zeigt im output nur noch den item.name an nicht das passwort
loop_control:
label: 'item.name'
- Zur Fehlerbeandlung kann mit dem failed_when erfolgen oder wird einfach mit ignore_errors:true umgangen.
- Seit ansible 2.0 kann man auch blocks erstellen. Diese können dann auch einen gewünschten Resuce ausführen bei einem Fehler. Beispiel
tasks:
- block:
- name: Verzeichnis anlegen
file:
path: /tmp/download
state: directory
- name: Dateien von benachbartem Server herunterladen
get_url:
url: http://192.168.150.20/{{item}}
dest: /tmp/download/{{item}}
with_items: [index.html, test1.txt]
rescue:
- debug: msg="Beim Herunterladen ging was schief"
- name: Aufräumen
file:
path: /tmp/download
state: absent
when:
- ansible_os_family == "Debian"
- Für ein Asynchrone ausführung gibt es die Parameter asnyc und poll. async ist die maximale Laufzeit und poll gibt den abfrage Intervall an.
- local_action führt den entsprechenden Task auf dem host aus und mit delegate_to: xxx kann ein Task delikiert werden (auch localhost).
- Manchmal ist es nötige eine Umgebungsvaribale für den Zielhost zu definieren. Das funktioniert dann mit dem Parameter „environment“.
- Mit dem Kommando ansible-inventory lassen sich Informationen aus dem Inventory gewinnen. Beispiele :
| ansible-inventory –graph | Zeigt das aktuelle inventory grafisch | ||
| ansible-inventory –list –yaml | Zeigt das inventory in yaml |
- Wenn man hosts hat und diese noch nicht im inventory sind können diese on-the-fly hinzugefügt werden. In dem Beispiel heißt die inventory gruppe temp_groups
- hosts: localhost
tasks:
- name: Hosts bekanntmachen
add_host:
hostname: "{{item.ip}}"
groups: temp_group
ansible_become: yes
ansible_become_method: "{{item.become_method |default(omit)}}"
ansible_become_pass: "ansible"
ansible_ssh_common_args: '-o StrictHostKeyChecking=no'
with_items:
- ip: 192.168.150.10
- ip: 192.168.150.20
become_method: su
- hosts: temp_group
tasks:
- debug: msg="Hallo {{inventory_hostname}}"
- command: head -1 /etc/shadow
- Des weiteren gibt es dynamische Gruppen im Inventory. Dieser werde mit group_by angelegt. Beispiel.
- name: Gruppieren nach Systemfamilien
hosts: all
tasks:
- group_by: key=os_{{ ansible_os_family }}
- name: Alle aus der Debian-Familie abarbeiten
hosts: os_Debian
tasks:
- debug: msg="Hallo {{ inventory_hostname }}"
- name: Und nun der Rest
hosts: all:!os_Debian
tasks:
- debug: msg="Hallo {{ inventory_hostname }
- die Struktur von Rollen beinhaltet folgende Unterverzeichnise. Mit dem Commando ansibe-galaxy init <Rolle> werden die Verzeichnise automatisch angelegt.
| <Role>/tasks/main.yml | Die Tasks der Rolle |
| <Role>/files/* | Datein zum Hochladen |
| <Role>/templates | Jinia-Templates |
| <Role>/handlers/main | Handlers für die Rolle |
| <Role>/vars/main.yml | Variablen mit hoher Priorität |
| <Role>/defaults/main.yml | Variablen mit schwacher Priorität |
| <Role>/meta/main.yaml | Metainformation z.B. Anhängigkeiten von anderen Rollen |
- Eine weitere möglochkeit für Modularisierung sind imports „import_tasks:“ und includes „include_tasks:“. Imports sind statisch und includes dynamisch. Beispiel Dynamisches laden von variablen.
- name: Include OS-specific setings
include_vars:
with_first:found:
- {{ansible_os_family}}.yml
- default.yml
- Wichtige Module
- mit ansible-vault können Daten verschlüsselt werden mit einer vault-id oder das ganze per vault-file
ansible-vault encrypt --vault-id security@prompt inventories/devel/host_vars/debian.yml
entschlüsseln
ansible-vault decrypt --vault-id security@prompt inventories/devel/host_vars/debian.yml
editieren
ansible-vault edit --vault-id film@prompt inventories/devel/host_vars/debian.ym
| package | gemeinsamer Nenner von allen package Modulen (apt,yum,usw) |
| firewalld | Firewallsverwalten |
| meta | Beendet ein Play |
| paclage_facts | Paketinformationen |
| copy | um Daten zu kopieren |
| tempate | für Jinia templates |
| file | Datein verwalten |
| lineinfile | Zeilen in Text verwalten |
| blockinfile | Textpassagen in Dateien verwalten |
| stat | Infomationen über Datein |
| replace | suchen und ersetzen |
| unarchive | hochladen und auspacken |
| service, service_facts | Service Starte/Stoppen, Service Information |
| cron | cronjobs verwalten |
| hostname | Hostname ändern |
| user,group | Benutzer und Gruppenverwaltung |
| reboot | Reboot ausführen |
| get_url | Download of Ressourcen |
| uri | Kommunikation mit ebservices |
| git | Git |
| wait_for, wait_for_connection | auf Ereigniss warten, warten bis der host wieder erreichbar ist |
| assert | sicherstellen das gewisse Bedingungen erfüllt sind |
| set_fact | variablen in der Laufzeit setzen |
- hinter der vault-id kann folgendes stecken. <ID>@prompt Passwort interaktiv einlesen <ID>@DATEI Passwort von Datei einlesen und <ID>@PROGRAM Passwort aus Progamm einlesen. Hier nun ein Beispiel von Herrn Miesen mit gpg und pass. In der variable ANSIBLE_VAULT_IDENTITY_LIST sucht ansible nach dem Password.
$gpg --gen-key # UserID ist zum identifizierne
$pacman -S pass
$ pass init "<Real name von gpg>"
$ pass insert ansible/vault/security
$ ansible-playbook deployments/apache-site.yml --vault-id=security@vault-keyring-client.pl
$ export ANSIBLE_VAULT_IDENTITY_LIST=security@vault-keyring-client.pl
#security@vault-keyring-client.pl
#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long;
my $pass_prefix = "ansible/vault";
my $id;
GetOptions("vault-id=s" => \$id);
exec "pass" , "$pass_prefix/$id";
- mit dem Aufruf -f können die FORKS die definiert werden. Forks sind die laufenden Prozesse (default=5) in großen umgebungen und mit einem schnell Linux kann man schon 20 wählen oder mehr 🙂
- Es gibt drei Strategien für das Orchstrieren, die mit der Variable strategy gesetzt werden.
| linear | Default wert für das nach und nach abarbeiten |
| free | ein Host kann sofort zum nächsten Task übergehen |
| host_pinned | ähnlich wie free (bei niedriegen fork wir die anzahl nicht überschritten) |
- Ansible kann auch gut mit Docker. Hier die wichtigsten Module :
| docker_host_info | Host informationen abfragen. |
| docker_container | Container verwalten |
| docker_container_info | Container information |
| docker_network | benutzer definierte verwaltung |
| docker_network_info | Netzwerkinformationen abfragen |
| docker_volumes | verwalten von docker volumes |
| docker_volume_info | Infos der Volumes |
| docker_login | registry Login |
| docker_prune | aufräumen |
| docker_images | Images verwalten |
| docker_compose | Schnittstelle zu docker-compose |
- Ein random Password kann mit dem module password erstellt werden. Hier ein einfaches Beispiel um User anzulegen. Auf den host werden diese dann unter /tmp/credentials gespeichert.
- hosts: debian
vars:
users:
- name: jonnybravo
fullname: Jonny Bravo
- name: mustermann
fullname: Max Mustermann
- name: winzig
fullname: Willi Winzig
tasks:
- name: Benutzer anlegen
user:
name: "{{item.name}}"
shell: /bin/bash
password: "{{ lookup('password',
'/tmp/credentials/pass_'
+ item.name
+ '.txt length=50 encrypt=sha512_crypt') }}"
with_items: "{{users}}"
Den Output kann mit entweder mit der Variable ANSIBLE_STDOUT_CALLBACK oder in der ansible.cfg defnieren. Es gibt folgende Plugins die bereits im ansible vorhanden sind (2.9).
| default | Die normale Ausgabe |
| null | keine Bildschirmausgabe |
| yaml | Ausgabe im YAML Format |
| json | Ausgabe in json |
| unixy | Ausgabe im UNIX Stil |
| dense | sehr kompakte Ausgabe |
| minimal | Ausgabe wie beim ansible KOmmando |
| oneline | Ausgabe wie bei ansible-o |
| debug | Metainformation und reine Ausgabe |
| selective | Gibt nur spezielle Tasks aus |
| counter_enabled | Ausgabe mit Zählern |
Ab der Version 2.9 wurden collections hinzugefügt. Collections sind eigne oder modulansammlungen von anderen Entwicklern. Installiert werden diese über den galaxy befehl.
ansible-galaxy collection install community.window
Diese Beispiel installiert die community.windows collection die auf der Ansible Website :
https://docs.ansible.com/ansible/latest/collections/community/windows/index.html
Liste alle Collections:
https://docs.ansible.com/ansible/latest/collections/index.html#list-of-collections
Ab hier werde ich Codeschnipsel zu Verfügung stellen. Für weitere Anregung und auch für mich selbst als Spickzettel : )
Dieses Beispiel fragt ab, ob ein User existiert mit dem Module getent. Diese Module ist sehr mächtig, da man da alles auf dem Linuxsystem abfragen kann.
https://docs.ansible.com/ansible/latest/collections/ansible/builtin/getent_module.html
- name: Test
hosts: localhost
gather_facts: true
vars:
testuser: "username"
tasks:
- name: Check if user exists
getent:
database: passwd
key: "{{testuser}}"
fail_key: False
- debug:
var: getent_passwd.{{testuser}}
- debug:
msg: "Der User existiert nicht"
when: getent_passwd[testuser] == none
~
Neueste Kommentare