vagrant/website/docs/source/v2/provisioning/ansible_intro.html.md

214 lines
8.7 KiB
Markdown

---
page_title: "Ansible - Short Introduction"
sidebar_current: "provisioning-ansible-intro"
---
# Ansible and Vagrant
The information below is applicable to both Ansible provisioners:
- [`ansible`](/v2/provisioning/ansible.html), where Ansible is executed on the **Vagrant host**
- [`ansible_local`](/v2/provisioning/ansible_local.html), where Ansible is executed on the **Vagrant guest**
The list of common options for these two provisioners is documented in a [separate documentation page](/v2/provisioning/ansible_common.html).
This documentation page will not go into how to use Ansible or how to write Ansible playbooks, since Ansible is a complete deployment and configuration management system that is beyond the scope of Vagrant documentation.
To learn more about Ansible, please consult the [Ansible Documentation Site](http://docs.ansible.com/).
## The Playbook File
The first component of a successful Ansible provisioner setup is the Ansible playbook which contains the steps that should be run on the guest. Ansible's
[playbook documentation](http://docs.ansible.com/playbooks.html) goes into great detail on how to author playbooks, and there are a number of [best practices](http://docs.ansible.com/playbooks_best_practices.html) that can be applied to use Ansible's powerful features effectively.
A playbook that installs and starts (or restarts) the NTP daemon via YUM looks like:
```
---
- hosts: all
tasks:
- name: ensure ntpd is at the latest version
yum: pkg=ntp state=latest
notify:
- restart ntpd
handlers:
- name: restart ntpd
service: name=ntpd state=restarted
```
You can of course target other operating systems that don't have YUM by changing the playbook tasks. Ansible ships with a number of [modules](http://docs.ansible.com/modules.html) that make running otherwise tedious tasks dead simple.
### Running Ansible
The `playbook` option is strictly required by both Ansible provisioners ([`ansible`](/v2/provisioning/ansible.html) and [`ansible_local`](/v2/provisioning/ansible_local.html)), as illustrated in this basic Vagrantfile` configuration:
```ruby
Vagrant.configure(2) do |config|
# Use :ansible or :ansible_local to
# select the provisioner of your choice
config.vm.provision :ansible do |ansible|
ansible.playbook = "playbook.yml"
end
end
```
Since an Ansible playbook can include many files, you may also collect the related files in a [directory structure](http://docs.ansible.com/playbooks_best_practices.html#directory-layout) like this:
```
.
|-- Vagrantfile
|-- provisioning
| |-- group_vars
| |-- all
| |-- roles
| |-- bar
| |-- foo
| |-- playbook.yml
```
In such an arrangement, the `ansible.playbook` path should be adjusted accordingly:
```ruby
Vagrant.configure(2) do |config|
config.vm.provision "ansible" do |ansible|
ansible.playbook = "provisioning/playbook.yml"
end
end
```
## The Inventory File
When using Ansible, it needs to know on which machines a given playbook should run. It does this by way of an [inventory](http://docs.ansible.com/intro_inventory.html) file which lists those machines. In the context of Vagrant, there are two ways to approach working with inventory files.
### Auto-Generated Inventory
The first and simplest option is to not provide one to Vagrant at all. Vagrant will generate an inventory file encompassing all of the virtual machines it manages, and use it for provisioning machines.
**Example with the [`ansible`](/v2/provisioning/ansible.html) provisioner:**
```
# Generated by Vagrant
default ansible_ssh_host=127.0.0.1 ansible_ssh_port=2200 ansible_ssh_user='vagrant' ansible_ssh_private_key_file='/home/.../.vagrant/machines/default/virtualbox/private_key'
```
Note that the generated inventory file is stored as part of your local Vagrant environment in
`.vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory`.
**Example with the [`ansible_local`](/v2/provisioning/ansible_local.html) provisioner:**
```
# Generated by Vagrant
default ansible_connection=local
```
Note that the generated inventory file is uploaded to the guest VM in a subdirectory of [`tmp_path`](/v2/provisioning/ansible_local.html), e.g. `/tmp/vagrant-ansible/inventory/vagrant_ansible_local_inventory`.
**How to generate Inventory Groups:**
The [`groups`](/v2/provisioning/ansible_common.html) option can be used to pass a hash of group names and group members to be included in the generated inventory file. It is also possible to specify [group variables](http://docs.ansible.com/ansible/intro_inventory.html#group-variables).
With this configuration example:
```
Vagrant.configure(2) do |config|
config.vm.box = "ubuntu/trusty64"
config.vm.define "machine1"
config.vm.define "machine2"
config.vm.provision "ansible" do |ansible|
ansible.playbook = "playbook.yml"
ansible.groups = {
"group1" => ["machine1"],
"group2" => ["machine2"],
"all_groups:children" => ["group1", "group2"],
"group1:vars" => {"variable1" => 9,
"variable2" => "example"}
}
end
end
```
Vagrant would generate an inventory file that might look like:
```
# Generated by Vagrant
machine1 ansible_ssh_host=127.0.0.1 ansible_ssh_port=2200 ansible_ssh_user='vagrant' ansible_ssh_private_key_file='/home/.../.vagrant/machines/machine1/virtualbox/private_key'
machine2 ansible_ssh_host=127.0.0.1 ansible_ssh_port=2222 ansible_ssh_user='vagrant' ansible_ssh_private_key_file='/home/.../.vagrant/machines/machine2/virtualbox/private_key'
[group1]
machine1
[group2]
machine2
[all_groups:children]
group1
group2
[group1:vars]
variable1=9
variable2=example
```
**Notes:**
- Prior to Vagrant 1.7.3, the `ansible_ssh_private_key_file` variable was not set in generated inventory, but passed as command line argument to `ansible-playbook` command.
- The generation of group variables blocks (e.g. `[group1:vars]`) is only possible since Vagrant ???. Note however that setting variables directly in the inventory is not the [preferred practice in Ansible](http://docs.ansible.com/intro_inventory.html#splitting-out-host-and-group-specific-data). If possible, group (or host) variables should be set in `YAML` files stored in the `group_vars/` or `host_vars/` directories in the playbook (or inventory) directory instead.
- Unmanaged machines and undefined groups are not added to the inventory, to avoid useless Ansible errors (e.g. *unreachable host* or *undefined child group*)
For example, `machine3` and `group3` in the example below would not be added to the generated inventory file:
```
ansible.groups = {
"group1" => ["machine1"],
"group2" => ["machine2", "machine3"],
"all_groups:children" => ["group1", "group2", "group3"]
}
```
### Static Inventory
The second option is for situations where you'd like to have more control over the inventory management.
With the `inventory_path` option, you can reference a specific inventory resource (e.g. a static inventory file, a [dynamic inventory script](http://docs.ansible.com/intro_dynamic_inventory.html) or even [multiple inventories stored in the same directory](http://docs.ansible.com/intro_dynamic_inventory.html#using-multiple-inventory-sources)). Vagrant will then use this inventory information instead of generating it.
A very simple inventory file for use with Vagrant might look like:
```
default ansible_ssh_host=192.168.111.222
```
Where the above IP address is one set in your Vagrantfile:
```
config.vm.network :private_network, ip: "192.168.111.222"
```
**Notes:**
- The machine names in `Vagrantfile` and `ansible.inventory_path` files should correspond, unless you use `ansible.limit` option to reference the correct machines.
- The SSH host addresses (and ports) must obviously be specified twice, in `Vagrantfile` and `ansible.inventory_path` files.
- Sharing hostnames across Vagrant host and guests might be a good idea (e.g. with some Ansible configuration task, or with a plugin like [`vagrant-hostmanager`](https://github.com/smdahlen/vagrant-hostmanager)).
### The Ansible Configuration File
Certain settings in Ansible are (only) adjustable via a [configuration file](http://docs.ansible.com/intro_configuration.html), and you might want to ship such a file in your Vagrant project.
When shipping an Ansible configuration file it is good to know that:
- it is possible to reference an Ansible configuration file via `ANSIBLE_CONFIG` environment variable, if you want to be flexible about the location of this file.
- `ansible-playbook` **never** looks for `ansible.cfg` in the directory that contains the main playbook file.
- As of Ansible 1.5, the lookup order is the following:
- `ANSIBLE_CONFIG` an environment variable
- `ansible.cfg` in the runtime current directory
- `.ansible.cfg` in the user home directory
- `/etc/ansible/ansible.cfg`