👁️
pierreinside
  • Introduction
  • Workbench
    • VirtualBox
    • Linux
      • Linux-Paketverwaltung
      • Linux Initialisierung
      • Ubuntu 14.10 LTS
      • Ubuntu 16.04 LTS
      • Ubuntu 18.04 LTS
      • Ubuntu 20.04 LTS
      • Ubuntu - Netzwerk
    • Konsole
      • ssh
      • zsh
      • cygwin
      • Babun
      • terminator
      • Terminal Multiplexer
      • Linux Tools
    • awesome
    • Entwicklungsumgebungen
      • Texteditors
      • Visual Studio Code
      • IntelliJ - IDEA
  • Softwareentwicklungsprozess
    • Schätzungen
    • Eventstorming
    • OKR
  • Architektur
    • Uncle Bob
    • Microservices
    • NoSQL
      • ElasticSearch
    • Hystrix
    • Reactive Programming
    • AngularJS
    • Service Mesh
  • Networking
    • Dependency Injection
  • Programming
    • Java Core/EE
      • Java 8
      • Java Annotationen
      • Bean Validation
      • Enterprise Java Beans Specification
      • Dependency Injection
    • JRebel
    • Webservices
      • HTTP
      • REST
      • Spring MVC REST
      • Swagger
      • Postman
    • Spring Ecosystem
      • Spring Core
      • Spring Boot
        • Programming
        • Production Ready
        • Testing
      • Spring Cloud
      • Spring Cloud Config
      • Spring MVC
      • Spring Data
      • Spring Petclinic
    • NodeJS
    • UI-Technologie
      • Thymeleaf
      • ionic
      • Web Fonts
      • Jinja Templates
      • Twitter Bootstrap
    • Python Ecosystem
      • Python Libraries
      • Python Testing
      • Python Best-Practices
      • Python Snippets
      • Python Selenium
      • Kivy UI
      • FastAPI
      • Typer CLI
      • Django
    • Groovy
    • Persistenz
      • Transactions
        • Java TX
        • JPA TX
      • TX Handling
      • JPA
        • Eclipse Link
      • MySQL
        • MySQL Performance
        • Docker MySQL
      • Hazelcast
    • Glassfish
    • YAML
    • Angular
    • Camel
    • Zeichenkodierung
    • Kinder lernen Programmieren
  • Testen
    • Easymock
    • Mockito
  • Performance & Scalability
    • Java Performance
      • Heapdump Analysis
    • Java Concurrency
    • Instana
  • Sicherheit
    • Authentifizierung
      • OpenID Connect
      • Web-Authentication API
    • Authorisierung
      • OAuth
      • SAML
    • Spring Security
    • Zertifikate
    • Kali Linux
    • VPN
    • Zero-Trust-Networks
  • Build und Deployment
    • Maven
    • Bamboo
    • Jenkins
      • Jenkins Pipelines
      • Jenkins Pipelines Tips und Tricks
      • Jenkins-configuration-as-Code
      • Jenkins IDE
    • Travis CI
    • Shellprogrammierung
      • jq - JSON Parsing
    • Konfiguration Management
    • Vagrant
      • Vagrant-Ansible-Integration
      • Vagrant Box bauen
    • Ansible
      • Getting Started
      • Ansible Details
    • Saltstack
    • LinuxKit
    • Container
      • Docker
        • Docker Getting Started
        • Debugging Docker
        • Docker Build
        • Docker Registry
        • Docker run
          • docker run
          • docker network
        • Docker Compose
        • docker machine
        • Docker@Windows
        • Docker Host
        • Docker Scaling
        • Docker Ressources
        • Docker Logging
        • windowsContainer
      • Cloud Deployment Provider
        • AWS
          • Anwendungsdeployment
          • Workload
          • Permissions
          • Netzwerke
          • AWS CLI
            • aws-vault
          • RDS
          • Static Website Hosting
          • EKS - Elastic Kubernetes Service
          • S3
        • Google Cloud Platform
      • Docker Orchestrierung
        • CoreOS
        • Kubernetes
          • microK8s
          • minikube
          • autoscaler
          • Docker
          • k9s
        • Nomad
    • PHP
  • Operations
    • Proxy
      • NGINX
    • DNS
    • Logging
      • Graylog
      • Fluentd
    • Monitoring
      • Grafana
    • Infrastructure-as-Code
      • Terraform
        • AWS-Provider
        • GitHub-Provider
      • Packer
    • Deployment
      • Vault
      • Consul
        • Consul Template
      • Fabio
  • Rechtliches
    • Software-Lizenzen
  • Git Ecosystem
    • Git
      • Git Lifecycle Hooks
    • GitHub
      • GitHub Organizations
    • GitHub Actions
    • GitHub Pages
    • GitHub CLI
    • GitHub Copilot
    • GitHub-AWS OIDC
    • GitBook
    • GitLab
    • Bitbucket/Stash
  • Publishing
    • WordPress
    • Markdown
    • Static Site Generators
      • Hugo
      • Jekyll
    • Tiddly Wiki
    • Leanpub
    • Animationsfilme
  • Storage
    • Synology 2012
    • Synology 2021
  • Collaboration
    • Übersicht
    • Microsoft Teams
  • Konferenzen
    • Velocity Berlin 2019
  • IT mit Kindern
    • Projekt Sportstracker
    • Scratch
    • Pico Spielekonsole
  • Schule
    • Mathematik
  • Misc
    • Foto/Video
      • Foto/Video Sammlung bis 2023
        • Handbrake
        • Onedrive
      • Foto/Video Sammlung ab 2024
      • Gopro
      • Panasonic FZ1000 ii
        • als Webcam
      • AV Receiver
      • Videos erstellen
        • OBS Studio
        • Touch Portal
        • Game-Streaming
      • Kameratasche
      • Kamera 2020
    • Handy
      • 2016
      • 2018
      • 2019
      • 2021
      • 2022
    • Computer
      • Laptop
        • 2018
        • Chromebook
      • Monitor
        • 4k
      • Software
        • Command Line Interface
        • Google API
        • Plant UML
        • Chromium
        • Passwort-Manager
        • GPG
      • Dell CNF 2665 Farbdrucker
      • Dockingstation
      • Gaming PC 2021
      • Mobiles BĂźro
      • Mobiles Internet
      • Mobiler Router
    • Beamer Benq W1000+
    • Spielekonsole
      • 2017
        • Playstation 4
      • Pico Spielekonsole
    • Gadgets
      • iPad Pro 2015 und 2016
      • iPad Air 2024
      • Macbook Pro
      • Smartwatch
      • Slate
      • Mudi
    • Fahrrad
      • Jonas 2018
      • SQLab
    • Auto
      • Auto 2022
      • Camping
        • Camping Touren Ideen
          • Camping Tour - Gardasee 2021
        • Camper
          • Camper klein - keine StehhĂśhe
            • VW Bus Erfahrungen
          • Camper gross - StehhĂśhe
    • Haus
      • Klimaanlage
      • Swimming Pool
      • Quick Mill Orione 3000
      • SpĂźlmaschine 2021
      • Hebe-SchiebetĂźr
      • Gasgrill
      • Minibar / Mini-KĂźhlschrank
      • Glasfaseranschluss (Fiber-to-the-Home)
      • Smart-Home
        • Raspberry Pi
        • Heimnetzwerk
      • Homeoffice
      • Energie
        • Solar
        • Wärmepumpe
    • Freizeit
      • Musik Streaming
      • Sky
      • Online Lernplattformen
      • eScooter - ePowerFun
    • Fußball
      • Meine Arbeit als Fußball-Trainer
      • Fußball Tools
      • DFB TalentfĂśrderung
    • Google Impact Challenge
  • Englisch
