https://github.com/trinker/reveal/blob/master/PRESENTATION/reveal.md#/0
- Schneller Einstieg
- Kurz: Was ist automatisierung
- Installation
- Ansible erstes Verständnis
- Was ist ansible
- Architektur & Aufbau Bild
- Ansible - Playbooks
- Ansible - Variablen
- Ansible - Simple Templates
- Ansible - Einfache Schleifen
- Ansible - When Statement
- Ansible - Inventories
- Ansible - Roles
- Ansible-Environment
- Erweitert
Created by gh-md-toc
Ansible wird einfach über den Paket manager installiert, oder über pip.
$ sudo apt-get update
$ sudo apt-get install software-properties-common
$ sudo apt-add-repository ppa:ansible/ansible
$ sudo apt-get update
$ sudo apt-get install ansible
Prüfen ob ansible "funktioniert"
# ansible --version
ansible 2.5.0
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/dist-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.12 (default, Dec 4 2017, 14:50:18) [GCC 5.4.0 20160609]
Ansible ist als CLI Tool nutzbar und kann somit sehr einfach ausgeführt werden.
Erstellen wir im ersten Beispiel einen neuen Nutzer:
# ansible localhost -m "user" -a "name=kathie state=present home=/home/kathie"
ubuntu | SUCCESS => {
"changed": true,
"comment": "",
"create_home": true,
"group": 1000,
"home": "/home/kathie",
"name": "kathi",
"shell": "",
"state": "present",
"system": false,
"uid": 1000
}
Ansible hat die "Resource" User mit dem namen Kathie angelegt. Was passiert, wenn wir dieses Kommando noch einmal ausführen?
# ansible localhost -m "user" -a "name=kathie state=present home=/home/kathie"
ubuntu | SUCCESS => {
"append": false,
"changed": false,
"comment": "",
"group": 1000,
"home": "/home/kathie",
"move_home": false,
"name": "kathie",
"shell": "",
"state": "present",
"uid": 1000
}
Verändern wir nun den Kommentar (comment) des Nutzers und schauen was passiert.
# ansible localhost -m "user" -a "name=kathie state=present home=/home/kathie comment='Kathie Wiese"
ubuntu | SUCCESS => {
"append": false,
"changed": true,
"comment": "Kathie Wiese",
"group": 1000,
"home": "/home/kathie",
"move_home": false,
"name": "kathie",
"shell": "",
"state": "present",
"uid": 1000
}
Dabei fällt auf, dass "changed" nun wieder auf "true" steht und der Kommentar nun nicht mehr leer ist.
ansible ist ein CLI Tool, das einfach einzusetzen ist.
# ansible localhost -m "user" -a "name=kathie state=present home=/home/kathie comment='Kathie Wiese"
- localhost beschreibt hier die Hosts auf denen der Lauf ausgeführt werden soll.
- -m gibt das Modul an, das ausgeführt werden soll
- -a Beschreibt die Parameter für das Modul, das mit -m übergeben wurde z.B. "user"
- Installiert das Programm nginx über die Kommandozeile.
- Deinstalliert das Programm wieder.
ansible <inventory> options
ansible localhost -a /bin/date
ansible localhost -m ping
ansible localhost -m package -a "name=vi state=latest"
ansible localhost -C -m package -a "name=vi state=latest"
Prüft die gegebene Situation auf dem System, ändert aber nichts. Nicht alle Module unterstützen den check mode, diese werden übersprungen. Dieser kann mit -C benutzt werden
ansible localhost -C -m package -a "name=vi state=latest"
- ansible ist eine simple "automation-language"
- außerdem ist ansible auch die "automation engine" die "Playbooks" ausführt
- Einfachheit
- "Human readable"
- Simples yaml Format
- Jeder soll Ansible lesen und verstehen können ohne es zu kennen
- Simple Struktur, Code wird immer von oben nach unten ausgeführt (in order)
- Schnell "produktiv" gehen
- Powerfull
- "einfach" anwendbar auf bestehende Infrastruktur
- Workflow Automatisierung
- "Lifecycle" Automatisierung
- Agentless
- benötigt nur SSH Zugriff (oder WinRM)
- keine weiteren Firewall-Konfigurationen nötig...
- keine "clients", die man ausnutzen oder aktuell halten muss.
- benötigt nur SSH Zugriff (oder WinRM)
Ansible versucht, jeden schnell an die Automatisierung von IT-Infrastruktur/Prozessen zu bringen und dabei Komplexität zu verringern.
Ansible ist eine Sprache, die den zu erreichenden Zustand beschreibt, nicht wie man zu dem Zustand kommt.
- Config Management
- App Deployment
- Provisionierung
- Continous Delivery
- Security Compliance
- Orchestration
Quelle: https://www.ansible.com/resources/videos/quick-start-video
Der eben erstellte User sollte noch existieren, versuchen wir ihn nun wieder zu löschen. Hierfür benutzen wir nun einen "task" und das Subtool "ansible-playbook"
Erstellen wir eine Datei auf dem Server mit folgendem Inhalt:
---
- hosts: localhost
tasks:
- name: ensure user Kathie Wiese
user:
name: kathie
comment: "Kathie Wiese"
state: absent
Nach dem Speichern kann man nun folgenden Befehl ausführen:
# ansible-playbook user_absent.yml
PLAY [localhost] **************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************************************************************************************************************
ok: [localhost]
TASK [ensure user Kathie Wiese] ***********************************************************************************************************************************************************************************
changed: [localhost]
PLAY RECAP ********************************************************************************************************************************************************************************************************
localhost : ok=1 changed=1 unreachable=0 failed=0
Ein weiteres Ausführen des Befehls wird keine Änderungen vornehmen:
# ansible-playbook user_absent.yml
PLAY [localhost] **************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************************************************************************************************************
ok: [localhost]
TASK [ensure user Kathie Wiese] ***********************************************************************************************************************************************************************************
ok: [localhost]
PLAY RECAP ********************************************************************************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0
Cool, somit habt ihr euren ersten Play geschrieben und ausgeführt.
Ansible playbook ist das tool um ansible "plays" und "playbooks" auszuführen.
- Ein Playbook benutzt "plays"
- Ein Play benutzt "tasks"
- Ein Task benutzt "module"
- Diese laufen sequentiell ab
Für jeden Play oder Playbook muss man sich entscheiden, für welchen Host und mit welchem User dieser ausgeführt werden soll.
# examples/plays/user_absent.yml
---
- hosts: localhost # diese Zeile beschreibt, für welche hosts der Play oder das Playbook ausgeführt werden soll.
remote_user: root # beschreibt, als welcher user der Play ausgeführt werden soll.
Genaueres zu Hosts und deren Patterns findet man hier: http://docs.ansible.com/ansible/latest/user_guide/intro_patterns.html
Schauen wir uns die Deklaration eines "modules" unter dem Punkt: "Tasks" genauer an. Es gibt viele verschiedene Module in Ansible und diese sind immmer recht ähnlich aufgebaut. Bleiben wir bei unserer "Kathie"
# examples/plays/user_absent.yml
- name: "ensure user Kathie Wiese" # ein task braucht immer einen namen der dann zur laufzeit angezeigt wird
user: # das modul in unserem falle user
# die "übergabe Werte" des User-Moduls
name: kathie
comment: "Kathie Wiese"
state: absent
Solche "snippets" werden Tasks genannt. Diese beinhalten einzelne Module für eine bestimmte Gruppe von Hosts.
Dies ist auch immernoch mit "ansible" ausführbar:
ansible localhost -m user -a "name=kathie comment='Kathie Wiese' state=absent"
Was das user Modul sonst noch so kann findet man hier: http://docs.ansible.com/ansible/latest/modules/user_module.html
- Kontrollieren System-Resourcen
- Ansible besitzt ~ 450 standard Module
- Ziel: Einfachheit
Weitere kleine Beispiele liegen in examples/plays
Hier findet man alle ansible Standard-Module: http://docs.ansible.com/ansible/devel/modules/modules_by_category.html
Nun haben wir einen kleinen Task erledigt, machen wir nun etwas mehr. Installieren wir SSHD und sorgen dafür das er beim Systemstart immer ausgeführt wird, eigentlich sollte hier nichts passieren.
---
- hosts: localhost
remote_user: root
tasks:
- name: ensure package ssh
package:
name: openssh-server
state: present
- name: ensure that ssh server is running
service:
name: sshd
enabled: true
state: started
Der einzige große Unterschied zu vorher ist, das wir eine weitere Task-Definition haben, auch ohne großes Ansible-Verständiss ist dieser "Definition leicht lesbar".
Ergebnis:
PLAY [localhost] **************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************************************************************************************************************
ok: [localhost]
TASK [ensure package ssh] ***************************************************************************************************************************************************************************************
changed: [localhost]
TASK [ensure that ssh server is running] *******************************************************************************************************************************************************************************
changed: [localhost]
PLAY RECAP ********************************************************************************************************************************************************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0
Lasst uns das Prüfen.
# systemctl status sshd
Ansible kann nicht nur Pakete und Benutzer verwalten sondern auch Dateien, hierführ gibt es mehrere Möglichkeiten.
Zurück zu unserem vorherigen Beispiel sshd, lass uns dieses etwas erweitern.
<snip>
- name: ensure etc/banner
file:
state: directory
dest: /etc/banner
owner: root
- name: copy isssue.net
copy:
src: issue.net
dest: /etc/banner/issue.net
owner: root
- name: Enable issue.net Banner
lineinfile:
path: /etc/ssh/sshd_config
regexp: '^Banner='
line: 'Banner=/etc/banner/issue.net'
</snip>
PLAY [localhost] ***************************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [ensure etc/banner] *******************************************************
changed: [localhost]
TASK [copy isssue.net] *********************************************************
changed: [localhost]
TASK [Enable issue.net Banner] *************************************************
changed: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=4 changed=3 unreachable=0 failed=0
All diese Module sind Standard-Module und lange nicht alle, was machen diese denn genau? Eine Liste aller "File" Module findet man hier: http://docs.ansible.com/ansible/latest/modules/list_of_files_modules.html
Dieses Modul beschreibt den Zustand einer Datei. http://docs.ansible.com/ansible/devel/modules/file_module.html
Kopiert Daten vom "Server" System zum Ziel System. http://docs.ansible.com/ansible/latest/modules/copy_module.html#copy
Es ist auch möglich, nur einzelne Teile einer Datei zu verändern und den Rest unverändert zu lassen. http://docs.ansible.com/ansible/latest/modules/lineinfile_module.html#lineinfile
Nun haben wir schon einiges gesehen:
- Ansible Plays
- Das Zusammenführen von mehreren Tasks in einem Play
- Manipulation von "services", Dateien, Paketen und Benutzern
Schreibe einen Play der Folgendes Erledigt:
- Nginx installieren
- Service nginx starten
- Service nginx bei jedem start mit hochfahren
- Eine rudimentaere "Welcome Page"
- Variablen helfen Playbooks unterschiedlich auszuführen
- Diese kann man aus mehreren Quellen beziehen:
- Command Line
- Den Playbooks selbst
- Files
- Inventory (group vars, host vars)
- Vom Ziel System (Facts)
- Ansible Tower
Variablen werden in Ansible fast immer mit {{ }} umklammert und in Playbooks zusätzlich mit "". Dies ist ein sehr komplexes Thema, deshalb wird auch hier nur auf die Basics eingegangen.
Variablen in der Commandline werden mittels -e key=value angegeben, diese können dann im kompletten Ansible-Kontext verwendet werden.
htop installieren:
ansible localhost -e htop_ensure=present -m package -a "name=htop state={{ htop_ensure }}"
htop deinstallieren:
ansible localhost -e htop_ensure=present -m package -a "name=htop state={{ htop_ensure }}"
---
- hosts: localhost
remote_user: root
vars:
user_comment: "Kathie Wiese"
tasks:
- name: ensure user Kathie Wiese
user:
name: kathie
comment: "{{ user_comment }}"
state: present
ansible localhost -m setup
localhost | SUCCESS => {
"ansible_facts": {
"ansible_apparmor": {
"status": "disabled"
},
"ansible_architecture": "x86_64",
"ansible_bios_date": "07/04/2017",
"ansible_bios_version": "1.3.7",
"ansible_cmdline": {
"acpi_backlight": "vendor",
"cryptdevice": "/dev/nvme0n1p2:cryptroot",
"initrd": "\\initramfs-linux.img",
"root": "/dev/mapper/cryptroot",
"rw": true
},
"ansible_date_time": {
"date": "2018-04-17",
"day": "17",
"epoch": "1523978477",
"hour": "15",
"iso8601": "2018-04-17T15:21:17Z",
"iso8601_basic": "20180417T152117234552",
"iso8601_basic_short": "20180417T152117",
"iso8601_micro": "2018-04-17T15:21:17.234600Z",
"minute": "21",
"month": "04",
"second": "17",
"time": "15:21:17",
"tz": "UTC",
"tz_offset": "+0000",
"weekday": "Tuesday",
"weekday_number": "2",
"weeknumber": "16",
"year": "2018"
},
...
Wow, was ein Haufen, all diese Variablen sind im ansible Play nutzbar. Dieser Vorgang nennt sich bei Playbooks gathering_facts und wird vor jedem Play für jeden Host ausgeführt. Dies kann man aber auch deaktivieren, falls man diese Variablen nicht braucht:
hosts: localhost
remote_user: root
gathering_facts: no # deaktiviert diese
tasks:
...
Jetzt hat man all den Kram, wie wendet man das nun sinnvoll an?
hosts: localhost
remote_user: root
gathering_facts: no
vars:
issue_text: "Welcome to my server"
tasks:
- name: "Templating issue.net"
template:
src: issue.net.j2
dest: /etc/banner/issue.net
owner: root
group: root
mode: 0644
# cat issue.net.j2
Ansible generated message:
{{ issue_text }}
In Ansible sind Schleifen möglich um komplexere Aufgaben zu erledigen. http://docs.ansible.com/ansible/devel/user_guide/playbooks_loops.html http://docs.ansible.com/ansible/latest/user_guide/playbooks_special_topics.html
Ansible benötigt eine Liste von Zielen auf denen die Playbooks ausgeführt werden können.
- Statisch eingetragene Server
- Custom geschriebenes Zeug
- Dynamische generierte Server Listen aus der Cloud oder sonstigem Tools (AWS, Consul, Google, uvm...)
Zurück zum Anfang:
ansible localhost -m user -a "name=kathi state=absent"
Hier an zweiter Stelle sagen wir ansible auf welchen Hosts das Modul ausgeführt werden soll. Bei ansible-playbook tun wir dies im Playbook.
- hosts: localhost #<----
remote_user: root
tasks:
- name: ensure user Kathie Wiese
user:
name: kathie
comment: "Kathie Wiese"
state: absent
Woher bezieht ansible diese Daten?
Ansible benutzt dafür eine "Inventory Datei", diese liegt zuallererst in /etc/ansible/inventory, dies ist aber auf viele Arten änderbar. z.B. mit -i.
cat examples/inventory/static_inventory
localhost
[webservers] # definiert eine Gruppe von Servern
foo.example.com # definiert die Rechner in der Gruppe
bar.example.com:1337
[dbservers]
one.example.com ansible_host=192.168.0.66 ansible_port=5512 # der Host hat keinen DNS Eintrag deshalb kann dieser verändert werden.
two.example.com
three.example.com
Es gibt noch weitere Methoden wie INI und YAML Format.
Um es mal erwähnt zu haben, auch Patterns sind möglich.
[desktop]
pc-bn-[01:50]
Sowie connection Types
[client]
localhost ansible_connection=local
other1.example.com ansible_connection=ssh ansible_user=mpdehaan
- Schreibt ein Inventory für euren Play und führt diesen über eine Gruppe aus. Das Inventory könnt ihr mit -i angeben.
ansible-playbook -i inventory play.yaml
Es ist möglich, für Hosts und Gruppen Variablen festzulegen, diese können in Plays individuell genutzt werden.
- all
- Beinhaltet alle hosts
- ungrouped
- Beinhaltet alle hosts die in keiner weiteren Gruppe sind.
Ändert euren Play so ab, dass dieser von eurem Rechner eine anderes System provisioniert.
ansible-galaxy ist hier dein Freund und Helfer.
ansible-galaxy init ansible-nginx
ansible-nginx/
|-- README.md
|-- defaults
| `-- main.yml
|-- files
|-- handlers
| `-- main.yml
|-- meta
| `-- main.yml
|-- tasks
| `-- main.yml
|-- templates
|-- tests
| |-- inventory
| `-- test.yml
`-- vars
`-- main.yml
Machen wir aus dem bisherigen Play ein richtiges Playbook.
Ansible ist auf viele Arten Konfigurierbar. Standard-Suchpfade für ansible.cfg sind:
- ANSIBLE_CONFIG (environment variablen sollten sie gesetzt sein)
- ansible.cfg (im aktuellen Verzeichnis)
- ~/.ansible.cfg (im User Home)
- /etc/ansible/ansible.cfg
Sample
[defaults]
inventory = ./inventory
host_key_checking = False
log_path = /tmp/ansible.log
roles_path = ./roles
ansible Galaxy ist eine Webseite, auf der man seine Playbooks hochladen und "veröffentlichen" kann. Dort findet man auch viele bereits fertige Playbooks, welche aber mit Vorsicht zu genießen sind, meist erfüllen sie nicht genau den Zweck. Allerdings sind diese sehr gut für Anregungen oder als Ausgangspunkt, sofern die Lizens dies zulässt.
Installieren von dependencies aus der galaxy ist möglich.
# from galaxy
- src: yatesr.timezone
# from GitHub
- src: https://github.com/bennojoy/nginx
# from GitHub, overriding the name and specifying a specific tag
- src: https://github.com/bennojoy/nginx
version: master
name: nginx_role
# from a webserver, where the role is packaged in a tar.gz
- src: https://some.webserver.example.com/files/master.tar.gz
name: http-role
# from Bitbucket
- src: git+http://bitbucket.org/willthames/git-ansible-galaxy
version: v1.4
# from Bitbucket, alternative syntax and caveats
- src: http://bitbucket.org/willthames/hg-ansible-galaxy
scm: hg
# from GitLab or other git-based scm
- src: git@gitlab.company.com:mygroup/ansible-base.git
scm: git
version: "0.1" # quoted, so YAML doesn't parse this as a floating-point value
Erstellt ein gekapseltes environment, was ansibleenv heißt und roles aus ansibleenv/roles bezieht.
- Check Mode
- Playbooks Tests
- Asserts