22 Inventory-Variablen: Professionelle Verwaltung und Priorisierung

22.1 Globale Variablen und deren Definition in group_vars und host_vars

In Ansible können Variablen auf verschiedenen Ebenen und durch unterschiedliche Mechanismen definiert werden, um flexible und wiederverwendbare Konfigurationen zu schaffen. Das Verständnis der Variablenauflösung und -priorisierung ist entscheidend für die professionelle Automatisierung.

22.1.1 Definition von globalen Variablen

Globale Variablen gelten für alle Hosts in einem Inventory und werden primär in group_vars/all.yml definiert. Diese Datei dient als Basis-Konfiguration, die durch spezifischere Variablen überschrieben werden kann.

Beispiel für globale Variablen:

# Datei: group_vars/all.yml
ntp_server: ntp.example.com
timezone: UTC
log_level: info
ansible_ssh_common_args: '-o StrictHostKeyChecking=no'

22.1.2 Gruppenvariablen für spezifische Host-Gruppen

Gruppenvariablen werden für definierte Host-Gruppen angewendet und überschreiben globale Variablen. Sie ermöglichen die Konfiguration von Umgebungen oder Rollen.

Beispiel für gruppenspezifische Variablen:

# Datei: group_vars/webservers.yml
http_port: 80
https_port: 443
max_clients: 200
ssl_certificate_path: /etc/ssl/certs/web.crt

# Datei: group_vars/dbservers.yml
db_port: 3306
max_connections: 100
innodb_buffer_pool_size: "1G"

22.1.3 Host-spezifische Variablen

Host-Variablen haben die höchste Priorität unter den inventory-basierten Variablen und ermöglichen individuelle Konfigurationen für einzelne Hosts.

Beispiel für host-spezifische Variablen:

# Datei: host_vars/web1.example.com.yml
ansible_host: 192.168.1.10
ansible_user: admin
ansible_ssh_private_key_file: ~/.ssh/web1_key
max_clients: 500  # Überschreibt Gruppenvariable

22.2 Vollständige Variablen-Precedence (Prioritätenreihenfolge)

Ansible verwendet eine komplexe Hierarchie zur Variablenauflösung. Die folgende Tabelle zeigt die wichtigsten Ebenen in absteigender Priorität:

Priorität Quelle Beschreibung Anwendungsfall
1 Extra Vars (-e) Kommandozeilen-Parameter Überschreibung zur Laufzeit
2 Task Vars Variablen innerhalb von Tasks Task-spezifische Werte
3 Block Vars Variablen in Block-Strukturen Block-spezifische Konfiguration
4 Role and Include Vars vars/main.yml in Rollen Rollen-Konfiguration
5 Play Vars vars: Sektion im Playbook Playbook-spezifische Werte
6 host_vars Host-spezifische Dateien Individuelle Host-Konfiguration
7 group_vars Gruppen-spezifische Dateien Gruppenbasierte Konfiguration
8 group_vars/all Globale Inventory-Variablen Basis-Konfiguration
9 Playbook group_vars Im Playbook-Verzeichnis Playbook-lokale Gruppenvariablen
10 Inventory group_vars Im Inventory-Verzeichnis Inventory-spezifische Gruppenvariablen
11 Inventory Vars Direkt im Inventory definiert Legacy-Methode
12 Role Defaults defaults/main.yml in Rollen Standard-Rollenwerte

Wichtiger Hinweis: set_facts-Module können zur Laufzeit Variablen definieren, die host_vars überschreiben können, je nach Ausführungskontext.

Beispiel zur Prioritätendemonstration:

# group_vars/webservers.yml
http_port: 80

# host_vars/web1.example.com.yml  
http_port: 8080

# Playbook mit extra vars
# ansible-playbook -e "http_port=9090" site.yml
# Resultat: web1.example.com verwendet Port 9090

22.3 Flexible Verzeichnisstrukturen und Pfadauflösung

22.3.1 Standard-Verzeichnisstrukturen

Ansible sucht group_vars und host_vars in mehreren Locations:

  1. Inventory-Verzeichnis (wenn Inventory eine Datei ist)
  2. Playbook-Verzeichnis (wenn aus Playbook-Verzeichnis ausgeführt)
  3. Aktuelles Arbeitsverzeichnis

Erweiterte Verzeichnisstruktur:

project/
├── inventories/
│   ├── production/
│   │   ├── hosts
│   │   ├── group_vars/
│   │   │   ├── all/
│   │   │   │   ├── main.yml
│   │   │   │   └── vault.yml
│   │   │   ├── webservers.yml
│   │   │   └── dbservers/
│   │   │       ├── main.yml
│   │   │       └── database.yml
│   │   └── host_vars/
│   │       └── web1.example.com/
│   │           ├── main.yml
│   │           ├── networking.yml
│   │           └── vault.yml
│   └── staging/
│       └── [ähnliche Struktur]
├── playbooks/
│   ├── group_vars/          # Playbook-lokale Variablen
│   └── host_vars/
└── roles/
    └── nginx/
        ├── vars/main.yml    # Rollen-Variablen
        └── defaults/main.yml # Rollen-Defaults

22.3.2 Verzeichnis-basierte Variablendefinition

Für komplexe Konfigurationen können Variablen in Verzeichnissen mit main.yml organisiert werden:

# host_vars/web1.example.com/main.yml
ansible_host: 192.168.1.10

# host_vars/web1.example.com/networking.yml
firewall_rules:
  - port: 80
    protocol: tcp
  - port: 443
    protocol: tcp

