In the previous post
on inventory file, we saw that inventory file is central location that stores
information about the remote hosts. It’s not necessary that we would always
want to deal with remote hosts. Ansible can also work on the control system
(localhost
).
$ cat /etc/ansible/hosts
localhost
[servers]
172.29.33.22
172.29.33.23
And let’s try the ping
module:
$ ansible -m ping all
localhost | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: Permission denied
(publickey,gssapi-keyex,gssapi-with-mic).\r\n",
"unreachable": true
}
172.29.33.23 | SUCCESS => {
"changed": false,
"ping": "pong"
}
172.29.33.22 | SUCCESS => {
"changed": false,
"ping": "pong"
}
Oops, that failed to ping localhost
- the only ping that we would expect to
work even if everything else failed. Let’s see the msg
part of the output -
Failed to connect to the host via ssh: Permission denied(publickey,gssapi-keyex,gssapi-with-mic).
. Why would I want to connect
to localhost
over SSH? Let’s set ansible_connection
in the inventory file:
$ cat /etc/ansible/hosts
localhost ansible_connection=local
[servers]
172.29.33.22
172.29.33.23
That tells Ansible to connect to localhost
using connection type local
. So,
no more SSH’ing into localhost
:
$ ansible -m ping all
localhost | SUCCESS => {
"changed": false,
"ping": "pong"
}
172.29.33.23 | SUCCESS => {
"changed": false,
"ping": "pong"
}
172.29.33.22 | SUCCESS => {
"changed": false,
"ping": "pong"
}
Voila! That was successful.
As you might have guessed by now, default ansible_connection
type is SSH. And
it can be changed by setting ansible_connection
to desired (and valid) value
in the inventory file. Other connection types include:
- SSH protocol types
- smart (default)
- ssh
- paramiko
- Non-SSH connection types
- local
- docker
Throughout the series, we’ll mainly be working using the default SSH connection
type. We’ll be deploying containers as well and will see if we need to use the
docker
connection type then. 😄
Host Variables Link to heading
We can easily assign host variables in the inventory file. These variables can then be used in playbooks.
$ cat /etc/ansible/hosts
[servers]
172.29.33.22 http_port=8080
172.29.33.23 http_port=9000
Above snippet defines http_port
to different values for the two hosts. Let’s
bring up httpd
webserver on these hosts on the specified port.
$ ansible -m yum --args="name=httpd state=present" servers
$ ansible -m lineinfile --args="regexp=\"^Listen\" path=/etc/httpd/conf/httpd.conf state=present line=\"Listen {{http_port }}\" " servers
$ ansible -m systemd --args="name=httpd state=restarted" servers
That’s handful of commands to execute. Let’s see what each one does.
- First we install
httpd
package using theyum
module.state=present
installs a package if it’s not already installed on the system. - Next, we replace a line in file (
lineinfile
) that starts withListen
(regexp="^Listen"
). The\
are used as escape characters so that a"
is not considered as closing quote. - Finally we start
httpd
service in those systems usingsystemd
module.
Now if we curl
these systems, we’ll be greeted with default Apache web
server page. All we need to do is curl 172.29.33.22:8080
or curl 172.29.33.23:9000
.
Group Variables Link to heading
If we’d like to set variables for entire group, servers
in our example, all
we need to do is:
$ cat /etc/ansible/hosts
[servers]
172.29.33.22
172.29.33.23
[servers:vars]
http_port=8080
And then executing similar commands as those we did earlier would start httpd
server for us on port 8080 of both the systems.
Aliases Link to heading
If you’ve used Linux command line for some time, chances are you have already heard of alias. It’s similar concept in Ansible as well.
An alias helps you define name for a host. In our example, we’ve specified IP
addresses of the hosts in our inventory file. If we’d like to ping
only one
system, we’ll have to do:
$ ansible -m ping 172.29.33.22
That doesn’t look cool. Let’s set aliases for our two hosts:
$ cat /etc/ansible/hosts
[servers]
host1 ansible_host=172.29.33.22
host2 ansible_host=172.29.33.23
And now we can simply do:
$ ansible -m ping host1
That’s it for this post Link to heading
In this post, we looked at some non-trivial ad-hoc commands of Ansible. It looks cool but, executing a bunch of commands every time on the command line is not really fun. Instead, we can use Ansible Playbooks to perform all tasks we did above with a single command. We’ll soon look at Ansible Playbooks!
As always, if you have any comments/feedback/suggestion, please let me know below! Until next time. 😉