EX407 Study Notes
EX407 Study Notes
## Exam objectives:
#---------------------------------------------------------------------
$ ansible --version
ansible 2.7.9
config file = /home/ansible/ansible.cfg
$ cp /etc/ansible/ansible.cfg ~/ansible.cfg
$ cp /etc/ansible/hosts ~/inventory
forks 5
$ cat ~/inventory
[myself]
127.0.0.1 ansible_connection=local
[web]
ansible[2:3].hl.local
[db]
ansible[4:5].hl.local ansible_user=dbadmin
[lab:children]
web
db
## There is a special group named "all" that matches all managed hosts
## in the inventory.
- hosts: all
- hosts: ungrouped
## Quote host patterns used on the CLI to protect them from unwanted
## shell expansion:
- hosts: '*.hl.local'
- hosts: '10.11.1.*'
- hosts: web,ansible3.hl.local
$ vim ansible.cfg
[privilege_escalation]
become = false
become_method = sudo
become_user = root
become_ask_pass = false
$ vim ansible.cfg
remote_user = ansible
$ vim ansible.cfg
log_path = /home/ansible/ansible.log
## NOTE: if possible, try to avoid the command, shell and raw modules
## in playbooks! It's easy to write non-idempotent playbooks this way.
$ ansible-doc -l
$ ansible-doc -s <module_name>
$ ansible-doc <module_name>
## Ansible executes plays and tasks in the order they are presented!
## How to check for YAML syntax errors:
## Playbook dry-run:
$ ansible-playbook -C <playbook>.yaml
## The beginning of each play begins with a single dash followed by a space.
## Playbook attributes:
##
## name - can be used to give a descriptive label to a play.
## hosts - must be defined in every play.
## remote_user - can be used to define the user that runs the tasks.
## become - can be used to enable privilege escalation.
## become_method - can be used to define the privilege escalation method.
## become_user - can define the user account to be used for privilege escalation.
## tasks - is defined as a list of dictionaries.
## blocks - can be used to group related tasks together.
## For each play in a playbook, you get to choose which machines in your
## infrastructure to target and what remote user to complete the steps as.
## You can use keyword "become" on a particular task instead of the play:
---
- hosts: webservers
remote_user: ansible
serial: 2
tasks:
- service:
name: httpd
state: started
become: yes
become_method: sudo
## Use the serial keyword to run the hosts through the play in batches.
## Host variables take precedence over group variables, but variables
## defined by a playbook take precedence over both.
#---------------------------------------------------------------------
## Note: "include" was replaced in Ansible 2.4 with new directives such
## as include_tasks, import_tasks, and import_playbook.
## These can be used to enhance the ability to reuse tasks and playbooks:
import_playbook:
import_tasks:
include_tasks:
## Examples:
tasks:
- name: Import task file and use variables
import_tasks: task.yml
vars:
package: vsftpd
service: vsft
#---------------------------------------------------------------------
## Settings explained:
#---------------------------------------------------------------------
#---------------------------------------------------------------------
## At the time of writing this, Ansible recognises both the new fact
## naming system (using ansible_facts) and the old pre 2.5 naming system
## where facts are injected as separate variables.
## You can use an ad hoc command to run the setup module to print the
## value of all facts:
## Filter results:
ansible_facts['hostname']
ansible_facts['fqdn']
ansible_facts['default_ipv4']['address']
ansible_facts['distribution']
ansible_facts['distribution_major_version']
ansible_facts['domain']
ansible_facts['memtotal_mb']
ansible_facts['processor_count']
## To disable fact gathering for a play, you can set the gather_facts
## keyword to "no":
gather_facts: no
#---------------------------------------------------------------------
## Ansible supports iterating a task over a set of items using the loop
## keyword. A simple loop iterates a task over a list of items.
## Since Ansible 2.5, the recommended way to write loops is to use the
## loop keyword. The old syntax used loops prefixed with "with_".
## Example conditionals:
Equal | ==
Less than | <
Greater than | >
Variable exists | is defined
Variable does not exist | is not defined
Boolean is true | values of 1, True, or yes evaluate to true
vars:
motd_value: "{{ lookup('file', '/etc/motd') }}"
tasks:
- debug:
msg: "motd value is {{ motd_value }}"
handlers:
- name: restart httpd service
service:
name: httpd
state: restarted
## If a task fails and the play aborts on that host, any handlers that
## had been notified by earlier tasks in the play will not run.
## Use the following to force execution of the handler:
force_handlers: yes
## Ignore errors:
ignore_errors: yes
#---------------------------------------------------------------------
## The file module acts like chcon when setting file contexts:
#---------------------------------------------------------------------
#---------------------------------------------------------------------
$ cat templates/index.j2
The system kernel is: {{ ansible_kernel }}
#---------------------------------------------------------------------
## As of Ansible 2.4, you can use roles inline with any other tasks
## using import_role or include_role:
---
- hosts: webservers
tasks:
- debug:
msg: "before we run our role"
- import_role:
name: example
- include_role:
name: example
- debug:
msg: "after we ran our role"
- src: http://katello.hl.local/pub/ansible-haproxy.tar.gz
name: haproxy
- src: http://katello.hl.local/pub/ansible-mysql.tar.gz
name: mysql
---
- hosts: webservers
roles:
- webservers
## Role dependencies are always executed before the role that includes
## them, and may be recursive.
$ ansible-galaxy list
- rhel-system-roles.selinux, (unknown version)
- linux-system-roles.network, (unknown version)
- rhel-system-roles.postfix, (unknown version)
- rhel-system-roles.timesync, (unknown version)
- rhel-system-roles.kdump, (unknown version)
- linux-system-roles.timesync, (unknown version)
- linux-system-roles.kdump, (unknown version)
- linux-system-roles.postfix, (unknown version)
- rhel-system-roles.network, (unknown version)
- linux-system-roles.selinux, (unknown version)
#---------------------------------------------------------------------
## Variables for hosts and host groups can be defined by creating two
## directories, group_vars and host_vars, in the same working directory
## as the inventory file or directory.
$ cat group_vars/webserver
my_package: httpd
$ cat group_vars/database
my_package: mariadb
## Whether or not you define any variables, you can access information
## about your hosts with the Special Variables Ansible provides,
## including "magic" variables, facts, and connection variables.
## The most commonly used magic variables are:
hostvars
groups
group_names
inventory_hostname
tasks:
- name: Install webserver packages
package:
name: "{{ item }}"
state: latest
loop:
- httpd
- firewalld
when: "'webserver' in group_names"
## The hostvars variable lets you access variables for another host,
## including facts that have been gathered about that host.
{{ hostvars['ansible2.hl.local']['ansible_default_ipv4']['address'] }}
{{ hostvars['ansible2.hl.local']['ansible_fqdn'] }}
#---------------------------------------------------------------------
## Meta tasks are a special kind of task which can influence Ansible
## internal execution or state. Choices:
* flush_handlers
* refresh_inventory
* noop
* clear_facts
* clear_host_errors
* end_play
* reset_connection
## Example meta task for how to run handlers after an error occurred:
tasks:
- name: Attempt and graceful roll back demo
block:
- debug:
msg: 'I execute normally'
notify: run me even after an error
- command: /bin/false
rescue:
- name: make sure all handlers run
meta: flush_handlers
handlers:
- name: run me even after an error
debug:
msg: 'This handler runs even on error'
#---------------------------------------------------------------------
- name: this task will run under checkmode and not change the system
lineinfile:
line: "PermitRootLogin no"
dest: /etc/ssh/sshd_config
state: present
check_mode: yes
## The above will force a task to run in check mode, even when the
## playbook is called without --check.
#---------------------------------------------------------------------
## The debugger keyword can be used on any block where you provide
## a name attribute, such as a play, role, block or task.
---
- hosts: ansible2.hl.local
tasks:
- unarchive:
src: files/archive.tgz
dest: /tmp/
remote_src: no
- name: archive file
debugger: on_failed
archive:
path: /tmp/archive.html
dest: /tmp/file.gz
format: tgz
#---------------------------------------------------------------------
## Playbooks will stop executing any more steps on a host that has a
## task fail. To ignore this behaviour, set "ignore_errors" to true:
## This is useful when you expect a task to fail. For example, you
## are checking if Apache website is reachable. It may be unreachable,
## but you don't want the play to fail because of that.
#---------------------------------------------------------------------
## There may be a need to only run a task one time for a batch of hosts:
## This can be achieved by configuring "run_once" on a task:
- command: /tmp/upgrade_database.sh
run_once: true
#---------------------------------------------------------------------
## There will be cases when you will need to abort the entire play on
## failure, not just skip remaining tasks for a host, to avoid breaking
## the system. The "any_errors_fatal" play option will mark all hosts
## as failed if any fails, causing an immediate abort:
- hosts: all
any_errors_fatal: true
roles:
- database
#---------------------------------------------------------------------
any_errors_fatal
become
become_method
become_user
check_mode
debugger
force_handlers
gather_facts
handlers
hosts
ignore_errors
name
no_log
order
port
post_tasks
pre_tasks
remote_user
roles
run_once
serial
tasks
vars
vars_files
always
block
rescue
when
loop
register
#---------------------------------------------------------------------
- hosts: all
become: true
module_defaults:
file:
owner: root
group: devops
mode: "664"
state: touch
tasks:
- file:
path: /tmp/file1
- file:
path: /tmp/file2
- file:
path: /tmp/file3
## It is a time saver when you need to use the same module repeatedly.
#---------------------------------------------------------------------