Powered by GitBook
On this page
  • Wichtige Konzepte
  • Idempotenz
  • AdHoc vs. Playbook
  • Multimachine
  • Local vs. Remote
  • Getting Started
  • Ansible Runtime Engine fĂźr Playbooks
  • LogLevel
  • Konfiguration
  • Wichtige Parameter
  • scp_if_ssh
  • Ansible Playbook DSL
  • YAML-Syntax
  • Module
  • Variablen
  • Lookups
  • Inventory
  • Wiederverwendung
  • Includes
  • Roles
  • Role Java
  • ProjektĂźbergreifende Wiederverwendung
  • Best Practices
  • Nicht verwenden "remote_user: root"
  • SSH-Agent starten und konfigurieren
  • Verwende Roles
  • Bewertung
  • Lernkurve
  • Pro
  • Contra
  • Performance
  • Alternativen
  • Alternative Shellscripting

Was this helpful?

  1. Build und Deployment

Ansible

Ansible wird zum automatisierten Provisioning von Systemen eingesetzt.

In einem Multimachine-Vagrant-Projekt, das aus 5 verschiedenen Images bestand und dessen Provisioning eine knappe Stunde dauerte, haben wir Shellscripting zum Provisioning eingesetzt. Das hatte einige Vorteile, aber auch einen ganz entscheidenden Nachteil: Fehlende Idempotenz.


Wichtige Konzepte

