Sunteți pe pagina 1din 26

Ansible adalah alat otomisasi IT yang bisa digunakan untuk melakukan konfigurasi

sistem, instalasi perangkat lunak, dan operasi IT yang lebih rumit seperti cont
inous deployments atau zero downtime rolling updates.
Ansible's goal: simplicity and maximum easy of use, strong focus on security and
reliability, minimum of moving parts, usage of OpenSSH for transport (accelerat
ed socket mode and pull mode), easy language for human
Simplicity is relevant to all size of environment and design for busy users of a
ll types - whether this means developers, sysadmins, release engineers, IT manag
ers, and everywhere in between.
Ansible: agentless, decentralized, relies on your existing OS credential, can ea
sily connect to Kerberos LDAP, and other centralized authentication management s
ystems
Installation
Control Machine: Use OS package manager, requirement: Python2.6 or Python2.7 (Re
d Hat, Debian, CentOS, OS X, any of the BSDs, and so on.)
Managed Node: Python2.4(with python-simplejson) or later
Remote Connection Information
Ansible 1.3 or later will use native OpenSSH communication when possible: Contro
lPersist(except for EL6 will use paramiko), Kerberos, options in ~/.ssh/config s
uch as Jump Host setup. For device that doesn't support SFTP, switch to SCP in a
nsible.cfg. Password can be provided using --ask-pass or --ask-sudo-pass. Run co
ntrol machine near managed nodes. Ansible also have options to manage things loc
ally, as well as manage chroot, lxc, and jail containers. A mode called 'ansible
via scheduled git checko
-pull' can also invert the system and have systems phone home
uts to pull configuration directives from a central repository.
Basic Command
Ansible hosts file: /etc/ansible/hosts (ansible inventory file, use SSH public k
ey auth for those nodes)
Set host_key_checking = False if needed
$ ansible all -m ping -u user [--sudo|--sudo-user]
Inventory
Ansible inventory file which define managed nodes: /etc/ansible/hosts
Patterns
Patterns in Ansible are how we decide which hosts to manage, what hosts to commu
nicate with, in terms of Playbooks it actually means what hosts to apply a parti
cular configuration or IT process to.
$ ansible <pattern_goes_here> -m <module_name> -a <arguments>
Ad-hoc Command
An ad-hoc command is something that you might type in to do something really qui
ck, but don t want to save for later.
Parallelism and Shell Commands
-f number of forks
--sudo/-s run command through sudo
--ask-sudo-pass/-K ask sudo password
--sudo-user/-U sudo to different user
shell: shell module
File Transfer
copy: copy module
ansible atlanta -m copy -a "src=/etc/hosts dest=/tmp/hosts"
file: file module
ansible webservers -m file -a "dest=/srv/foo/b.txt mode=600 owner=mdehaan group=

mdehaan"
ansible webservers -m file -a "dest=/path/to/c mode=755 owner=mdehaan group=mdeh
aan state=directory"
ansible webservers -m file -a "dest=/path/to/c state=absent"
Managing Packages
yum: yum module
ansible webservers
ansible webservers
ansible webservers
ansible webservers

-m
-m
-m
-m

yum
yum
yum
yum

-a
-a
-a
-a

"name=acme state=present"
"name=acme-1.5 state=present"
"name=acme state=latest"
"name=acme state=absent"

Users and Groups


user: user and group module
ansible all -m user -a "name=foo password=<crypted password here>"
ansible all -m user -a "name=foo state=absent"
Deploy from Source Control
git: git module
ansible webservers -m git -a "repo=git://foo.example.org/repo.git dest=/srv/myap
p version=HEAD"
Managing Service
service: service module
ansible webservers -m service -a "name=httpd state=started"
ansible webservers -m service -a "name=httpd state=restarted"
ansible webservers -m service -a "name=httpd state=stopped"
Time Limited Background Operations
ansible all -B 3600 -P 0 -a "/usr/bin/long_running_operation --do-stuff"
async_status: module to check job status later
ansible web1.example.com -m async_status -a "jid=488359678239.2844"
polling
ansible all -B 1800 -P 60 -a "/usr/bin/long_running_operation --do-stuff"
Gathering Facts
Facts are described in the playbooks section and represent discovered variables
about a system. These can be used to implement conditional execution of tasks bu
t also just to get ad-hoc information about your system.
ansible all -m setup
The Ansible Configuration File
Ansible Playbooks
Playbooks: ansible configuration, deployment, and orchestration language
Basic:
Hosts and Users
--- hosts: mx1-test
remote_user: root
vars:
ansible_python_interpreter: /usr/local/bin/python
tasks:
- name: install python
raw: env ASSUME_ALWAYS_YES=YES /usr/sbin/pkg install python
- name: update portsnap
command: /usr/sbin/portsnap fetch extract

- name: install postfix


portinstall: pkg=postfix state=present
notify:
- enable postfix
- start postfix
- name: configure postfix
template: src=/ dest=/usr/local/etc/postfix
notify:
- restart postfix
- name: ensure apache is running (and enable it at boot)
service: name=httpd state=started enabled=yes
handlers:
- name: enable postfix
command: "{{ item }}"
with_items:
- /usr/sbin/sysrc postfix_enable=YES
- /usr/sbin/sysrc sendmail_enable=NO
- /usr/sbin/sysrc sendmail_submit_enable=NO
- /usr/sbin/sysrc sendmail_outbond_enable=NO
- /usr/sbin/sysrc sendmail_msp_queue_enable=NO
- name: start postfix
service: name=postfix state=running
- name: restart postfix
service: name=postfix state=restarted
--- hosts: ntp-servers
user: ansible
sudo: yes
tasks:
- name: enable ntpdate
action: command sysrc ntpdate_enable=yes
- name: enable ntpdate server
action: command sysrc ntpdate_hosts=pool.ntp.org
- name: enable ntpd
action: command sysrc ntpd_enable=yes
- name: copy ntp.server.conf to servers
action: copy src=/home/ansible/freebsd/etc/ntp.server.conf
dest=/etc/ntp.conf owner=root group=wheel mode=0644
notify:
- restart ntpd
- include: tasks/pf-compile.yml
handlers:
- include: handlers/restarts.yml
--#build pf.conf from template
- name: configure firewall
template: src=/home/ansible/freebsd/etc/pf.conf.j2
dest=/etc/pf.conf owner=0 group=0 mode=0444
validate='/sbin/pfctl -nf %s'
notify:
- reload pf

--#restart assorted services


