Ansible is a configuration management tool maintained by Red Hat. It has to be installed on a controll machine. On the target machine, no configuration is needed. The control machine connects to the target machines via SSH.
Which problem does it solve?
In short: Ansible makes configurations repeatable.
Why this is good:
- Disaster Recovery: You have a web service running on AWS. Your account was hacked and deleted. Having your infrastructure defined as code (IaC), you can re-create all resources with the configuration you had before.
- Site Reliability: Having IaC, you can have code reviews for changes. This helps to reduce human error.
- Scalability: If we want to add more services, it is easier to repeat patterns. So this might help different teams at a company to keep in sync.
In long:
If you have a web service running, you hopefully have the code for that service
under version control (e.g. git
).
Version control helps to keep the same state
everywhere, find the changes (git bisect
(docs) / git blame
),
undo the change (git revert
). So the
version control gives you documentation and archives changes.
However, if you have a web service running, the software is not the only important thing. It has to run somewhere. This means you actually need a physical machine. You don't need to own it / take care about the hardware, but it needs to exist. Suppose you use Amazons Cloud AWS. Then you can use Terraform / AWS CloudFormation to define in code on which kinds of machines it is running. The idea to have this written in code is called Infrastructure as code (IaC). It allows you to have the infrastructure under version control and get the same benefits as were mentioned about version control for code.
Next, you need to configure the machines: Add certificates, SSH keys, LDAP, install Docker. This is where Ansible helps.
You might also want to read a real world example.
Installation
Ansible is written in Python. For this reason, the simplest way to install it
might be via the Python Package installer pip
:
$ pip install ansible
To test if it worked:
$ ansible --version
ansible 2.9.0
config file = None
configured module search path = ['/home/moose/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /home/moose/.local/lib/python3.6/site-packages/ansible
executable location = /home/moose/.local/bin/ansible
python version = 3.6.8 (default, Oct 7 2019, 12:59:55) [GCC 8.3.0]
Vocabulary
- Task
- A task is a command executed on the target machine. A task is a call to an Ansible module.
- Role
- A list of tasks. Every role is a directory below
/roles
and contains a `main.yml` which defines the tasks. - Playbook
- Determines which task/role should be applied to which target machine.
- Facts
- Facts are information derived from speaking with your remote systems.
- Idempotency
- An idempotent operation can be applied multiple times without changing the result beyond the initial application. Basically, it means "repeatable".
- Convergence
- Bring resources to a desired state if they diverge
- Immutability
- Resources are never changed. They are only created and destroyed. (Terraform and CloudFormation work like this)
Usage
Ad hoc command to check the connection:
$ ansible -m ping all
Ad hoc command to get the available disk space:
# ansible -m [module] -a '[module options]' [target]
$ ansible -m shell -a 'df -h' all
Ansible executes stuff with your account. If you need root, specify -b
and
-k
to ask for a password.
The default project structure is:
.
├── playbook.yml
└── roles
├── example-role
│ ├── files
│ │ └── foo.txt
│ └── tasks
│ └── main.yml
└── foo-role
└── tasks
└── main.yml
The main.yml
files have the following structure:
# Choose a descriptive name for the task as ansible will print them when
# executing
- name: Install a list of packages
apt: # The ansible module
pkg: # install the following packages
- foo
- bar
- name: Add some file to the target machines
copy:
src: ../files/foo.txt
dest: /absolute/path/foo.txt
The playbook.yml
file has the following structure:
- hosts: all
become: true # become another user; by default root
You can then execute the playbook via
$ ansible-playbook playbook.yml
Alternatives
Puppet and Chef are two other configuration management tools which are often used.
Where Ansible is push-based, Puppet and Chef are pull-based. So the target machines need to have an agent running which pulls.
See also
- Ben's IT Lessons: Ansible - A Beginner's Tutorial, Part 1 / Part 2, 2017.
- Ansible: List of Ansible Modules
- halfercode on Reddit: Does Docker make Ansible and similar orchestration tools redundant?, 2017.
- Lou Bichard: Configuration Management: What Is It and Why Is It Important?, 2019.