Idempotenz

Idempotenz erlaubt es ein Script mehrfach hintereinander ablaufen zu lassen, ohne daß sich das Ergebnis verändert. Einige Praxisbeispiele:

  • Beispiel 1: fĂźr meinen Workbench-Anwendnungsfall besonders wichtig

    • Skripte entwickeln sich weiter und neu entwickelte Teile sollen auch sofort genutzt werden kĂśnnen. Ohne Idempotenz darf/kann ich bereits ausgefĂźhrte Schritte nicht einfach wiederholen, sondern muß sie auskommentieren (o. ä. ... was evtl. gar nicht so einfach ist).

    • enthält ein Skript mkdir /tmp/test, so ist das nicht idempotent. Bei der zweiten AusfĂźhrung schlägt das Kommando fehl, weil das Verzeichnis schon existiert. Ohne Idempotenz-Support muß man dann mĂźhselig (und fehlerträchtig) entsprechende if-clauses einbauen oder andere Befehle nutzen.

  • Beispiel 2:

    • Bricht das Provisioning nach 20 Minuten Laufzeit mit einem Fehler ab, dann bedeutet das nach Beheben des Fehlers oftmals (wenn man nicht mehrere Minuten in das manuelle Anpassen der Scripte investieren will), daß das Image komplett platt gemacht und neu aufgebaut wird ... also wieder 20 Minuten warten bis man Ăźberhaupt wieder so weit ist wie man schon mal war.

Fehlende Idempotenz hat zumeist zur Folge, daß die Skripte nicht regelmäßig ausgeführt werden (weil: zu umständlich) und das wiederum hat zur Folge, daß man bei jeder Ausführung Schlimmstes befürchten muß.

Ansible unterstĂźtzt Idempotenz (state=present):

lineinfile: 
    dest=~/.zshrc
    state=present
    line='ZSH_THEME=robbyrussell'

AdHoc vs. Playbook

  • http://docs.ansible.com/ansible/intro_adhoc.html

AdHoc-Kommandos werden per ansible (--args aka -a)

 ansible all --args "/bin/echo hello"

abgeschickt und sind so komfortabel wie Shell-Kommandos ... nur eben mit der Mächtigkeit sehr viele Hosts mit der Abarbeitung des Kommandos zu beauftragen.

Ein Playbook hingegen ist eher fĂźr umfangreichere Aktionen gedacht:

ansible-playbook myplaybook.yml

Hierzu wird eine Playbook-Datei benĂśtigt.

Multimachine

Während man es bei Shellscripting und Vagrantscripting gewohnt ist auf EINER Maschine zu arbeiten, ist Ansible dazu gedacht Kommandos auf vielen Maschinen (evtl. Tausende) gleichzeitig auszuführen. Das erleichtert insbesondere die Wartung von Serverfarmen. Hierzu lassen sich Maschinen über das Inventory-File (/etc/ansible/hosts) kategorisieren, so daß per

ansible webservers -a "/bin/df -h"

alle als Webserver kategorisierte Maschinen ihre Plattenbelegung ausgeben.

Local vs. Remote

Ansible unterscheidet zwischen

  • Local-Verbindung: hierbei wird das Ansible-Skript/Kommando nicht per ssh zum Zielrechner (= localhost) gebracht ... insofern muß die ssh-Infrastruktur auch nicht existieren. Allerdings funktionieren dann Properties wie remote_user nicht ... stattdessen wird become verwendet, um in eine andere Rolle zu schlĂźpfen (beispielsweise als root zu agieren)

  • Remote-Verbindung: hierbei wird das Kommando auf dem Zielrechner per ssh -c ... ausgefĂźhrt. Das kann auch passieren, wenn der Zielrechner localhost ist.

Wenn nicht explizit angegeben wurde, ob Ansible local oder remote verwenden soll, dann versucht Ansible ein Auto-Detection. Man kann Ansible aber auch unter die Arme greifen, um die Connection-Variante explizit zu bestimmen (/etc/ansible/hosts):

localhost ansible_connection=local

Das Scripting unterscheidet sich bei den AusfĂźhrungsformen nicht. Allerdings benĂśtigt die Remote-AusfĂźhrung ein erweitertes Setup (ssh-Infrastrutur).

ACHTUNG: fßrs Entwickeln der Skripte ist der Local-Mode sicherlich ganz brauchbar, aber integrativ sollte man dann tatsächlich auch im Remote-Mode testen

Remote-Mode

Über den Parameter -vvvvvv kann man die einzelnen Schritte erkennen, die Ansible für die Remote-Ausführung macht - hier am Beispiel ansible ansible-target --args "/bin/echo hello" -vvvvvv:

