De kunst van het schrijven van Ansible-roles

Introductie

Tools zoals CFEngine, Puppet, Chef en Ansible hebben infrastructure automation ingrijpend veranderd door een gestructureerd framework te bieden voor het organiseren en delen van configuration management code, waarbij Ansible een van de nieuwere tools is. Ansible wordt breed gebruikt om de configuratie van je IT-omgeving te automatiseren en is zeer flexibel. De makers noemen Ansible “open-source automation die simpel, flexibel en krachtig is”. Wat Ansible code betrouwbaar maakt, is daarmee nog niet duidelijk. En zo simpel als het klinkt is het in de praktijk niet altijd—zeker niet in complexere omgevingen en setups.
Binnen Ansible zijn roles een concept waarmee je code inkapselt. In roles zitten tasks, variables, handlers en files, samengebracht in een modulaire, herbruikbare unit die, als je hem goed schrijft, eenvoudig te delen is tussen projecten en teams. Of je nu een handvol servers beheert of complexe (multi)cloudomgevingen orkestreert: roles helpen je schonere, beter onderhoudbare code te schrijven. Tegelijk is het lastig om een role te ontwerpen die je betrouwbaar en compleet zou noemen. In dit blog geven we daarom vuistregels voor een betrouwbare Ansible role, zodat je betere roles schrijft.

Een aantal vuistregels

De vuistregels in deze blog zijn:

  1. De main.yml van een role gebruik je alleen om tasks te includen of importeren
  2. Alle tasks moeten geoptimaliseerd zijn voor efficiëntie
  3. Data en code moeten volledig gescheiden zijn
  4. Tasks moeten op include-basis draaien
  5. Roles moeten check mode correct afhandelen
  6. Alle tasks moeten idempotent zijn
  7. Variabelen moeten een correcte namespace hebben en hiërarchisch zijn
  8. Tags moeten geïmplementeerd én gedocumenteerd zijn
  9. Roles moeten gevalideerd worden
  10. Roles moeten gedocumenteerd worden

Let op: dit zijn vuistregels. Afhankelijk van het gebruik en de requirements van een role kunnen sommige regels minder relevant zijn of juist extra regels nodig zijn. Over het algemeen zijn ze in veel situaties toepasbaar. Hieronder werken we ze één voor één uit, met context en voorbeelden.

Illustraties met een role: linux_user

Om de vuistregels te illustreren maken we een role die Linux-users kan aanmaken. Dat doen we als volgt:

# Creation of a basic role structure using ansible-galaxy
ansible-galaxy role init linux_user

# Navigate into the new role
cd linux_user/

# Create a supplementary tasks file
touch tasks/linux_user.yml
                                                        

Kopieer code

Onze directorystructuur ziet er nu als volgt uit:

# ls ./*
./README.md

./defaults:
main.yml

./files:

./handlers:
main.yml

./meta:
main.yml

./tasks:
linux_user.yml  main.yml

./templates:

./tests:
inventory  test.yml

./vars:
main.yml
                                                        

Kopieer code

Dit biedt ons een basisstructuur om mee te werken. In main.yml nemen we de taken op voor alle user-gerelateerde taken:

# cat tasks/main.yml
---
- name: Include Linux user tasks
  loop: "{{ linux_users }}"
  loop_control:
    loop_var: user
    label: "{{ user }}"
  tags:
    - linux_user
    - linux_user_authorized_keys
    - linux_user_create
  when:
    - ansible_facts["os_family"] in linux_user_allowed_os_families
    - linux_user_allowed_target_hostgroups | intersect(group_names)
  ansible.builtin.include_tasks: linux_user.yml
                                                        

Kopieer code

Het hierboven opgenomen linux_user.yml-bestand bevat de daadwerkelijke taken voor het aanmaken van users.

# cat tasks/linux_user.yml
---
- name: Create user "{{ user.name }}"
  become: true
  notify:
    - "Send mail notification about user creation"
  tags:
    - linux_user
    - linux_user_create
  ansible.builtin.user:
    # Required
    name: "{{ user.name }}"

    # Optional
    append: "{{ user.append | default(omit) }}"
    comment: "{{ user.comment | default(omit) }}"
    create_home: "{{ user.create_home | default(omit) }}"
    force: "{{ user.force | default(omit) }}"
    group: "{{ user.group | default(omit) }}"
    groups: "{{ user.groups | default(omit) }}"
    hidden: "{{ user.hidden | default(omit) }}"
    home: "{{ user.home | default(omit) }}"
    password: "{{ user.password | default(omit) }}"
    password_expire_account_disable: "{{ user.password_expire_account_disable | default(omit) }}"
    password_expire_max: "{{ user.password_expire_max | default(omit) }}"
    password_expire_min: "{{ user.password_expire_min | default(omit) }}"
    password_expire_warn: "{{ user.password_expire_warn | default(omit) }}"
    password_lock: "{{ user.password_lock | default(omit) }}"
    remove: "{{ user.remove | default(omit) }}"
    shell: "{{ user.shell | default(omit) }}"
    state: "{{ user.state | default(omit) }}"
    system: "{{ user.system | default(omit) }}"
    uid: "{{ user.uid | default(omit) }}"
    umask: "{{ user.umask | default(omit) }}"
    update_password: "{{ user.update_password | default(omit) }}"

- name: Set authorized keys for user "{{ user.name }}"
  become: true
  loop: "{{ user.authorized_keys | default(linux_user_default_authorized_keys) }}"
  loop_control:
    loop_var: key
    label: "{{ key.key }}"
  tags:
    - linux_user
    - linux_user_authorized_keys
  ansible.posix.authorized_key:
    # Required
    key: "{{ key.key }}"
    user: "{{ user.name }}"

    # Optional
    comment: "{{ key.comment | default(omit) }}"
    exclusive: "{{ key.exclusive | default(omit) }}"
    key_options: "{{ key.key_options | default(omit) }}"
    path: "{{ key.path | default(omit) }}"
    state: "{{ key.state | default(omit) }}"
                                                        

Kopieer code

In het bovenstaande takenbestand is een handler geconfigureerd met de naam ‘Send mail notification about user creation’, die er als volgt uitziet:

Blijf op de hoogte
Door je in te schrijven voor onze nieuwsbrief verklaar je dat je akkoord bent met onze privacyverklaring.

Klaar om je Ansible-configuratie te verbeteren?

Michael Veentjer
Michaël Veentjer

Neem direct contact op


Klaar om je Ansible-configuratie te verbeteren?

* verplicht

Door dit formulier te verzenden bevestig je dat je onze privacyverklaring hebt gelezen en begrepen.
SUE Cloud Native Solutions
Privacyoverzicht
Deze website gebruikt cookies. We gebruiken cookies om onze website en diensten goed te laten functioneren, om inzicht te krijgen in het gebruik van onze website en om onze producten en marketing te verbeteren. Lees voor meer informatie ons privacy- en cookiebeleid.