The Occasion
Since work uses puppet quite a lot, and puppet changed considerably after its major version upgrade, and since puppet is written in ruby — a tech stack I don’t have — I could only reuse other people’s modules. So in my spare time I researched alternatives and discovered Ansible. Of course similar tools include chef and saltstack, but I’ve only used Ansible briefly; if I get the chance I’ll study those two as well.
For in-depth use of Ansible please consult the official documentation; this post only covers my own usage and understanding — please point out anything inappropriate.
Simple Usage
Installation
On my machine I can just use yaourt -S ansible; other Linux distributions can try
their own package managers — it should be there too.
Connecting to the First Machine
Ansible connects over ssh, which means we need to give it some SSH parameters. Here I paste my own configuration directly as a reference:
1 | # Save the configuration in a file called hosts — note, NOT /etc/hosts; these are two different things |
If you’re not sure you can connect, better to try an ssh connection first; as long as it connects, you’re good.
1 | ssh [email protected] -p 22 -i ~/.ssh/id_rsa_raspberry |
Viewing Some Metadata
1 | # use -i hosts to specify the input file |
The result may be long; I suggest using ansible -i hosts ubt -m setup | less to scroll through it.
The First playbook
Using a playbook, configuration can be solidified and reused. official playbook docs
1 | ansible_study ❤️ cat site_test.yml git:master* |
You can see the result printed by the [Test] task.
A Visualization Interface for Ansible
After using Ansible I also found a GUI tool: ara, open-sourced by Redhat. The usage is:
1 | # Install ARA |

Comparing Some Ansible & Puppet Operations
Next I’ll introduce some practices from my current usage, covering both Ansible and puppet. Since the parts below are all used in daily work, I focus the comparison on these items; please point out anything inappropriate.
Creating Files and Folders
Using puppet
1 | # create a folder |
Using Ansible
1 | - name: Create nginx dir |
Variable Definition and Template Usage
The two differ slightly: puppet uses ruby templates while Ansible uses jinja templates. In real use the difference is actually small; besides ordinary variables, both of course support if and for statements. Readers will definitely use them when actually writing templates.
Using puppet
1 | # this defines a variable in a class, usable only within the class |
Using Ansible
1 | # This is how I use Ansible variables |
Creating crontabs
During use I found that crontab configs created by puppet can be viewed directly with crontab -e,
while crontab files generated by Ansible are placed in the /etc/cron.d directory — worth noting when using them.
Using puppet
1 | cron { "do-something": |
Using Ansible
Ansible’s cron documentation
1 | - name: Creates a cron file under /etc/cron.d |
Package Management on debian-family Systems
I only tested briefly on debian and ubuntu; for yum usage, readers please try it yourselves.
Using puppet
1 | # deb package |
Using Ansible
1 | - name: Install git |
Conditional Task Execution
That is, when to execute and when to bypass a task — both puppet and Ansible support this. Personally I prefer puppet’s version; if statements feel comfortable. yaml has no if statements, though you can use when, and it also supports embedded jinja statements.
Using puppet
1 | if $test_var == "my_vars" { |
Using Ansible
1 | # a fairly complex when statement, still practical |
systemctl and service Operations
This part is mainly about reloading some programs after certain config items are updated. I’ll use reloading Nginx as an example; essentially the difference between the two is not big.
Using puppet
1 | exec { "reload nginx": |
Using Ansible
1 | --- |
Summary Comparison of puppet and Ansible
In puppet, many features are provided by modules — for example filebeat and mysql are introduced as modules. Values can be passed in a function-call-like form, giving a more procedural feel. Also in puppet, task dependencies are specified explicitly via require; you can write tasks anywhere, and in the end just add the requires properly. puppet also has its own syntax; overall this syntax is fairly easy to understand — reading a section basically tells you what it does. Moreover, the official project provides a module management tool; whatever module you need can be installed directly. In my view, the only bad thing is that the puppet 3→4 version upgrade brought many incompatibilities — also one reason I started researching Ansible.
In Ansible, all playbook configuration files are in yaml format. It feels more like a declarative language. One nice point is that yaml config files are rendered with jinja, so you can still use variables in the config files. Compared with puppet’s module, Ansible has a more abstract structure called role; unlike puppet’s built-in module management, Ansible’s role repositories are scattered all over Github with no official management tool. In my view, at the current stage Ansible is still suitable for writing light deployment configurations; writing large configurations from scratch is not an easy task.
Some Suggestions
From my feeling — since I’m a Python developer — I still recommend Ansible. But if you use puppet for historical reasons, there’s no need to struggle to switch. When using puppet, I suggest keeping up with new versions; some modules don’t support versions below 4.0, and you definitely don’t want to write puppet modules yourself. (If you’re considering writing your own, then what this rookie said doesn’t count.)