╭─pfh@workbench ~/.ssh  
╰─➤  ansible ansible-target --args "/bin/echo hello" -vvvvvv
Using /etc/ansible/ansible.cfg as config file
Loaded callback minimal of type stdout, v2.0
<ansible-target> ESTABLISH SSH CONNECTION FOR USER: admin
<ansible-target> SSH: ansible.cfg set ssh_args: 
      (-o)(ControlMaster=auto)
      (-o)(ControlPersist=60s)
<ansible-target> SSH: ansible_password/ansible_ssh_pass not set: 
      (-o)(KbdInteractiveAuthentication=no)
      (-o)(PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey)
      (-o)(PasswordAuthentication=no)
<ansible-target> SSH: ANSIBLE_REMOTE_USER/remote_user/ansible_user/user/-u set: (-o)(User=admin)
<ansible-target> SSH: ANSIBLE_TIMEOUT/timeout set: (-o)(ConnectTimeout=10)
<ansible-target> SSH: PlayContext set ssh_common_args: ()
<ansible-target> SSH: PlayContext set ssh_extra_args: ()
<ansible-target> SSH: found only ControlPersist; added ControlPath: 
      (-o)(ControlPath=/home/pfh/.ansible/cp/ansible-ssh-%h-%p-%r)
<ansible-target> SSH: EXEC ssh -C -vvv 
      -o ControlMaster=auto 
      -o ControlPersist=60s 
      -o KbdInteractiveAuthentication=no 
      -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey 
      -o PasswordAuthentication=no 
      -o User=admin 
      -o ConnectTimeout=10 
      -o ControlPath=/home/pfh/.ansible/cp/ansible-ssh-%h-%p-%r -tt ansible-target 
      '( umask 22 && mkdir -p "$( echo $HOME/.ansible/tmp/ansible-tmp-1490084266.37-148070795341843 )" 
      && echo "$( echo $HOME/.ansible/tmp/ansible-tmp-1490084266.37-148070795341843 )" )'
<ansible-target> PUT /home/pfh/temp/tmpY_WJOP TO 
     /home/admin/.ansible/tmp/ansible-tmp-1490084266.37-148070795341843/command
<ansible-target> SSH: ansible.cfg set ssh_args: 
      (-o)(ControlMaster=auto)
      (-o)(ControlPersist=60s)
<ansible-target> SSH: ansible_password/ansible_ssh_pass not set: 
      (-o)(KbdInteractiveAuthentication=no)
      (-o)(PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey)
      (-o)(PasswordAuthentication=no)
<ansible-target> SSH: ANSIBLE_REMOTE_USER/remote_user/ansible_user/user/-u set: (-o)(User=admin)
<ansible-target> SSH: ANSIBLE_TIMEOUT/timeout set: (-o)(ConnectTimeout=10)
<ansible-target> SSH: PlayContext set ssh_common_args: ()
<ansible-target> SSH: PlayContext set sftp_extra_args: ()
<ansible-target> SSH: found only ControlPersist; added ControlPath: 
      (-o)(ControlPath=/home/pfh/.ansible/cp/ansible-ssh-%h-%p-%r)
<ansible-target> SSH: EXEC sftp -b - -C -vvv 
      -o ControlMaster=auto 
      -o ControlPersist=60s 
      -o KbdInteractiveAuthentication=no 
      -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey 
      -o PasswordAuthentication=no 
      -o User=admin 
      -o ConnectTimeout=10 
      -o ControlPath=/home/pfh/.ansible/cp/ansible-ssh-%h-%p-%r '[ansible-target]'