- name: restart ntpd
service: name=ntpd state=restarted
- name: reload pf
action: shell /sbin/pfctl -f /etc/pf.conf
#{{ ansible_managed }}
#$Id: pf.conf.j2,v 1.2 2014/01/16 16:10:54 mwlucas Exp $
ext_if="{{ ansible_default_ipv4.device }}"
include "/etc/pf.mgmt.conf"
include "/etc/pf.ournets.conf"
set block-policy return
set loginterface $ext_if
set skip on lo0
scrub in all
block in all
pass in on $ext_if proto icmp all
pass in on $ext_if proto icmp6 all
#this host may initiate anything
pass out on $ext_if from any to any
#mgmt networks can talk to this host on any service
pass in on $ext_if from to any
#Allowed services, in port order
{% if inventory_hostname in groups['dns'] %}
#DNS access
pass in on $ext_if proto {tcp, udp} from any to any port 53
{% endif %}
{% if inventory_hostname in groups['tftpd'] %}
#allow tftp from the world
pass in on $ext_if proto udp from any to any port 69
{% endif %}
{% if inventory_hostname in groups['ntp-servers'] %}
#allow time from our networks
pass in on $ext_if proto udp from to any port 123
{% endif %}
#end of services

I allow access from my management networks, allow ICMP, default block, all the r
outine packet filter stuff. The next interesting bit is the allowed services. I
check for the host s presence in a group, and if it s there
I add a rule to permit the
ss that protocol needs.
One detail that gave me trouble made me use inventory_hostname rather than ansib

le_fqdn or ansible_hostname to check group membership. I manage systems in sever


al domains, and many of them have one name in our management systems and another
in DNS. I put machines in Ansible by their fully qualified domain name. Using a
nsible_fqdn to get a hostname returns the hostname given in reverse DNS. invento
ry_hostname returns the hostname as it appears in the hosts file. If ansible_fqd
n doesn t match the hostname in the hosts file, the group comparison fails. Using in
ventory_hostname gave me one consistent set of hostnames for comparisons.
So now I can easily deploy a secure NTP configuration to my servers. When I have
to deploy some other service that requires updating the packet filter, I can in
clude the same task file. And the handlers are now similarly reusable.
MX Playbooks
common:
dumpon
mailgraph
newsyslog
nfsclient
ntpd
ntpdate
rsyncd
sendmail
snmpd
snmptrapd
sshd
syslogd
mx1:
bacula_fd
hostname
ipfilter
ipnat
network
pf
pflog
postfix
routing
handlers
-

disable sendmail
enable apache24
enable bacula_fd
enable mailgraph
enable newsyslog
enable ntpd
enable ntpdate
enable nfsclient
enable postfix
enable rsync
enable snmp
enable snmptrapd
enable syslogd

Command Examples:
cd ansible/openstack/
man ansible
mkdir ansible

mkdir -p ansible/files
mv ansible/files ansible/openstack
mv ansible/openstack/hosts.openstack ansible/openstack/hosts
sudo cp /etc/ansible/{hosts,hosts.old}
sudo vi /etc/ansible/group_vars/mx
sudo vi /etc/ansible/group_vars/mx
sudo vi /etc/ansible/group_vars/mx
sudo vi /etc/ansible/group_vars/mx
sudo vi /etc/ansible/group_vars/mx
sudo vi /etc/ansible/group_vars/mx
sudo vi /etc/ansible/group_vars/mx
sudo vi /etc/ansible/group_vars/mx
sudo vi /etc/ansible/group_vars/mx
sudo vi /etc/ansible/group_vars/mx
sudo vi /etc/ansible/hosts
vi ansible/files/hosts.openstack
vi ansible/openstack/eth1.11
vi /etc/ansible/hosts
sudo vi /etc/ansible/ansible.cfg
sudo vi /etc/ansible/hosts
sudo vi /etc/ansible/hosts
sudo vi /etc/ansible/hosts.old
sudo yum install ansible
ansible mx -m copy -a "src=/etc/hosts dest=/tmp/hosts" -u root
ansible openstack -m copy -a "src=/home/pras/ansible/files/hosts.openstack dest=
/etc/hosts mode=0644 owner=root group=root" --ask-sudo-pass
ansible openstack -m copy -a "src=/home/pras/ansible/files/hosts.openstack dest=
/etc/hosts mode=0644 owner=root group=root" -s --ask-sudo-pass
ansible openstack -m copy -a "src=/home/pras/ansible/files/hosts.openstack dest=
/etc/hosts mode=644 owner=root group=root" -K
ansible 167.205.23.38 -m copy -a "src=/home/pras/ansible/openstack/eth2.11 dest=
/etc/sysconfig/network-scripts/ifcfg-eth2 mode=0644 owner=root group=root" -s -K
ansible 167.205.23.39 -m copy -a "src=/home/pras/ansible/openstack/eth2.21 dest=
/etc/sysconfig/network-scripts/ifcfg-eth2 mode=0644 owner=root group=root" -s -K
ansible 167.205.23.40 -m copy -a "src=/home/pras/ansible/openstack/eth2.31 dest=
/etc/sysconfig/network-scripts/ifcfg-eth2 mode=0644 owner=root group=root" -s -K
ansible 167.205.23.38 -m copy -a "src=/home/pras/ansible/openstack/mariadb_opens
tack.cnf dest=/etc/my.cnf.d/mariadb_openstack.cnf mode=0644 owner=root group=roo
t" -s -K
ansible 167.205.23.38 -m copy -a "src=/home/pras/ansible/openstack/ntp.conf.mast
er dest=/etc/ntp.conf mode=0644 owner=root group=root" -s -K
ansible 167.205.23.39,167.205.23.40 -m copy -a "src=/home/pras/ansible/openstack
/ntp.conf.slaves dest=/etc/ntp.conf mode=0644 owner=root group=root" -s -K
ansible 167.205.23.39 -m copy -a "src=/home/pras/ansible/openstack/ntp.conf.slav
es dest=/etc/ntp.conf mode=0644 owner=root group=root" -s -K
ansible 167.205.23.40 -m copy -a "src=/home/pras/ansible/openstack/ntp.conf.slav
es dest=/etc/ntp.conf mode=0644 owner=root group=root" -s -K
sudo mkdir -p /etc/ansible/group_vars
ansible 167.205.23.38 -m firewalld -a "port=5672 permanent=true state=enabled" s -K
ansible 167.205.23.38 -m firewalld -a "port=5672/tcp permanent=true state=enable
d" -s -K
ansible 167.205.23.38 -m firewalld -a "service=mariadb-server permanent=true sta
te=enabled" -s -K
ansible 167.205.23.38 -m firewalld -a "service=maria permanent=true state=enable
d" -s -K
ansible 167.205.23.38 -m firewalld -a "service=mysql permanent=true state=enable
d" -s -K
ansible 167.205.23.38 -m firewalld -a "service=ntpd permanent=true state=enabled
" -s -K

ansible 167.205.23.38 -m firewalld -a "service=ntpd permanent=true state=enabled


