What is Ansible?
Long story short, Ansible is a tool which helps server administrators automate and execute tasks on multiple servers at the same time. Imagine having 20 Linux servers, each needing an installtion
of a web server. In the good old days, you would have to login to each server individually and perform the task, now though you can do it with a single command.
Why is Ansible preferred – other automation tools require you to install additional software on your remote servers, while Ansible does the job through SSH, which means no additional software on your target servers, less resources/low overhead, less things to troubleshoot then things go wrong.
We will refer to the machine we install Ansible on as the command server. This could be your own laptop, stand alone server, or a small VPS. I personally run it on a small vps with 1GB ram and 50GB space from servercheap.net running CentOS 6
1 ) Let’s update our system with the latest packages
[root@ansible ~]# yum -y update
2) Enable EPEL repo
[root@ansible ~]# wget http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm [root@ansible ~]# rpm -ivh epel-release-6-8.noarch.rpm
3) Install Ansible via YUM
[root@ansible ~]# yum install ansible
4) Verify Ansible is installed
[root@ansible ~]# ansible --version ansible 22.214.171.124 config file = /etc/ansible/ansible.cfg configured module search path = Default w/o overrides python version = 2.6.6 (r266:84292, Aug 18 2016, 15:13:37) [GCC 4.4.7 20120313 (Red Hat 4.4.7-17)]
Setup SSH Keys/Password-less login
This step is necessary so Ansible is able to login to our remote server without you having to enter your root password every time and for each server.
1) Generate a public key on our control server
[root@ansible ~]# ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /root/.ssh/id_rsa. Your public key has been saved in /root/.ssh/id_rsa.pub. The key fingerprint is: 53:48:d1:09:35:c6:3f:09:4f:33:36:c8:44:1a:8c:12 root@ansible The key's randomart image is: +--[ RSA 2048]----+ | E. o=X*o | | . ...=B.* | | . o .* = | | . = | | S . | | . | | | | | | | +-----------------+
2) Copy the key we just generated from /root/.ssh/id_rsa.pub
[root@ansible ~]# cat /root/.ssh/id_rsa.pub ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0xRif65UF6W0vdmG7FPcQJLsZZBREam2lxOFZudZUHMgYR+R3CaLedHrO5+66Mo0C4kzFgrC1NySqBe9LMG1T8Mj/bxA81RwSLOSXf+nyz8oRHr1xb73pS7W0VlYqSFTK+RG9JZNad1Pc6PVb60jHWhtRxWwDF/2Cj4aVhpOmQnfiMZrTAvhy4VK6fU63JKKrOYzw71MYrkOclSYiAaeUd9+gBniAKYmJx7geC3Z+/JWs9EghQPE2yTKeY12jd/xHfNlrq+/V+V8TNd6aa5SMTZdGTlBnwArmZGCOd2Czv1PogDpS48W1mGIBei+LaD2YxIcqOz7zNUc/eCFEavs5w== root@ansible
3) Place the above public key in /root/.ssh/authorized_keys on all your Linux servers and save the file
nano /root/.ssh/authorized_keys ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0xRif65UF6W0vdmG7FPcQJLsZZBREam2lxOFZudZUHMgYR+R3CaLedHrO5+66Mo0C4kzFgrC1NySqBe9LMG1T8Mj/bxA81RwSLOSXf+nyz8oRHr1xb73pS7W0VlYqSFTK+RG9JZNad1Pc6PVb60jHWhtRxWwDF/2Cj4aVhpOmQnfiMZrTAvhy4VK6fU63JKKrOYzw71MYrkOclSYiAaeUd9+gBniAKYmJx7geC3Z+/JWs9EghQPE2yTKeY12jd/xHfNlrq+/V+V8TNd6aa5SMTZdGTlBnwArmZGCOd2Czv1PogDpS48W1mGIBei+LaD2YxIcqOz7zNUc/eCFEavs5w== root@ansible
4) Let’s test it, if we have done everything properly, when we try to ssh to our linux server from our ansible control server, we should not be asked for password.
From our ansible control server we run:
[root@ansible ~]# ssh 126.96.36.199 The authenticity of host '[188.8.131.52] ([184.108.40.206])' can't be established. RSA key fingerprint is 86:88:3f:9d:35:41:e4:a8:0e:6b:15:26:3d:77:01:4b. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '[220.127.116.11]' (RSA) to the list of known hosts. Last login: Thu Jul 13 17:58:07 2017 from . [firstname.lastname@example.org ~]#
Configure Ansible Hosts
We need to tell Ansible the IPs of the servers we want to administer. This is done by adding your server ips in /etc/ansible/hosts
The default file looks like this:
[root@ansible ~]# cat /etc/ansible/hosts # This is the default ansible 'hosts' file. # # It should live in /etc/ansible/hosts # # - Comments begin with the '#' character # - Blank lines are ignored # - Groups of hosts are delimited by [header] elements # - You can enter hostnames or ip addresses # - A hostname/ip can be a member of multiple groups # Ex 1: Ungrouped hosts, specify before any group headers. ## green.example.com ## blue.example.com ## 192.168.100.1 ## 192.168.100.10 # Ex 2: A collection of hosts belonging to the 'webservers' group ## [webservers] ## alpha.example.org ## beta.example.org ## 192.168.1.100 ## 192.168.1.110 # If you have multiple hosts following a pattern you can specify # them like this: ## www[001:006].example.com # Ex 3: A collection of database servers in the 'dbservers' group ## [dbservers] ## ## db01.intranet.mydomain.net ## db02.intranet.mydomain.net ## 10.25.1.56 ## 10.25.1.57 # Here's another example of host ranges, this time there are no # leading 0s: ## db-[99:101]-node.example.com
Now let’s add our first host. At the bottom of the file we can do:
[test] LinuxServer1:7777 ansible_ssh_host=18.104.22.168
In the above example [test] is the name of the group which will contain our Linux servers. You can have as many groups as you wish.
LinuxServer1 is the friendly name of our first server.
:7777 tells Ansible that the SSH port of our server is 7777. If your server runs SSH on the standard port 22, you can leave that part out.
ansible_ssh_host=22.214.171.124 tells Ansible the IP of our server
So far so good. By now we have Ansible installed and our first server is configured.
Let’s run some sample commands:
[root@ansible ~]# ansible LinuxServer1 -m shell -a 'ps ax' LinuxServer1 | SUCCESS | rc=0 >> PID TTY STAT TIME COMMAND 1 ? Ss 0:49 init -z 2 ? S 0:00 [kthreadd/342] 3 ? S 0:00 [khelper/342] 60 ? Ss 0:02 /usr/lib/systemd/systemd-journald 67 ? Ss 0:00 /usr/lib/systemd/systemd-udevd 106 ? Ss 0:15 /usr/lib/systemd/systemd-logind 107 ? Ss 0:32 /bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation 108 ? Ss 0:00 /usr/sbin/xinetd -stayalive -pidfile /var/run/xinetd.pid 112 ? Ssl 0:00 /usr/sbin/rsyslogd -n 138 ? Ss 0:00 /usr/sbin/saslauthd -m /run/saslauthd -a pam -n 2 139 ? S 0:00 /usr/sbin/saslauthd -m /run/saslauthd -a pam -n 2 153 ? Ss 0:00 /usr/sbin/sshd 165 ? Ss 0:00 /bin/sh /usr/bin/mysqld_safe --basedir=/usr 197 ? Ss 0:01 /usr/sbin/crond -n 202 tty2 Ss+ 0:00 /sbin/agetty --noclear tty2 linux 204 tty1 Ss+ 0:00 /sbin/agetty --noclear --keep-baud console 115200 38400 9600 vt220 386 ? Sl 17:06 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin --log-error=/var/log/mysqld.log --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/lib/mysql/mysql.sock 406 ? Ss 0:28 sendmail: accepting connections 436 ? Ss 0:00 sendmail: Queue runner@01:00:00 for /var/spool/clientmqueue 5723 ? Ss 0:01 /sbin/rpcbind -w 11951 ? Ss 0:25 /usr/sbin/httpd -DFOREGROUND 20486 ? S 0:02 /usr/sbin/httpd -DFOREGROUND 20487 ? S 0:04 /usr/sbin/httpd -DFOREGROUND 20488 ? S 0:03 /usr/sbin/httpd -DFOREGROUND 23767 ? Ss 0:00 sshd: root@pts/0 23797 pts/0 Ss+ 0:00 /bin/sh -c /usr/bin/python /root/.ansible/tmp/ansible-tmp-1499985693.17-135220611748439/command.py; rm -rf "/root/.ansible/tmp/ansible-tmp-1499985693.17-135220611748439/" > /dev/null 2>&1 && sleep 0 23808 pts/0 S+ 0:00 /usr/bin/python /root/.ansible/tmp/ansible-tmp-1499985693.17-135220611748439/command.py 23809 pts/0 S+ 0:00 /usr/bin/python /tmp/ansible_nWpKck/ansible_module_command.py 23810 pts/0 R+ 0:00 ps ax
Cool, we now see all the running processes on our remote server. Alternatively we can run:
[root@ansible ~]# ansible test -m shell -a 'ps ax'
Remember we created a group called test in our /etc/ansible/hosts file? The above command will then execute the command ‘ps ax’ on all servers under the group test. Since currently we only have one server, the output will be the same as above.
With the above example you can automate a lot of things, however Ansible is all about playbooks. What is a playbook? – it is just a text file in YAML format, where you list a bunch of commands for Ansible to execute. Let’s get right into some examples.
Scenario: Let’s image we are administering 20 linux servers. On each of them we have a custom shell script running. We have now made changes to our script and we would like to update it on all 20 servers. In the good old days you would have had to login to each server individually and update the file, let’s see how we can perform this task with the help of Ansible in just a few seconds.
Lets create a file called test.yaml in /etc/ansible (the location of the files do not matter and you are free to place them where ever you wish)
[root@localhost ansible]# cd /etc/ansible/ [root@localhost ansible]# nano test.yaml
And we insert the following yaml code:
--- - hosts: LinuxServer1 tasks: - name: Copy scripts over synchronize: src=/etc/ansible/test.yaml dest=/root - name: Set execute persmission on ave file: path=/root/test.yaml owner=root group=wheel mode=0775 state=file
Lets break the above code down:
– hosts: LinuxServer1 – the destination server, alternatively you could put the group name, in our case ‘test’, which would then cause ansible to copy our file to all servers in the group.
– name: Copy scripts over – a general description of our task.
synchronize: src=/etc/ansible/test.yaml dest=/root – this line tells ansible to copy the file test.yaml which is located in /etc/ansible on our local control server and place it in /root on the destination server.
file: path=/root/test.yaml owner=root group=wheel mode=0775 state=file – this line tells ansible to change the permissions of the test.yaml once it is copied to the destination server.
And we execute it:
[root@ansible ~]# ansible-playbook test.yaml
If we now check our destination server, we will see test.yaml in /root with 755 permission
Pretty cool eh ? Now you have a basic knowledge and understanding of what Ansible is and how it works. But don’t just stop here. Ansible is a massively powerful tool which can allow you to automated almost anything you can think of.