In some of our previous blog entries we’ve discussed Puppet for config management. Today we are going to talk about another, easier to setup, config management service, Ansible. Ansible is written in Python and uses YAML configuration playbooks to handle pushing out configurations. Ansible, like Puppet, is used to control what the final state of things should look like. Since we’ve discussed Puppet, it is only fair to stack the two up and see what is different.
Puppet | Ansible |
---|---|
Master/Agent model, with agent installed on each client. | No particular Master node. Any node with Ansible, a list of hosts, a playbook, and SSH keys will serve as Master. |
Pull model, where agents must check in to receive changes. | Push model, where Master uses SSH to kick off playbooks on clients immediately. |
Puppet Domain Specific Language (DSL) used for manifests and classes. Can be extended with Ruby. | YAML Playbooks which can be extended with Ansible Python API. |
Can purchase Puppet Enterprise which comes with support and advanced UI to simplify management. | Can purchase Ansible Tower which comes with support and an advanced UI to simplify management. |
Puppet Labs Website | Ansible Website |
So, which is better? The answer to that is completely subjective. To answer that you have to ask which language better suits you, which model better suits your use case, and which method suits your workflow. There is no right answer to these questions. Puppet’s model is incredibly powerful and highly extensible, but it requires more setup in the front end, deploying and configuring agents. Ansible’s model is incredibly flexible, only requiring SSH keys and a list of hosts. Both have been adopted by large corporate enterprises. Some big names for Puppet are Red Hat, Cisco, ADP, and a long list of other major players. Ansible in a press release claims it added 300 major companies to its ranks in 2014 alone including the likes of Twitter, Apple, Juniper, Grainger, WeightWatchers, SaveMart, and NASA. Both projects are darlings of the Open Source community while also having business ventures to support their projects monetarily.
How do I deploy Ansible?
Well in Red Hat/CentOS world the answer to that is simple. Add the EPEL repository to your machine and run yum -y install ansible
and watch the magic happen. You only need to install it on the host(s) you wish to use as master(s). Then you set up a list of the hosts you wish to manage, write a playbook that defines what the final state of said hosts should look like, and fire off your playbook.
That sounds easy, but I still want to practice.
Good for you. Hopefully my blogs are rubbing off on you and you have already started your Ravello trial, or better have already become a full fledged customer and want to kick the tires to plan and test your own Ansible implementation in a lab with your own system images on AWS and Google Cloud. Good news! I’ve created a blueprint called 11-Ansible-bp in Ravello to get you started. You can request ravello support to move this blueprint to your account to get started. 11-Ansible-bp, has Ansible set up on the host server.example.com with an Ansible hosts file that includes client.example.com in a server group and a sample playbook that deploys httpd with a templated config file and sets up a user. All root passwords are set to ravellosystems. You will need to use a key-pair with this application and the SSH user for that key-pair is centos.
Get your Ansible playbook lab on AWS/Google cloud
Let’s take a look at how I created this blueprint. I took the CentOS 7 Generic cloud image found on CentOS.org, added ssh keys and some repositories I use for this and other demonstrations. They can ssh to and from each other as root with no worries. To use, connect as the user centos with your key-pair to server.example.com. Then run “sudo su -” to become root. Then you can look at the history on root. Let’s look at the pertinent bits.
# First we install ansible [root@server ~]# yum -y install ansible # Then we create a hosts file setting up the group [webservers] [root@server ~]# vim /etc/ansible/hosts #---- Contents of hosts: [webservers] client.example.com # Then we create the YAML playbook that deploys our webserver [root@server ~]# vim /etc/ansible/web.yml #---- Contents of web.yml (note, indents are important in YAML) #---- Also, YAML files must begin with ‘---’. --- - name: Deploy Apache to webservers group hosts: webservers vars: http_port: 80 remote_user: root tasks: - name: ensure apache is at the latest version yum: pkg=httpd state=latest - name: write the apache config file template: src=/etc/ansible/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf notify: - restart apache - name: write the index.html for the website template: src=/etc/ansible/index.html.j2 dest=/var/www/html/index.html notify: - restart apache - name: ensure apache is running (and enable it at boot) service: name=httpd state=started enabled=yes handlers: - name: restart apache service: name=httpd state=restarted # Here I’m installing apache to get a copy of httpd.conf # to template [root@server ~]# yum -q -y install httpd [root@server ~]# cp /etc/httpd/conf/httpd.conf \ /etc/ansible/httpd.conf.j2 # Here I replace ‘Listen 80’ with the Jinja2 template variable # http_port thus ‘Listen {{ http_port }}’ in the template. [root@server ~]# vim /etc/ansible/httpd.conf.j2 # Here I create an index.html to have it deploy. [root@server ~]# vim /etc/ansible/index.html.j2 # Here I run the playbook and it deploys to the client. [root@server ~]# ansible-playbook /etc/ansible/web.yml
So, let’s take a moment and break that down. In the hosts file we use a simple ini format. The ini sections indicate host groups. Any host you don’t want in a group goes before you declare your first group. A more complex example might look like this:
lonewolf.example.com [db] bd[1:50].example.com [web] www[1:100].example.com [foo] foo.example.com bar.example.com
In the above, we have 50 servers in the [db] group, 100 in the [web] group, one in the [foo] group and one not in any group. The only thing needed on the client is Python 2.5 or greater and ssh keys set up from the Ansible host to each either as root or an account with full sudo rights.
Next we look at the playbook, web.yml.
--- - name: Deploy Apache to webservers group hosts: webservers vars: http_port: 80 remote_user: root tasks: - name: ensure apache is at the latest version yum: pkg=httpd state=latest - name: write the apache config file template: src=/etc/ansible/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf notify: - restart apache - name: write the index.html for the website template: src=/etc/ansible/index.html.j2 dest=/var/www/html/index.html notify: - restart apache - name: ensure apache is running (and enable it at boot) service: name=httpd state=started enabled=yes handlers: - name: restart apache service: name=httpd state=restarted
In YAML we start the file with three dashes as a start of file indicator. Think of it like the HTML DOCTYPE declaration, only more strictly enforced. Indents and spacing matter as Python is picky about such things. Don’t use tabs. I use two spaces per level of indent. You could use a different number, but they must be consistent.
The first - name
declares the name for the play. Make it descriptive and unique to that play. Future you will thank you. Good play names are like love notes to your future self when you are trying to edit the play. We then declare the hosts, or in this case host group, to which this play applies. We then set a value for the template variable we set in httpd.conf.j2 so when it places the final file it has a legitimate value there. We then declare this is to be done as root. We could set a non-root user with sudo rights equally well, but my keys are set up as root.
Then we start the tasks section which is the real payload of the play. We name each task descriptively and uniquely, then tell it how to do the task. The first task ensures Apache is installed and updated. The second deploys our template or checks for differences and deploys the updates if changed. If there are changes, it notifies the handler that then restarts the Apache service. The third deploys our actual web page. The fourth verifies the service is started and enabled. Finally we declare the handler the notify operations called.
Once the playbook is written and the template files are in place, it is time to deploy. Playbooks can be run as many times as you like, as often as you like. You could even setup a cron job to enforce the state you declare in the playbook at regular intervals. Playbooks can even call other snippets called roles to create modular playbooks. Templates can be declared to set values on the fly using Jinja2 markup. The options are endless.
To test the playbook, pull up your browser and browse to the public IP of your client server. It should have your handy dandy webpage ready to go.
I encourage you to look at the files I have in /etc/ansible on server.example.com as a starting point. Then think about what you want to do. The Ansible documentation is a great place to get started. There is also the Ansible cookbook with great tips and tricks at Ansbile Cookbook.
Ansible is yet another powerful tool in our DevOps arsenal. With simple setup and incredibly low overhead it is definitely worth consideration and testing. Enjoy testing Ansible with the Ravello blueprint and as always, happy computing.
The post Ansible SmartLab on Ravello appeared first on The Ravello Blog.