Difference between revisions of "Ansible"

From ArchWiki
Jump to navigation Jump to search
(Playbook: Fix YAML and make more Ansible-like; style & grammar)
 
(78 intermediate revisions by 6 users not shown)
Line 1: Line 1:
 
[[Category:System administration]]
 
[[Category:System administration]]
 
[[ja:Ansible]]
 
[[ja:Ansible]]
From [http://docs.ansible.com/ docs.ansible.com]:
+
From [https://www.ansible.com/how-ansible-works www.ansible.com]:
  
::''Ansible is an IT automation tool. It can configure systems, deploy software, and orchestrate more advanced IT tasks such as continuous deployments or zero downtime rolling updates.''
+
:Ansible is a radically simple IT automation engine that automates cloud provisioning, configuration management, application deployment, intra-service orchestration, and many other IT needs.
  
 
== Installation ==
 
== Installation ==
  
On the control machine (server, master), [[Install]] the {{Pkg|ansible}} package.  
+
On the control machine (master), [[install]] the {{Pkg|ansible}} package. {{Pkg|python}} is a dependency of the package and is required on the master.
  
On the managed machines (clients, slaves), where you want to automate deployment or configuration tasks, install {{Pkg|python2}} and {{Pkg|openssh}}.  (Or you can use {{Pkg|python}} instead of {{Pkg|python2}}, but Python 3 support in Ansible is currently experimental.)
+
On the managed machines (nodes), where you want to automate deployment or configuration tasks, {{Pkg|python}} is required and it may be necessary to indicate the specific [[#Python binary location]] in some circumstances.
 +
A way to communicate with the node is also necessary, this is usually [[SSH]]. Note that a functioning [[SSH_keys#Copying_the_public_key_to_the_remote_server|SSH key]] setup eases the use of Ansible but is not required.
  
Note that a functioning [[SSH_keys#Copying_the_public_key_to_the_remote_server|SSH key]] setup makes the use of Ansible much more frictionless (but this is not required).
+
== Basic usage ==
 +
=== Configuration ===
 +
Ansible parameters are set in the configuration file which can either be {{ic|ansible.cfg}} in the current directory,  {{ic|.ansible.cfg}} in the home directory or {{ic|/etc/ansible/ansible.cfg}}, whichever it finds first.
 +
 
 +
A template is available at [https://raw.githubusercontent.com/ansible/ansible/devel/examples/ansible.cfg GitHub example ansible.cfg].
  
== Basic usage ==
 
 
=== Inventory ===
 
=== Inventory ===
According to the default settings in {{ic|/etc/ansible/ansible.cfg}}, one can define its infrastructure in {{ic|/etc/ansible/hosts}}. For instance, the following inventory defines a tiny cluster with three nodes:
+
The infrastructure is listed in the Ansible inventory file, which defaults to being saved in the location {{ic|/etc/ansible/hosts}} or one can specify a different inventory file using the {{ic|-i}} command line switch. For instance, the following inventory defines a cluster with 7 nodes organized into two groups:
{{hc|/etc/ansible/hosts|
+
{{hc|/etc/ansible/hosts|2=
 
[control]
 
[control]
 
192.168.12.1
 
192.168.12.1
 +
foo-[a:c].example.org
 +
localhost ansible_connection=local
  
 
[managed]
 
[managed]
 
192.168.12.2
 
192.168.12.2
192.168.12.3
+
192.168.12.3}}
}}
+
 
 +
One can assign specific attributes to every node in the infrastructure file at the corresponding line or in the {{ic|ansible.cfg}} configuration file.
 +
By default Ansible executes playbooks over SSH, the {{ic|ansible_connection}} parameter extends the connection to:
 +
* {{ic|local}} to deploy the playbook to the control machine itself
 +
* {{ic|docker}} deploys the playbook directly into Docker containers
  
One can assign specific attributes to every node in the file.  Check [http://docs.ansible.com/ansible/latest/intro_inventory.html the official document] for details.
+
Check [http://docs.ansible.com/ansible/latest/intro_inventory.html Ansible - intro inventory] for details.
  
 
=== Ping ===
 
=== Ping ===
Line 49: Line 59:
 
Then, run the playbook script:
 
Then, run the playbook script:
  
  # ansible-playbook syu.yml
+
  $ ansible-playbook --ask-become-pass syu.yml
 +
 
 +
=== Vault ===
 +
A [http://docs.ansible.com/ansible/latest/playbooks_vault.html#using-vault-in-playbooks vault] can be used to keep sensitive data in an encrypted form in playbooks or roles, rather than in plaintext.
 +
The vault password can be stored in plaintext in a file, for example {{ic|''vault_pass.txt''}} containing {{ic|''myvaultpassword''}}, to be used later on as a command parameter:
 +
 
 +
$ ansible-playbook ''site.yml'' --vault-id ''vault_pass.txt''
 +
 
 +
In order to encrypt the content {{ic|''the var content''}} of a variable named {{ic|''varname''}} using the password stored in {{ic|''vault_pass.txt''}}, the following command should be used:
 +
 
 +
$ ansible-vault encrypt_string --vault-id ''vault_pass.txt'' '<i>the var content</i>' --name ''varname''
 +
 
 +
More securely, to avoid inputting the variable content in the command line and be prompted for it instead, one can use:
 +
 
 +
{{hc|$ ansible-vault encrypt_string --vault-id ''vault_pass.txt'' --stdin-name ''varname''|Reading plaintext input from stdin. (ctrl-d to end input)}}
 +
 
 +
The command returns directly the protected variable that can be inserted into a playbook. Encrypted and non-encrypted variables can coexist in a YAML file as illustrated below:
 +
{{bc|notsecret: myvalue
 +
 
 +
mysecret: !vault {{!}}
 +
          $ANSIBLE_VAULT;1.1;AES256
 +
          66386439653236336462626566653063336164663966303231363934653561363964363833313662
 +
          6431626536303530376336343832656537303632313433360a626438346336353331386135323734
 +
          62656361653630373231613662633962316233633936396165386439616533353965373339616234
 +
          3430613539666330390a313736323265656432366236633330313963326365653937323833366536
 +
          3462
 +
 
 +
other_not_secret: othervalue}}
 +
 
 +
=== Package management ===
 +
==== Official repositories ====
 +
Ansible has a [http://docs.ansible.com/ansible/latest/pacman_module.html pacman module] to handle installation, removal and system upgrades with [[pacman]].
 +
 
 +
==== AUR ====
 +
For the [[Arch User Repository]] ''(AUR)'', an external module is required:
 +
{{App|ansible-aur|Ansible module to install packages from the AUR|https://github.com/kewlfft/ansible-aur|{{aur|ansible-aur-git}}}}
 +
 
 +
While Ansible expects to ssh as root, AUR helpers do not allow executing operations as root, they all fail with "you cannot perform this operation as root". For Ansible automation, it is therefore recommended to create a user, for example named ''aur_builder'', that has no need for password with pacman in [[sudoers]]. This can be done in Ansible with the following actions:
 +
{{hc|task.yml|2=
 +
- user: name=''aur_builder''
 +
 
 +
- lineinfile:
 +
    path: /etc/sudoers.d/''aur_builder-allow-to-sudo-pacman''
 +
    state: present
 +
    line: "''aur_builder'' ALL=(ALL) NOPASSWD: /usr/bin/pacman"
 +
    validate: /usr/sbin/visudo -cf %s
 +
    create: yes}}
 +
 
 +
Then, AUR helpers or [[makepkg]] can be used associated with the Ansible parameters {{ic|become: yes}} and {{ic|become_user: aur_builder}}
  
 
== Tips and tricks ==
 
== Tips and tricks ==
=== Telling Ansible where Python is located ===
+
=== User account creation ===
 +
Ansible can manage user accounts and in particular it is able to create new ones. This is achieved in playbooks with the [http://docs.ansible.com/ansible/latest/user_module.html user module] which takes an optional {{ic|password}} argument to set the user's password. It is the '''hashed value of the password''' that needs to be provided to the module.
 +
The hashing can simply be performed on the fly within Ansible using one of its internal [http://docs.ansible.com/ansible/latest/playbooks_filters.html#hash-filters hash-filters]:
  
Ansible requires [[Python]] on the target machine, Python 3 is supported as a preview [https://docs.ansible.com/ansible/python_3_support.html] but might not work for all modules. By default Ansible assumes it can find a {{ic|/usr/bin/python}} on your remote system that is a 2.X or 3.X version of Python, specifically 2.4 or higher.
+
- user:
 +
  name: ''user_name''
 +
  password: "<nowiki>{{</nowiki> '<i>user_password</i>' | password_hash('sha512', '<i>mypermsalt</i>') }}"
 +
  shell: /usr/bin/nologin
  
If some of your modules requires Python 2 you need to tell Ansible where to find Python 2 by setting the {{ic|ansible_python_interpreter}} variable in your Ansible inventory file. This can be done succinctly by using host groups in the inventory:
+
{{Tip|The salt should be fixed and explicitly supplied as a second parameter of the hash function for the operation to be idempotent (can be repeated without changing the state of the system).}}
  
{{hc|Inventory file|
+
With this approach it is recommended to vault-encrypt ''user_password'' so that it does not appear in plain text, see [[#Vault]]. However, an encrypted variable cannot be piped directly and will first need to be assigned to another one that will be piped.
 +
 
 +
Alternatively, the hashing can be performed outside Ansible. The following commands return respectively the [[Wikipedia:MD5|MD5]] and the [[Wikipedia:SHA-2|SHA512]] hashed values of ''user_password'':
 +
 
 +
$ openssl passwd -1 ''user_password''
 +
 
 +
$ python -c 'import crypt; print(crypt.crypt("''user_password''", crypt.mksalt(crypt.METHOD_SHA512)))'
 +
 
 +
=== Python binary location ===
 +
 
 +
Ansible requires [[Python]] on the target machine. By default Ansible assumes it can find a {{ic|/usr/bin/python}} on the remote system that is a 2.X or 3.X version, specifically 2.6 or higher.
 +
 
 +
If some of your modules specifically require Python2, you need to inform Ansible about its location by setting the {{ic|ansible_python_interpreter}} variable in the inventory file. This can be done by using host groups in the inventory:
 +
 
 +
{{hc|/etc/ansible/hosts|2=
 
[archlinux]
 
[archlinux]
 
server1
 
server1
Line 67: Line 144:
  
 
[archlinux:vars]
 
[archlinux:vars]
ansible_python_interpreter<nowiki>=</nowiki>/usr/bin/python2
+
ansible_python_interpreter=/usr/bin/python2
 
}}
 
}}
  
More information this is available in [https://docs.ansible.com/ansible/python_3_support.html], [http://docs.ansible.com/faq.html#how-do-i-handle-python-pathing-not-having-a-python-2-x-in-usr-bin-python-on-a-remote-machine] and [http://docs.ansible.com/intro_inventory.html#list-of-behavioral-inventory-parameters].
+
More information about Python version support in Ansible is available in [https://docs.ansible.com/ansible/python_3_support.html], [http://docs.ansible.com/faq.html#how-do-i-handle-python-pathing-not-having-a-python-2-x-in-usr-bin-python-on-a-remote-machine] and [http://docs.ansible.com/intro_inventory.html#list-of-behavioral-inventory-parameters].
 +
 
 +
== Troubleshooting ==
 +
=== Unarchive ===
 +
The {{ic|unarchive}} module unpacks an archive. However ''tar'' files are not well supported and several outstanding issues are reported in [https://github.com/ansible/ansible/labels/unarchive GitHub - unarchive].
 +
In particular when the parameter {{ic|keep_newer}} is set to {{ic|yes}}, idempotence is not observed. In case you face an issue with the module, you can use instead the ''zip'' format which is better integrated in ansible.
  
 
== See also ==
 
== See also ==
* [https://www.ansible.com/quick-start-video Ansible concept in 12 minutes]
+
* https://www.ansible.com/quick-start-video - Ansible concept in 12 minutes
* [http://docs.ansible.com/ansible/latest/pacman_module.html pacman module details]
+
* http://docs.ansible.com/ansible/latest/pacman_module.html - pacman module official documentation

Latest revision as of 16:50, 13 October 2018

From www.ansible.com:

Ansible is a radically simple IT automation engine that automates cloud provisioning, configuration management, application deployment, intra-service orchestration, and many other IT needs.

Installation

On the control machine (master), install the ansible package. python is a dependency of the package and is required on the master.

On the managed machines (nodes), where you want to automate deployment or configuration tasks, python is required and it may be necessary to indicate the specific #Python binary location in some circumstances. A way to communicate with the node is also necessary, this is usually SSH. Note that a functioning SSH key setup eases the use of Ansible but is not required.

Basic usage

Configuration

Ansible parameters are set in the configuration file which can either be ansible.cfg in the current directory, .ansible.cfg in the home directory or /etc/ansible/ansible.cfg, whichever it finds first.

A template is available at GitHub example ansible.cfg.

Inventory

The infrastructure is listed in the Ansible inventory file, which defaults to being saved in the location /etc/ansible/hosts or one can specify a different inventory file using the -i command line switch. For instance, the following inventory defines a cluster with 7 nodes organized into two groups:

/etc/ansible/hosts
[control]
192.168.12.1
foo-[a:c].example.org
localhost ansible_connection=local

[managed]
192.168.12.2
192.168.12.3

One can assign specific attributes to every node in the infrastructure file at the corresponding line or in the ansible.cfg configuration file. By default Ansible executes playbooks over SSH, the ansible_connection parameter extends the connection to:

  • local to deploy the playbook to the control machine itself
  • docker deploys the playbook directly into Docker containers

Check Ansible - intro inventory for details.

Ping

You may check if all the nodes listed in the inventory are alive by

$ ansible all -m ping

Playbook

Playbooks are the main organizational unit to configure and deploy the whole infrastructure. Check the official document for more details. Here is an extremely simple demonstration, where the administrator of the above inventory wants to perform a full system upgrade on a set of Arch Linux hosts. First, create a playbook file, with YAML formatting (always 2 spaces indentation):

syu.yml
---
- name: All hosts up-to-date
  hosts: control managed
  become: yes
  
  tasks:
    - name: full system upgrade
      pacman:
        update_cache: yes
        upgrade: yes

Then, run the playbook script:

$ ansible-playbook --ask-become-pass syu.yml

Vault

A vault can be used to keep sensitive data in an encrypted form in playbooks or roles, rather than in plaintext. The vault password can be stored in plaintext in a file, for example vault_pass.txt containing myvaultpassword, to be used later on as a command parameter:

$ ansible-playbook site.yml --vault-id vault_pass.txt

In order to encrypt the content the var content of a variable named varname using the password stored in vault_pass.txt, the following command should be used:

$ ansible-vault encrypt_string --vault-id vault_pass.txt 'the var content' --name varname

More securely, to avoid inputting the variable content in the command line and be prompted for it instead, one can use:

$ ansible-vault encrypt_string --vault-id vault_pass.txt --stdin-name varname
Reading plaintext input from stdin. (ctrl-d to end input)

The command returns directly the protected variable that can be inserted into a playbook. Encrypted and non-encrypted variables can coexist in a YAML file as illustrated below:

notsecret: myvalue

mysecret: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          66386439653236336462626566653063336164663966303231363934653561363964363833313662
          6431626536303530376336343832656537303632313433360a626438346336353331386135323734
          62656361653630373231613662633962316233633936396165386439616533353965373339616234
          3430613539666330390a313736323265656432366236633330313963326365653937323833366536
          3462

other_not_secret: othervalue

Package management

Official repositories

Ansible has a pacman module to handle installation, removal and system upgrades with pacman.

AUR

For the Arch User Repository (AUR), an external module is required: ansible-aur — Ansible module to install packages from the AUR

https://github.com/kewlfft/ansible-aur || ansible-aur-gitAUR

While Ansible expects to ssh as root, AUR helpers do not allow executing operations as root, they all fail with "you cannot perform this operation as root". For Ansible automation, it is therefore recommended to create a user, for example named aur_builder, that has no need for password with pacman in sudoers. This can be done in Ansible with the following actions:

task.yml
- user: name=aur_builder

- lineinfile:
     path: /etc/sudoers.d/aur_builder-allow-to-sudo-pacman
     state: present
     line: "aur_builder ALL=(ALL) NOPASSWD: /usr/bin/pacman"
     validate: /usr/sbin/visudo -cf %s
     create: yes

Then, AUR helpers or makepkg can be used associated with the Ansible parameters become: yes and become_user: aur_builder

Tips and tricks

User account creation

Ansible can manage user accounts and in particular it is able to create new ones. This is achieved in playbooks with the user module which takes an optional password argument to set the user's password. It is the hashed value of the password that needs to be provided to the module. The hashing can simply be performed on the fly within Ansible using one of its internal hash-filters:

- user:
  name: user_name
  password: "{{ 'user_password' | password_hash('sha512', 'mypermsalt') }}"
  shell: /usr/bin/nologin
Tip: The salt should be fixed and explicitly supplied as a second parameter of the hash function for the operation to be idempotent (can be repeated without changing the state of the system).

With this approach it is recommended to vault-encrypt user_password so that it does not appear in plain text, see #Vault. However, an encrypted variable cannot be piped directly and will first need to be assigned to another one that will be piped.

Alternatively, the hashing can be performed outside Ansible. The following commands return respectively the MD5 and the SHA512 hashed values of user_password:

$ openssl passwd -1 user_password
$ python -c 'import crypt; print(crypt.crypt("user_password", crypt.mksalt(crypt.METHOD_SHA512)))'

Python binary location

Ansible requires Python on the target machine. By default Ansible assumes it can find a /usr/bin/python on the remote system that is a 2.X or 3.X version, specifically 2.6 or higher.

If some of your modules specifically require Python2, you need to inform Ansible about its location by setting the ansible_python_interpreter variable in the inventory file. This can be done by using host groups in the inventory:

/etc/ansible/hosts
[archlinux]
server1
server2

[debian]
server3

[archlinux:vars]
ansible_python_interpreter=/usr/bin/python2

More information about Python version support in Ansible is available in [1], [2] and [3].

Troubleshooting

Unarchive

The unarchive module unpacks an archive. However tar files are not well supported and several outstanding issues are reported in GitHub - unarchive. In particular when the parameter keep_newer is set to yes, idempotence is not observed. In case you face an issue with the module, you can use instead the zip format which is better integrated in ansible.

See also