User Tools

Site Tools


Writing /app/www/public/data/meta/development/applications/ansible.meta failed
development:applications:ansible

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
development:applications:ansible [2018/08/30 15:17] mzubaldevelopment:applications:ansible [2021/06/25 10:09] (current) – external edit 127.0.0.1
Line 1: Line 1:
 +====== Ansible ======
  
 +Ansible is an open source command line tool for automating server configuration and deployment. Ansible is designed to be set up and operated entirely from the controlling machine - the servers being configured do not need to have any sort of ansible server software - they just need Python and to be accessable via SSH. This makes it extremely simple to get existing ansible playbooks running on a new server.
 +
 +An ansible configuration is broken into several parts, each defined by their own [[https://en.wikipedia.org/wiki/YAML|YAML]] files. Playbooks define a set of roles and tasks to run against servers defined in an inventory file and using variables defined in group_vars and host_vars files.
 +
 +Overall Ansible is extremely flexable and powerful and capable of a lot more than the simple examples shown below. For (much) more information see the [[http://docs.ansible.com/ansible/latest/intro.html|official documentation]].
 +
 +Going through an example Ansible setup such as the [[https://bitbucket.org/errigal/cluster-setup/src|cluster setup repository]] while reading through this is probably a good idea.
 +
 +
 +===== Modules =====
 +
 +To perform any action with ansible you must specify a module to use. [[http://docs.ansible.com/ansible/latest/list_of_all_modules.html|There is a huge number of modules to use]] that all provide different actions - from simple file transfer to managing MySQL users, git repository management, crontab management or partitioning drives. In each task a single module must be specified.
 +
 +===== Tasks =====
 +
 +A task is exactly what is sounds like. Tasks are defined in roles and look like this:
 +
 +<code>
 +- name: add server cluster to hostfile
 +  lineinfile:
 + path: /etc/hosts
 + line: "{{item}}"
 +  with_items:
 + - "0.0.0.1  server1"
 + - "0.0.0.2  server2"
 + - "0.0.0.3  server3"
 +  become: yes
 +</code>
 +
 +The first line simply defines the name of the task which also describes its purpose. The second line defines that the task is using the lineinfile module. This module then takes two parameters - the path to a text file and a string that we want to make sure exists as a line in the file. If the line already exists no action is taken, otherwise it is inserted. An important factor in creating tasks is that they should always be idempotent - i.e. running them multiple times should have no effect after the first run.
 +
 +In this case the line is not set to a normal string but to a variable named 'item' - this is what the curly brackets signify. The task has the special parameter with_items which defines a list of items that the task will iterate over and run once for each. The with_items parameter is one of many special parameters that can be used with any task. The 'become' parameter on the last line means that the task is using privilege escallation. This can be configured to work in different ways but by default it simply means the command will be run as sudo - which is needed to edit the hosts file.
 +
 +So this task simply makes sure that the hosts file contains entries for server1, server2 and server3 and adds them if they don't already exist.
 +
 +===== Roles =====
 +
 +Roles are a way of organising tasks for reuse with a defined file structure. Roles can vary in structure but a typical role has a tasks subdirectory which contains a file called "main.yml" which defines a set of tasks in a similar structure to the above. It may also have other folders like files or templates folder which respectively contain files or templates that are to be deployed to servers as part of the role's tasks.
 +
 +Example role structure:
 +
 +<code>
 +roles/
 +├── role1/
 +│   ├── tasks/
 +│       ├── main.yml
 +│   ├── files/
 +│       ├── file1.tgz
 +│       ├── file1.tgz
 +│   templates/
 +│       ├── template.j2
 +</code>
 +
 +For more details on this see the [[http://docs.ansible.com/ansible/2.4/playbooks_reuse_roles.html|official documentation]].
 +
 +For more information on our existing roles, refer: [[development:applications:ansible:roles|Ansible Roles]]
 +
 +
 +===== Inventory =====
 +
 +Inventory files define a list of servers that roles are to be used against. It can simply be a list of hostnames or it can be broken up into groups denoted by square brackets.
 +
 +Example inventory:
 +
 +<code>
 +[cluster]
 +server1
 +server2
 +server3
 +
 +[database]
 +server3
 +
 +[applications]
 +server1
 +server2
 +
 +[backups]
 +server2
 +server3
 +</code>
 +
 +More complicated inventory structures are possible including setting variables in the inventory file and child groups. See [[http://docs.ansible.com/ansible/latest/intro_inventory.html|official documentation]] for more info.
 +
 +===== Playbooks =====
 +
 +Playbooks are YAML files that bring everything else together - they call tasks or roles to be acted against specific hosts or host groups as defined in the inventory file. Simple example playbook:
 +
 +
 +<code>
 +---
 +- hosts: all
 +  roles:
 +  - {role: user-setup}
 +  - {role: configure-network-settings}
 +
 +- hosts: applications
 +  roles:
 +  - {role: install-tomcat}
 +  - {role: install-java}
 +  - {role: create-app-environments}
 +...
 +</code>
 +
 +
 +===== Variables =====
 +
 +I haven't talked much about variables other than the 'item' variable in the task example but variables can be used in pretty anywhere in your tasks or templates and can be defined in many different places. Most usefully they can be defined per host and per group by creating a folder of the name of the host or group in a host_vars or group_vars folder. In general more specific variables override more general ones - so if a variable is defined for a host but also for one of the groups it's in the definition on the host level takes precedence while a variable set by in the task definition itself would take precedence.
 +
 +There's also a large list of 'magic variables' that are provided by ansible automatically. The hostvars variable is a map of all kinds of information about the current host, this can be used to pull e.g. it's IP address. The group_names variable is a list of all groups the current host belongs to. This is useful for configuring templates based on certain groups. The groups varaible is a list of all of the groups defined in the inventory.
 +
 +Sometimes variables can be defined within the task itself such as the use of the item variable above.
 +
 +===== Tips&Tricks =====
 +==== Ansible settings ====
 +There are couple of useful settings, which you likely want to set globally for all your ansible stuff.
 +These get configured in ~/.ansible.cfg. The 2 most useful settings are to disable host checking (so you don't need to have all the servers in your known_hosts) and to enable pipelining, which increases the playbook speed.
 +Example of ~/.ansible.cfg:
 +<code>
 +[defaults]
 +host_key_checking = False
 +timeout = 30
 +
 +[ssh_connection]
 +pipelining = True
 +ssh_args = -o ControlMaster=auto -o ControlPersist=600s
 +</code>
 +
 +===== Troubleshooting =====
 +==== Install libselinux-python when it doesn't work through yum ====
 +
 +Sometimes the libselinux-python cannot be installed because yum cannot find it.
 +In that case it is needed to figure the libselinux version first:
 +<code>
 +[scotty@Blade5(sfqadb1) ~]$yum list | grep libselinux
 +libselinux.x86_64                              2.0.94-5.8.el6               @anaconda-RedHatEnterpriseLinux-201409260744.x86_64/6.6
 +libselinux-python.x86_64                       2.0.94-5.8.el6               installed
 +libselinux-utils.x86_64                        2.0.94-5.8.el6               @anaconda-RedHatEnterpriseLinux-201409260744.x86_64/6.6
 +</code>
 +
 +And then download the according rpm of libselinux-python:
 +<code>
 +wget ftp://mirror.switch.ch/pool/4/mirror/scientificlinux/6.6/x86_64/os/Packages/libselinux-python-2.0.94-5.8.el6.x86_64.rpm
 +</code>
 +
 +And then install the rpm:
 +<code>
 +sudo rpm -Uvh libselinux-python-2.0.94-5.8.el6.x86_64.rpm
 +</code>