" -s -K
ansible 167.205.23.38 -m firewalld -a "service=ntp permanent=true state=enabled"
-s -K
ansible 167.205.23.38 -m firewalld -a "service=ntp permanent=true state=enabled"
-s -K
ansible 167.205.23.38 -m firewalld -a "service=rabbitmq-server permanent=true st
ate=enabled" -s -K
ansible 167.205.23.38 -m firewalld -a "service=rabbitmq-server permanent=true st
ate=enabled" -s -K
ansible openstack -m ping
ansible all -m ping -u pras
ansible all -m ping -u pras
ansible all -m ping -u [ras
ansible all -m ping -u root
ansible all -m ping -u root
ansible all -m ping -u root
ansible all -m ping -u root
ansible all -m ping -u root
ansible all -m ping -u root
ansible all -m ping -u root
ansible all -m ping -u root
ansible all -m ping -u root
ansible all -m ping -u root
ansible all -m ping -u root
ansible openstack -m ping -u root
ansible all -m raw -a 'env ASSUME_ALWAYS_YES=YES pkg install python' -u root
ansible 167.205.23.38 -m raw -a "firewall-cmd --add-service=ntp --permanent" -s
-K
ansible all -m raw -a 'pkg install python'
ansible all -m raw -a 'pkg install python'
ansible all -m raw -a 'pkg install python' -u root
ansible all -m raw -a 'rehash' -u root
ansible openstack -m raw -a "yum install http://dl.fedoraproject.org/pub/epel/7/
x86_64/e/epel-release-7-5.noarch.rpm" -s -K
ansible openstack -m raw -a "yum -y install ftp://ftp.itb.ac.id/pub/Fedora/epel/
7/x86_64/e/epel-release-7-5.noarch.rpm" -s -K
ansible openstack -m raw -a "yum -y install http://rdo.fedorapeople.org/openstac
k-kilo/rdo-release-kilo.rpm" -s -K
ansible 167.205.23.38 -m service -a "name=firewalld state=reloaded" -s -K
ansible 167.205.23.38 -m service -a "name=firewalld state=reloaded" -s -K
ansible openstack -m service -a "name=firewalld state=reloaded" -s -K
ansible 167.205.23.38 -m service -a "name=firewalld state=restarted" -s -K
ansible 167.205.23.38 -m service -a "name=firewalld state=restarted" -s -K
ansible 167.205.23.38 -m service -a "name=firewalld state=restarted" -s -K
ansible 167.205.23.38 -m service -a "name=firewalld state=restarted" -s -K
ansible 167.205.23.38 -m service -a "name=firewalld state=running" -s -K
ansible 167.205.23.38 -m service -a "name=mariadb state=running enabled=yes" -s
-K
ansible 167.205.23.38 -m service -a "name=mariadb state=running" -s -K
ansible openstack -m service -a "name=network state=restarted" -s -K
ansible openstack -m service -a "name=ntpd state=restarted" -s -K
ansible openstack -m service -a "name=ntpd state=restarted" -s -K
ansible openstack -m service -a "name=ntpd state=restarted" -s -K
ansible mx -m service -a "name=ntpd state=restarted" -u root
ansible openstack -m service -a "name=ntpd state=running enabled=yes" -s -K
ansible openstack -m service -a "name=ntpd state=started" -s -K
ansible openstack -m service -a "name=ntp state=present" -s -K
ansible openstack -m service -a "name=ntp state=started" -s -K
ansible openstack -m service -a "name=ntp state=start" -s -K

ansible 167.205.23.38 -m service -a "name=rabbitmq-server state=running enabled=


yes" -s -K
ansible 167.205.23.38 -m service -a "service=firewalld state=reloaded" -s -K
ansible 167.205.23.38 -m service -a "service=firewalld state=reloaded" -s -K
ansible mx -m shell -a "echo $TERM" -u root
ansible 167.205.23.38 -m yum -a "name=mariadb,mariadb-server,MySQL-python state=
present" -s -K
ansible openstack -m yum -a "name=mariadb,mariadb-server,MySQL-python state=pres
ent" -s -K
ansible openstack -m yum -a "name=ntp state=present" -s -K
ansible openstack -m yum -a "name=openstack-selinux state=present" -s -K
ansible openstack -m yum -a "name=openstack-selinux state=present" -s -K
ansible 167.205.23.38 -m yum -a "name=rabbitmq-server state=present" -s -K
ansible openstack -m yum -a "name=* state=latest" -s -K
ansible openstack -m yum -a "name=* state=latest" -s -K
# Ebook: Ansible Configuration Management, Daniel Hall
## Machine
Servers where we execute ansible commands: controller machine
Servers which we configure using ansible: managed machine
## Inventory file
example:
cat ./hosts:
[kvm]
vm1 ansible_ssh_user=pras ansible_ssh_host=167.205.1.44
vm2 ansible_ssh_host=167.205.1.45
vms1 ansible_ssh_host=167.205.51.131
VMS1 ansible_ssh_host=167.205.51.135
vms4 ansible_ssh_host=167.205.51.136
ansible_ssh_private_key_file=/home/pras/.ssh/id_rsa
[ai3]
vm1
vm2
[labtek5]
VMS1
vms1
vms4
## Ping module to check connectivity, if no ssh-key configured, use --ask-pass/k to ask ssh password
example:
ansible -i ./hosts ai3 -m ping
vm1 | SUCCESS => {
"changed": false,
"ping": "pong"
}
vm2 | SUCCESS => {
"changed": false,
"ping": "pong"
}
## Setup module to get "facts" about managed machines, use --become/-b and --ask
-become-pass/-K (--become-method=[ sudo | su | pbrun | pfexec | runas | doas | d
zdo ], default sudo) to use sudo
example:
ansible -i ./hosts ai3 -bK -m setup

SUDO password:
vm2 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"167.205.1.45",
"192.168.122.1"
],
...
},
"changed": false
}
vm1 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"167.205.1.44",
"192.168.122.1"
],
...
},
"changed": false
}
## File module for manipulating file in Linux/UNIX
example: check file status
ansible -i ./hosts vm1 -m file -a "path=/etc/fstab"
vm1 | SUCCESS => {
"changed": false,
"gid": 0,
"group": "root",
"mode": "0644",
"owner": "root",
"path": "/etc/fstab",
"size": 962,
"state": "file",
"uid": 0
}
example: create test directory
ansible -i ./hosts vm1 -bK -m file -a "path=/tmp/test state=directory mode=0700
owner=root"
SUDO password:
vm1 | SUCCESS => {
"changed": true,
"gid": 0,
"group": "root",
"mode": "0700",
"owner": "root",
"path": "/tmp/test",
"size": 4096,
"state": "directory",
"uid": 0
}
example: remove file /tmp/testing in managed machine(s)
ansible -i ./hosts vm1 -m file -a 'path=/tmp/testing state=absent'
vm1 | SUCCESS => {
"changed": true,
"path": "/tmp/testing",

"state": "absent"
}
## Copy module which accept similar argument as file module and used to copy fil
es/directories from controller machine to managed machine(s)
example: copy controller /etc/fstab to managed /tmp/fstab
ansible -i ./hosts vm1 -bK -m copy -a "src=/etc/fstab dest=/tmp/fstab mode=0700
owner=root"
SUDO password:
vm1 | SUCCESS => {
"changed": true,
"checksum": "34d76332c6cee1b7bacaa1c8d84b3bb9e3366b50",
"dest": "/tmp/fstab",
"gid": 0,
"group": "root",
"md5sum": "ec8055831664f653d5cf53ce1b1e6ad7",
"mode": "0700",
"owner": "root",
"size": 913,
"src": "/home/pras/.ansible/tmp/ansible-tmp-1466496898.81-140941064107821/so
urce",
"state": "file",
"uid": 0
}
## Command module to execute arbitrary command on managed machine(s), doesn't ru
n command within shell so you cannot perform redirection, use pipes, expand shel
l variables or background command, use creates or removes arguments to help this
module notice any changes, often it is better to use another module in place of
command module
example: remove /tmp/testing from managed machine
ansible -i ./hosts vm1 -m command -a 'rm /tmp/testing removes=/tmp/testing'
vm1 | success | rc=0 >>
skipped, since /tmp/testing does not exist
example: create file /tmp/testing in managed machine
ansible -i ./hosts vm1 -m command -a 'touch /tmp/testing creates=/tmp/testing'
vm1 | success | rc=0 >>
## Shell module to execute commands in shell so you can use redirection, pipes,
or job backgrounding, support creates argument but not removes
example:
ansible machinename -m shell -a '/opt/fancyapp/bin/installer.sh > /var/log/fancy
appinstall.log creates=/var/log/fancyappinstall.log'
## Ansible-doc to get information about ansible module
example: get short description from all module
ansible-doc -l
a10_server
Manage A10 Networks AX/SoftAX/Thunder/vThunde
r devices
a10_service_group
Manage A10 Networks devices' service groups
a10_virtual_server
Manage A10 Networks devices' virtual servers
acl
Sets and retrieves file ACL information.
add_host
add a host (and alternatively a group) to the
ansible-playbook in-memory inventory
...
example: get information from file module
ansible-doc file
> FILE

