{"id":6234,"date":"2020-06-24T20:45:32","date_gmt":"2020-06-24T17:45:32","guid":{"rendered":"https:\/\/kifarunix.com\/?p=6234"},"modified":"2024-03-14T21:12:21","modified_gmt":"2024-03-14T18:12:21","slug":"install-and-setup-ansible-on-ubuntu-20-04","status":"publish","type":"post","link":"https:\/\/kifarunix.com\/install-and-setup-ansible-on-ubuntu-20-04\/","title":{"rendered":"Install and Setup Ansible on Ubuntu 20.04\/Ubuntu 22.04"},"content":{"rendered":"\n
How to setup Ansible in Ubuntu? In this tutorial, we are going to learn how to install and setup Ansible on Ubuntu 20.04\/Ubuntu 22.04. Ansible<\/a> is a simple agentless IT automation tool. It handles configuration management, application deployment, cloud provisioning, ad-hoc task execution, network automation, and multi-node orchestration over the SSH protocol. Ansible makes complex changes like zero-downtime rolling updates with load balancers easy.<\/p>\n\n\n\n Since Ansible is used to manage remote hosts via SSH protocol, the node on which you install Ansible, becomes the Before you can proceed, ensure that your system package cache is up-to-date;<\/p>\n\n\n\n There different methods you can use to install Ansible on Ubuntu 20.04\/Ubuntu 22.04 systems;<\/p>\n\n\n\n To install Ansbile using Python PIP command, proceed as follows;<\/p>\n\n\n\n Ensure that PIP is available on the system;<\/p>\n\n\n\n Such an output should be printed if PIP is available;<\/p>\n\n\n\n If PIP is available, then you can proceed to install Ansible.<\/p>\n\n\n\n Otherwise, install PIP before you can proceed;<\/p>\n\n\n\n If PIP is already installed, you might want to upgrade it;<\/p>\n\n\n\n With PIP being available on the system, you can install Ansbile for the current user only by running the command below;<\/p>\n\n\n\n All the Ansible binaries are installed in ‘ You can add this path to PATH environment variable temporarily using;<\/p>\n\n\n\n Or load it when you start your shell (if using bash);<\/p>\n\n\n\n Or, you simply install Ansible for system wide users using the command below;<\/p>\n\n\n\n Check Ansible version;<\/p>\n\n\n\n Ubuntu default repos provides Ansible packages. However, such packages may not be up-to-date.<\/p>\n\n\n\n To check available versions of the Ansible package, run the command below;<\/p>\n\n\n\n Sample output from Ubuntu 20.04;<\/p>\n\n\n\n You can as well install Ansible PPA repos that will also provide latest Ansible packages;<\/p>\n\n\n\n You can then install Ansible by executing the command below;<\/p>\n\n\n\n Once the installation is done, you can check the version of install Ansible as follows;<\/p>\n\n\n\n Now that Ansible is installed on an Ubuntu 20.04\/Ubuntu 22.04 control node, it is time to set it up to enable you automate deployment of your tasks on the managed remote hosts via SSH protocol.<\/p>\n\n\n\n An Ansible inventory<\/a> is a file that list or defines the hosts to be managed via Ansible. An inventory file can also be used to store variable values that relate to a specific host or group in inventory.<\/p>\n\n\n\n In the inventory file:<\/p>\n\n\n\n See examples below to create a hosts file with ungrouped hosts, grouped hosts and a range of hosts.<\/p>\n\n\n\n In this tutorial, I will create my inventory in my home directory.<\/p>\n\n\n\n NOTE: Any individual host, (Ungrouped hosts),should be specified before any group headers.<\/strong><\/p>\n\n\n\n Save and exit the file.<\/p>\n\n\n\n You can list the hosts in your inventory using the Read more on how to build ansible inventory<\/a>.<\/p>\n\n\n\n Use of passwordless SSH key authentication is one of the common methods that by default Ansible uses for managing remote hosts. Therefore, you need to generate passwordless SSH key and copy the keys to the remote hosts your want to manage with Ansible.<\/p>\n\n\n\n For passwordless SSH key generation, simply press ENTER for empty password.<\/p>\n\n\n\n Read more about other connection methods on Ansible connection plugins<\/a> page.<\/p>\n\n\n\n Next, copy the keys to the remote hosts. Use a remote user with sudo rights.<\/strong><\/p>\n\n\n\n In this demo, we will be using a user with passwordless sudo rights. To enable a user to run commands with sudo without being prompted for password, run the command below on the remote hosts being managed.<\/p>\n\n\n\n Read more on Ansible privileges escalation page<\/a>.<\/p>\n\n\n\n Ansible uses ping module to verify the reachability to the remote hosts defined on the inventory file. Below is our test inventory;<\/p>\n\n\n\n To test the connection, as user Both 192.168.56.111 and 192.168.56.112 are CentOS 8 servers.<\/strong><\/p>\n\n\n\n If you have tasks that you would rarely repeat, ad-hoc commands come in so handy. With ad-hoc commands, you can manage user accounts, services, packages, run ad-hoc system commands like check free RAM, gather system facts.<\/p>\n\n\n\n To see a few examples, check if the remote systems have internet connectivity using ping command;<\/p>\n\n\n\n To check free memory;<\/p>\n\n\n\n To install a package, for example a vim editor, as user Read more about ad-hoc commands on Introduction to ad-hoc commands<\/a>.<\/p>\n\n\n\n Playbooks are Ansible\u2019s configuration, deployment, and orchestration language. They define roles and tasks (a set of steps to take to set up a specific process) to be executed on the remote hosts.<\/p>\n\n\n\n In this demo, we will cover two simple examples of playbooks;<\/p>\n\n\n\n So before we can proceed, create Ansible roles directory. Ansible Roles defines a collections of variables, tasks, files, templates and any other ansible artefacts.<\/p>\n\n\n\n For our example, we will have two roles, Below is our simple sample Roles directory structure;<\/p>\n\n\n\n To create the relevant directories as per above structure;<\/p>\n\n\n\n Create master playbook, site.yml to define values that will be applicable to all other tasks;<\/p>\n\n\n\n The playbook for creating user account is as per my roles directory structure above. So create a file in which you will define particulars of a user to be created.<\/p>\n\n\n\n Similarly, create task file for installing Apache web server on Ubuntu 20.04 and CentOS 8 systems;<\/p>\n\n\n\n To list master Ansible Playbook tasks;<\/p>\n\n\n\n To check your playbook without making any changes on the remote host, use the Once you have verified that there is not error with the checks above, proceed to execute the playbook;<\/p>\n\n\n\n You can create yet another master playbook to verify if user account for janedoe<\/strong> is created as well as checking is Apache is installed by checking its service if available. Both of these can be checked using Ansible getent module<\/a>.<\/p>\n\n\n\n Execute the playbook;<\/p>\n\n\n\n And there you go.<\/p>\n\n\n\n That marks the end of our tutorial on how to install and setup Ansible on Ubuntu 20.04. We hope this was informative. Enjoy.<\/p>\n\n\n\n Getting Started with Ansible<\/a><\/p>\n\n\n\n Install and Deploy Kubernetes Cluster on Ubuntu 20.04<\/a><\/p>\n\n\n\nInstalling Ansible on Ubuntu 20.04<\/a>\/Ubuntu 22.04<\/h2>\n\n\n\n
control node<\/code><\/strong> and the node which you will manage using Ansible is called
managed hosts<\/code><\/strong>.<\/p>\n\n\n\n
Run System Update<\/h3>\n\n\n\n
sudo apt update<\/code><\/pre>\n\n\n\n
Install Ansible on Ubuntu 20.04<\/a>\/Ubuntu 22.04<\/h3>\n\n\n\n
\n
Install Ansbile using PIP on Ubuntu<\/h4>\n\n\n\n
python3 -m pip -V<\/code><\/pre>\n\n\n\n
pip 22.3.1 from \/usr\/local\/lib\/python3.8\/dist-packages\/pip (python 3.8)<\/code><\/pre>\n\n\n\n
apt install python3-pip<\/code><\/pre>\n\n\n\n
python3 -m pip install --upgrade pip<\/code><\/pre>\n\n\n\n
python3 -m pip install --user ansible<\/code><\/pre>\n\n\n\n
$HOME\/.local\/bin<\/code><\/strong>‘ which is not on PATH.<\/p>\n\n\n\n
export PATH=$PATH:~\/.local\/bin<\/code><\/pre>\n\n\n\n
echo \"export PATH=$PATH:~\/.local\/bin\" >> ~\/.bashrc<\/code><\/pre>\n\n\n\n
source ~\/.bashrc<\/code><\/pre>\n\n\n\n
sudo python3 -m pip install ansible<\/code><\/pre>\n\n\n\n
ansible --version<\/code><\/pre>\n\n\n\n
\nansible [core 2.14.2]\n config file = None\n configured module search path = ['\/home\/kifarunix\/.ansible\/plugins\/modules', '\/usr\/share\/ansible\/plugins\/modules']\n ansible python module location = \/home\/kifarunix\/.local\/lib\/python3.10\/site-packages\/ansible\n ansible collection location = \/home\/kifarunix\/.ansible\/collections:\/usr\/share\/ansible\/collections\n executable location = \/home\/kifarunix\/.local\/bin\/ansible\n python version = 3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0] (\/usr\/bin\/python3)\n jinja version = 3.0.3\n libyaml = True\n<\/code><\/pre>\n\n\n\n
Install Ansible using APT Package Manager<\/h4>\n\n\n\n
sudo apt-cache policy ansible<\/code><\/pre>\n\n\n\n
\nansible:\n Installed: (none)\n Candidate: 2.9.6+dfsg-1\n Version table:\n 2.9.6+dfsg-1 500\n 500 http:\/\/us.archive.ubuntu.com\/ubuntu focal\/universe amd64 Packages\n<\/code><\/pre>\n\n\n\n
apt -y install software-properties-common<\/code><\/pre>\n\n\n\n
sudo apt-add-repository ppa:ansible\/ansible --yes<\/code><\/pre>\n\n\n\n
sudo apt install ansible<\/code><\/pre>\n\n\n\n
ansible --version<\/code><\/pre>\n\n\n\n
Setting up Ansible on Control Node<\/h3>\n\n\n\n
Setup Ansible Inventory<\/a><\/h4>\n\n\n\n
\/etc\/ansible\/hosts<\/code> is the default Ansible inventory file. It is also possible to define a custom file as your Ansible inventory file. When you use a non-default inventory file, you have to specify the path to it with
-i <path><\/strong><\/code> option while running ansible.<\/p>\n\n\n\n
\n
[header]<\/code> elements<\/li>\n\n\n\n
mkdir $HOME\/ansible<\/code><\/pre>\n\n\n\n
vim $HOME\/ansible\/hosts<\/code><\/pre>\n\n\n\n
\n# Ungrouped list of hosts\nserver01.kifarunix-demo.com\n192.168.58.5\n\n# Range of hosts\n192.168.56.[111:112]\n\n[webapps]\napp[01:04].kifarunix-demo.com\n\n# Grouped Hosts\n[database]\ndb[01:03].kifarunix-demo.com\ndb05.kifarunix-demo.com\ndb07.kifarunix-demo.com\n<\/code><\/pre>\n\n\n\n
ansible-inventory<\/code> command. For example, to display the contents of our hosts list above in YAML format;<\/p>\n\n\n\n
ansible-inventory -i $HOME\/ansible\/hosts --list -y<\/code><\/pre>\n\n\n\n
\nall:\n children:\n database:\n hosts:\n db01.kifarunix-demo.com: {}\n db02.kifarunix-demo.com: {}\n db03.kifarunix-demo.com: {}\n db05.kifarunix-demo.com: {}\n db07.kifarunix-demo.com: {}\n ungrouped:\n hosts:\n 192.168.56.111: {}\n 192.168.56.112: {}\n 192.168.58.5: {}\n server01.kifarunix-demo.com: {}\n webapps:\n hosts:\n app01.kifarunix-demo.com: {}\n app02.kifarunix-demo.com: {}\n app03.kifarunix-demo.com: {}\n app04.kifarunix-demo.com: {\n<\/code><\/pre>\n\n\n\n
Setting up Ansible SSH key authentication<\/h3>\n\n\n\n
Generate SSH Keys<\/h4>\n\n\n\n
ssh-keygen<\/code><\/pre>\n\n\n\n
\nGenerating public\/private rsa key pair.\nEnter file in which to save the key (\/home\/koromicha\/.ssh\/id_rsa): \nEnter passphrase (empty for no passphrase): \nEnter same passphrase again: \nYour identification has been saved in \/home\/koromicha\/.ssh\/id_rsa\nYour public key has been saved in \/home\/koromicha\/.ssh\/id_rsa.pub\nThe key fingerprint is:\nSHA256:Ba9LyP0epsCPIVN5nvIVT9zgnLCRL1P\/dmgiAvWjbMc koromicha@koromicha\nThe key's randomart image is:\n+---[RSA 3072]----+\n| . |\n| o . |\n| . * o |\n| . = + X = |\n| * S B B o |\n| o * * B o |\n| o = O E o o +|\n| o O B o o ..|\n| . + . |\n+----[SHA256]-----+\n<\/code><\/pre>\n\n\n\n
Copy the keys to remote hosts<\/h4>\n\n\n\n
for i in 192.168.58.5 192.168.56.111 192.168.56.112; do ssh-copy-id -o StrictHostKeyChecking=no johndoe@$i; done<\/code><\/pre>\n\n\n\n
echo \"johndoe ALL=(ALL:ALL) NOPASSWD: ALL\" > \/etc\/sudoers.d\/johndoe<\/code><\/pre>\n\n\n\n
Test Ansible Connection to Remote Hosts<\/h4>\n\n\n\n
ansible-inventory -i $HOME\/ansible\/demo --list -y<\/code><\/pre>\n\n\n\n
\nall:\n children:\n centos:\n hosts:\n 192.168.56.111: {}\n 192.168.56.112: {}\n ungrouped: {}\n<\/code><\/pre>\n\n\n\n
johndoe<\/code><\/strong>, whose keys we copied above;<\/p>\n\n\n\n
ansible -i $HOME\/ansible\/demo -m ping -u johndoe all<\/code><\/pre>\n\n\n\n
\n192.168.56.111 | SUCCESS => {\n \"ansible_facts\": {\n \"discovered_interpreter_python\": \"\/usr\/libexec\/platform-python\"\n },\n \"changed\": false,\n \"ping\": \"pong\"\n}\n192.168.56.112 | SUCCESS => {\n \"ansible_facts\": {\n \"discovered_interpreter_python\": \"\/usr\/libexec\/platform-python\"\n },\n \"changed\": false,\n \"ping\": \"pong\"\n}\n<\/code><\/pre>\n\n\n\n
Running Ansible ad-hoc commands<\/h3>\n\n\n\n
ansible -i $HOME\/ansible\/demo -a \"ping 8.8.8.8 -c 3\" all -u johndoe<\/code><\/pre>\n\n\n\n
ansible -i $HOME\/ansible\/demo -a \"free -h\" all -u johndoe<\/code><\/pre>\n\n\n\n
\n192.168.56.112 | CHANGED | rc=0 >>\n total used free shared buff\/cache available\nMem: 818Mi 234Mi 196Mi 10Mi 387Mi 444Mi\nSwap: 819Mi 0B 819Mi\n192.168.56.111 | CHANGED | rc=0 >>\n total used free shared buff\/cache available\nMem: 818Mi 230Mi 214Mi 10Mi 373Mi 452Mi\nSwap: 819Mi 0B 819Mi\n<\/code><\/pre>\n\n\n\n
johndoe<\/strong><\/code> with sudo rights (
--become<\/a><\/strong><\/code>);<\/p>\n\n\n\n
ansible -i $HOME\/ansible\/demo -m apt -m yum -a \"name=vim state=present\" all -u johndoe --become<\/code><\/pre>\n\n\n\n
Using Ansible Playbooks<\/h3>\n\n\n\n
\n
useraccount<\/code> and
apache<\/code>, for defining what user account to create and the package to be installed.<\/p>\n\n\n\n
\nmyplaybooks\n\tsite.yml\n\troles\/\n\t useraccounts\n\t\ttasks\/\n main.yml\n\t webserver\/\n\t\ttasks\/\n main.yml\n<\/code><\/pre>\n\n\n\n
mkdir -p myplaybooks\/roles\/{useraccounts\/tasks,webserver\/tasks}<\/code><\/pre>\n\n\n\n
vim myplaybooks\/site.yml<\/code><\/pre>\n\n\n\n
\n---\n#\n# A common Playbook to Create a user accounts.\n#\n- hosts: all \n remote_user: johndoe\n become: yes\n roles:\n - useraccounts\n - webserver\n<\/code><\/pre>\n\n\n\n
Ansible Playbook to Create User Account<\/h4>\n\n\n\n
vim myplaybooks\/roles\/useraccounts\/tasks\/main.yml<\/code><\/pre>\n\n\n\n
\n---\n#\n# Create a user account\n#\n- name: Add User Jane Doe to the system\n user:\n name: janedoe\n password: \"{{ 'strongpassword' | password_hash('sha512') }}\"\n groups: wheel\n shell: \/bin\/bash\n comment: Jane Doe\n expires: 1584993090\n<\/code><\/pre>\n\n\n\n
Ansible Playbook to Install Apache Web server<\/h4>\n\n\n\n
vim myplaybooks\/roles\/webserver\/tasks\/main.yml<\/code><\/pre>\n\n\n\n
\n---\n#\n# Install Apache Web server on CentOS 8\n#\n- name: Install Apache on CentOS 8\n yum:\n name: httpd\n update_cache: yes\n state: latest\n<\/code><\/pre>\n\n\n\n
ansible-playbook myplaybooks\/site.yml --list-tasks -i demo<\/code><\/pre>\n\n\n\n
\nplaybook: myplaybooks\/site.yml\n\n play #1 (all): all\tTAGS: []\n tasks:\n useraccounts : Add User Jane Doe to the system\tTAGS: []\n webserver : Install Apache on CentOS 8\tTAGS: []\n<\/code><\/pre>\n\n\n\n
Running Ansible Playbook Dry Run checks<\/h4>\n\n\n\n
--check<\/code> option.<\/p>\n\n\n\n
ansible-playbook myplaybooks\/site.yml --check -i $HOME\/ansible\/demo<\/code><\/pre>\n\n\n\n
\nPLAY [all] *****************************************************************************************************************************************************************\n\nTASK [Gathering Facts] *****************************************************************************************************************************************************\nok: [192.168.56.112]\nok: [192.168.56.111]\n\nTASK [useraccounts : Add User Jane Doe to the system] **********************************************************************************************************************\nchanged: [192.168.56.112]\nchanged: [192.168.56.111]\n\nTASK [webserver : Install Apache on CentOS 8] ******************************************************************************************************************************\nchanged: [192.168.56.111]\nchanged: [192.168.56.112]\n\nPLAY RECAP *****************************************************************************************************************************************************************\n192.168.56.111 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 \n192.168.56.112 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0\n<\/code><\/pre>\n\n\n\n
Executing Ansible Playbook<\/h4>\n\n\n\n
ansible-playbook myplaybooks\/site.yml -i $HOME\/ansible\/demo<\/code><\/pre>\n\n\n\n
\nPLAY [all] *****************************************************************************************************************************************************************\n\nTASK [Gathering Facts] *****************************************************************************************************************************************************\nok: [192.168.56.112]\nok: [192.168.56.111]\n\nTASK [useraccounts : Add User Jane Doe to the system] **********************************************************************************************************************\nchanged: [192.168.56.111]\nchanged: [192.168.56.112]\n\nTASK [webserver : Install Apache on CentOS 8] ******************************************************************************************************************************\nchanged: [192.168.56.111]\nchanged: [192.168.56.112]\n\nPLAY RECAP *****************************************************************************************************************************************************************\n192.168.56.111 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 \n192.168.56.112 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 \n<\/code><\/pre>\n\n\n\n
Verify User Account Creation and Package installed using Ansible<\/a><\/h4>\n\n\n\n
vim myplaybooks\/check.yml<\/code><\/pre>\n\n\n\n
\n---\n- hosts: centos\n remote_user: johndoe\n become: yes\n gather_facts: no # or it will fail on the setup step\n tasks:\n - name: Check if user Jane Doe (janedoe) is created.\n getent:\n database: passwd\n key: janedoe\n - name: Check if Apache service exists.\n getent:\n database: services\n key: http\n<\/code><\/pre>\n\n\n\n
ansible-playbook myplaybooks\/check.yml -i $HOME\/ansible\/demo<\/code><\/pre>\n\n\n\n
\nPLAY [centos] **************************************************************************************************************************************************************\n\nTASK [Check if user Jane Doe (janedoe) is created.] ************************************************************************************************************************\nok: [192.168.56.112]\nok: [192.168.56.111]\n\nTASK [Check if Apache service exists.] *************************************************************************************************************************************\nok: [192.168.56.112]\nok: [192.168.56.111]\n\nPLAY RECAP *****************************************************************************************************************************************************************\n192.168.56.111 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 \n192.168.56.112 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0\n<\/code><\/pre>\n\n\n\n
Further Reading<\/h3>\n\n\n\n
Other Tutorials<\/h3>\n\n\n\n