IT-automatisering optimaliseren: Best Practices voor Ansible
Ansible is een bijzonder flexibel en gebruiksvriendelijk automatiseringstool. Dat is ideaal, want je kunt er snel mee aan de slag om je taken te automatiseren. Tegelijkertijd betekent dit ook dat er veel verschillende manieren zijn om Ansible in te richten. Juist daarom zijn tips en best practices essentieel om alles op de lange termijn soepel te laten draaien en jezelf tijd en moeite te besparen. Zonder verder oponthoud delen we hieronder een aantal aandachtspunten die we in de afgelopen tien jaar hebben opgedaan door te werken met Ansible, Tower en AWX.
Source code management
- Gebruik een source code management-systeem, bij voorkeur GIT.
- Commit NOOIT direct naar MASTER/PRIMARY. Echt niet. De master branch moet altijd werkende, geteste en functioneel correcte code bevatten (voor zover je weet).
- Alle development doe je op een aparte branch. Test en review deze, en merge pas naar de master branch wanneer bewezen is dat alles correct werkt.
- Gebruik version tags voor je roles. Tag je roles bij elke wijziging. Dit is niet alleen handig voor jezelf, maar vooral voor anderen die je roles gebruiken. Zij kunnen zo een specifieke versie vastzetten en erop vertrouwen dat hun code blijft werken.
- Eén GIT-repo per role. Dit maakt het eenvoudig voor anderen om je roles te includen in hun playbooks.
- Gebruik één of meerdere aparte repositories voor je playbooks. Als je meerdere repos gebruikt, is het slim om je environments-directory af te splitsen naar een aparte repo, zodat je niet meerdere sets met dezelfde variabelen hoeft te onderhouden.
Directory structuur
Gebruik gewoon de standaard directorystructuur voor je roles. Je kunt eenvoudig een nieuwe role-structuur aanmaken met ansible-galaxy init.
Voor je playbooks en inventories kun je bijvoorbeeld de volgende structuur gebruiken:
/
├── ansible/
│ ├── ansible.cfg
│ ├── environments/
│ │ ├── 00-superglobal.yml
│ │ ├── dev/
│ │ │ ├── hosts
│ │ │ └── group_vars/
│ │ │ ├── all/
│ │ │ │ └── 00-superglobal.yml
│ │ │ │ └── 10-allvars.yml
│ │ │ ├── group_1
│ │ │ └── group_2
│ │ ├── prod/
│ │ │ └── group_vars/
│ │ │ ├── all/
│ │ │ │ └── 00-superglobal.yml
│ │ │ │ └── 10-allvars.yml
│ │ │ ├── group_1
│ │ │ └── group_2
│ │ └── sandbox/
│ │ └── group_vars/
│ │ ├── all/
│ │ │ └── 00-superglobal.yml
│ │ │ └── 10-allvars.yml
│ │ ├── group_1
│ │ └── group_2
│ └── playbooks/
│ ├── playbook.yml
│ └── roles/
│ └── requirements.yml
└── test/
Copy code
In deze boomstructuur zie je vier 00-superglobal.yml-bestanden. De bestanden in de all-directories zijn symlinks naar het bestand in de environments-directory. Dit geeft je een manier om variabelen over alle omgevingen heen te definiëren, zonder dat je ze telkens hoeft te herhalen.
group_1 en group_2 kunnen zowel bestanden zijn (die dan moeten eindigen op .yml) als directories die YAML-bestanden bevatten.
Ik geef variabele- en inventorybestanden graag een numerieke prefix, omdat Ansible de bestanden in group_vars en inventories in lexicografische volgorde verwerkt. Zo kun je de leesvolgorde van variabelen sturen, wat handig kan zijn wanneer je gebruikmaakt van YAML-mechanismen zoals references en pointers.
Playbook structuur
Als je veel taken in één playbook hebt, is het verstandig om te overwegen deze taken om te zetten naar een role.
Stel geen variabelen in binnen een playbook (als je het kunt vermijden). Verderop in dit document ga ik daar nog uitgebreid op in.
Als je andere playbooks wilt includen voor uitvoering binnen het playbook waar je aan werkt, is het aan te raden om dat andere playbook om te zetten naar een role.
Structureer je playbook logisch. Ook als je niet werkt volgens de indeling pre-tasks, roles en post-tasks, is het verstandig om je playbook op een vergelijkbare manier op te bouwen.
Moet je meerdere packages installeren op een yum-based systeem, gebruik dan de yum-module in plaats van package en maak gebruik van de lijstfunctionaliteit binnen het name-gedeelte. Dit is een stuk sneller dan package gebruiken met een lijst van packages. Bij een zeer grote lijst aan packages kun je ook packages_fact gebruiken en vervolgens een list difference toepassen om de uiteindelijke lijst met te installeren packages te bepalen.
Gebruik altijd het laagst mogelijke permissieniveau. Gebruik geen algemene become: yes bovenaan je playbook. Ja, het is makkelijk en handig, maar je loopt ook het risico op onbedoelde wijzigingen aan privileged bestanden en instellingen.
Role inclusion
Gebruik roles/requirements.yml om roles in je playbook op te nemen. Dit voorkomt duplicatie van code. Pin altijd de versie van de role die je wilt gebruiken. Zo ziet roles/requirements.yml eruit.
Als je playbooks wilt gebruiken met verschillende versies van dezelfde role, maak dan voor elk playbook een aparte playbook-directory aan, met daaronder een eigen roles/requirements.yml.
Collections inclusion
Gebruik collections/requirements.yml om collections in je playbook op te nemen. Niet alle collections en modules zijn standaard beschikbaar in AWX (bijvoorbeeld maven_artifact uit community_general). Je moet de gebruikte collections expliciet toevoegen aan requirements.yml. AWX downloadt deze collections automatisch voordat het playbook wordt uitgevoerd.
Ansible.cfg configuratiebestand
Ansible ondersteunt meerdere manieren om het gedrag te configureren, waaronder een ini-bestand met de naam ansible.cfg. Dit bestand plaats je in de directory boven de directories met playbooks, roles en environments.
[defaults]
inventory = environments/sandbox
host_key_checking = False
remote_tmp = /var/tmp/.ansible/tmp
remote_user = ansible
roles_path = roles
collections_path = collections
Copy code
Host key checking staat standaard uitgeschakeld in AWX. In Ansible Tower kan deze controle worden ingeschakeld, omdat Tower host-based is in plaats van container-based. Hiervoor moet je het known_hosts-bestand vullen voor de Tower application user voordat je een host in Tower kunt gebruiken.
Uitleg van de instellingen
inventory = environments/sandbox
Omdat je in de voorbeeldstructuur alle omgevingen in één project hebt, is het verstandig om de standaard inventory te laten wijzen naar de omgeving die de minste schade veroorzaakt als er iets misgaat. Zo moet je bij het uitvoeren van playbooks via de commandline expliciet een kritischere omgeving opgeven.
host_key_checking = False
Dit schakelt SSH host key checking uit. In AWX is dit de standaardinstelling, omdat playbooks worden uitgevoerd in een aparte execution container die op elk moment kan worden verwijderd. Omdat de SSH-gebruiker per playbook kan verschillen, is er geen eenvoudige manier om een known_hosts-bestand in AWX te injecteren.
Let op: host key checking is alleen een goede securitymaatregel als de host keys vanaf het begin bekend zijn. Wanneer je Ansible gebruikt vanaf de commandline op een persistente host, raad ik sterk aan om host_key_checking op true te laten (oftewel: de instelling weg te laten), wat ook de standaardinstelling van Ansible is.
remote_tmp = /tmp/.ansible/tmp
Dit kan dienen als extra beveiligingsmaatregel. Maak bij de initiële installatie van een host een aparte tijdelijke directory aan met uitsluitend rechten voor de bedoelde Ansible remote user. Zo voorkom je dat een lokale aanvaller (op het doelsysteem) toegang krijgt tot tijdelijke data of scripts die Ansible naar de host pusht, zolang deze aanvaller geen verhoogde rechten heeft.
remote_user = ansible
Dit is de standaard remote user. In AWX wordt deze instelling overschreven door de machine credential die is ingesteld in de playbook template.
Variabeledefinities en hun locatie
Variabelen benoemen
Gebruik underscores voor langere variabelenamen. Gebruik alsjeblieft geen CaMeLCaSiNg. Je variabelenaam mag best wat langer zijn; dat is beter voor de leesbaarheid en je hoeft echt geen tekens te besparen.
Volgens de YAML 1.1-spec mogen eenvoudige keys zelfs tot 1024 tekens lang zijn.
Gebruik duidelijke variabelenamen. In eenvoudige loops kun je wegkomen met één letter als iterator, maar de leesbaarheid verbetert enorm als je beschrijvende namen gebruikt.
Als je kiest voor een andere naamgevingsconventie, doe dit dan consistent en gebruik dezelfde aanpak overal.
Lijsten
Ik gebruik graag een extra inspringniveau bij het definiëren van lijsten. Dit verhoogt de leesbaarheid. In het onderstaande voorbeeld lijkt het verschil klein, maar bij complexe dictionaries wordt het voordeel snel duidelijk.
listdefinition:
- item1
- item2
- item3
nextdefinition:
- item_a
- item_b
- item_c
something_else
Copy code
YAML anchors
YAML heeft een handige feature om configuratie te hergebruiken via zogeheten anchors. Met de &-syntax kun je een configuratie definiëren en die later opnieuw gebruiken:
- name: this is a first task
action1: &config
username: test
password: "{{ password }}"
state: present
config1: true
- name: this is a second task
action2:
<<: *config
state: absent
config2: false
Copy code
Met deze shorthand voorkom je duplicatie van veelgebruikte opties zoals gebruikersnamen, wachtwoorden, URL’s, namespaces, enzovoort.
Met meer dan tien jaar ervaring in het inzetten van Ansible, Tower en AWX om IT-operaties te stroomlijnen en te beveiligen, heeft ons team automatisering tot in de puntjes geperfectioneerd. Onze best practices voor Ansible weerspiegelen niet alleen onze expertise, maar ook onze toewijding om jouw automatiseringsreis zo efficiënt en effectief mogelijk te maken. Naarmate technologie zich blijft ontwikkelen, wordt het belang van security binnen automatisering alleen maar groter. Ons team loopt hierin voorop en integreert continu de nieuwste trends en securitymaatregelen om je infrastructuur te beschermen.
We begrijpen dat het navigeren door de complexiteit van automatisering en het waarborgen van robuuste én veilige systemen uitdagend kan zijn. Daarom staat ons team van gecertificeerde specialisten klaar om je organisatie te ondersteunen. Of je nu je huidige setup wilt optimaliseren, nieuwe automatiseringsstrategieën wilt adopteren of je systemen wilt beschermen tegen de nieuwste dreigingen: wij helpen je graag.
Laat de complexiteit van automatisering je niet afremmen. Benut onze expertise en laat ons je begeleiden bij elke stap van je automatiseringsreis. Neem contact met ons op en ontdek hoe we jouw organisatie helpen voorop te blijven lopen in een continu veranderend technologisch landschap.