Sets attributes of files, symlinks, and directories, or removes files/symlinks


/directories. Many other modules support the same options as the [file] module including [copy],
[template], and [assemble].
Options (= is mandatory):
- follow
This flag indicates that filesystem links, if they exist, should be foll
owed. (Choices: yes, no) [Default: no]
- force
force the creation of the symlinks in two cases: the source file does no
t exist (but will appear later); the destination exists and is a file (so, we ne
ed to unlink the
"path" file and create symlink to the "src" file in place of it). (Choic
es: yes, no) [Default: no]
- group
name of the group that should own the file/directory, as would be fed to
`chown' [Default: None]
...
## Ansible playbooks is a method to use ansible scripting ability to full extend
, playbooks in ansible are expressed in YAML and using standard YAML parser, the
command to execute playbook is ansible-playbook
example: execute playbook example-play.yml
ansible-playbook example-play.yml
## Ansible playbooks are made up of one or more plays, a play is consists of thr
ee sections: the target section, the variable section, and the task section
example: a simple example of play
--- hosts: localhost
user: root
vars:
motd_warning: 'WARNING: Use by ACME Employees ONLY'
tasks:
- name: setup a MOTD
copy: dest=/etc/motd content={{ motd_warning }}
### the target section defines hosts on which the play will be run and how it wi
ll run, set ssh username, other ssh-related settings
example: a simple target section
- hosts: webservers
user: root
sudo: [ yes | no ]
user:
sudo_user:
connection: [ local | ssh | paramiko ]
gather_facts: [ true | false ]
### the variable section defines variables which will be made available to the p
lay while running, you can also make ansible prompt for variables if they weren'
t supplied, variables in this section can be overidden by machine facts, but the
y override facts in inventory, you can use placeholders like {{ variablename }},
${variablename}, or $variablename, for complex variables use dotted notation e.
g. {{ httpd.maxclients }}, {{ ansible_eth0.ipv4.address }}, variables in this se
ction do not survive between different plays in the same playbook, however, fact
s gathered by setup module or set by set_fact do, so for second play you can set
gather_facts to false
example: a simple variable section
vars:
apache_version: 2.6

motd_warning: 'WARNING: Use by ACME Employees ONLY'


testserver: yes
example: load variables from external yaml file
vars_files:
/conf/country-AU.yml
/conf/datacenter-SYD.yml
/conf/cluster-mysql.yml
example: external variables yaml file
--ntp: 'ntp1.au.example.com'
TZ: 'Australia/Sydney'
example: ansible variable prompt for sensitive variables or which required human
interaction (e.g. SSL passphrase)
vars_prompt:
- name: 'https_passphrase'
prompt: 'Key Passphrase'
private: yes
### the task section lists all the modules in the order that you want them to be
run by ansible, there are several ways to represent each module configuration,
try to stick with one so the code will be easier to maintain
example: simple task section with three style shown
tasks:
- name: install apache
action: yum name=httpd state=installed
- name: configure apache
copy: src=files/httpd.conf dest=/etc/httpd/conf/httpd.conf
- name: restart apache
service:
name: httpd
state: restarted
### the handlers section lists all modules which only run when they called by mo
dules in task section, just add notify key with value the name of handler
example: handlers section for isc-dhcp service
--- hosts: dhcp
tasks:
- name: update to latest DHCP
action: yum name=dhcp state=latest
notify: restart dhcp
- name: copy the DHCP config
action: copy src=dhcp/dhcpd.conf dest=/etc/dhcp/dhcpd.conf
notify: restart dhcp
- name: start DHCP at boot
action: service name=dhcpd state=started enabled=yes
handlers:
- name: restart dhcp
action: service name=dhcpd state=restarted
example: call multiple handlers from a single task
--- hosts: qroud
tasks:
- name: checkout Qroud
action: git repo=git@github.com:smarthall/Qroud.git dest=/opt/apps/Qroud for
ce=no
notify:
- migrate db
- generate static
- restart httpd

handlers:
- name: migrate db
action: command chdir=/opt/apps/Qroud ./manage.py migrate all
- name: generate static
action: command chdir=/opt/apps/Qroud ./manage.py collectstatic -c noinput
- name: restart httpd
action: service name=httpd state=restarted
## Playbook modules consist of modules which cannot run in command line because
they depends on facts gathered from setup modules and other modules which can ru
n in command line but are able to provide enhanced functionalities when used in
a playbook
### the template module requires facts from ansible and allows you to design an
outline of a configuration file then have ansible insert values in the right pla
ces using jinja2 and also use complex structures such as conditional, loops, and
macros
example: jinja2 template for BIND configuration
# {{ ansible_managed }}
options {
listen-on port 53 {
127.0.0.1;
{% for ip in ansible_all_ipv4_addresses %}
{{ ip }};
{% endfor %}
};
listen-on-v6 port 53 { ::1; };
directory
"/var/named";
dump-file
"/var/named/data/cache_dump.db";
statistics-file "/var/named/data/named_stats.txt";
memstatistics-file "/var/named/data/named_mem_stats.txt";
};
zone "." IN {
type hint;
file "named.ca";
};
include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";
{# Variables for zone config #}
{% if 'authorativenames' in group_names %}
{% set zone_type = 'master' %}
{% set zone_dir = 'data' %}
{% else %}
{% set zone_type = 'slave' %}
{% set zone_dir = 'slaves' %}
{% endif %}
zone "internal.example.com" IN {
type {{ zone_type }};
file "{{ zone_dir }}/internal.example.com";
{% if 'authorativenames' not in group_names %}
masters { 192.168.2.2; };
{% endif %}
};
example: using template module on playbook
--- name: Setup BIND
host: allnames
tasks:
- name: configure BIND
template: src=templates/named.conf.j2 dest=/etc/named.conf

owner=root group=named mode=0640


### the set_fact module allows you to build your own facts on the machine inside
an ansible play, you should use this to avoid putting complex logic into templa
tes
example: configure mysql server to have an innodb buffer size approximately hal
f of the total ram available
--- name: Configure MySQL
hosts: mysqlservers
tasks:
- name: install MySql
yum: name=mysql-server state=installed
- name: Calculate InnoDB buffer pool size
set_fact: innodb_buffer_pool_size_mb="{{ ansible_memtotal_mb / 2 }}"
- name: Configure MySQL
template: src=templates/my.cnf.j2 dest=/etc/my.cnf owner=root group=root mod
e=0644
notify: restart mysql
- name: Start MySQL
service: name=mysqld state=started enabled=yes
handlers:
- name: restart mysql
service: name=mysqld state=restarted
example: template file for configure mysql server
# {{ ansible_managed }}
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# Settings user and group are ignored when systemd is used.
# If you need to run mysqld under a different user or group,
# customize your systemd unit file for mysqld according to the
# instructions in http://fedoraproject.org/wiki/Systemd
# Configure the buffer pool
innodb_buffer_pool_size = {{ innodb_buffer_pool_size_mb|default(128) }}M
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
### the pause module stop execution of playbook for a certain period of time, yo
u should not use it for waiting for networked daemons to start up, you should us
e wait_for module
example: using the pause module first in the user interactive mode and then in t
he timed mode
--- hosts: localhost
tasks:
- name: wait on user input
pause: prompt="Warning! Detected slight issue. ENTER to continue CTRL-C a to
quit."
- name: timed wait
pause: seconds=30
### the wait_for module is used to poll a particular tcp port and not continue u
ntil that port accepts a remote connection
example: use wait_for to recognize tomcat is ready to accept connection
--- hosts: webapps

tasks:
- name: Install Tomcat
yum: name=tomcat7 state=installed
- name: Start Tomcat
service: name=tomcat7 state=started
- name: Wait for Tomcat to start
wait_for: port=8080 state=started
### the assemble module combines several files in managed machine and saves them
to another file on the managed machine
example: this play will send a bunch of ssh public keys and assemble it in root
user's home directory
--- hosts: all
tasks:
- name: Make a Directory in /opt
file: path=/opt/sshkeys state=directory owner=root group=root mode=0700
- name: Copy SSH keys over
copy: src=keys/{{ item }}.pub dest=/opt/sshkeys/{{ item }}.pub owner=root gr
oup=root mode=0600
with_items:
- dan
- kate
- mal
- name: Make the root users SSH config directory
file: path=/root/.ssh state=directory owner=root group=root mode=0700
- name: Build the authorized_keys file
assemble: src=/opt/sshkeys dest=/root/.ssh/authorized_keys owner=root group=
root mode=0700
### the add_host module lets you dynamically add new machine inside a play, the
module takes a hostname and groups argument
### the group_by module can create groups based on the facts about the machine,
the group_by module accept one argument: key
example: create group based on operating systems
--- name: Create operating system group
hosts: all
tasks:
- group_by: key=os_{{ ansible_distribution }}
- name: Run on CentOS hosts only
hosts: os_CentOS
tasks:
- name: Install Apache
yum: name=httpd state=latest
- name: Run on Ubuntu hosts only
hosts: os_Ubuntu
tasks:
- name: Install Apache
apt: pkg=apache2 state=latest
## Advanced playbooks using many techniques to give much more control over the e
xecution of your playbook
## ansible can run operation in parallel, by default ansible will fork up to fiv
e times so it will run an operation on five different machine at once, if you ha
ve large number of machine or have lowered this maximum fork value, then you may
want to launch things asynchronously, to run an operation in parallel, use the
async and poll keywords, the async keyword triggers ansible to run the job in pa

rallel and its value will be the maximum time that ansible will wait for the com
mand to complete, the value of poll indicates to ansible how often to poll to ch
eck if the command has been completed
example: play to run updatedb across entire cluster
e following code:
- hosts: all
tasks:
- name: Install mlocate
yum: name=mlocate state=installed
- name: Run updatedb
command: /usr/bin/updatedb
async: 300
poll: 10
## you will want to use ansible's polling in the following situations: you have
a long-running task that may hit the timeout, you need to run an operation acros
s a large number of machines, you have an operation for which you don't need to
wait to complete. there are also a few situations where you should not use async
or poll: if your job acquires locks that prevent other things from running, you
job only takes a short time to run
## looping: ansible allow you to repeat a module several times with different in
put using with_items key, in addition, ansible can also use what are called look
up plugins, these plugins allow you to tell ansible to fetch the data from somew
here else
example: secure config files
tasks:
- name: Secure config files
file: path=/etc/{{ item }} mode=0600 owner=root group=root
with_items:
- my.cnf
- shadow
- fstab
example: upload public keys in a directory and then assemble them in authorized_
keys file for the root user
tasks:
- name: Make key directory
file: path=/root/.sshkeys ensure=directory mode=0700 owner=root group=root
- name: Upload public keys
copy: src={{ item }} dest=/root/.sshkeys mode=0600 owner=root group=root
with_fileglob:
- keys/*.pub
- name: Assemble keys into authorized_keys file
assemble: src=/root/.sshkeys dest=/root/.ssh/authorized_keys mode=0600 owner=
root group=root
## repeating modules can be used in the following situations: repeating a module
many times with similar settings, iterating over all the values of a fact that
is a list, used to create many files for later use with the assemble module to
combine into one large file, used with_fileglob to copy a directory of files usi
ng the glob pattern matching
## conditional execution: some modules, such as the copy module, provide mechani
sm to configure it to skip the module at certain condition, to skip a module you
can use the when key
example: choose between apt and yum for debian and redhat system
--- name: Install VIM
hosts: all
tasks:

- name: Install VIM via yum


yum: name=vim-enhanced state=installed
when: ansible_os_family == "RedHat"
- name: Install VIM via apt
apt: name=vim state=installed
when: ansible_os_family == "Debian"
- name: Unexpected OS family
debug: msg="OS Family {{ ansible_os_family }} is not supported" fail=yes
when: not ansible_os_family == "RedHat" or ansible_os_family == "Debian"
## there are numerous uses of skipping actions; here are a few suggestions: work
ing around differences in operating systems, prompting a user and only then perf
orming actions that they request, improving performance by avoiding a module tha
t you know won't change anything but may take a while to do so, refusing to alte
r systems that have a particular file present, checking if custom written script
s have already been run
## task delegation: if you need to perform an action on a different host than th
e one ansible is operation on, you can use delegation using the delegate_to key
example: a playbook that will use the get_url option to download the configurati
on from a bunch of webservers
--- name: Fetch configuration from all webservers
hosts: webservers
tasks:
- name: Get config
get_url: dest=configs/{{ ansible_hostname }} force=yes url=http://{{ ansib
le_hostname }}/diagnostic/config
delegate_to: localhost
example: shortcut to delegate to the localhost using the local_action key
--- name: Fetch configuration from all webservers
hosts: webservers
tasks:
- name: Get config
local_action: get_url dest=configs/{{ ansible_hostname }}.cfg url=http://{
{ ansible_hostname }}/diagnostic/config
## delegation is not limited to the local machine. you can delegate to any host
that is in the inventory. some other reasons why you might want to delegate are:
removing a host from a load balancer before deployment, changing dns to direct
traffic away from a server you are about to change, creating an iscsi volume on
a storage device, using an external server to check that access outside the netw
ork works
## extra variables:
### The hostvars variable allows you to retrieve variables about all the hosts t
hat the current play has dealt with
example: sets a variable called zone master to the server
--- name: Setup DNS Servers
hosts: allnameservers
tasks:
- name: Install BIND
yum: name=named state=installed
- name: Setup Slaves
hosts: slavenamesservers
tasks:
- name: Get the masters IP
set_fact: dns_master="{{ hostvars.ns1.ansible_default_ipv4.address }}"

- name: Configure BIND


template: dest=/etc/named.conf src/templates/named.conf.j2
### to find the address of a machine named in the variable the_machine you would
use, {{ hostvars.[the_machine].default_ipv4.address }}
### The groups variable containes a list of all hosts in the inventory grouped b
y inventory group
example: play to configure database
--- name: Configure the database
hosts: dbservers
user: root
tasks:
- name: Install mysql
yum: name={{ item }} state=installed
with_items:
- mysql-server
- MySQL-python
- name: Start mysql
service: name=mysqld state=started enabled=true
- name: Create a user for all app servers
with_items: groups.appservers
mysql_user: name=kate password=test host={{ hostvars.[item].ansible_eth0.i
pv4.address }} state=present
example: play create a known_hosts files for all of your machines containing hos
t keys of all other machines
--hosts: all
tasks:
- name: Setup known hosts
hosts: all
tasks:
- name: Create known_hosts
template: src=templates/known_hosts.j2
dest=/etc/ssh/ssh_known_hosts owner=root group=root mode=0644
example: known_hosts.j2 template
{% for host in groups['all'] %}
{{ hostvars[host]['ansible_hostname'] }} {{ hostvars[host]['ansible_ssh_host_key
_rsa_public'] }}
{% endfor %}
### The group_names variable contains a list of strings with the names of all th
e groups the current host is in, the variable is mostly useful for skipping a ta
sk or in a template as a condition
example: play to configure secure and less secure sshd
- name: Setup SSH
hosts: sshservers
tasks:
- name: For secure machines
set_fact: sshconfig=files/ssh/sshd_config_secure
when: "'secure' in group_names"
- name: For non-secure machines
set_fact: sshconfig=files/ssh/sshd_config_default
when: "'secure' not in group_names"
- name: Copy over the config
copy: src={{ sshconfig }} dest=/tmp/sshd_config
### The inventory_hostname variable stores the hostname of the server as recorde
d in the inventory, you should use this if you have chosen not to run the setup

module on the current host or if for various reasons the value detected by the s
etup module is not correct, this is useful when you are doing the initial setup
of the machine and changing the hostname
### The inventory_hostname_short variable is same as previous one, however, it o
nly includes the characters up to the first dot
### The inventory_dir variable is the path name of the directory containing the
inventory file
### The inventory_file variable is the same as previous one except it is also in
clude the filename
## you can dereference variables in all module argument using {{ and }}, you can
also find files using variables
example: play to select different config file for NRPE based on architecture
--- name: Configure NRPE for the right architecture
hosts: ansibletest
user: root
tasks:
- name: Copy in the correct NRPE config file
copy: src=files/nrpe.{{ ansible_architecture }}.conf dest=/etc/nagios/nrpe
.cfg
example: check several config file and get the first file found using copy
--- name: Install an Apache config file
hosts: ansibletest
user: root
tasks:
- name: Get the best match for the machine
copy: dest=/etc/apache.conf src={{ item }}
first_available_file:
- files/apache/{{ ansible_os_family }}-{{ ansible_architecture }}.cfg
- files/apache/default-{{ ansible_architecture }}.cfg
- files/apache/default.cfg
## environment variables can be used in ansible to set remote access
example: play to upload a remote file via S3
--- name: Upload a remote file via S3
hosts: ansibletest
user: root
tasks:
- name: Setup EPEL
command rpm -ivh http://download.fedoraproject.org/pub/epel/6/i386/epel-re
lease-6-8.noarch.rpm creates=/etc/yum.repos.d/epel.repo
- name: Install pip
yum: name=python-pip state=installed
- name: Install the AWS tools
pip: name=awscli state=present
- name: Upload the file
shell: aws s3 put-object --bucket=my-test-bucket --key={{ ansible_hostname
}}/fstab --body=/etc/fstab --region=eu-west-1
environment:
AWS_ACCESS_KEY_ID: XXXXXXXXXXXXXXXXXXX
AWS_SECRET_ACCESS_KEY: XXXXXXXXXXXXXXXXXXXXX
## some ansible modules such as get_url, yum, and apt will also use environment
variables to set their proxy server, some of the other situations where you migh

t want to set environment variables are as follows: running application installe


rs, adding extra items to the path when using the shell module, loading librarie
s from a place not included in the system library search path, using an ld_prelo
ad hack while running a module
## you can do external data lookup using ansible to fetch data from outside sour
ces like environment variables from controller machine
example: get http_proxy value from environment and send it through to the config
ured machine
--- name: Downloads a file using the same proxy as the controlling machine
hosts: all
tasks:
- name: Download file
get_url: dest=/var/tmp/file.tar.gz url=http://server/file.tar.gz
environment:
http_proxy: "{{ lookup('env', 'http_proxy') }}"
example: dynamically register a webapp farm using with_sequence
--- name: Registers the app server farm
hosts: localhost
connection: local
vars:
hostcount: 5
tasks:
- name: Register the webapp farm
local_action: add_host name={{ item }} groupname=webapp
with_sequence: start=1 end={{ hostcount }} format=webapp%02x
## situations where lookup plugins are useful are as follows: copying a whole di
rectory of apache config to a conf.d style directory, using environment variable
s to adjust what the playbooks does, getting configuration from dns txt records,
fetching the output of a command into a variable
## you can store the returned variable from ansible modules and use them later i
n the playbook using the register key
example: play to look at the mode in the /tmp directory and create new directory
with the same mode
--- name: Using register
hosts: ansibletest
user: root
tasks:
- name: Get /tmp info
file: dest=/tmp state=directory
register: tmp
- name: Set mode on /var/tmp
file: dest=/tmp/subtmp mode={{ tmp.mode }} state=directory
## register allows you to make your own facts about hosts from modules already a
vailable to you. this can be useful in many different circumstances: getting a l
ist of files in a remote directory and downloading them all with fetch, running
a task when a previous task changes, before the handlers run, getting the conten
ts of the remote host ssh key and building a known_hosts file
## you can debug playbooks using ansible verbose mode or a debug module, you can
also use modules such as fetch and get_url for help
### The debug module takes two optional arguments, msg and fail, msg sets the me
ssage that will be printed by the module and fail, if set to yes indicates a fai
lure to ansible, which will stop playbook execution for that host

example: use debug module to list all the interfaces available on the machine
--- name: Demonstrate the debug module
hosts: ansibletest
user: root
vars:
hostcount: 5
tasks:
- name: Print interface
debug: msg="{{ item }}"
with_items: ansible_interfaces
output:
PLAY [Demonstrate the debug module] *********************************
GATHERING FACTS *****************************************************
ok: [ansibletest]
TASK: [Print IP address] ********************************************
ok: [ansibletest] => (item=lo) => {"item": "lo", "msg": "lo"}
ok: [ansibletest] => (item=eth0) => {"item": "eth0", "msg": "eth0"}
PLAY RECAP **********************************************************
ansibletest
: ok=2 changed=0 unreachable=0 failed=0
### The verbose mode is other option for debugging, especially useful if you are
using the register keyword, simply add --verbose to command-line
### The check mode instructs ansible to walk through the play without actually m
aking any changes to remote systems, ansible also has diff mode which shows the
changes that are made by the template module
### The pause module is used to pause the playbook while you examine the configu
red machine as it runs
## Larger projects need special methods to prevent things from going out of cont
rol, such as: separating playbooks into different files and including them from
some other location, using roles to include multiple files that perform a simila
r function, methods for increasing speed at which ansible configures your machin
es
## you can use includes to split your plays into multiple section and then inclu
de each section from other plays, there are four types of includes: variable inc
ludes which allow you to put your variables in external yaml files, playbook inc
ludes which is used to include plays from other files in a single play, task inc
ludes which let you put common tasks in other files and include them wherever re
quired, handler includes which let you put all your handlers in the one place
## task includes can be used when you have a lot of common tasks that will be re
peated, task includes inherit facts from the play they are included from and you
can also provide your own variables, task includes can have conditionals applie
d on them, the file to include as a task includes contains a list of tasks
example: task includes to create a bunch of users and set up their environment w
ith their public keys
--# Requires a user variable to specify user to setup
- name: Create user account
user: name={{ user }} state=present
- name: Make user SSH config dir
file: path=/home/{{ user }}/.ssh owner={{ user }} group={{ user }} mode=0600 s
tate=directory
- name: Copy in public key
copy: src=keys/{{ user }}.pub dest=/home/{{ user }}/.ssh/authorized_keys mode=
0600 owner={{ user }} group={{ user }}

example: play which use task includes above


--- hosts: ansibletest
user: root
tasks:
- include: usersetup.yml user={{ item }}
with_items:
- mal
- dan
- kate
## handler includes look same as task includes and allow you to reuse same handl
ers multiple times, ansible allows you to include other files in the handlers se
ction
example: a tipical handler include file after configuring email
--- name: config sendmail
command: make -C /etc/mail
notify: reload sendmail
- name: config aliases
command: newaliases
notify: reload sendmail
- name: reload sendmail
service: name=sendmail state=reloaded
- name: restart sendmail
service: name=sendmail state=restarted
example: play which use handler include above
--hosts: mailers
tasks:
- name: update sendmail
yum: name=sendmail state=latest
notify: restart sendmail
- name: configure sendmail
template: src=templates/sendmail.mc.j2 dest=/etc/mail/sendmail.mc
notify: config sendmail
handlers:
- include: sendmailhandlers.yml
## playbook includes should be used when you want to include a whole set of task
s designated for a set of machines, it allows you to include the whole plays, th
is is handy when you want to run multiple different actions at once
example: use multiple playbooks for site upgrade operation
--- include "drfailover.yml"
- include "upgradeapp.yml"
- include "drfailback.yml"
- name: Notify management
hosts: local
tasks:
- local_action: mail to="mgmt-team@example.com" msg='The application has bee
n upgraded and is now live'
- include "drupgrade.yml"
## roles allow you to group files together in a defined format, roles allows you
to place your variables, files, tasks, templates, and handlers in a folder, the
n easily include them, roles are commonly set up to be services provided by mach
ines, but they can also be daemons, options, or simply characteristics
## things you may want to configure in a role are as follows: webservers, such a
s nginx, apache; messages of the day customized for the security level of the ma

chine, database servers running postgresql or mysql


## to manage roles in ansible perform the following steps:
1. Create a folder named roles with your playbooks.
2. In the roles folder, make a folder for each role that you would like.
3. In the folder for each role, make folders named files, handlers, meta, tasks,
templates, and finally vars. If you aren't going to use all these, you can leav
e the ones you don't need off. Ansible will silently ignore any missing files or
directories when using roles.
4. In your playbooks, add the keyword roles followed by a list of roles that you
would like to apply to the hosts.
5. For example, if you had the common, apache, website1, and website2 roles, you
r directory structure would look similar to the following example. The site.yml
file is for reconfiguring the entire site, and the webservers1.yml and webserver
s2.yml files are for configuring each web server farm.
example: tree directory of roles
+- inventory.ini
+- roles
| +- apache
| | +- files
| | +- handlers
| | | +- main.yml
| | +- meta
| | +- tasks
| | | +- main.yml
| | +- templates
| | | +- httpd.conf.j2
| | +- vars
| |
+- main.yml
| +- common
| | +- files
| | | +- bashrc
| | +- handlers
| | +- meta
| | +- tasks
| | | +- main.yml
| | +- templates
| | | +- motd.j2
| | +- vars
| |
+- main.yml
| +- website1
| | +- files
| | +- handlers
| | | +- main.yml
| | +- meta
| | +- tasks
| | | +- main.yml
| | +- templates
| | | +- environment.yml.j2
| | | +- website1.conf.j2
| | +- vars
| |
+- main.yml
| +- website1
|
+- files
|
+- handlers
|
| +- main.yml
|
+- meta
|
+- tasks
|
| +- main.yml
|
+- templates

|
| +- environment.yml.j2
|
| +- website2.conf.j2
|
+- vars
|
+- main.yml
+- website1.yml
+- website2.yml
example: example content of website1.yml
--- name: Setup servers for website1.example.com
hosts: website1
roles:
- common
- apache
- { role: website1, port: 80 }
## ansible will then try to load roles/common/tasks/main.yml as a task include,
roles/common/handlers/main.yml as a handler include, and roles/common/vars/main.
yml as a variable file include, if all of these files are missing, ansible will
throw an error, however, if one of the files exists then the others, if missing,
will be ignored, the following directories are used by a default install of ans
ible
## other directories may be used by different modules:
1. tasks: the tasks folder should contain a main.yml file, which should include
a list of the tasks for this role, any task includes that are contained in these
roles will look for their files in this folder also, this allows you to split a
large number of tasks into separate files, and use other features of task inclu
des
2. files: the files folder is the default location for files in the roles that a
re used by the copy or the script module
3. templates: the templates directory is the location where the template module
will automatically look for the jinja2 templates included in the roles
4. handlers: the handlers folder should contain a main.yml file, which specifies
the handlers for the roles, and any includes in that folder will also look for
the files in the same location
5. vars: the vars folder should contain a main.yml file, which contains the var
iables for this role
6. meta: the meta folder should contain a main.yml file, this file can contain s
ettings for the role, and a list of its dependencies, this feature is available
only in ansible 1.3 and above
7. defaults: you should use the default folder if you are expecting variables to
be sent to this roles, and you want to make them optional, a main.yml file in t
his folder is read, to get the initial values for variables that can be overridd
en by variables, which are passed from the playbook calling the role, this featu
re is only available in ansible 1.3 and above
## ansible 1.3 have two new features, the first feature is the metadata roles, t
he allow you to specify that your role depends on the other roles, the second fe
ature is variable defaults values, if you place a main.yml file in the default d
irectory for the role, these variables will be read into the role, however they
can be overridden by variables in the vars/main.yml
example: a simple meta/main.yml
--allow_duplicates: no
dependencies:
- apache
example: a simple defaults/main.yml
--port: 80

## there are several tricks to make ansible work faster on bigger scale, ansible
tags are feature that allow you to select which parts of a playbook you need to
run and which should be skipped, if you know you don't need certain actions to
be run, you can select only run modules that have been tagged with a particular
tag, if you don't specify tags on command-line the default action is to run ever
y tasks
example: install and setup webserver using tag
--- name: Install and setup our webservers
hosts: webservers
tasks:
- name: install latest software
action: yum name=$item state=latest
notify: restart apache
tags:
- patch
with_items:
- httpd
- webalizer
- name: Create subdirectories
action: file dest=/var/www/html/$item state=directory mode=755 owner=apache
group=apache
tags:
- deploy
with_items:
- pub
- name: Copy in web files
action: copy src=website/$item dest=/var/www/html/$item mode=755 owner=apach
e group=apache
tags:
- deploy
with_items:
- index.html
- logo.png
- style.css
- app.js
- pub/index.html
- name: Copy webserver config
tags:
- deploy
- config
action: copy src=website/httpd.conf dest=/etc/httpd/conf/httpd.conf mode=644
owner=root group=root
notify: reload apache
- name: set apache to start on startup
action: service name=httpd state=started enabled=yes
handlers:
- name: reload apache
service: name=httpd state=reloaded
- name: restart apache
service: name=httpd state=restarted
example: run a playbook with tags
$ ansible-playbook webservers.yml --tags deploy
example: configure roles to execute with tags
--- hosts: website1
roles:
- common
- { role: apache, tags: ["patch"] }
- { role: website2, tags: ["deploy", "patch"] }

## ansible include pull mode which can drastically improve the scalability of yo
ur playbooks, in this mode, you provide your configuration in a git repository w
hich ansible downloads and uses to configure your machine, pull mode requires so
me setup on the nodes you want configured
example: setup play mode on a machine
--- name: Ansible Pull Mode
hosts: pullhosts
tasks:
- name: Setup EPEL
action: command rpm -ivh http://download.fedoraproject.org/pub/epel/6/i386
/epel-release-6-8.noarch.rpm creates=/etc/yum.repos.d/epel.repo
- name: Install Ansible + Dependencies
yum: name={{ item }} state=latest enablerepo=epel
with_items:
- ansible
- git-core
- name: Make directory to put downloaded playbooks in
file: state=directory path=/opt/ansiblepull
- name: Setup cron
cron: name="ansible-pull" user=root minute="*/5" state=present job="ansibl
e-pull -U https://git.int.example.com.com/gitrepos/ansiblepull.git -D /opt/ansib
lepull {{ inventory_hostname_short }}.yml"
## you should use ansible's pull mode in the following situations: your node mi
ght not be available when configuring them, such as members of auto-scaling serv
er farms; you have a large amount of machines to configure and even with large v
alues of forks, it would take a long time to configure them all; you want machin
es to update their configuration automatically when the repository changes; you
want to run ansible on a machine that may not have network access yet, such as i
n a kick start post install
## however, pull mode does have the following disadvantages that make it unsuita
ble for certain circumstances: to connect to other machines and gather variables
, or copy a file you need to have credentials on the managed nodes; you need to
co-ordinate the running of the playbook across a server farm, for example, if yo
u could only take three servers offline at a time; the servers are behind strict
firewalls that don't allow incoming ssh connections from the nodes you use to c
onfigure them for ansible

S-ar putea să vă placă și