# host_vars/web1.example.com/vault.yml (verschlüsselt)
db_password: !vault |
  $ANSIBLE_VAULT;1.1;AES256
  66396439396439643964396439643964...

22.4 Erweiterte Variablen-Mechanismen

22.4.1 Dynamisches Laden mit vars_files

---
- hosts: webservers
  vars_files:
    - "vars/common.yml"
    - "vars/{{ env }}.yml"
    - "vars/secrets/{{ inventory_hostname }}.yml"
  tasks:
    - name: Configure application
      template:
        src: app.conf.j2
        dest: /etc/app/app.conf

22.4.2 Conditional Loading mit include_vars

- name: Load OS-specific variables
  include_vars: "{{ item }}"
  with_first_found:
    - "vars/{{ ansible_distribution }}-{{ ansible_distribution_version }}.yml"
    - "vars/{{ ansible_distribution }}.yml"
    - "vars/{{ ansible_os_family }}.yml"
    - "vars/default.yml"

- name: Load environment-specific secrets
  include_vars:
    file: "vault/{{ env }}_secrets.yml"
  when: env is defined

22.4.3 Runtime Facts mit set_fact

- name: Calculate derived configuration
  set_fact:
    nginx_worker_processes: "{{ ansible_processor_vcpus }}"
    max_client_body_size: "{{ (ansible_memtotal_mb * 0.1) | int }}m"

- name: Merge configuration dictionaries
  set_fact:
    app_config: "{{ default_config | combine(env_config, recursive=True) }}"

22.5 Debugging und Variablen-Analyse

22.5.1 CLI-Tools für Variablen-Debugging

Inventory-Struktur anzeigen:

# Vollständige Inventory-Struktur mit allen Variablen
ansible-inventory -i inventories/production/ --list

# Spezifische Host-Variablen anzeigen
ansible-inventory -i inventories/production/ --host web1.example.com

# Gruppenvariablen einer spezifischen Gruppe
ansible-inventory -i inventories/production/ --list | jq '.webservers.vars'

# YAML-Format für bessere Lesbarkeit
ansible-inventory -i inventories/production/ --list --yaml

Ad-hoc Variable Debugging:

# Alle Facts und Variablen eines Hosts
ansible web1.example.com -i inventories/production/ -m setup

# Spezifische Variablen testen
ansible web1.example.com -i inventories/production/ -m debug -a "var=http_port"

# Variable Precedence testen
ansible-playbook -i inventories/production/ debug.yml --limit web1.example.com -v

Debug-Playbook Beispiel:

---
- hosts: all
  gather_facts: no
  tasks:
    - name: Show variable precedence
      debug:
        msg: |
          Host: {{ inventory_hostname }}
          HTTP Port: {{ http_port | default('not defined') }}
          All variables: {{ hostvars[inventory_hostname] }}

    - name: Show group membership
      debug:
        var: group_names

    - name: Show variable source analysis
      debug:
        msg: "Variable 'http_port' resolved to: {{ http_port }}"
      when: http_port is defined

22.6 Erweiterte Best Practices für Enterprise-Umgebungen

22.6.1 Strukturelle Organisation

Environment-basierte Trennung:

inventories/
├── production/
│   ├── group_vars/all/
│   │   ├── main.yml          # Basis-Konfiguration
│   │   ├── monitoring.yml    # Monitoring-spezifisch
│   │   └── vault.yml         # Verschlüsselte Werte
├── staging/
└── development/

Namenskonventionen:

# Präfix-basierte Namensgebung
app_name: myapp
app_version: "1.2.3"
app_port: 8080
app_config_dir: "/etc/{{ app_name }}"

# Umgebungsspezifische Präfixe
prod_db_host: db.prod.example.com
staging_db_host: db.staging.example.com

# Rollenspezifische Gruppierung
nginx_worker_processes: 4
nginx_worker_connections: 1024
nginx_keepalive_timeout: 65

22.6.2 Sicherheit und Verschlüsselung

Vault-Integration:

# Vault-Dateien erstellen
ansible-vault create group_vars/all/vault.yml
ansible-vault create host_vars/web1.example.com/vault.yml

# Vault-Password-File nutzen
echo "vault_password" > .vault_pass
chmod 600 .vault_pass
export ANSIBLE_VAULT_PASSWORD_FILE=.vault_pass

Sichere Variable-Referenzierung:

# group_vars/all/vault.yml (verschlüsselt)
vault_db_password: "secret123"
vault_api_key: "api_key_here"

# group_vars/all/main.yml (unverschlüsselt)
db_password: "{{ vault_db_password }}"
api_key: "{{ vault_api_key }}"

22.6.3 Validierung und Testing

Variable-Validierung:

- name: Validate required variables
  assert:
    that:
      - app_name is defined
      - app_version is defined
      - app_port is number
      - app_port > 1024
    fail_msg: "Required application variables not properly defined"

- name: Validate environment consistency
  assert:
    that:
      - env in ['production', 'staging', 'development']
    fail_msg: "Environment '{{ env }}' is not valid"

Test-Playbook für Variable-Konsistenz:

---
- hosts: all
  gather_facts: no
  tasks:
    - name: Collect all host variables
      set_fact:
        all_host_vars: "{{ hostvars[inventory_hostname] }}"

    - name: Generate variable report
      template:
        src: variable_report.j2
        dest: "reports/{{ inventory_hostname }}_variables.yml"
      delegate_to: localhost

    - name: Validate critical variables exist
      fail:
        msg: "Critical variable {{ item }} is not defined for {{ inventory_hostname }}"
      when: hostvars[inventory_hostname][item] is not defined
      loop:
        - ansible_host
        - app_name
        - env