Man sieht hier sehr schÜn wie die Kommunikation under-the-hood abläuft:

  • ssh -c, um ein Zielverzeichnis (~/.ansibe/tmp/ansible-tmp-foo( fĂźr das auszufĂźhrende Kommando anzulegen

  • sftp, um das Kommando zum Target-Host zu transportieren

    • kann man von SFTP auf SSH umkonfigurieren (Stichwort scp_if_ssh=True)

    • ACHTUNG: das Kommando-Verzeichnis wird i. a. am Ende wieder gelĂśscht (es sei denn man verwendet export ANSIBLE_KEEP_REMOTE_FILES=1)

  • ssh-Connection Sharing Ăźber ControlPath erfolgt


Getting Started

siehe eigener Abschnitt


Ansible Runtime Engine fĂźr Playbooks

Das CLI ansible-playbook hat ein paar interessante Parameter:

--inventory-file
--limit
-vvvv

Diese Parameter sind insbes. fĂźr die Entwicklung von Ansible-Skripten durchaus hilfreich.

LogLevel

Über -v wird das LogLevel definiert ... je mehr v's desto geschwätziger:

ansible-playbook myplaybook.yml -vvvv

Konfiguration

Die Konfiguration erfolgt in ansible.cfg. Hier werden verschiedene Locations herangezogen:

  • im aktuellen Verzeichnis

  • /etc/ansible/ansible.cfg

Wichtige Parameter

scp_if_ssh

In der Default-Einstellung wird SFTP verwendet, um das Ansible-Play vom Ansible-Controller zum Target-Host zu transportieren.

ANSIBLE_KEEP_REMOTE_FILES=1

Ansible bietet zur Spezifikation der Playbooks eine DSL an, aus der zur Ausführungszeit intern in Python-Code generiert wird. Im Ansible-Remote-Modus wird ein Python-Script (selbst im Fall eines einfachen ansible ansible-target -a "/bin/echo hello" ist dieses Script 90 Kilobyte groß) vom Ansible-Controller zum Target-Server transportiert und in ~/.ansible/tmp/ansible-tmp-foo/command gespeichert.

Bei der AusfĂźhrung wird eine Result in JSON-Form ausgegben (hier im Falle eines erfolgreichen echo hello)

```json
{
    "changed": true,
    "end": "2017-03-21 09:48:19.398800",
    "stdout": "hello",
    "cmd": ["/bin/echo", "hello"],
    "rc": 0,
    "start": "2017-03-21 09:48:19.397007",
    "stderr": "",
    "delta": "0:00:00.001793",
    "invocation": {
        "module_args": {
            "warn": true,
            "executable": null,
            "chdir": null,
            "_raw_params": "/bin/echo hello",
            "removes": null,
            "creates": null,
            "_uses_shell": false
        }
    },
    "warnings": []
}
```

das der Ansible-Controller erhält.

Nach der AusfĂźhrung wird das Command-Skript per default gelĂśscht. Mit der Environment-Variable export ANSIBLE_KEEP_REMOTE_FILES=1 kann das LĂśschen verhindert werden ... bei der Fehlersuche sehr hilfreich, denn dann kann man mal einen Blick in das generierte Python-Skript werfen!!!

Natürlich muß man seine Konsole nicht dauerhaft verändern - bei folgendem Aufruf wird die Command-datei nur für diesen einen Aufruf behalten:

```bash
ANSIBLE_KEEP_REMOTE_FILES=1 ansible ansible-target -a "/bin/echo hello"
```

Ansible Playbook DSL

  • Beispiele: https://github.com/ansible/ansible-examples

  • alle Module: http://docs.ansible.com/ansible/list_of_all_modules.html

  • https://liquidat.wordpress.com/2016/01/26/howto-introduction-to-ansible-variables/

YAML-Syntax

siehe eigener Abschnitt

ACHTUNG: yaml ist bei den EinrĂźckungen sehr strikt und Fehler in diesem Bereich sind schwer zu finden

Module

Ansible DSL baut auf Modulen auf: http://docs.ansible.com/ansible/modules_by_category.html

Die sog. Core-Modules werden vom offiziellen Ansible-Team bereitgestellt und immer mit Ansible ausgeliefert. Drittanbieter kĂśnnen eigene Module bereitstellen/verkaufen, die dann aber extra installiert werden mĂźssen.

Variablen

  • Playbook-Variablen

  • alles Ăźber Variablen

Variablen kĂśnnen auf sehr vielen Ebenen definiert werden. Vom Betriebssystem bis zum Playbook. Wenn sich die Variablen Ăźberschreiben (was durchaus gewollt sein kann), wird es schnell mal schwierig - dieses Feature sollte also mit Bedacht eingesetzt werden.

Gather Facts

Ansible sammelt (sog. Gather Facts) zu den Hosts Informationen (z. B. CPU, OS), die als Variablen zur VerfĂźgung stehen. Diese Variablen kĂśnnen per

ansible -m setup localhost

Statt localhost kann jeder registrierte Host eingetragen werden (siehe /etc/ansible/hosts). Auf diese Weise findet man beispielsweise heraus, daß es eine Variable ansible_kernel gibt, die die die Kernel-Version enthält (anstatt uname -r).

Umgebungsvariablen

Umgebungsvariablen kĂśnnen Ăźber Gather Facts Informationen

vars:
   executingUser: "{{ ansible_env.HOME') }}"

oder Ăźber

    vars:
       executingUser: "{{ lookup('env','USER') }}"

abgefragt werden.

Lookups

Über lookup lassen sich Inhalte von Dateien auslesen. Beispielsweise wird der Public-Key (in .ssh/id_rsa.pub) ausgelesen und in die authorized_keys des Users vagrant auf einer anderen Maschine übertragen:

tasks:
  - set_fact:
      current_user_default_public_ssh_key: "{{ ansible_env.HOME }}/.ssh/id_rsa.pub"
  - authorized_key: 
      user: vagrant 
      key: "{{ lookup('file', current_user_default_public_ssh_key) }}/.ssh/id_rsa.pub"

Inventory

  • Dokumentation

Im Inventory-File (konfigurierbar Ăźber --inventory-file=/tmp/myinventory) werden die Zielsysteme definiert, gruppiert und der Zugriff konfiguriert, u. a.

  • Host und Port fĂźr den ssh-Zugriff

  • Private-Keys

  • ...


Wiederverwendung

  • http://docs.ansible.com/ansible/playbooks_roles.html

Über Rollen läßt sich in Ansible Modularisierung abbilden, um Wiederverwendung zu erreichen. Wiederverwendung ist sicherlich erst dann erforderlich, wenn man mehr macht als nur ein einziges Playbook zusammenzubasteln.

Verwendet man Playbook fĂźr verschiedene Use-Cases, dann ergibt sich allerdings sehr schnell der Wunsch nach einer Modularisierung (Beispiel: Sicherstellung einer Java-JDK-Installation).

Includes

Modularisierung über Includes läßt sich auf allen abstrakten Ebenen verwenden:

  • Playbooks verwenden weitere Playbooks

- name: this is a playbook
  hosts: all
  tasks:
  - name: greetings
    shell: echo "hello world"
- include: otherPlaybook1.yml
- include: otherPlaybook2.yml
  • Tasks verwenden weitere Tasks

tasks:
  - include: java.yml
    vars:
        version: 8
        provider: oracle
  • Handlers verwenden weitere Handlers

handlers:
  - include: handlers/myhandler.yml

Parametrisierung

Da der Use-Case dem zu verwendenden Modul nicht bekannt ist, mĂźssen die Module entsprechend parametrisiert werden. Damit lassen sich einfache Anpassungen vornehmen (auf der Ebene eines Attributwertes).

Beispiel: Ensure-Java

Die Sicherstellung einer passenden Java-Installation kÜnnte ein wiederverwendbarer Baustein sein, der in vielen Playbooks benÜtigt wird. In manchen Situationen wird Java 7 und in anderen Java 8 benÜtigt. Das Modul ensureJdkInstallation.yml erhält hierzu einen Parameter version:

tasks:
  - include: ensureJdkInstallation.yml
    vars:
        version: 8
        provider: oracle

In java.yml wird der Parameter per {{ version }} erferenziert.

Conditionals

Mit Conditionals kÜnnen beispielsweise Include-Anweisungen bestßckt werden, um auf diese Weise betriebssystemabhängige Weichen einzubauen:

---

- include: centos7.yml
  when: ansible_distribution == "CentOS"
        and ansible_distribution_major_version == "7"
- include: ubuntu.yml
  when: ansible_distribution == "Ubuntu"

Roles

Roles bauen einen Convention-over-Configuration-Mechanismus um Includes auf. Auf Basis einer vorgegebenen Ordnerstruktur erfolgt der Aufbau eines Plays (= Playbook zur Laufzeit) nahezu automatisch. Durch Verzicht auf explizite Konfiguration sind Skripte leichter erweiterbar/anpassbar. Das erinnert sehr stark an den Ansatz, den Spring-Boot mit der annotationsbasierten ApplicationContext-Aufbau geht.

Convention: Ordnerstruktur

Zentrales Element der Konvention ist die Filesystem-Struktur:

site.yml
webservers.yml
fooservers.yml
roles/
    myRole/
        files/
        templates/
        tasks/
        handlers/
        vars/
        defaults/
        meta/

Ausgehend davon werden sog. Plays (Playbooks zur Laufzeit) nach folgenden Regeln dynamisch zusammengebaut (kopiert von hier):

  • If roles/x/tasks/main.yml exists, tasks listed therein will be added to the play

  • If roles/x/handlers/main.yml exists, handlers listed therein will be added to the play

  • If roles/x/vars/main.yml exists, variables listed therein will be added to the play

  • If roles/x/meta/main.yml exists, any role dependencies listed therein will be added to the list of roles (1.3 and later)

  • Any copy, script, template or include tasks (in the role) can reference files in roles/x/{files,templates,tasks}/ (dir depends on task) without having to path them relatively or absolutely

Es besteht allerdings weiterhin die MĂśglichkeit, Tasks, Handlers, Variablen explizit in Playbooks zu verwenden.

Das Playbook (site.yml) sieht dann beispielsweise so aus:

---
- hosts: webservers
  roles:
     - common
     - webservers

Darin werden Rollen referenziert, wodurch der Play größer wird. In Rollen selbst können Role Dependencies (s. u.) definiert werden, die den Play ihrerseits erweitern.

Ansible wird dadurch sehr mächtig ... aber vielleicht auch sehr komplex.

Role Dependencies

Eine Rolle kann in <role>/meta/main.yml Abhängigkeiten auf weitere Rollen definieren ... diese Abhängigkeiten kÜnnen parametrisiert werden.

Conditionals

Rollen kÜnnen in Abhängigkeit bestimmter Zustände (z. B. Betriebssystem) gezogen werden.

Auf diese Weise lassen sich beispielsweise betriebssystemabhängige Weichen einbauen wie diese:

---

- include: centos7.yml
  when: ansible_distribution == "CentOS" 
        and ansible_distribution_major_version == "7"
- include: ubuntu.yml
  when: ansible_distribution == "Ubuntu"

Ansible Galaxy

... ist ein Repository fĂźr Community-Developed Ansible Roles ...

Role Java

In meinem ersten Ansible-Projekt stand ich vor der Aufgabe Java 8 auf mindestens CentOS zu installieren.

ProjektĂźbergreifende Wiederverwendung

Die oben vorgestellte Wiederverwendung Ăźber Roles funktioniert gut, wenn das gesamte Projekt unter der eigenen Kontrolle ist. Wenn nun aber drei getrennte Projekte auf eine gemeinsame Scripting-Basis (im wesentlichen Roles) zugreifen sollen, dann hat Ansible derzeit noch keine passende Antwort.

Ansible Galaxy scheint in diese Richtung zu gehen ...


Best Practices

  • Offizielle Best-Practices: http://docs.ansible.com/ansible/playbooks_best_practices.html

  • Code-Beispiele: https://github.com/ansible/ansible-examples

Nicht verwenden "remote_user: root"

Besser ist, sich als normaler User zu verbinden und dann gezielt fĂźr einzelne Kommandos per become in die Rolle des root zu schlĂźpfen.

SSH-Agent starten und konfigurieren

siehe separate Seite

Um Ansible-Skripte komplett automatisiert (also nicht interaktiv) ausführen zu lassen, muß der SSH-Agent mit dem/den Private-Key(s) gefüttert werden, denn ansonsten muß der Benutzer die Passphrase (wenn vorhanden - RECOMMENDED!!!) interaktiv eingeben.

Verwende Roles

  • http://docs.ansible.com/ansible/playbooks_roles.html

Über Rollen läßt sich in Ansible Modularisierung abbilden, um Wiederverwendung zu erreichen. Wiederverwendung ist sicherlich erst dann erforderlich, wenn man mehr macht als nur ein einziges Playbook zusammenzubasteln.

weitere Details: siehe oben


Bewertung

Lernkurve

Man kommt tatsächlich sehr schnell (wenn man mal die Ansible-Infrastruktur mit ssh, sudo aufgebaut hat) zu brauchbaren Ergebnissen. Häufig braucht man gar nicht so viele Module ... es sind 5-10 Module, die wirklich ständig im Einsatz sind.

Ich arbeite an einer Infrastruktur bestehend aus Controller und verschiedenen Target-Hosts. Mir ist es schon häufiger passiert, daß

  • ich vom Target-Host das Ansible-Skript starten wollte ... dort ist aber gar kein Ansible installiert

  • ich vom Controller-System Remote-Konfigurationen angestoßen habe und die Änderungen lokal gesucht habe

An diese Denkweise muß man sich erst einmal gewöhnen. Insbesonder, wenn man - wie ich - im privaten Gebrauch ausschließlich lokal arbeitet (um die Workbench aufzubauen) und im geschäftlichen Umfeld ausschließlich remote.

Pro

  • IDEMPOTENZ ist leichter mĂśglich als bei Shellscripts (der Entwickler muß die Skripte aber auch idempotent gestalten!!!)

  • gute Dokumentation

  • Remote-Installationen mĂśglich

  • flache Lernkurve (s. o.), Komplexität Ăźberschaubar

    • keine Agenten (Puppet) notwendig, die auf den Zielsystemen installiert sein mĂźssen ... ssh + sudo + python

    • die Reihenfolge der TaskausfĂźhrung ist bei Ansible klar definiert (nämlich genau die aus dem Playbook)

    • nur Push, kein Pull (kann auch als Nachteil gesehen werden)

    • kein interner Dependency Graph und den damit verbundenen Problemen (unsynchronisierte Redundanzen)

  • gute Lesbarkeit

    • insbes. fĂźr Gelegenheitsanwender (z. B. Entwickler) interessant

  • angeblich gute Fehlermeldungen (noch keine eigene Erfahrung damit gemacht)

  • guter Support fĂźr On-Premise- und Cloud-Deployments

  • gute Vagrant-Integration

  • Ansible basiert auf Python ... fĂźr mich als nicht Ruby (Puppet) Entwickler kĂśnnte das Vorteile haben

  • Templating basiert auf dem Jinja2-Templating (Subset von Django), mit dem viele Entwickler vertrauter sind

  • die Fehlermeldungen sind meistens ganz brauchbar

  • Ausgabe bei der Abarbeitung der Playbooks sehr Ăźbersichtlich:

    pfh@workbench ~/windows_de.cachaca.workbench (git)-[master] % ansible-playbook playbook.yml

    PLAY ***************************************************************************

    TASK [setup] ******************************************************************* ok: [localhost]

    TASK [system | update package meta-data] *************************************** ok: [localhost]

    TASK [system | install aptitude ... needed for succeeding "upgrade system"] *** ok: [localhost]

    TASK [system | upgrade system] ************************************************* ok: [localhost]

    TASK [devcon | create directory strcuture for user pfh] ************************ ok: [localhost] => (item=/bin) ok: [localhost] => (item=/src) ok: [localhost] => (item=/temp) ok: [localhost] => (item=/zipfiles)

Contra

  • manchmal (u. a. fehlende schließende Gänsefüßchen, falsche EinrĂźckungen im Ansible-Playbook) sind die Fehlermeldungen wenig hilfreich

Performance

Tatsächlich scheint mir die Performance nicht so berauschend. Fßr meinen Anwendungsfall (wenige Tasks auf wenigen Knoten) ist es aber ok.

Vielleicht helfen die Einstellungen pipelining = True und host_key_checking = False in ansible.cfg.


Alternativen

  • https://dantehranian.wordpress.com/2015/01/20/ansible-vs-puppet-overview/

  • https://dantehranian.wordpress.com/2015/01/20/ansible-vs-puppet-hands-on-with-ansible/

  • ein sehr ausfĂźhrlicher Vergleich zwischen Ansible und Saltstack: http://ryandlane.com/blog/2014/08/04/moving-away-from-puppet-saltstack-or-ansible/

"After three years of using Puppet at VMware and Virtual Instruments, the thought of not continuing to use the market leader in configuration management tools seemed like a radical idea when it was first suggested to me. After spending several weeks researching Ansible and using it hands-on, I came to the conclusion that Ansible is a perfectly viable alternative to Puppet. I tend to agree with Lyft’s conclusion that if you have a centralized Ops team in change of deployments then they can own a Puppet codebase. On the other hand if you want more wide-spread ownership of your configuration management scripts, a tool with a shallower learning curve like Ansible is a better choice." (Dan Tehranian's Blog, https://dantehranian.wordpress.com/2015/01/20/ansible-vs-puppet-hands-on-with-ansible/)

Alternative Shellscripting

Ganz ohne Frage ... Shellscripting hat ein paar Vorteile (die Nachteile habe ich umfassend in einem eigenen Abschnitt aufgelistet:

  • ganz dicht am manuellen Aufsetzen - klar Scripting bedeutet dann oftmals auch, daß eine gewisse Art von Konfigurierbarkeit in die Scripte eingebaut wird, um sie an bestimmte Umgebungen anzupassen. Verzichtet man aber auf die Konfigurierbarkeit, dann genĂźgt es, die fĂźr eine manuelle Installation/Konfiguration eines System erforderlichen Befehle, in eine Shelldatei zu packen. Viola :-)

  • kein weiteres Layer zwischen den Befehlen und dem System ... ich bin mir aber nicht sicher, ob das wirklich ein Vorteil ist, denn Fehlersuche in Shellscripten ist wirklich alles andere als eine Freude ... insbes. aufgrund der fehlenden Idempotenz

Ich habe ein komplexes Setup Ăźber Vagrant und Shellscripting-Provisioning umgesetzt (Laufzeit 50 Minuten). Erst danach habe ich Ansible kennengelernt.

Mein Fazit: Ansible ist der klare Sieger

PreviousVagrant Box bauenNextGetting Started

Last updated 3 years ago

Was this helpful?