Tips of Ansible Up and Running - xiuyanduan/xiuyanduan.github.io GitHub Wiki

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

⚠️ **GitHub.com Fallback** ⚠️