When you are using Puppet you might know this problem:
How can I execute arbitrary commands on all or some of my Puppet nodes?
In this article, I explain how you can do so with Ansible . Ansible it another configuration management tool like Puppet and Chef. My colleague Daniel Schneller gives a great introduction in his article “Ansible, simple yet powerful automation” . There are already a lot of comparisons of Puppet and Ansible available for example [1] and [2 ]. In this post I focus on the combination of Ansible and Puppet.
An often encountered problem with Puppet is that it does not provide a remote executor by itself but relies on mcollective. Ansible’s advantage over Puppet is that it does not need an agent on each server. It uses ssh to execute commands on remote hosts. In order for this to work, Ansible needs an inventory enumerating all the servers it shall manage. Taking a look at the Ansible documentation, an inventory is usually a file. The simplest form is just a list of hostnames:
1web01.example.com
2web02.example.com
3db01.example.com
4db02.example.com
5...
In order to facilitate Ansible to run Puppet commands, we need to create such an inventory. As Puppet knows all the servers it manages, it can help us to create the inventory. Puppet uses certificates to secure the communication between Puppet agent and server. It stores these certificates on its master and you can access this information. For example, the output of puppet cert list --all
looks like this:
1+ "web01.example.com" (SHA256) 11:AB:C5:A3:7D:7B:90:40:57:FC:03:97:D7:73:07:E3:F8:D1:F5:81:3C:80:C0:4A:B2:F4:69:A7:BC:85:C8:59 2+ "web02.example.com" (SHA256) 9A:84:F1:14:19:6B:BC:65:4D:29:C9:31:C1:2A:6A:BD:DC:7A:DD:28:09:42:C1:23:59:4F:9C:31:DF:DC:3B:D5 3+ "db01.example.com" (SHA256) D2:00:26:F8:3F:9B:19:CD:1F:AB:D2:74:1A:93:35:11:9C:AB:1E:C2:50:4A:72:A7:81:82:5E:83:AB:3C:50:EF 4+ "db01.example.com" (SHA256) FD:A2:F1:F1:5D:0C:1A:6B:02:3A:66:FA:51:C3:DF:88:2B:83:95:D8:BB:4C:11:CB:50:82:BF:C8:CA:26:3B:90 5...
There you see a list of all managed hosts.
The next step is to convert the output of puppet cert
to an Ansible inventory. The simplest way is to convert the output into a corresponding Ansible inventory You can do this with a bash command:
1puppet cert list --all | egrep "^\+.*" | awk-F"\"" '{ print $2 }' > /etc/ansible/puppet_hosts
You can use the created file as inventory for Ansible:
1ansible “all” -i /etc/ansible/puppet_hosts -a "uptime"
This command will produce an output like this:
1web01.example.com | success | rc=0 >> 215:27:00 up 238 days, 21:20, 1 user, load average: 0.58, 0.60, 0.63 3 4web02.example.com | success | rc=0 >> 515:27:00 up 176 days, 22:07, 1 user, load average: 0.83, 0.74, 0.73 6 7db01.example.com | success | rc=0 >> 815:27:00 up 310 days, 5:51, 1 user, load average: 0.00, 0.00, 0.00 9 10db02.example.com | success | rc=0 >> 1115:27:00 up 210 days, 10 min, 1 user, load average: 1.19, 0.89, 0.77 12…
Ansible calls such an inventory a static inventory. As your managed hosts will change over time you want to have something more dynamic. Therefore, Ansible also supports so called dynamic inventories. To use a dynamic inventory, just replace the inventory file from above with an executable, e.g. a script. The dynamic inventory script in our case looks like this :
1#!/bin/bash 2 3/usr/bin/puppet cert list --all > /dev/null 2>&1 4if [ $? -ne 0 ] 5then 6 echo "Puppet error" 7 exit 1 8fi 9 10HOSTS="{\n\t\"all\":\n\t\t[\n" 11FIRST_HOST="true" 12 13while read hostname 14do 15 # this way i don't get a trailing comma 16 if [ "${FIRST_HOST}" == "true" ] 17 then 18 HOSTS="${HOSTS}\t\t\t\"${hostname}\"" 19 unset FIRST_HOST 20 else 21 HOSTS="${HOSTS}, \"${hostname}\"" 22 fi 23done < <(/usr/bin/puppet cert list --all | egrep "^\+.*" | awk -F"\"" '{ print $2 }' | grep "example.com") 24 25HOSTS="${HOSTS}\n\t\t]\n}" 26 27echo -e "${HOSTS}"
This script creates one long list of hosts with the help of Puppet and prints this list in Ansible compatible JSON to standard output:
1{ 2 "all": 3 [ 4 "web01.example.com", "web02.example.com", "db01.example.com", "db02.example.com", ... 5 ] 6}
For a broader introduction to Dynamic Inventories and another example take a look at this post by my colleague Lukas Pustina. He describes how to use Ansible features like host facts and host groups with dynamic inventories.
With the dynamic inventory script, the command shown above changes to:
1ansible “all” -i /usr/local/bin/puppet_dyn_hosts -a "uptime"
The Ansible command converts the current Puppet certificate list and executes the command on the selected hosts:
1web01.example.com | success | rc=0 >> 215:27:00 up 238 days, 21:20, 1 user, load average: 0.58, 0.60, 0.63 3 4web02.example.com | success | rc=0 >> 515:27:00 up 176 days, 22:07, 1 user, load average: 0.83, 0.74, 0.73 6 7db01.example.com | success | rc=0 >> 815:27:00 up 310 days, 5:51, 1 user, load average: 0.00, 0.00, 0.00 9 10db02.example.com | success | rc=0 >> 1115:27:00 up 210 days, 10 min, 1 user, load average: 1.19, 0.89, 0.77 12…
This command is just an example. You can replace uptime
with any other command. When you have a more complex task at hand, you can even write Ansible playbooks and execute them on the hosts.
Here is an example where you first stop a service, change file permissions and start the service again:
1--- 2- name: Updates splunkforwarder 3 hosts: all 4 tasks: 5 - name: Stop splunk to change uid 6 sudo: yes 7 service: name=splunk state=stopped 8 9 - name: Change file permissions 10 sudo: yes 11 file: path=/opt/splunkforwarder owner=splunk group=splunk recurse=yes 12 13 - name: Start splunk 14 sudo: yes 15 service: name=splunk state=started
You can even integrate calls to Puppet agent into your Ansible playbooks, but this will be the topic of another post.
When you have more questions about how to combine Ansible and Puppet, do not hesitate to contact me.
More articles
fromChristian Zunker
Your job at codecentric?
Jobs
Agile Developer und Consultant (w/d/m)
Alle Standorte
More articles in this subject area
Discover exciting further topics and let the codecentric world inspire you.
Gemeinsam bessere Projekte umsetzen.
Wir helfen deinem Unternehmen.
Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.
Hilf uns, noch besser zu werden.
Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.
Blog author
Christian Zunker
Do you still have questions? Just send me a message.
Do you still have questions? Just send me a message.