I use Ansible to manage all my infrastructure. It's about 50 bare metal servers that sit in my basement.
It works well, but I have a few issues:
- It can be very slow
- YAML can be very tricky to edit
- Sometimes, it takes ages to find how to do something that seems very simple
- The output is not helpful, it is either not detailed enough, or a huge flow of debug information
The third one is the biggest pain point. I spent sometimes hours trying to get how to use some plugin to do something simple.
Ansible provides a lot of plugins, but most of them can be replaced by simple commands.
Some, which are a bit harder to replace, like
lineinfile which "ensure there
is a line in a file" I try to avoid, and instead have the whole file in my
devops system and replace it.
I started to replace a few playbooks with shell scripts. And it works wonders. Everything is so simple.
Here is an example:
--- - name: Michi pdns configuration gather_facts: false hosts: michi tasks: - package: name: - powerdns - entr state: present - service: name: pdns_server state: stopped - copy: src: pdns.conf dest: /etc/pdns/pdns.conf - copy: src: check-dynupdates.lua dest: /etc/pdns/check-dynupdates.lua - file: path: /var/db/pdns/ state: directory - copy: src: schema-sqlite3.sql dest: /var/db/pdns/schema-sqlite3.sql - file: path: /var/db/pdns/pdns.sqlite3 state: absent - shell: sqlite3 /var/db/pdns/pdns.sqlite3 < /var/db/pdns/schema-sqlite3.sql - file: path: /var/db/pdns/schema-sqlite3.sql state: absent - service: name: pdns_server state: started enabled: true - copy: src: sync.sh dest: /etc/pdns/sync.sh mode: 0700 - copy: src: sync_daemon.sh dest: /etc/pdns/sync_daemon.sh mode: 0700 - copy: src: pdns_sync dest: /etc/rc.d/pdns_sync mode: 0700 - service: name: pdns_sync state: started enabled: true
#!/bin/sh set -x cd "$(dirname "$0")" export TERM=vt100 SSH="ssh michi doas" $SSH pkg_add powerdns entr $SSH rcctl stop pdns_server cat pdns.conf | $SSH tee /etc/pdns/pdns.conf > /dev/null cat check-dynupdates.lua | $SSH tee /etc/pdns/check-dynupdates.lua > /dev/null $SSH mdir -p /var/db/pdns/ cat schema-sqlite3.sql | $SSH tee /var/db/pdns/schema-sqlite3.sql > /dev/null $SSH rm /var/db/pdns/pdns.sqlite3 $SSH sh -c 'sqlite3 /var/db/pdns/pdns.sqlite3 < /var/db/pdns/schema-sqlite3.sql' $SSH rm /var/db/pdns/schema-sqlite3.sql $SSH rcctl start pdns_server $SSH rcctl enable pdns_server cat sync.sh | $SSH tee /etc/pdns/sync.sh > /dev/null $SSH chmod 700 /etc/pdns/sync.sh cat sync_daemon.sh | $SSH tee /etc/pdns/sync_daemon.sh > /dev/null $SSH chmod 700 /etc/pdns/sync_daemon.sh cat pdns_sync | $SSH tee /etc/rc.d/pdns_sync > /dev/null $SSH chmod 700 /etc/rc.d/pdns_sync $SSH rcctl enable pdns_sync
This is for a single host, but for multiple host, you can do something like:
HOSTS="michi kiki" for HOST in $HOSTS do SSH="ssh $HOST ls" $SSH <do something> done
I converted a dozen playbook to scripts and here are a few point:
- It is much, MUCH easier to write, but this would depend on your
- It is much faster to run. If you have many hosts, I would look into GNU parallel because now it is sequential.
- It is more extensible without having to read documentation.
- Scripts are much shorter and easier to read (the above script has no comment for the example, but by real scripts have extensible comments)