Tips of Ansible Up and Running

Some tips learning from “Ansible Up & Running”.
The repo of this book https://github.com/lorin/ansiblebook

Introduction

In a way, YAML is to JSON what Markdown is to HTML.

Installing Ansible

$ sudo pip install ansible

ansible.cfg

Ansible looks for an ansible.cfg file in the following places, in this order:

  1. File specified by the ANSIBLE_CONFIG environment variable
  2. ./ansible.cfg (ansible.cfg in the current directory)
  3. ~/.ansible.cfg (.ansible.cfg in your home directory)
  4. /etc/ansible/ansible.cfg

Playbooks:A Beginning

web-notls.yml

---
- name: Configure webserver with nginx
hosts: webservers
sudo: True
tasks:
- name: install nginx
apt: name=nginx update_cache=yes
- name: copy nginx config file
copy: src=files/nginx.conf dest=/etc/nginx/sites-available/default
- name: enable configuration
file: >
dest=/etc/nginx/sites-enabled/default
src=/etc/nginx/sites-available/default
state=link
- name: copy index.html
template: src=templates/index.html.j2 dest=/usr/share/nginx/html/index.html mode=0644
- name: restart nginx
service: name=nginx state=restarted

YAML truthy and falsey

  • YAML truthy

true, True, TRUE, yes, Yes, YES, on, On, ON, y, Y

  • YAML falsey

false, False, FALSE, no, No, NO, off, Off, OFF, n, N

Cowsay

apt-get install cowsay

Disable cowsay be setting the ANSIBLE_NOCOWS environment variable like this:

$ export ANSIBLE_NOCOWS=1

Also add the following in ansible.cfg file

[defaults]
nocows = 1

Playbooks Are YAML

Ansible playbooks are written in YAML syntax. YAML is a file format similar in intent to JSON, but generally easier for humans to read and write. Before we go over the playbook, let’s cover the concepts of YAML that are most important for writing playbooks.

the JSON equivalent of web-notls.yml

[
{
"name": "Configure webserver with nginx",
"hosts": "webservers",
"sudo": true,
"task": [
{
"name": "Install nginx",
"apt": "name=nginx update_cache=yes"
},
{
"name": "copy nginx config file",
"template": "src=files/nginx.conf dest=/etc/nginx/sites-availabe/default"
},
{
"name": "enable configuration",
"file": "dest=/etc/nginx/sites-enabled/default src=/etc/nginx/sites-available/default state=link"
},
{
"name": "copy index.html",
"template": "src=templates/index.html.j2 dest=/usr/share/nginx/html/index.html mode=0644"
},
{
"name": "restart nginx",
"service": "name=nginx state=restarted"
}
]
}
]

Handlers

Handlers are one of the conditional forms that Ansible supports. A handler is similar to a task, but it runs only if it has been notified by a task. A task will fire the notifica‐ tion if Ansible recognizes that the task has changed the state of the system.
web-tls.yml

---
- name: Configure webserver with nginx and tls
hosts: webservers
sudo: True
vars:
key_file: /etc/nginx/ssl/nginx.key
cert_file: /etc/nginx/ssl/nginx.crt
conf_file: /etc/nginx/sites-available/default
server_name: localhost
tasks:
- name: Install nginx
apt: name=nginx update_cache=yes cache_valid_time=3600
- name: create directories for TLS certificates
file: path=/etc/nginx/ssl state=directory
- name: copy TLS key
copy: src=files/nginx.key dest={{ key_file }} owner=root mode=0600
notify: restart nginx
- name: copy TLS certificate
copy: src=files/nginx.crt dest={{ cert_file }}
notify: restart nginx
- name: copy nginx config file
template: src=templates/nginx.conf.j2 dest={{ conf_file }}
notify: restart nginx
- name: enable configuration
file: dest=/etc/nginx/sites-enabled/default src={{ conf_file }} state=link
notify: restart nginx
- name: copy index.html
template: src=templates/index.html.j2 dest=/usr/share/nginx/html/index.html mode=0644
handlers:
- name: restart nginx
service: name=nginx state=restarted

Inventory: Describing Your Servers

Behavioral Inventory Parameters

Name Default Description
ansible_ssh_host name of host Hostname or IP address to SSH to
ansible_ssh_port 22 Port to SSH to
ansible_ssh_user root User to SSH to
ansible_ssh_pass none Password to use for SSH authentication
ansible_connection smart How Ansible will connect to host
ansible_ssh_private_key_file none SSH private key to use for SSH authentication
ansible_shell_type sh Shell to use for commands
ansible_python_interpreter /usr/bin/python Pyhton interpreter on host
ansible_*_interpreter none Like ansible_python_interpreter for other languages

