Ansible/Roles: Difference between revisions
From charlesreid1
| Line 279: | Line 279: | ||
* If the variable will change from role to role, put it in the <code>playbooks/<role-name>/defaults/main.yml</code> file | * If the variable will change from role to role, put it in the <code>playbooks/<role-name>/defaults/main.yml</code> file | ||
=== | ===Webapp role=== | ||
Here we will go through the webserver or webapp role, which runs the application that operates the web frontend for our application. | |||
All files related to this role should go in <code>playbooks/roles/webapp/</code>. | |||
====Files==== | |||
The files we will use with this role are as follows: | |||
Here are the files that the role comprises: | |||
Default variable values: | |||
* roles/mezzanine/defaults/main.yml | |||
Role variables: | |||
* roles/mezzanine/vars/main.yml | |||
Handlers: | |||
* roles/mezzanine/handlers/main.yml | |||
Tasks: | |||
* roles/mezzanine/tasks/django.yml | |||
* roles/mezzanine/tasks/main.yml | |||
* roles/mezzanine/tasks/nginx.yml | |||
Templates: | |||
* roles/mezzanine/templates/gunicorn.conf.py.j2 | |||
* roles/mezzanine/templates/local_settings.py.filters.j2 | |||
* roles/mezzanine/templates/local_settings.py.j2 | |||
* roles/mezzanine/templates/nginx.conf.j2 | |||
* roles/mezzanine/templates/supervisor.conf.j2 | |||
=Flags= | =Flags= | ||
{{AnsibleFlag}} | {{AnsibleFlag}} | ||
Revision as of 23:37, 13 November 2018
Playbook Roles
What are Ansible roles?
Roles allow you to split your playbook into different parts for different servers.
For example, a webapp with a database backend can define a webserver role and a database role, and it becomes much easier to modify the playbook to run these on the same host or on different hosts.
Feature: pre-tasks and post-tasks
In the playbook you can specify a pre-task and a post-task for a role.
For example, suppose you want to update aptitude before deploying the web server, and you want to send a notification to Slack when you are finished.
Then you could use the following playbook, which defines a pre_tasks list of things to do before the roles are defined, and a post_task list of things to do once the roles have been carried out.
- name: deploy mezzanine on vagrant
hosts: web
vars_files:
- secrets.yml
pre_tasks:
- name: update the apt cache
apt: update_cache=yes
roles:
- role: mezzanine
database_host: "{{ hostvars.db.ansible_eth1.ipv4.address }}"
live_hostname: 192.168.33.10.xip.io
domains:
- 192.168.33.10.xip.io
- www.192.168.33.10.xip.io
post_tasks:
- name: notify Slack that the servers have been updated
local_action: >
slack
domain=acme.slack.com
token={{ slack_token }}
msg="web server {{ inventory_hostname }} configured"
Feature: role files
If a role is particularly complicated or has details of its own to take care of, you can put all of the files specific to one particular role into a directory.
Suppose you have two roles, webserver and database. Then your directory structure would look like this:
playbooks/
roles/
database/
tasks/
main.yml
handlers/
main.yml
files/
pg_hba.conf
postgresql.conf
webserver/
...
Tasks, handlers, files, templates, etc. are all put into subfolders with the same name as the role.
Example
Let's look at an example of deploying an application with Ansible that a classic architecture: a web frontend with a database backend.
The web frontend can use an nginx web server playbook (see Ansible/Nginx Playbook for sample nginx playbook).
Example Playbook: Single Host
Here is an example playbook with two roles, web and database.
- name: deploy webapp on vagrant
hosts: web
vars_files:
- secrets.yml
roles:
- role: database
database_name: "{{ mezzanine_proj_name }}"
database_user: "{{ mezzanine_proj_name }}"
- role: webserver
live_hostname: 192.168.33.10.xip.io
domains:
- 192.168.33.10.xip.io
- www.192.168.33.10.xip.io
Example Playbook: Single Host with Pre and Post Tasks
Here is the same playbook but running a pre/post task before/after the roles are defined. These pre/post tasks will be run once per host.
- name: deploy mezzanine on vagrant
hosts: web
vars_files:
- secrets.yml
pre_tasks:
- name: update the apt cache
apt: update_cache=yes
roles:
- role: database
database_name: "{{ mezzanine_proj_name }}"
database_user: "{{ mezzanine_proj_name }}"
- role: webserver
live_hostname: 192.168.33.10.xip.io
domains:
- 192.168.33.10.xip.io
- www.192.168.33.10.xip.io
post_tasks:
- name: notify Slack that the servers have been updated
local_action: >
slack
domain=acme.slack.com
token={{ slack_token }}
msg="web server {{ inventory_hostname }} configured"
Example Playbook: Multiple Hosts
Here is the prior playbook adapted to multiple hosts:
- name: deploy postgres on vagrant
hosts: db
vars_files:
- secrets.yml
roles:
- role: database
database_name: "{{ mezzanine_proj_name }}"
database_user: "{{ mezzanine_proj_name }}"
- name: deploy mezzanine on vagrant
hosts: web
vars_files:
- secrets.yml
roles:
- role: mezzanine
database_host: "{{ hostvars.db.ansible_eth1.ipv4.address }}"
live_hostname: 192.168.33.10.xip.io
domains:
- 192.168.33.10.xip.io
- www.192.168.33.10.xip.io
Database role
The database role has multiple files associated with it, to define the tasks, default variable values, handlers, files, and templates used by Ansible.
These should go in playbooks/roles/database/.
The Ansible/Directory Layout article gives much more detail on the directory structure that should be in place for a role.
Tasks File
The main thing we want to define for our database role are the tasks required to set up the database server. These will be specific to the database role and are not executed by the webserver.
The task file is located in playbooks/roles/database/tasks/main.yml and are defined like normal tasks:
- install packages
- copy postgres config file into machine
- copy client authentication config file
- create project locale
- create postgresql user
- create the database as the postgresql user
playbooks/roles/database/tasks/main.yml:
- name: install apt packages
apt: pkg={{ item }} update_cache=yes cache_valid_time=3600
become: True
with_items:
- libpq-dev
- postgresql
- python-psycopg2
- name: copy configuration file
copy: >
src=postgresql.conf dest=/etc/postgresql/9.3/main/postgresql.conf
owner=postgres group=postgres mode=0644
become: True
notify: restart postgres
- name: copy client authentication configuration file
copy: >
src=pg_hba.conf dest=/etc/postgresql/9.3/main/pg_hba.conf
owner=postgres group=postgres mode=0640
become: True
notify: restart postgres
- name: create project locale
locale_gen: name={{ locale }}
become: True
- name: create a user
postgresql_user:
name: "{{ database_user }}"
password: "{{ db_pass }}"
become: True
become_user: postgres
- name: create the database
postgresql_db:
name: "{{ database_name }}"
owner: "{{ database_user }}"
encoding: UTF8
lc_ctype: "{{ locale }}"
lc_collate: "{{ locale }}"
template: template0
become: True
become_user: postgres
Note that copying the configuration file includes a notify: restart postgres. These are handler notifications (see next section).
Handlers File
Handlers can be defined in the handlers folder of the directory for this role.
Recall that handlers are simply tasks that are dependent on other tasks.
We define a task to restart the postgresql service. Whenever the configuration files are changed, this handler is notified/run.
playbooks/roles/database/handlers/main.yml:
- name: restart postgres service: name=postgresql state=restarted become: True
Defaults
To define defaults, we can use the defaults folder following the same patterns as above.
roles/database/defaults/main.yml:
database_port: 5432
Variables
Note that we defined a vars_files variable at the top of the playbook:
- name: deploy mezzanine on vagrant
hosts: web
vars_files:
- secrets.yml
The secrets.yml file will contain, we presume, secrets like the database password.
The variables we referred to were:
- database_name
- database_user
- db_pass
- locale
The rest of the variables can be defined as follows:
- If the variable will be the same across all roles, define the variable in
playbooks/group_vars/all
- If the variable will change from role to role, put it in the
playbooks/<role-name>/defaults/main.ymlfile
Webapp role
Here we will go through the webserver or webapp role, which runs the application that operates the web frontend for our application.
All files related to this role should go in playbooks/roles/webapp/.
Files
The files we will use with this role are as follows:
Here are the files that the role comprises:
Default variable values:
- roles/mezzanine/defaults/main.yml
Role variables:
- roles/mezzanine/vars/main.yml
Handlers:
- roles/mezzanine/handlers/main.yml
Tasks:
- roles/mezzanine/tasks/django.yml
- roles/mezzanine/tasks/main.yml
- roles/mezzanine/tasks/nginx.yml
Templates:
- roles/mezzanine/templates/gunicorn.conf.py.j2
- roles/mezzanine/templates/local_settings.py.filters.j2
- roles/mezzanine/templates/local_settings.py.j2
- roles/mezzanine/templates/nginx.conf.j2
- roles/mezzanine/templates/supervisor.conf.j2
Flags