What is Ansible?
Ansible is an open-source automation tool used primarily for configuration management, application deployment, and task automation across IT environments. It helps system administrators and DevOps teams automate repetitive tasks such as server provisioning, configuration, software installation, and management of cloud resources.
Prerequisites for Installing Ansible
- Ubuntu 24.04.1 installed on both the control node (the machine that runs Ansible) and the managed nodes (the machines that Ansible is managing)
- Python installed on both control node (version between Python 3.10 and above) and managed nodes (version between Python 3.7 and above)
- OpenSSH server and client installed on control node and on managed nodes.
- root user access on all nodes or user with sudo privileges to root user on all nodes
Lab information
For this process, we will utilize the following control node and managed nodes. While we can scale the number of managed nodes as needed, we will demonstrate the process using two managed nodes in this example.
Control Node IP | 192.168.2.100 |
Managed Node 1 IP | 192.168.2.101 |
Managed Node 2 IP | 192.168.2.102 |
Verify prerequisites for all nodes
Switch to root user and check following prerequisites
Check Ubuntu Version
Open terminal and run following command to check Ubuntu version on all nodes, it should be Ubuntu 24.04
cat /etc/issue
Output should look like following
$ cat /etc/issue
Ubuntu 24.04.1 LTS \n \l
$
Check Python version
Open terminal and run following command to check Python version on all nodes, on control node (version between Python 3.10 and above) and and managed nodes (version between Python 3.7 and above)
python3 --version
Output should look like following
$ python3 --version
Python 3.12.3
$
Check OpenSSH client is installed
Open terminal and type following command to check openSSH client version
ssh -V
Output should look like following
$ ssh -V
OpenSSH_9.6p1 Ubuntu-3ubuntu13.5, OpenSSL 3.0.13 30 Jan 2024
$
Check OpenSSH server is installed and running
Open terminal and type following command to check openSSH servers version and if its running
sshd -V
systemctl status ssh
Output should look like following
$ sshd -V
OpenSSH_9.6p1 Ubuntu-3ubuntu13.5, OpenSSL 3.0.13 30 Jan 2024
$ systemctl status ssh
● ssh.service - OpenBSD Secure Shell server
Loaded: loaded (/usr/lib/systemd/system/ssh.service; disabled; preset: enabled)
Active: active (running) since Tue 2024-12-31 20:32:57 UTC; 21h ago
TriggeredBy: ● ssh.socket
Docs: man:sshd(8)
man:sshd_config(5)
Process: 528 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS)
Main PID: 529 (sshd)
Tasks: 1 (limit: 532)
Memory: 3.8M (peak: 4.8M)
CPU: 145ms
CGroup: /system.slice/ssh.service
└─529 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups"
Dec 31 20:33:48 admin sshd[582]: Connection closed by authenticating user ubuntu 192.168.2.28 port 58170 [preauth]
Dec 31 20:33:48 admin sshd[584]: Accepted publickey for ubuntu from 192.168.2.28 port 50846 ssh2: RSA SHA256:9nOZn6g99yM+0ndMpqaaI7h7wt8szGun5328FPFCqX0
Dec 31 20:33:48 admin sshd[584]: pam_unix(sshd:session): session opened for user ubuntu(uid=1000) by ubuntu(uid=0)
Dec 31 20:33:48 admin sshd[584]: pam_unix(sshd:session): session closed for user ubuntu
Dec 31 20:33:52 admin sshd[618]: Connection closed by authenticating user ubuntu 192.168.2.28 port 50848 [preauth]
Dec 31 20:33:52 admin sshd[620]: Accepted publickey for ubuntu from 192.168.2.28 port 50862 ssh2: RSA SHA256:9nOZn6g99yM+0ndMpqaaI7h7wt8szGun5328FPFCqX0
Dec 31 20:33:52 admin sshd[620]: pam_unix(sshd:session): session opened for user ubuntu(uid=1000) by ubuntu(uid=0)
Dec 31 20:33:52 admin sshd[620]: pam_unix(sshd:session): session closed for user ubuntu
Dec 31 20:34:46 admin sshd[647]: Accepted publickey for ubuntu from 192.168.2.28 port 34446 ssh2: RSA SHA256:9nOZn6g99yM+0ndMpqaaI7h7wt8szGun5328FPFCqX0
Dec 31 20:34:46 admin sshd[647]: pam_unix(sshd:session): session opened for user ubuntu(uid=1000) by ubuntu(uid=0)
$
Update Ubuntu repository
Open a terminal and run the following command to update your local package index (repository information) on all nodes using root user:
apt update
output should look like following
$ apt update
Hit:1 http://archive.ubuntu.com/ubuntu noble InRelease
Get:2 http://security.ubuntu.com/ubuntu noble-security InRelease [126 kB]
Get:3 http://archive.ubuntu.com/ubuntu noble-updates InRelease [126 kB]
Get:4 http://archive.ubuntu.com/ubuntu noble-backports InRelease [126 kB]
Fetched 378 kB in 0s (887 kB/s)
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
All packages are up to date.
$
Install pipX on control node
What is pipX?
pipx
is a tool for installing and running Python applications in isolated environments. It makes it easier to manage Python-based applications and tools that you want to use globally, without polluting your system Python environment.
Installing pipX
Open terminal and run following commands to install pipX on control node using root user
apt install pipx -y
Output should look like following
$ apt install pipx -y
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
python3-argcomplete python3-packaging python3-pip-whl python3-platformdirs python3-psutil python3-setuptools-whl python3-userpath python3-venv python3.12-venv
The following NEW packages will be installed:
pipx python3-argcomplete python3-packaging python3-pip-whl python3-platformdirs python3-psutil python3-setuptools-whl python3-userpath python3-venv python3.12-venv
0 upgraded, 10 newly installed, 0 to remove and 0 not upgraded.
Need to get 3508 kB of archives.
After this operation, 7832 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu noble-updates/universe amd64 python3-pip-whl all 24.0+dfsg-1ubuntu1.1 [1703 kB]
Get:2 http://archive.ubuntu.com/ubuntu noble-updates/universe amd64 python3-setuptools-whl all 68.1.2-2ubuntu1.1 [716 kB]
Get:3 http://archive.ubuntu.com/ubuntu noble-updates/universe amd64 python3.12-venv amd64 3.12.3-1ubuntu0.3 [5678 B]
Get:4 http://archive.ubuntu.com/ubuntu noble-updates/universe amd64 python3-venv amd64 3.12.3-0ubuntu2 [1034 B]
Get:5 http://archive.ubuntu.com/ubuntu noble-updates/universe amd64 python3-argcomplete all 3.1.4-1ubuntu0.1 [33.8 kB]
Get:6 http://archive.ubuntu.com/ubuntu noble/main amd64 python3-packaging all 24.0-1 [41.1 kB]
Get:7 http://archive.ubuntu.com/ubuntu noble/main amd64 python3-platformdirs all 4.2.0-1 [16.1 kB]
Get:8 http://archive.ubuntu.com/ubuntu noble/universe amd64 python3-userpath all 1.9.1-1 [9416 B]
Get:9 http://archive.ubuntu.com/ubuntu noble/universe amd64 pipx all 1.4.3-1 [787 kB]
Get:10 http://archive.ubuntu.com/ubuntu noble/main amd64 python3-psutil amd64 5.9.8-2build2 [195 kB]
Fetched 3508 kB in 0s (8084 kB/s)
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package python3-pip-whl.
(Reading database ... 18589 files and directories currently installed.)
Preparing to unpack .../0-python3-pip-whl_24.0+dfsg-1ubuntu1.1_all.deb ...
Unpacking python3-pip-whl (24.0+dfsg-1ubuntu1.1) ...
Selecting previously unselected package python3-setuptools-whl.
Preparing to unpack .../1-python3-setuptools-whl_68.1.2-2ubuntu1.1_all.deb ...
Unpacking python3-setuptools-whl (68.1.2-2ubuntu1.1) ...
Selecting previously unselected package python3.12-venv.
Preparing to unpack .../2-python3.12-venv_3.12.3-1ubuntu0.3_amd64.deb ...
Unpacking python3.12-venv (3.12.3-1ubuntu0.3) ...
Selecting previously unselected package python3-venv.
Preparing to unpack .../3-python3-venv_3.12.3-0ubuntu2_amd64.deb ...
Unpacking python3-venv (3.12.3-0ubuntu2) ...
Selecting previously unselected package python3-argcomplete.
Preparing to unpack .../4-python3-argcomplete_3.1.4-1ubuntu0.1_all.deb ...
Unpacking python3-argcomplete (3.1.4-1ubuntu0.1) ...
Selecting previously unselected package python3-packaging.
Preparing to unpack .../5-python3-packaging_24.0-1_all.deb ...
Unpacking python3-packaging (24.0-1) ...
Selecting previously unselected package python3-platformdirs.
Preparing to unpack .../6-python3-platformdirs_4.2.0-1_all.deb ...
Unpacking python3-platformdirs (4.2.0-1) ...
Selecting previously unselected package python3-userpath.
Preparing to unpack .../7-python3-userpath_1.9.1-1_all.deb ...
Unpacking python3-userpath (1.9.1-1) ...
Selecting previously unselected package pipx.
Preparing to unpack .../8-pipx_1.4.3-1_all.deb ...
Unpacking pipx (1.4.3-1) ...
Selecting previously unselected package python3-psutil.
Preparing to unpack .../9-python3-psutil_5.9.8-2build2_amd64.deb ...
Unpacking python3-psutil (5.9.8-2build2) ...
Setting up python3-setuptools-whl (68.1.2-2ubuntu1.1) ...
Setting up python3-pip-whl (24.0+dfsg-1ubuntu1.1) ...
Setting up python3-platformdirs (4.2.0-1) ...
Setting up python3-psutil (5.9.8-2build2) ...
Setting up python3-packaging (24.0-1) ...
Setting up python3-argcomplete (3.1.4-1ubuntu0.1) ...
Setting up python3-userpath (1.9.1-1) ...
Setting up python3.12-venv (3.12.3-1ubuntu0.3) ...
Setting up python3-venv (3.12.3-0ubuntu2) ...
Setting up pipx (1.4.3-1) ...
$
exit from root user in terminal and run following command as a normal user to set pipX in PATH
pipx ensurepath
output should look like following
$ pipx ensurepath
Success! Added /home/ubuntu/.local/bin to the PATH environment variable.
Consider adding shell completions for pipx. Run 'pipx completions' for instructions.
You will need to open a new terminal or re-login for the PATH changes to take effect.
Otherwise pipx is ready to go! ✨ 🌟 ✨
$
Install Ansible on control node
Open new terminal and run following command to install Ansible as normal user
pipx install --include-deps ansible
output should look like following
$ pipx install --include-deps ansible
installed package ansible 11.1.0, installed using Python 3.12.3
These apps are now globally available
- ansible
- ansible-community
- ansible-config
- ansible-console
- ansible-doc
- ansible-galaxy
- ansible-inventory
- ansible-playbook
- ansible-pull
- ansible-test
- ansible-vault
done! ✨ 🌟 ✨
$
check Ansible version with following command
ansible --version
output should look like following
$ ansible --version
ansible [core 2.18.1]
config file = None
configured module search path = ['/home/ubuntu/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /home/ubuntu/.local/share/pipx/venvs/ansible/lib/python3.12/site-packages/ansible
ansible collection location = /home/ubuntu/.ansible/collections:/usr/share/ansible/collections
executable location = /home/ubuntu/.local/bin/ansible
python version = 3.12.3 (main, Nov 6 2024, 18:32:19) [GCC 13.2.0] (/home/ubuntu/.local/share/pipx/venvs/ansible/bin/python)
jinja version = 3.1.5
libyaml = True
$
Create ssh key pair on control node
We will use this ssh key pair to communicate with managed node
Open terminal and run following command to create ssh key pair as normal user
ssh-keygen -t rsa -f /home/ubuntu/ansible/ansiblekey
ssh-keygen : command to create key pair
-t : type of algorithm to use, here we are using rsa
-f : key files location and private key name /home/ubunut/ansible is location and ansiblekey is private key name in that location
It will ask for passphrase please enter your desired passphrase, we need this passphrase while we use this key pair
output should look like following
$ ssh-keygen -t rsa -f /home/ubuntu/ansible/ansiblekey
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/ubuntu/ansible/ansiblekey
Your public key has been saved in /home/ubuntu/ansible/ansiblekey.pub
The key fingerprint is:
SHA256:hSkZSgur5jdrFmWAi/bEcpHJ2yFnuHvj5/Po9q7qom0 ubuntu@admin
The key's randomart image is:
+---[RSA 3072]----+
| + = . |
| . % * o o |
|. + % + o . |
|.= * + . . |
|o.= + S |
|o + o |
| . o+ . |
| oEo. +. |
| .=ooo*=*+ |
+----[SHA256]-----+
$
Configure ssh key pair to connect to managed nodes
Run following command on control node to copy above public key to managed nodes. We need to run following command twice on control node with different IPs of managed nodes
command will ask if you want to continue, answer yes and thereafter it ask for the password of remote user ‘ubuntu’ please provide
# run command for every managed node
ssh-copy-id -i /home/ubuntu/ansible/ansiblekey.pub ubuntu@<managed-node-ip>
ssh-copy-id : is command to copy ssh public key to remote node
-i : location of ssh public key file
ubuntu : remote user which has sudo access to root account on managed node
output should look like following
$ ssh-copy-id -i /home/ubuntu/ansible/ansiblekey.pub ubuntu@192.168.2.102
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/ubuntu/ansible/ansiblekey.pub"
The authenticity of host '192.168.2.102 (192.168.2.102)' can't be established.
ED25519 key fingerprint is SHA256:ky4vGlJBVycdHUn8c1a6cxrLcQ3x9aEE22hu0l86ih0.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
ubuntu@192.168.2.102's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'ubuntu@192.168.2.102'"
and check to make sure that only the key(s) you wanted were added.
$
Try logging into the managed node with below command
it will ask for the passphrase set while creating this key pair, please provide
# check connectivity with all managed nodes
ssh -i /home/ubuntu/ansible/ansiblekey ubuntu@<managed-node-ip>
Please note, in this command we are passing private key
output should look like following
$ ssh -i /home/ubuntu/ansible/ansiblekey ubuntu@192.168.2.102
Enter passphrase for key '/home/ubuntu/ansible/ansiblekey':
Welcome to Ubuntu 24.04.1 LTS (GNU/Linux 6.8.0-51-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro
This system has been minimized by removing packages and content that are
not required on a system that users do not log into.
To restore this content, you can run the 'unminimize' command.
Last login: Thu Jan 2 18:01:10 2025 from 192.168.2.100
$
Configure Ansible inventory file
Add managed nodes in ansible inventory file /home/ubuntu/ansible/hosts
Open terminal and add following command to add managed nodes in ansible inventory file
echo "[managed]
ubuntu@192.168.2.101
ubuntu@192.168.2.102" >> /home/ubuntu/ansible/hosts
output should look like following
$ echo "[managed]
> ubuntu@192.168.2.101
> ubuntu@192.168.2.102" >> /home/ubuntu/ansible/hosts
$
Run ssh agent
we need to run ssh agent to supply ssh private key passphrase during ansible execution
run following commands to run ssh agent and cache ssh private key password, please supply correct passphrase in ssh-add command
eval "$(ssh-agent -s)"
ssh-add /home/ubuntu/ansible/ansiblekey
output should look like following
ubuntu@admin:~$ eval "$(ssh-agent -s)"
Agent pid 1336
ubuntu@admin:~$ ssh-add /home/ubuntu/ansible/ansiblekey
Enter passphrase for /home/ubuntu/ansible/ansiblekey:
Identity added: /home/ubuntu/ansible/ansiblekey (ubuntu@admin)
ubuntu@admin:~$
Test connectivity with managed nodes
run ansible ping module as following in terminal to test connectivity
ansible managed -m ping -i /home/ubuntu/ansible/hosts --private-key /home/ubuntu/ansible/ansiblekey
ansible : ansible command
managed : host group name to target from ansible inventory file /home/ubuntu/ansible/hosts
–private-key : private key to be used for this command
output should look like following, we can ignore python warnings in output
$ ansible managed -m ping -i ~/ansible/hosts --private-key /home/ubuntu/ansible/ansiblekey
[WARNING]: Platform linux on host ubuntu@192.168.2.101 is using the discovered Python interpreter at /usr/bin/python3.12, but future installation of another Python interpreter could change the
meaning of that path. See https://docs.ansible.com/ansible-core/2.18/reference_appendices/interpreter_discovery.html for more information.
ubuntu@192.168.2.101 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3.12"
},
"changed": false,
"ping": "pong"
}
[WARNING]: Platform linux on host ubuntu@192.168.2.102 is using the discovered Python interpreter at /usr/bin/python3.12, but future installation of another Python interpreter could change the
meaning of that path. See https://docs.ansible.com/ansible-core/2.18/reference_appendices/interpreter_discovery.html for more information.
ubuntu@192.168.2.102 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3.12"
},
"changed": false,
"ping": "pong"
}
$
Congratulations! we have installed ansible on control node and tested connectivity with managed node using ansible.
Pingback: Installing PostgreSQL using Ansible – RevaSys