Ansible Code Promotion in a Shared Hosting Environment¶
We are deploying our nifty web portal to two web and two app servers. The app servers will also act as alternate web servers, so they must be configered for both roles.
The machines are web01, web02, app01, and app02.
They are members of the groups webs and apps, respectively.
Structure of a Role¶
A sample role directory looks like this. Have the CDS (e.g. Jenkins) deploy to …/roles/<rolename>/src/.
Content |
Purpose |
---|---|
…/tasks |
Contains the main.yml that specifies state for the installation. This is the file that calls for templating configuration based on variables. |
…/vars |
Contains the main.yml that lists mock (or dummy) variables. |
…/handlers |
Contains the main.yml for triggered tasks. This is very convenient. For example, a change in httpd.conf should trigger an Apache2 restart. |
…/templates |
Contains the *.j2 files that become text files built with variable content. These are Jinja2 and the variables are in plain YAML. No tricks. |
…/src |
This is a home for all that copies to the host without templating. Putting everything in “templates” is not harmful as long as tasks/main.yml makes sense. |
…/meta |
Contains the main.yml that tracks dependencies among roles. |
Sample Web Server Role¶
These tasks install Apache and push the configuration file. I can also add an application server role in this doc, but you probably get the point.
1---
2- name: Ensure Apache2 exists and is the current version
3 yum: name=httpd state=latest
4
5- name: Build our configuration files from templates and variables
6 template: src=/etc/ansible/roles/webserver/templates/{{ item }}.j2 dest=/etc/httpd/conf.d/{{item }} mode=0644 owner=www-data group=www-data setype=httpd_config_t backup=yes
7 with_items:
8 - portal.conf
9 - ssl.conf
10 notify: "restart Apache"
This handler restarts Apache when triggered.
1- name: Restart and enable Apache
2 service: name=httpd state=restarted enabled=true
3 listen: "restart Apache"
This Apache configuration template serves a directory Ansible replaces {{portalpath}} with the content of that variable. See Ansible configuration below.
1Alias /portal {{ portalpath }}
2# This is obviously not a portal. I just wanted an illustrative Apache config.
3<Directory {{ portalpath }}>
4 AuthType None
5 Options Indexes FollowSymLinks MultiViews
6 IndexOptions +FancyIndexing +FoldersFirst +ScanHTMLTitles +TrackModified +DescriptionWidth=*
7 AllowOverride None
8 Order allow,deny
9 Allow from all
10</Directory>
Playbooks¶
To apply these roles, we need a playbook to bind our instructions together.
1---
2# This file is a wrapper for the project
3- include: web.yml
4- include: app.yml
Notice how the web.yml installs the web server role to both the web servers and the application servers. This is for illustration.
1---
2# This file tells Ansible to apply the web server role
3- name: ensure web servers are deployed
4 hosts: webs apps
5 become: true
6 gather_facts: true
7 roles:
8 - web
Whereas the app role only applies to the application servers.
1---
2# This file tells Ansible to apply the application server role
3- name: ensure application servers are deployed
4 hosts: apps
5 become: true
6 gather_facts: true
7 roles:
8 - app
Ansible configuration¶
Our hosts file groups our nodes and declares them for Ansible.
1[webs]
2web01
3web02
4
5[apps]
6app01
7app02
Our group variables file sets these variables for every member of webs.
1portalpath: /var/www/html/portal/
2somelistvariable:
3 - value1
4 - value2
One of our nodes needs special treatment, so its variable file overwrites the value of portalpath.
1portalpath: /var/www/html/site/
Run the Playbook¶
Now, we run this thing. The option flags are…
-k to prompt for an SSH password
-K to prompt for a sudo password (or press enter for them to be the same)
-D show the deltas imposed by Ansible on the target node.
1ansible-playbook -kKD /etc/ansible/playbooks/mywebsite.yml