The Interface for a Dynamic Inventory Script

An Ansible dynamic inventory script must support two command-line flags:

  • –host= for showing host details
  • –list for listing groups

Adding Entries at Runtime with add_host and group_by

add_by

The add_host module adds a host to the inventory. This module is useful if you’re using Ansible to provision new virtual machine instances inside of an infrastructure- as-a-service cloud.

group_by

Use the ansible_distribution fact to group hosts by Linux distribution(e.g., Ubuntu, CentOS)

- name: create groups based on Linux distribution
group_by: key={{ ansible_distribution }}

Example. Creating ad-hoc(点对点) groups based on Linux distribution

- name: group hosts by distribution
hosts: myhosts
gather_facts: True
tasks:
- name: create groups based on distro
group_by: key={{ ansible_distribution }}
- name: do something to Ubuntu hosts
hosts: Ubuntu
tasks:
- name: install htop
apt: name=htop
# ...
- name: do something to CentOS hosts
hosts: CentOS
tasks:
- name: install htop
yum: name=htop
# ...

Variables and Facts

Defining Variables in Playbooks

The simplest way to define variables is to put a vars section in your playbook with the names and values of variables.

vars:
key_file: /etc/nginx/ssl/nginx.key
cert_file: /etc/nginx/ssl/nginx.crt
conf_file: /etc/nginx/sites-available/default
server_name: localhost

Ansible also allows you to put variables into one or more files, using a section called vars_files.

vars_files:
- nginx.yml

The nginx.yml file would look like:

key_file: /etc/nginx/ssl/nginx.key
cert_file: /etc/nginx/ssl/nginx.crt
conf_file: /etc/nginx/sites-available/default
server_name: localhost

Registering Variables

- name: capture output of id command
command: id -un
register: login
- debug: msg="Logged in as user {{ login.stdout }}"

Facts

Viewing All Facts Associated with a Server

$ ansible server1 -m setup

Viewing a Subset of Facts

$ ansible web -m setup -a 'filter=ansible_eth*'

Local Facts

Ansible also provides an additional mechanism for associating facts with a host. You can place one or more files on the host machine in the /etc/ansible/facts.d directory. Ansible will recognize the file if it’s:

Deploying Mezzanine with Ansible

Listing Tasks in a Playbook

$ ansible-playbook --list-tasks mezzanine.yml

Using Iteration(with_items) to Install Multiple Packages

- name: install apt packages
apt: pkg={{ item }} update_cache=yes cache_valid_time=3600
sudo: True
with_items:
- git
- libjpeg-dev
- libpq-dev
- memcached
#- ...

equal to below:

- name: install git
apt: pkg=git
- name: install libjpeg-dev
apt: pkg=libjpeg-dev
# ...

Installing Packages into a virtualenv

- name: install required python packages
pip: name={{ item }} virtualenv={{ venv_path }}
with_items:
- gunicorn
- setproctitle

directory of requirements is in remote host(client host),也可以写成virtualenv路径的相对路径

- name: install requirements.txt
pip: requirements={{ proj_path }}/{{ reqs_path }} virtualenv={{ venv_path }}

Complex Arguments in Tasks

- name: python packages
pip: name={{ item.name }} version={{ item.version }} virtualenv={{ venv_path }}
with_items:
- {name: mezzanine, version: 3.1.10 }
- {name: gunicorn, version: 19.1.1 }
- {name: setproctitle, version: 1.1.8 }
- {name: south, version: 1.0.1 }

Complex Playbooks

Running a Task on a Machine Other Than the Host

delegate_to

- name: enable alerts for web servers
hosts: web
tasks:
- name: enable alerts
nagios: action=enable_alerts service=web host={{ inventory_hostname }}
delegate_to: nagios.example.com

In this example, Ansible would execute the nagios task on nagios.example.com, but the inventory_hostname variable referenced in the play would evaluate to the web host.

Encrypting Sensitive Data with Vault

$ ansible-vault encrypt secrets.yml
$ ansible-vault decrypt secrets.yml

Roles:Scaling Up Playbooks

Basic Structure of a Role

roles/database/tasks/main.yml
Tasks

roles/database/files/
Holds files to be uploaded to hosts

roles/database/templates/
Holds Jinja2 template files

roles/database/handlers/main.yml
Handlers

roles/database/vars/main.yml
Variables that shouldn’t be overridden

roles/database/defaults/main.yml
Default variables that can be overridden

roles/database/meta/main.yml
Dependency information about a role