TL;DR

export ANSIBLE_VERSION=x.x.x

mkdir -p ~/ansible_venv
cd ~/ansible_venv
python3 -m venv ansible${ANSIBLE_VERSION}
source ansible${ANSIBLE_VERSION}/bin/activate
pip install --upgrade pip setuptools
pip install ansible==${ANSIBLE_VERSION} ansible-lint netaddr pbr hvac jmespath passlib bcrypt
. ~/ansible_venv/ansible${ANSIBLE_VERSION}/bin/activate

Long story

Install python3-venv package:

sudo apt install python3-venv

Create an ~/ansible_venv directory:

mkdir ~/ansible_venv

From ~/ansible_venv directory, create your virtual ansible environment:

e.g for ansible 2.9.16:

python3 -m venv ansible2.9.16

Once this environment created, activate it:

source ansible2.9.16/bin/activate

You will see your shell has changed, with name of virtualenv you are currently using.

(ansible2.9.16) $

Currently, this environment has no modules installed. The first thing we will want to do is upgrade pip and setuptools.

pip install --upgrade pip setuptools

We can now install ansible with some other modules:

pip install ansible==2.9.16 ansible-lint netaddr pbr hvac jmespath passlib bcrypt

You can check you are using the correct ansible with which command:

(ansible2.9.16) $ which ansible
/home/jc/ansible_venv/ansible2.9.16/bin/ansible
(ansible2.9.16) $ ansible --version
ansible 2.9.16
  config file = None
  configured module search path = ['/home/jc/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/jc/ansible_venv/ansible2.9.16/lib/python3.8/site-packages/ansible
  executable location = /home/jc/ansible_venv/ansible2.9.16/bin/ansible
  python version = 3.8.6 (default, Sep 25 2020, 09:36:53) [GCC 10.2.0]

To quit a python virtualenv, just execute the deactivate command.