- The following commands are for RockyLinux, RedHat, CentOS, on other distros it will be almost the same.
- I’ve made the choice to connect to a user called ansible, and inside his home directory I’ve created a directory called ansible, in which I will initiate the virtual environment via pipenv (you should have read https://nicodevlog.com/2022/05/17/python-and-virtual-environments-on-linux-os/)
Introduction: python and ansible
Ansible has been written in python language and require python to be executed. It means that on your target hosts you need python installed. Any ansible operation requires python on the target node except the
Also, most of ansible modules are written in python and also need python on the OS.
Ansible-core vs Ansible community
Since ansible 2.9, ansible distinguish ansible-core from ansible community.
Later in this post, when you will execute pipenv install ansible (or pip install ansible in case you use pip), you will install ansible community which includes:
- ansible-core (the command line interface tool + builtin plugins and modules)
- thousands of plugins and modules (grouped by collections)
As you understand ansible community (or if you prefer ‘ansible’) contains ansible-core plus thousands of plugin and modules.
Ansible-core allow to developers to only work on the heart of ansible, and it’s easily maintanable because you can make merges only on ansible-core in case of corrections/evolutions. Also, it could be used to have only a set of plugins and modules that are useful for you, and then have a light installation.
Ansible-core contains a minimal amount of plugins and modules, you can see all the modules and plugins contained in the ansible-core here (it’s the ansible.builtin collection): https://docs.ansible.com/ansible/latest/collections/ansible/builtin/index.html
If you want to refer to the distinct documentations of ansible-core and ansibile community just go to the home page https://docs.ansible.com and choose the one you want to dive into.
- See the interesting Q&A from RedHat about the changes from 2.9 and prior, to 3.0.0 and later
- the ansible community package has a semantic versioning, it’s not the case of ansible-core.
Installing ansible 5 inside python virual environment
First you need to have a recent version of python avaible on your server.
Refer to the following post to install python 3.10.4 on your Linux OS and to understand how to create virtual environment in python: https://nicodevlog.com/2022/05/17/python-and-virtual-environments-on-linux-os/
To see which version of ansible community package is available to install you can go to pypi (python package installer), and type “ansible” and you’ll find this.
At the time of this writing, the version is ansible 5.8.0 (avaible since the 18th of may 2022)
Suppose you are a root user (or a sudo user):
yum -y install sshpass # sshpass is used by ansible in cases you define a ssh connection with login and password pip3.10 install pipenv useradd ansible # and set your ansible password su - ansible mkdir ansible cd ansible pipenv --python 3.10 # create a virtual environment that uses python 3.10.x pipenv install ansible # install python inside the virtual environment
[ansible@ansible ansible]$ pipenv run ansible --version ansible [core 2.12.5] config file = None configured module search path = ['/home/ansible/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules'] ansible python module location = /home/ansible/.local/share/virtualenvs/ansible-ZNHM7g56/lib/python3.10/site-packages/ansible ansible collection location = /home/ansible/.ansible/collections:/usr/share/ansible/collections executable location = /home/ansible/.local/share/virtualenvs/ansible-ZNHM7g56/bin/ansible python version = 3.10.4 (main, May 16 2022, 10:31:24) [GCC 8.5.0 20210514 (Red Hat 8.5.0-4)] jinja version = 3.1.2 libyaml = True [ansible@ansible ansible]$ ls Pipfile Pipfile.lock
Ansible quick start
First create an inventory file in order to reference the ansible target nodes. In this example we will use a basic authentication with login and password to linux and windows machines. Note that for windows machines you’ll need winrm installed.
But there are better ways to connect to your hosts like with ssh keys for linux, and the equivalent of ssh keys with kerberos configured on your windows hosts.
For example here a simple inventory that you call hosts.yml and put something like this:
# Here you list all your connections web1 ansible_host=web1.yourdomain.com ansible_connection=ssh ansible_user=web1login ansible_ssh_pass=web1password web2 ansible_host=web2.yourdomain.com ansible_connection=ssh ansible_user=web2login ansible_ssh_pass=web2password web3 ansible_host=web3.yourdomain.com ansible_connection=ssh ansible_user=web3login ansible_ssh_pass=web3password web4 ansible_host=web4.yourdomain.com ansible_connection=winrm ansible_user=web4login ansible_ssh_pass=web4password api1 ansible_host=api1.yourdomain.com ansible_connection=ssh ansible_user=api1login ansible_ssh_pass=api1password # [web] allow you to group/tag your hosts [web] web1 ansible_host=web1.yourdomain.com ansible_connection=ssh ansible_user=web1login ansible_ssh_pass=web1password web2 ansible_host=web2.yourdomain.com ansible_connection=ssh ansible_user=web2login ansible_ssh_pass=web2password web3 ansible_host=web3.yourdomain.com ansible_connection=ssh ansible_user=web3login ansible_ssh_pass=web3password web4 ansible_host=web4.yourdomain.com ansible_connection=winrm ansible_user=web4login ansible_ssh_pass=web4password [notweb] api1 ansible_host=api1.yourdomain.com ansible_connection=ssh ansible_user=api1login ansible_ssh_pass=api1password [mylinux] web1 ansible_host=web1.yourdomain.com ansible_connection=ssh ansible_user=web1login ansible_ssh_pass=web1password web2 ansible_host=web2.yourdomain.com ansible_connection=ssh ansible_user=web2login ansible_ssh_pass=web2password web3 ansible_host=web3.yourdomain.com ansible_connection=ssh ansible_user=web3login ansible_ssh_pass=web3password api1 ansible_host=api1.yourdomain.com ansible_connection=ssh ansible_user=api1login ansible_ssh_pass=api1password [mywin] web4 ansible_host=web4.yourdomain.com ansible_connection=winrm ansible_user=web4login ansible_ssh_pass=web4password
You can test your hosts.yml by usind the builtin module ping (present inside ansible-core). For example here we ping the host referenced as web1 inside our inventory hosts.yml:
pipenv run ansible -i ./hosts.yml -m ping web1
To avoid specifying each time where is located your inventory, with the option -i, you can create an ansible configuration file named ansible.cfg
When you are inside your project directory, where you’ve executed pipenv to create the virtual environment, create an ansible.cfg file in which you will specify. You’ll then will have:
[ansible@ansible ansible]$ ls ansible.cfg hosts.yml Pipfile Pipfile.lock
By default ansible will look for this file and read it if present, ansible will search in this order:
- ANSIBLE_CONFIG (an environment variable)
- Current directory
- Ansible Home directory
Then in my case I’m connected to the user ansible, and in his home directory I’ve created a directory ansible inside which I’ve initiated the virtual environment. The for ansible the current directory is /home/ansible/ansible
Inside this file you also have to specify host_key_checking = false to avoir the error that indicated that you ansible server doesn’t know the target host (it means the finger print of the target host is not inside the ~/.ssh/known_hosts file):
[defaults] host_key_checking = false inventory = ./hosts.yml
Avoid use ssh connection on a root user
For several security reasons, you should instead connect to a sudo user if you need some root permissions:
- On the target host you’ll be able to make the distinction between root user and the sudo user used by ansible (history, process started by, …)
- you can define fine-grained permissions to your sudo user