3 ms·
I always read that ansible can only be used for very simple things. However I never read what things are too complicated with ansible. Can you share an example?
by zufallsheld 6y ago
I always read that ansible can only be used for very simple things. However I never read what things are too complicated with ansible. Can you share an example?
- Xophmeister 6y agoAnsible is good at putting configuration files in the right place and setting their appropriate values to what you want — provided it’s relatively simple, otherwise prepare yourself for complex templates — or installing software from a package manager, etc., etc. As soon as you go outside what its modules provide, it gets more difficult. Modules themselves are actually easy to write, provided you maintain Ansible’s (completely reasonable) maxim of idempotency. Sometimes, however, idempotency is hard to enforce. The best example I’ve come across is building software from source. When there’s no package, you have to do this. Some may argue that this is not Ansible’s job, but I don’t see how it’s different from `apt install`, nor where else it would fit into the pipeline. Anyway, the way I solved this for example was by pinning the idempotency on the existence of build artefacts. Those are often software-specific, so it’s quite fiddly/non-general to find the right artefact.
- snuxoll 6y agoYou should be building packages for the software, of course. If it’s some random internal app you’re chucking into a container it’s one thing, but if you’re deploying it across VMs or physical hosts you probably should put the effort into writing a rpmspec or whatever the hell Debian does (this is a large reason why I don’t do Debian-based systems, I have never been able to properly wrap my head around dpkg builds - there’s too much magic in debhelper and not enough documentation).
- notabee 6y agoI'd be interested in how you solved this, if you don't mind sharing. I tried writing a role to build source RPMs and it kind of works after doing some really dirty regex tricks, but only barely. I kept feeling that there must be a better way that I wasn't seeing.
- Xophmeister 6y agoDon’t say I didn’t warn you ;) This is not used any more — and the repo’s history looks messed up — but it was my solution to the “configure, make, make install” dance in Ansible: https://github.com/wtsi-hgi/hgi-systems/blob/master/ansible/roles/irods-client/tasks/jansson.yml https://github.com/wtsi-hgi/hgi-systems/blob/master/ansible/... The replies to my original post say this is not something Ansible should be doing. Fair enough :P I was young!
- aprdm 6y agoAnsible should be distributing the software artifact not building it. Package it as a deb as part of the CI in say jenkins and then apt install it with ansible.
- trabant00 6y agoWorst scenario for me was trying to implement a quasi hierarchical set of roles for a little over 1000 machines. Meaning I had grouping by datacenters, packages, configuration, domain, apps, etc, but also some differences. Inheritence sucks for both salt and ansible. http://reclass.pantsfullofunix.net/index.html http://reclass.pantsfullofunix.net/index.html helped a lit but still not perfect
- aprdm 6y agoWas it over a single inventory file ? You can break it by app, like, having many git repos one per app and then use ansible galaxy to reuse code Or you can try having a dynamic inventory that pulls metadata from say consul. We’re in the ballpark of 2k machines and still happy !
- trabant00 6y agoI wanted a mono repo and I did manage to do it. But it was not elegant and I kind of pity whoever came after me and needed to maintain and extend that without me being there to explain the model.
- notabee 6y agoHere's an example: you can register the output of a task into a variable, but if you use the same registered variable for multiple tasks even skipped tasks overwrite the registered variable. Say you want either task A or task B to run depending on the OS version, and do something based on that result in task C. Easy enough, just make two different registered variables, and have a separate conditional check for each registered variable on task C. But then, say it's only one of task A, B, C, or D, and task Z needs to know which one ran along with some other conditional logic. The conditional logic gets really hairy at that point. A way around this is to use the same registered variable repeatedly, and save its output via set_fact after each task, if that task ran, to a second variable. The set_fact module will only define the second variable if the conditional is true, unlike the registered variables which get redefined regardless. Then you can check for just the second variable later in the play and see which of the four tasks defined it. But now your 4 tasks have become 8 tasks of workaround repetition. This is just one of the quirks that starts to come up when a playbook gets more complicated than install x, write template y, done. Basically, it's better to stick with tasks that stand on their own. As soon as you stick complex task logic in it becomes kind of a Rube Goldberg machine. That being said, you can pull off quite a bit if you just test rigorously and write defensively.