├── .drone.yml
├── .gitignore
├── .gitmodules
├── .travis.yml
├── README.md
├── advanced
├── chapter_00.yml
├── chapter_01.yml
├── chapter_02.yml
├── chapter_03.yml
├── chapter_04.yml
├── chapter_05.yml
├── chapter_06.yml
├── chapter_07.yml
├── chapter_08.yml
├── chapter_09.yml
├── chapter_10.yml
├── chapter_11.yml
├── resources
│ ├── chapter06
│ │ └── shot1.png
│ └── hosts
│ │ ├── hosts.graphml
│ │ ├── hosts.png
│ │ └── hosts.svg
└── root.yml
├── advanced_lab
├── .advanced_lab
├── chapter_05
│ └── variable_override.yml
├── chapter_07
│ ├── secrets.yml
│ └── vault-test.yml
├── chapter_08
│ ├── lab.yml
│ └── lamp_haproxy
│ │ ├── README.md
│ │ ├── group_vars
│ │ ├── all
│ │ ├── dbservers
│ │ ├── lbservers
│ │ └── webservers
│ │ ├── hosts
│ │ ├── roles
│ │ ├── base-apache
│ │ │ └── tasks
│ │ │ │ └── main.yml
│ │ ├── common
│ │ │ ├── files
│ │ │ │ ├── RPM-GPG-KEY-EPEL-6
│ │ │ │ └── epel.repo
│ │ │ ├── handlers
│ │ │ │ └── main.yml
│ │ │ ├── tasks
│ │ │ │ └── main.yml
│ │ │ └── templates
│ │ │ │ ├── iptables.j2
│ │ │ │ └── ntp.conf.j2
│ │ ├── haproxy
│ │ │ ├── handlers
│ │ │ │ └── main.yml
│ │ │ ├── tasks
│ │ │ │ └── main.yml
│ │ │ └── templates
│ │ │ │ └── haproxy.cfg.j2
│ │ ├── nagios
│ │ │ ├── files
│ │ │ │ ├── ansible-managed-services.cfg
│ │ │ │ ├── localhost.cfg
│ │ │ │ └── nagios.cfg
│ │ │ ├── handlers
│ │ │ │ └── main.yml
│ │ │ ├── tasks
│ │ │ │ └── main.yml
│ │ │ └── templates
│ │ │ │ ├── dbservers.cfg.j2
│ │ │ │ ├── lbservers.cfg.j2
│ │ │ │ └── webservers.cfg.j2
│ │ └── web
│ │ │ └── tasks
│ │ │ └── main.yml
│ │ ├── rolling_update.yml
│ │ └── site.yml
├── chapter_09
│ └── mysql-users.yml
└── chapter_11
│ ├── iptables.yml
│ └── templates
│ └── iptables.j2
├── build.yml
├── build_single.py
├── builder.sh
├── chapter_template.yml
├── development
├── chapter_0.yml
├── chapter_1.yml
├── chapter_2.yml
├── chapter_3.yml
├── chapter_4.yml
└── root.yml
├── fundamentals
├── chapter_0.yml
├── chapter_1.yml
├── chapter_2.yml
├── chapter_3.yml
├── chapter_4.yml
└── root.yml
├── operational
├── chapter_0.yml
├── chapter_1.yml
├── chapter_2.yml
├── chapter_3.yml
├── chapter_4.yml
├── chapter_5.yml
├── chapter_6.yml
├── chapter_7.yml
├── chapter_8.yml
└── root.yml
├── operational_lab
├── adhoc_commands.sh
├── group_vars
│ └── all
├── lab3-7.yml
├── labs.yml
├── labs1_2.yml
├── nginx.repo
└── templates
│ ├── nginx.conf
│ └── vhost.conf
└── syntax_check.py
/.drone.yml:
--------------------------------------------------------------------------------
1 | image: linuturk/ubuntu-devel
2 | script:
3 | - apt-get install python-yaml -y
4 | - bash builder.sh
5 | publish:
6 | swift:
7 | username: {{rax_username}}
8 | password: {{rax_apikey}}
9 | auth_url: https://identity.api.rackspacecloud.com/v2.0
10 | region: IAD
11 | container: ansible-slides
12 | source: output
13 | branch: master
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /revelator
2 | /reveal_*
3 | /output
4 | /.yml
5 |
6 | *.swp
7 |
8 | *.py[co]
9 |
10 | # Packages
11 | *.egg
12 | *.egg-info
13 | dist
14 | build
15 | eggs
16 | parts
17 | bin
18 | var
19 | sdist
20 | develop-eggs
21 | .installed.cfg
22 |
23 | # Installer logs
24 | pip-log.txt
25 |
26 | # Unit test / coverage reports
27 | .coverage
28 | .tox
29 |
30 | #Translations
31 | *.mo
32 |
33 | #Mr Developer
34 | .mr.developer.cfg
35 |
36 | .DS_Store
37 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "revelator"]
2 | path = revelator
3 | url = https://github.com/mpdehaan/revelator.git
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | ---
2 | language: python
3 |
4 | python:
5 | - 2.7
6 |
7 | install:
8 | - pip install PyYAML
9 |
10 | before_script:
11 | - git clone https://github.com/mpdehaan/revelator.git
12 |
13 | script:
14 | - python syntax_check.py fundamentals/*.yml
15 | - python build_single.py fundamentals/ > fundamentals.yml && cd revelator && ./write_it ../fundamentals.yml fundamentals/
16 | - cd .. && python syntax_check.py operational/*.yml
17 | - python build_single.py operational/ > operational.yml && cd revelator && ./write_it ../operational.yml operational/
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ansible-sprint
2 |
3 | ## Build Instructions
4 |
5 | Build instructions can be found in build.yml.
6 |
7 | ### Dependencies
8 |
9 | * PyYAML
10 |
11 | ## Syntax Checking
12 |
13 | ```
14 | python syntax_check.py *.yml
15 | ```
16 |
--------------------------------------------------------------------------------
/advanced/chapter_00.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Justin Phelps
4 | title: Advanced Ansible
5 | description: Advanced Ansible Course
6 |
7 | slides:
8 | -
9 | - nested:
10 | -
11 | - h1: Advanced Ansible
12 |
13 | -
14 | - h2: Learning Objectives
15 | - p: Students will be able to understand
16 | - p: |
17 |
18 | - Configuration Entries
19 | - Different connection methods
20 | - Variable types and precedences
21 | - Dynamic Inventories
22 | - Encrypted data for use within Ansible
23 | - Roles
24 | - Task Delegatation
25 | - Jinja2 Templates
26 |
27 |
--------------------------------------------------------------------------------
/advanced/chapter_01.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Foo
4 | title: Advanced Ansible
5 | description: Advanced Ansible Course
6 |
7 | slides:
8 | -
9 | - nested:
10 | -
11 | - h1: Assessment Questions
12 | - link:
13 | - http://bit.ly/ansible_advanced
14 | - http://bit.ly/ansible_advanced
15 |
--------------------------------------------------------------------------------
/advanced/chapter_02.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Paul Durivage
4 | title: "Chapter 1, Understanding configuration files and environment variables"
5 | description: Ansible Advanced Course
6 |
7 | slides:
8 |
9 | - set_global:
10 | transition: rotate
11 | background: '#007777'
12 | #background: 'black'
13 |
14 | -
15 | - nested:
16 | -
17 | - h1: Configuration Files
18 | - class_notes: |
19 | Configuration files accept configuration directives to modify
20 | the way Ansible runs, for example: configuring a specific
21 | connection type, or to set the number of forks.
22 | -
23 | - h3: File locations
24 | - ul:
25 | - "ansible.cfg (in the current directory)"
26 | - ".ansible.cfg (in the home directory)"
27 | - "/etc/ansible/ansible.cfg"
28 | - class_notes: |
29 | These are the three locations where configuration files are kept.
30 | The configuration files in these locations are read and evaluated
31 | in an order of precedence. The system file in /etc/ansible/ansible.cfg
32 | has the lowest precedence, the "~/.ansible.cfg" is next highest, and
33 | "./ansible.cfg" is the highest precedence.
34 |
35 | -
36 | - h3: Environment Variables
37 | - code: |
38 | ANSIBLE_KEEP_ALL_FILES=True ansible -i hosts ...
39 | - class_notes: |
40 | Environment variables have the highest precedence of all, and work similarly
41 | to configuration directives in config files
42 |
43 | -
44 | - h3: Environment Variables
45 | - ul:
46 | - Highest precedence
47 | - "Enviroment variables & configuration directives"
48 | - constants.py
49 | - class_notes: |
50 | An enviroment variable is going to squash configuration directives
51 | at all levels. Important to note: enviroment variables do not always
52 | have an equivalent configuration directive.
53 | Enviroment variables are not well documented, and are, for the most part
54 | documented only in code, in the "constants.py" file inside Ansible
55 |
56 | -
57 | - h3: Configuration Sections
58 | - ul:
59 | - defaults
60 | - paramiko
61 | - ssh_connection
62 | - accelerate
63 | - class_notes: |
64 | Each of the bullets are a "section" under which their respective directives
65 | should be used. The config file uses INI format.
66 |
67 | -
68 | - h3: Configuration Sections
69 | - code: |
70 | $ cat ansible.cfg
71 | [defaults]
72 | ...
73 | - class_notes: |
74 | Sections are literally section headers for INI files. Configuration
75 | directives for each section are placed under their appropriate,
76 | respective section header.
77 |
78 | -
79 | - h3: Configuration Options
80 | - p: Each section has its own directives
81 | - code: |
82 | [defaults]
83 | hostfile = hosts
84 | private_key_file = ~/.ssh/id_rsa
85 | ...
86 | - class_notes: |
87 | The directives are defined under their respective section.
88 | The Ansible documentation provides all the configuration directives
89 | for each section.
90 | -
91 | - h3: Configuration Options
92 | - link: [ 'http://docs.ansible.com/intro_configuration.html', 'http://docs.ansible.com/intro_configuration.html' ]
93 |
94 | -
95 | - h3: Example Configuration
96 | - code: |
97 | [defaults]
98 | hostfile = hosts
99 | private_key_file = /Users/username/.ssh/id_rsa
100 | nocows = 1
101 | forks = 50
102 | transport = ssh
103 | remote_user = ansibleuser
104 | ask_sudo_pass = True
105 | ask_vault_pass = True
106 | roles_path = roles
107 |
108 | [ssh_connection]
109 | pipelining = True
110 | scp_if_ssh = True
111 | - class_notes: |
112 | This is configuration file that was made to ensure Ansible complies
113 | with the local environment configuration. For example, it explictly
114 | forces ssh, asks for a sudo pass, sets forks to 50, etc.
115 |
116 | -
117 | - h3: Config File Tour
118 | - class_notes: |
119 | Students check their config files
120 |
121 |
--------------------------------------------------------------------------------
/advanced/chapter_03.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: DF and TG
4 | title: Connection Types
5 | description: Connection to Remote Machines
6 |
7 | slides:
8 |
9 | -
10 | - nested:
11 | -
12 | - h1: "Connection Types"
13 | - class_notes: Title slide. Ansible has a number of ways to connect to remote machines. SSH is the default, and there are two SSH mechanisms. This chapter will cover the differences between the two, as well as other connection mechanisms.
14 |
15 | -
16 | - h1: "Smart (SSH auto-detected)"
17 | - p: placeholder for diagram to show smart, openssh, and paramiko?
18 | - class_notes: By default, Ansible auto-detects the right SSH-based connection mechanism to use. There are two, Paramiko and OpenSSH. Paramiko is used when your version of OpenSSH on the control machine is too old to support "Control Persist/Control Master", which greatly improve connection performance. Ubuntu has a modern version of OpenSSH, but CentOS/RHEL6 do not.
19 |
20 | -
21 | - h1: "OpenSSH"
22 | - class_notes: With the OpenSSH connection type, you can use regular SSH configuration use things like jump hosts to bounce from one host to another, Kerberos authentication, and any other SSH configuration that you need. OpenSSH also supports control master/control persist which improves the performance of multiple connections to the same machine, which is useful for Ansible.
23 |
24 | -
25 | - h1: "Pipelining"
26 | - class_notes: If you're using OpenSSH, you can enable pipelining, which greatly increases SSH performance. It is enabled in the ansible.cfg configuration file. Pipelining is disabled by default because it requires a little bit of target machine configuration for sudo. You must disable ‘requiretty’ in /etc/sudoers on all managed hosts.
27 |
28 |
29 | -
30 | - h1: "Paramiko"
31 | - class_notes: Paramiko is a very simple Python implementation of an SSH client. Ansible uses it as a fallback when the version of OpenSSH on the control machine is not suitable. It doesn't support the advanced OpenSSH configuration like jump hosts, etc.
32 |
33 | -
34 | - h1: "Accelerated Mode"
35 | - p: "http://docs.ansible.com/playbooks_acceleration.html"
36 |
37 |
38 | - class_notes: Accelerated mode is a special kind of connection that sets up a temporary listener on the target server and then bypasses SSH using a special encrypted connection to run the rest of the tasks without having to establish a new SSH connection every time. It is about as fast as pipelined SSH, but it can have some additional performance benefits if you are transferring a lot of large files to the target systems.
39 |
40 | -
41 | - h1: "Local Connections"
42 |
43 | -
44 | - h1: "Connection Plugins"
45 |
--------------------------------------------------------------------------------
/advanced/chapter_04.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Matt Martz
4 | title: jinja2 templates
5 | description: Some jinja2 stuff
6 |
7 | slides:
8 |
9 | -
10 | - nested:
11 | -
12 | - h1: Jinja2 Templates
13 | - p: I mustache you a question.
14 |
15 | -
16 | - h2: Jinja2 Templates
17 | - ul:
18 | - Delimiters
19 | - Control Structures
20 | - Jinja2 Environment
21 | - Python Data Types
22 | - Filters and Tests
23 |
24 | -
25 | - h2: Delimiters
26 | - code: |
27 | {{ variable }}
28 | - code: |
29 | {% for server in groups.webservers %}
30 | - class_notes: There are 2 (default) delimiters in jinja2. The first prints the result of the expression. The latter is used to execute statements such as for loops or assigning values.
31 |
32 | -
33 | - h2: Control Structures
34 | - p: |
35 |
36 | - for
37 | - if
38 | - macros
39 | - call
40 | - filters
41 | - assignments
42 | - extends
43 | - block
44 | - include
45 | - import
46 |
47 | - class_notes: This is a list of all control strucutres as mentioned in the jinja2 docs. The ones most people need to know about are "for" and "if". Point students to http://jinja.pocoo.org/docs/templates/ for additional information about the other types.
48 |
49 | -
50 | - h2: For Loop
51 | - code: |
52 | {% for server in groups.webservers %}
53 | {{ hostvars[server].ansible_default_ipv4.address }}
54 | {% endfor %}
55 | - class_notes: Ending a control structure in jinja2 is generally done with endTYPE, where TYPE in the above case is "for".
56 |
57 | -
58 | - h2: If Statement
59 | - code: |
60 | {% if server == inventory_hostname %}
61 | {{ 127.0.0.1 }}
62 | {% else if server in groups.database %}
63 | {{ hostvars[server].ansible_eth1.address }}
64 | {% else %}
65 | {{ hostvars[server].ansible_default_ipv4.address }}
66 | {% endif %}
67 | - class_notes: This is an example of an if/else if/else statement, nothing too special here.
68 |
69 | -
70 | - h2: Accessing Variables from Other Hosts
71 | - p: The "hostvars" variable contains facts for all hosts that have had facts gathered.
72 | - code:
73 | hostvars['web01'].ansible_eth1.address
74 | - class_notes: Group variables are not held independent of the hosts. During inventory parsing, group vars are merged into the individual hosts facts.
75 |
76 | -
77 | - h2: Manipulating Jinja2 Environment
78 | - p: Ansible configures jinja2 with a set of sane defaults. In some cases these defaults are not optimal, usually in the case of variable_start_string or trim_blocks. The first line of a jinja2 template can include a jinja2 environment configuration line
79 | - code: |
80 | #jinja2:variable_start_string:'[%' , variable_end_string:'%]'
81 | - class_notes: This example shows changing "{{ ... }}" to "[% ... %]". This is valuable in the case where you may need to use the "{{" or "}}" strings in your template that are not part of jinja2. http://jinja.pocoo.org/docs/api/#jinja2.Environment
82 |
83 | -
84 | - h2: Jinja2 Variables are Python Data Types
85 | - p: In some cases there will not be Jinja2 filters that do what you want, such as a lack of a "split" filter. This can be achieved using the ".split()" method on a python string object.
86 | - code: |
87 | {% set servers = "server1,server2,server3" %}
88 | {% for server in servers.split(",") %}
89 | {{ server }}
90 | {% endfor %}
91 |
92 | -
93 | - h2: Filters and Tests
94 | - p: Jinja2 provides you with a number of filters and tests to manipulate and test data. Ansible also provides a number of filters.
95 | - link:
96 | - http://docs.ansible.com/playbooks_variables.html#jinja2-filters
97 | - http://docs.ansible.com/playbooks_variables.html#jinja2-filters
98 |
99 | -
100 | - h2: Filters
101 | - p: Filters are invoked similarly to unix shell pipes and manipulate variables and return the results
102 | - code: |
103 | variable | replace("-", "_")
104 | - class_notes: Additional details can be found at http://jinja.pocoo.org/docs/templates/#filters
105 |
106 | -
107 | - h2: Tests
108 | - p: Tests can be used to test a variable against a common expression
109 | - code: |
110 | {% if variable is defined %}
111 | - class_notes: Additional details can be found at http://jinja.pocoo.org/docs/templates/#tests
112 |
--------------------------------------------------------------------------------
/advanced/chapter_06.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Paul Durivage
4 | title: "Chapter 4, Dynamic Inventory"
5 | description: ""
6 |
7 | slides:
8 |
9 | -
10 | - nested:
11 | -
12 | - h1: Dynamic Inventories
13 |
14 | -
15 | - h3: What is Dynamic Inventory?
16 | - ul:
17 | - Executable script
18 | - Queries a service that holds data about servers
19 | - Returns the data to Ansible (as JSON)
20 | - class_notes: |
21 | Dynamic inventory is a script that queries a service, like a cloud
22 | provider API or a management application like Spacewalk. This data
23 | is formatted in an Ansible-specific JSON data structure and is used in
24 | lieu of hardcoded, static inventory files.
25 |
26 | -
27 | - h3: Why Dynamic Inventory?
28 | - ul:
29 | - Time
30 | - Accuracy
31 | - class_notes: |
32 | Ideally, the source of data for our dynamic inventory scripts is 100%
33 | correct, and is automatically updated as infrastructure changes. This
34 | is especially useful in environments where machines are coming on and offline
35 | all the time, like a cloud or virtual environment.
36 |
37 | -
38 | - h3: Manual Invocation
39 | - code: |
40 | $ ./docker.py (--list | --host)
41 | - class_notes: |
42 | Manual invocation of a dynamic inventory script is straight forward.
43 | Dynamic inventory scripts must be executable, so calling them explictly will
44 | invoke the script and return JSON as output.
45 | All inventory scripts must accept two optional arguments, list and host. 'List'
46 | lists hosts, and 'host' accepts a hostname as an argument and returns data on the host.
47 | Note, '--host' is functionally optional because of the '_meta' hash returned in the
48 | '--list' results. More on that later.
49 |
50 | -
51 | - h3: Results
52 | - image: "https://raw.githubusercontent.com/Linuturk/ansible-sprint/master/advanced/resources/chapter06/shot1.png"
53 | - class_notes: |
54 | The output of this command is returned as JSON, in an Ansible-specific structure.
55 | This image shows the invocation of the Docker inventory script. The script queries
56 | a Docker host and requests information about containers. The script creates groups,
57 | which we see as arrays of hostnames.
58 | The '_meta' hash has data about hosts -- essentially this data becomes hostvars for
59 | eac host.SSH host, port information plus additional host variables are returned by
60 | the script which can later be used in plays.
61 |
62 | -
63 | - h3: Ansible with Dynamic Inventory
64 | - code: |
65 | $ ansible -i ./docker.py --list-hosts running
66 | suspicious_ptolemy
67 | ecstatic_albattani
68 | - class_notes: |
69 | This is an example of an ad-hoc command using the inventory script.
70 | We use the -i argument just as we would with any other inventory script, however
71 | we use a path to a dynamic inventory script with this argument rather
72 | than a path to a static inventory file.
73 | You can see from this command we have asked to list hosts that the limit matches. In
74 | this example, we are matching the group "running".
75 |
76 | -
77 | - h3: Combining Inventory Types
78 | - code: |
79 | $ tree
80 | .
81 | ├── common.yml
82 | ├── prod
83 | │ ├── docker.py
84 | │ └── servers
85 | └── site.yml
86 |
87 | 1 directory, 4 files
88 |
89 | $ ansible-playbook -i prod site.yml
90 | - class_notes: |
91 | One can combine inventory types, both static and dynamic inventories, by
92 | placing them in a directory and referencing the directory as the value of the
93 | optional '-i' argument.
94 | In the example in this slide, you can see a static inventory file called 'servers',
95 | a dynamic inventory script called 'docker.py', in a directory called 'prod'. Notice
96 | that the value passed to the '-i' argument is the name of the directory, 'prod'.
97 | -
98 | - h3: Lab
99 | - p: |
100 | Using the dynamic inventory script for today's infrastructure, provision several
101 | instances. Manually run the inventory script to query information on
102 | the instances. Then, run the inventory script using an Ansible command to
103 | list and then ping the instances.
104 |
--------------------------------------------------------------------------------
/advanced/chapter_07.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: TG
4 | title: Advanced Ansible
5 | description: Encrypting Sensitive Data with Vault
6 |
7 | slides:
8 |
9 | - set_global:
10 | transition: rotate
11 | background: '#007777'
12 | #background: 'black'
13 |
14 | -
15 | - nested:
16 | -
17 | - h1: Ansible Vault
18 | - p: What are you trying to hide?
19 | -
20 | - h1: Ansible Vault
21 | - p: "Ansible Vault is a tool to encrypt YAML variables files that may contain sensitive data."
22 | - ul:
23 | - Password-based
24 | - Separate command line tool
25 | - Encrypts YAML files
26 | - class_notes: Ansible Vault is a command line tool that can be used to encrypt files that may contain sensitive data. it's usually used to encrypt variables files, but it can encrypt entire playbooks as well. When Ansible is operating on a playbook that refers to an encrypted file, it can either prompt for the password or be fed a password via file. 'Question ideas; what kinds of information should be encrypted?'
27 |
28 | -
29 | - h2: Vault Operations
30 | - ul:
31 | - create
32 | - edit
33 | - rekey
34 | - encrypt
35 | - decrypt
36 | - class_notes: ansible-vault is the CLI tool, and it has several operations.
37 |
38 | -
39 | - h2: Vault Operations
40 | - code: ansible-vault create secrets.yml
41 | - class_notes: Create a new file and open it in $EDITOR. When it's saved, it will be encrypted.
42 |
43 | -
44 | - h2: Vault Operations
45 | - code: ansible-vault edit secrets.yml
46 | - class_notes: Edit an existing file in $EDITOR. Ansible will decrypt it to a temporary location and open it in an editor, and then when saved, re-encrypt it.
47 |
48 | -
49 | - h2: Vault Operations
50 | - code: ansible-vault rekey secrets.yml
51 | - class_notes: Change the password on an encrypted file.
52 |
53 | -
54 | - h2: Vault Operations
55 | - code: ansible-vault encrypt secrets.yml
56 | - class_notes: Encrypt an existing file.
57 |
58 | -
59 | - h2: Vault Operations
60 | - code: ansible-vault decrypt secrets.yml
61 | - class_notes: Permanently decrypt an encrypted file.
62 |
63 | -
64 | - h2: Running a Playbook
65 | - code: ansible-playbook --ask-vault-pass vault-test.yml
66 | - code: ansible-playbook --vault-password-file ../vault-pw vault-test.yml
67 | - class_notes: There are two ways to run a playbook that refers to encrypted content. The first one prompts at runtime. The second method is to refer to a file on disk that contains the password.
68 |
69 | -
70 | - h2: 'Lab: Vault'
71 | - ul:
72 | - Create a new encrypted file
73 | - Edit that file
74 | - Re-key the file
75 | - Use an encrypted file in a playbook
76 | - h6: 'Objective: Create a vault-encrypted vars file for a subsequent lab.'
77 |
--------------------------------------------------------------------------------
/advanced/chapter_08.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: DF and TG
4 | title: Roles
5 | description: Ansible Roles and Content Organization
6 |
7 | slides:
8 |
9 | -
10 | - nested:
11 | -
12 | - h1: "Roles"
13 | - p: Reusing and sharing Ansible content.
14 | - class_notes: Title slide. Roles are a way to organize and reuse Ansible content in a standard way.
15 |
16 | -
17 | - h2: "Filesystem Structure"
18 | - p: Roles use specific file structures.
19 | - class_notes: Roles search for variables, files and templates in specific places. We'll discuss the file structure over the next few slides.
20 |
21 | -
22 | - h3: "Example Role Structure in a Project Folder:"
23 | - code: |
24 | site.yml
25 | roles/
26 | role1/
27 | files/
28 | templates/
29 | tasks/
30 | handlers/
31 | vars/
32 | meta/
33 |
34 | -
35 | - h3: "Calling a role in a playbook example:"
36 | - code: |
37 | ---
38 | - hosts: webservers
39 | roles:
40 | - common
41 | - webservers
42 |
43 | -
44 | - h3: "Behavior examples of role X:"
45 | - ul:
46 | - If roles/x/tasks/main.yml exists, tasks listed therein will be added to the play
47 | - If roles/x/handlers/main.yml exists, handlers listed therein will be added to the play
48 | - If roles/x/vars/main.yml exists, variables listed therein will be added to the play
49 | - If roles/x/meta/main.yml exists, any role dependencies listed therein will be added to the list of roles
50 | - Any copy tasks can reference files in roles/x/files/
51 | - Any script tasks can reference scripts in roles/x/files/
52 | - Any template tasks can reference files in roles/x/templates/
53 | - Any include tasks can reference files in roles/x/tasks/
54 |
55 | -
56 | - h3: "Parameterize Your Roles:"
57 | - code: |
58 | ---
59 | - hosts: webservers
60 | roles:
61 | - common
62 | - { role: foo, dir: '/opt/a', port: 5000 }
63 | - { role: foo, dir: '/opt/b', port: 5001 }
64 |
65 | -
66 | - h3: "Call Roles Conditionally:"
67 | - code: |
68 | ---
69 | - hosts: webservers
70 | roles:
71 | - { role: foo, when: "ansible_os_family == 'RedHat'" }
72 |
73 | -
74 | - h3: "Pre and Post Tasks, Use of roles in a top level playbook:"
75 | - code: |
76 | ---
77 | - hosts: webservers
78 |
79 | pre_tasks:
80 | - shell: echo 'Hello.'
81 |
82 | roles:
83 | - { role: some_role }
84 |
85 | tasks:
86 | - shell: echo 'I called a role!'
87 |
88 | post_tasks:
89 | - shell: echo 'Goodbye.'
90 |
91 | -
92 | - h2: "Variables Defaults"
93 | - p: It is possible to set default variables for your roles.
94 | - class_notes: Role default variables allow you to set default variables for included or dependent roles. To create defaults, simply add a defaults/main.yml file in your role directory. These variables will have the lowest priority of any variables available, and can be easily overridden by any other variable, including inventory variables.
95 |
96 | -
97 | - h2: "Role Dependencies"
98 | - p: Role Dependencies allow for roles to automatically pull in other roles.
99 | - class_notes: Role dependencies allow you to automatically pull in other roles when using a role. Role dependencies are stored in the meta/main.yml file contained within the role directory. This file should contain a list of roles and parameters to insert before the specified role.
100 |
101 | -
102 | - h3: Example role dependency entry in the meta/main.yml file
103 | - code: |
104 | ---
105 | dependencies:
106 | - { role: common, some_parameter: 3 }
107 | - { role: apache, port: 80 }
108 | - { role: postgres, dbname: blarg, other_parameter: 12 }
109 | -
110 | - h3: Duplicate Role Dependiencies
111 | - p: You can call a role dependency multiple times with various parameters.
112 | - code: |
113 | ---
114 | allow_duplicates: yes
115 | dependencies:
116 | - { role: apache, port: 80 }
117 | - { role: apache, port: 8080 }
118 | - class_notes: Not a common use case, but you can parameterize role dependencies in a repeated way. Such as having multiple runs of apache based on the dependencies of another role. This could get you multiple versions of a stack of apache, tomcat and a database with different parameters. The order of execution would be the order of the duplicates and repeat the roles that depend on it. For example, this could be tomcat, apache with port 80, then tomcat, apache with port 8080, and so on. They will rerun against the same inventory, of course.
119 |
120 | -
121 | - h2: "Embedding Custom Modules"
122 | - p: Role-specific custom modules can be packaged with the role.
123 | - class_notes: This is an advanced topic that should not be relevant for most users. If you write a custom module you may wish to distribute it as part of a role. Generally speaking, Ansible as a project is very interested in taking high-quality modules into ansible core for inclusion, so this shouldn’t be the norm, but it’s quite easy to do.
124 |
125 | -
126 | - h3: "Examples of embedding a custom module in a role:"
127 | - code: |
128 | roles/
129 | my_role/
130 | library/
131 | module1
132 | module2
133 | - class_notes: Alongside the ‘tasks’ and ‘handlers’ structure of a role, add a directory named ‘library’. In this ‘library’ directory, then include the module directly inside of it.
134 |
135 | -
136 | - h3: "Calling the role with a custom module in a playbook:"
137 | - code: |
138 | - hosts: webservers
139 | roles:
140 | - my_role
141 | - class_notes: As you can see, we call a role with a custom module just as we would a role without one. This is because our custom module also follows the file structure as previously described.
142 |
143 | -
144 | - h2: "Ansible Galaxy"
145 | - p: Sharing is caring. visit http://galaxy.ansible.com
146 | - class_notes: Ansible Galaxy is a free site for finding, downloading, rating, and reviewing all kinds of community developed Ansible roles and can be a great way to get a jumpstart on your automation projects. You can sign up with social auth, and the download client ‘ansible-galaxy’ is included in Ansible 1.4.2 and later.
147 |
148 | -
149 | - h3: "One last trick: Galaxy has you covered."
150 | - code: |
151 | ansible-galaxy init mynewrole
152 | - class_notes: the ansible-galaxy command doesn't just download an install roles from the public service, it will also initialize an empty role with the role name of your choosing. This means it will place all the folders, skeleton files and file structure as needed. Use this to write roles without having to remember to create every file or folder.
153 |
--------------------------------------------------------------------------------
/advanced/chapter_09.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Jesse K
4 | title: Delegation
5 | description: "How delegation can be used to redirect tasks to a different host."
6 |
7 | slides:
8 |
9 | -
10 | - nested:
11 | -
12 | - h1: Delegation
13 | - p: I like things done my way but by somebody else.
14 | - class_notes: |
15 | In this chapter we discuss delegation, how tasks in a play
16 | can be redirected to an alternate host for execution.
17 | What use cases can you think of for looping over hosts to
18 | execute a task, but have that task execute somewhere else?
19 |
20 | -
21 | - h2: Delegation
22 | - ul:
23 | - Local actions and actions on other hosts
24 | - Delegation to a host in inventory
25 | - Delegation to a host not in inventory
26 | - Task execution concurrency with delegation
27 | - class_notes: |
28 | Actions can be done locally, or on another system in your
29 | inventory, or out of your inventory. Execution concurrency
30 | is a concern as well.
31 |
32 | -
33 | - h2: Local actions and actions on other hosts
34 | - p: "Task control keyword: delegate_to"
35 | - code: |
36 | - name: take out of load balancer pool
37 | command: /usr/bin/take_out_of_pool {{ inventory_hostname }}
38 | delegate_to: localhost
39 |
40 | - name: update packages
41 | yum: name=acme-web-stack state=latest
42 |
43 | - name: add back to load balancer pool
44 | command: /usr/bin/add_back_to_pool {{ inventory_hostname }}
45 | delegate_to: localhost
46 | - class_notes: |
47 | The delegate_to keyword is what tells Ansible to redirect the
48 | task to the system listed. The variables you reference are
49 | attached to the host in the loop, not the host you are
50 | delegating to. So the task has the context of the host in the
51 | loop but it just gets executed on the host you delegate to.
52 |
53 | Is there another way to indicate that an action needs to
54 | happen locally?
55 |
56 | -
57 | - h2: Delegation to a host in inventory
58 | - p: Delegation most often targets another host in your inventory
59 | - p: Uses connection variable data from delegate target
60 | - ul:
61 | - ansible_connection
62 | - ansible_ssh_host
63 | - ansible_ssh_port
64 | - ansible_ssh_user
65 | - etc...
66 | - class_notes: |
67 | When delegating to a host listed in your inventory, data
68 | from your delegation target will be used when creating the
69 | connection to the delegation target, but only the connection
70 | related variables. The rest will be read from the host in the
71 | loop.
72 |
73 | -
74 | - h2: Delegation to a host not in inventory
75 | - p: "Delegation: not just limited to hosts in your inventory"
76 | - p: Make use of add_host to adjust connection details
77 | - code: |
78 | - name: add delegation host
79 | add_host: name=hubert ansible_ssh_host=192.168.10.2
80 | ansible_ssh_user=fred
81 | - class_notes: |
82 | You can also delegate to a host that doesn't exist in your
83 | inventory. In this case, ansible will use the string provided
84 | verbatim and attempt to connect to it with the current connection
85 | type and details. If you need to adjust the connection details,
86 | make use of the add_host task to create an ephemeral host in your
87 | inventory with connection data defined.
88 |
89 | -
90 | - h2: 'Lab: ephemeral host task delegation'
91 | - p: Create an ephemeral host and delegate a task to it
92 | - ul:
93 | - Create a play for localhost
94 | - Create a host using add_host with detailed connection variables
95 | - Create a simple task that is delegated to the added host
96 | - Run playbook with -vvvv to observe the connection details
97 | - class_notes: |
98 | This is a simple contrived lab that will exercise making use of
99 | add_host to create an ephemeral host to delegate a task to. This
100 | host doesn't have to actually exist, a connection failure on the
101 | task will suffice to see the connection details to observe the
102 | delegation. Feel free to play with values and observe how they
103 | reflect in running the lab.
104 | - h6: 'Objective: Using an ephemeral host to delegate a single task to'
105 |
106 | -
107 | - h2: Sample Play
108 | - code: |
109 | ---
110 | - name: test play
111 | hosts: localhost
112 |
113 | tasks:
114 | - name: add delegation host
115 | add_host: name=hubert ansible_ssh_host=192.168.10.2
116 | ansible_ssh_user=fred
117 |
118 | - name: silly echo
119 | command: echo {{ inventory_hostname }}
120 | delegate_to: hubert
121 |
122 | - code: |
123 | $ ansible-playbook test-play.yml -vvvv
124 |
125 | -
126 | - h2: Task execution concurrency with delegation
127 | - p: Delegated tasks will run for every host in the loop
128 | - p: Tasks will run with configured forks / serial
129 | - p: Be aware of race conditions and concurrency issues
130 | - class_notes: |
131 | Delegated tasks will run for every host in the hosts: , but this
132 | can create issues with race conditions, particularly when using
133 | conditionals in the task, as the forks count will be used to create
134 | multiple concurrent tasks. This can also create a thundering
135 | herd problem of too many connections opening at once to a single
136 | host. SSH servers have a MaxStartups config option that can limit
137 | how many concurrent connections it'll allow. Easy to overflow.
138 |
139 | What happens when you have five hosts in your set, five or more
140 | forks, a task that is conditional on the existence of a file, and
141 | the task creates the file. All five tasks will run at once, racing
142 | to create the file.
143 |
144 | -
145 | - h2: 'Lab: multi-host task delegation'
146 | - ul:
147 | - Create a play to loop over 'webservers' group
148 | - Create a task to use mysql_user module to add a user
149 | - Use host specific mysql user / password data
150 | - delegate_to should be used to execute on the first 'databases' server
151 | - h6: 'Objective: Add mysql users to a database for a set of hosts'
152 |
153 | -
154 | - h2: Sample Play
155 | - code: |
156 | ---
157 | - name: MySQL Users
158 | hosts: webservers
159 |
160 | tasks:
161 | - name: add a mysql user for the server
162 | mysql_user: name={{ db_username }} host={{ inventory_hostname }}
163 | password='{{ db_password }}' priv='ansible.*:ALL'
164 | state=present
165 | delegate_to: databases[0]
166 | - p: |
167 | When ran with -vvvv one can clearly see the connection debugging
168 | output which will show the delegation in action.
169 |
--------------------------------------------------------------------------------
/advanced/chapter_10.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Matt Martz
4 | title: jinja2 template labs
5 | description: Some jinja2 stuff
6 |
7 | slides:
8 |
9 | -
10 | - nested:
11 | -
12 | - h1: Jinja2 Templates Labs
13 |
14 | -
15 | - h2: Lab
16 | - p: Create playbook and a jinja2 template to achieve the following results
17 | - ul:
18 | - Template out /etc/sysconfig/iptables
19 | - Only allow access to MySQL (tcp/3306) from servers in the webservers group
20 | - A play to create this file from the template
21 | - The play should have a handler to reload iptables when the file changes
22 | - iptables should be enabled and configured to start on boot
23 |
24 | -
25 | - h2: Sample template
26 | - code: |
27 | *filter
28 | :INPUT ACCEPT [0:0]
29 | :FORWARD ACCEPT [0:0]
30 | :OUTPUT ACCEPT [0:0]
31 |
32 | {% for server in groups['webservers'] %}
33 | -A INPUT -p tcp -s {{ hostvars[server].ansible_eth1.ipv4.address }} -i eth1 -d {{ ansible_eth1.ipv4.address }} --dport 3306 -j ACCEPT
34 | {% endfor %}
35 |
36 | {% for server in groups['databases'] %}
37 | {% if server != inventory_hostname %}
38 | -A INPUT -p tcp -s {{ hostvars[server].ansible_eth1.ipv4.address }} -i eth1 -d {{ ansible_eth1.ipv4.address }} --dport 3306 -j ACCEPT
39 | {% endif %}
40 | {% endfor %}
41 |
42 | -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
43 | -A INPUT -p icmp -j ACCEPT
44 | -A INPUT -i lo -j ACCEPT
45 | -A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
46 | -A INPUT -j REJECT --reject-with icmp-host-prohibited
47 | -A FORWARD -j REJECT --reject-with icmp-host-prohibited
48 | COMMIT
49 |
50 | -
51 | - h2: Sample play
52 | - code: |
53 | ---
54 | - hosts: webservers
55 | gather_facts: true
56 |
57 | - hosts: databases
58 | handlers:
59 | - name: Reload iptables
60 | service: name=iptables state=reloaded
61 |
62 | tasks:
63 | - name: Template /etc/sysconfig/iptables
64 | template: src=templates/iptables.j2 dest=/etc/sysconfig/iptables
65 | notify: Reload iptables
66 |
67 | - name: Ensure iptables is started and enabled
68 | service: name=iptables state=started enabled=yes
69 |
70 |
--------------------------------------------------------------------------------
/advanced/chapter_11.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Foo
4 | title: Advanced Ansible
5 | description: Advanced Ansible Course
6 |
7 | slides:
8 | -
9 | - nested:
10 | -
11 | - h1: Assessment Questions
12 | - link:
13 | - http://bit.ly/ansible_advanced
14 | - http://bit.ly/ansible_advanced
15 |
--------------------------------------------------------------------------------
/advanced/resources/chapter06/shot1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ansible/training-content/a5e45373d919d90738afa64350d5303a69022147/advanced/resources/chapter06/shot1.png
--------------------------------------------------------------------------------
/advanced/resources/hosts/hosts.graphml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | web01
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | db01
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | ansible
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | <?xml version="1.0" encoding="utf-8"?>
117 | <svg version="1.1"
118 | xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
119 | x="0px" y="0px" width="36px" height="57px" viewBox="0 -0.741 36 57" enable-background="new 0 -0.741 36 57"
120 | xml:space="preserve">
121 | <defs>
122 | </defs>
123 | <linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="230.1768" y1="798.6021" x2="180.3346" y2="798.6021" gradientTransform="matrix(1 0 0 1 -195.2002 -770.8008)">
124 | <stop offset="0" style="stop-color:#4D4D4D"/>
125 | <stop offset="1" style="stop-color:#8D8D8D"/>
126 | </linearGradient>
127 | <rect y="0.943" fill="url(#SVGID_1_)" width="34.977" height="53.716"/>
128 | <linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="224.6807" y1="798.6021" x2="200.6973" y2="798.6021" gradientTransform="matrix(1 0 0 1 -195.2002 -770.8008)">
129 | <stop offset="0.0319" style="stop-color:#848484"/>
130 | <stop offset="0.1202" style="stop-color:#8C8C8C"/>
131 | <stop offset="0.308" style="stop-color:#969696"/>
132 | <stop offset="0.5394" style="stop-color:#999999"/>
133 | <stop offset="0.5501" style="stop-color:#9C9C9C"/>
134 | <stop offset="0.6256" style="stop-color:#B0B0B0"/>
135 | <stop offset="0.7118" style="stop-color:#BEBEBE"/>
136 | <stop offset="0.8178" style="stop-color:#C7C7C7"/>
137 | <stop offset="1" style="stop-color:#C9C9C9"/>
138 | </linearGradient>
139 | <path fill="url(#SVGID_2_)" d="M5.497,0.943c7.945-1.258,16.04-1.258,23.983,0c0,17.905,0,35.811,0,53.716
140 | c-7.943,1.258-16.039,1.258-23.983,0C5.497,36.753,5.497,18.848,5.497,0.943z"/>
141 | <path fill="#515151" d="M5.497,14.621c7.995,0,15.989,0,23.983,0c0,13.346,0,26.693,0,40.037c-7.943,1.258-16.039,1.258-23.983,0
142 | C5.497,41.314,5.497,27.967,5.497,14.621z"/>
143 | <path opacity="0.43" fill="#565656" d="M5.497,4.745c7.982-0.628,16.001-0.628,23.983,0c0,2.707,0,5.413,0,8.12
144 | c-7.994,0-15.989,0-23.983,0C5.497,10.158,5.497,7.452,5.497,4.745z"/>
145 | <path opacity="0.43" fill="none" stroke="#4D4D4D" stroke-width="0.0999" stroke-miterlimit="10" d="M5.497,4.745
146 | c7.982-0.628,16.001-0.628,23.983,0c0,2.707,0,5.413,0,8.12c-7.994,0-15.989,0-23.983,0C5.497,10.158,5.497,7.452,5.497,4.745z"/>
147 | <polygon opacity="0.43" fill="#565656" stroke="#4D4D4D" stroke-width="0.0135" stroke-miterlimit="10" enable-background="new " points="
148 | 6.496,5.746 9.869,5.606 9.869,6.661 6.496,6.799 "/>
149 | <rect x="31.307" y="2.517" fill="#E7ED00" stroke="#717171" stroke-width="0.1926" stroke-miterlimit="10" width="3.692" height="1.505"/>
150 | <rect x="31.307" y="5.8" fill="#C8FF00" stroke="#717171" stroke-width="0.1926" stroke-miterlimit="10" width="3.692" height="1.507"/>
151 | <linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="29.4414" y1="35.1235" x2="5.4995" y2="35.1235">
152 | <stop offset="0" style="stop-color:#808080"/>
153 | <stop offset="0.1907" style="stop-color:#828282"/>
154 | <stop offset="0.2955" style="stop-color:#8A8A8A"/>
155 | <stop offset="0.3795" style="stop-color:#989898"/>
156 | <stop offset="0.4524" style="stop-color:#ACACAC"/>
157 | <stop offset="0.5175" style="stop-color:#C5C5C5"/>
158 | <stop offset="0.5273" style="stop-color:#C9C9C9"/>
159 | <stop offset="0.5914" style="stop-color:#C9C9C9"/>
160 | <stop offset="0.9681" style="stop-color:#C9C9C9"/>
161 | </linearGradient>
162 | <path fill="url(#SVGID_3_)" d="M5.5,14.822c0,13.22,0,26.438,0,39.66c7.931,1.256,16.012,1.256,23.941,0c0-13.222,0-26.439,0-39.66
163 | C21.461,14.822,13.48,14.822,5.5,14.822z M28.396,18.703c-0.74,0.01-1.482,0.02-2.225,0.029c0-0.951,0-1.901-0.001-2.85
164 | c0.742-0.003,1.483-0.005,2.224-0.008C28.396,16.817,28.396,17.76,28.396,18.703z M16.354,42.496c0-0.961,0-1.924,0-2.885
165 | c0.744,0.006,1.489,0.006,2.233,0c0,0.961,0,1.924,0,2.885C17.843,42.503,17.098,42.503,16.354,42.496z M18.587,43.568
166 | c0,0.955,0,1.91,0,2.866c-0.744,0.009-1.489,0.009-2.234,0c0-0.956,0-1.911,0-2.866C17.098,43.574,17.843,43.574,18.587,43.568z
167 | M18.586,27.742c0,0.961,0,1.922,0,2.886c-0.744,0.004-1.488,0.004-2.231,0c0-0.964,0-1.925,0-2.886
168 | C17.099,27.746,17.842,27.746,18.586,27.742z M16.354,26.671c0-0.955,0-1.91,0-2.865c0.743,0.002,1.487,0.002,2.23,0
169 | c0,0.955,0,1.91,0,2.865C17.842,26.675,17.099,26.675,16.354,26.671z M16.354,34.583c0-0.961,0-1.924,0-2.885
170 | c0.744,0.004,1.488,0.004,2.231,0c0,0.961,0,1.924,0,2.885C17.842,34.588,17.099,34.588,16.354,34.583z M18.586,35.656
171 | c0,0.961,0,1.924,0.001,2.885c-0.745,0.008-1.489,0.008-2.233,0c0-0.961,0-1.924,0-2.885C17.099,35.66,17.842,35.66,18.586,35.656z
172 | M15.307,30.619c-0.742-0.01-1.484-0.021-2.227-0.039c0-0.957,0-1.916,0-2.875c0.742,0.014,1.485,0.023,2.226,0.029
173 | C15.307,28.695,15.307,29.656,15.307,30.619z M15.307,31.689c0,0.961,0,1.924,0,2.885c-0.742-0.012-1.485-0.025-2.227-0.047
174 | c0-0.959,0.001-1.92,0.001-2.877C13.822,31.667,14.565,31.68,15.307,31.689z M15.307,35.644c0,0.959,0,1.922-0.001,2.883
175 | c-0.742-0.012-1.485-0.031-2.228-0.056c0-0.959,0.001-1.918,0.001-2.877C13.821,35.617,14.564,35.633,15.307,35.644z M15.306,39.597
176 | c0,0.96,0,1.922,0,2.883c-0.742-0.016-1.486-0.037-2.228-0.064c0-0.959,0-1.916,0.001-2.877
177 | C13.82,39.564,14.563,39.585,15.306,39.597z M19.637,39.597c0.742-0.012,1.484-0.033,2.227-0.059c0,0.959,0,1.918,0,2.875
178 | c-0.741,0.029-1.483,0.052-2.227,0.064C19.637,41.519,19.637,40.559,19.637,39.597z M19.637,38.527c0-0.961,0-1.924,0-2.883
179 | c0.74-0.012,1.482-0.027,2.225-0.05c0,0.959,0,1.918,0.002,2.876C21.121,38.496,20.377,38.515,19.637,38.527z M19.637,34.572
180 | c0-0.961,0-1.922-0.002-2.883c0.741-0.01,1.483-0.021,2.225-0.039c0.002,0.957,0.002,1.916,0.002,2.875
181 | C21.119,34.547,20.376,34.564,19.637,34.572z M19.635,30.619c0-0.963,0-1.924,0-2.885c0.74-0.006,1.483-0.017,2.225-0.029
182 | c0,0.959,0,1.916,0,2.875C21.118,30.599,20.376,30.609,19.635,30.619z M19.633,26.666c0-0.955,0-1.909,0-2.864
183 | c0.741-0.005,1.483-0.013,2.227-0.021c0,0.951,0,1.903,0,2.856C21.118,26.65,20.375,26.66,19.633,26.666z M19.633,22.732
184 | c-0.001-0.963-0.001-1.924-0.001-2.885c0.741-0.002,1.483-0.006,2.226-0.012c0,0.959,0.002,1.918,0.002,2.877
185 | C21.116,22.72,20.374,22.728,19.633,22.732z M18.586,22.736c-0.744,0.002-1.487,0.002-2.23,0c0-0.963,0-1.924,0-2.887
186 | c0.743,0.002,1.487,0.002,2.23,0C18.586,20.813,18.586,21.773,18.586,22.736z M15.309,22.732c-0.742-0.004-1.483-0.012-2.226-0.02
187 | c0-0.959,0.001-1.918,0.001-2.877c0.742,0.006,1.484,0.01,2.226,0.012C15.31,20.808,15.309,21.769,15.309,22.732z M15.309,23.801
188 | c0,0.955,0,1.91,0,2.864c-0.742-0.006-1.483-0.016-2.227-0.027c0-0.953,0-1.906,0-2.859C13.825,23.789,14.566,23.796,15.309,23.801z
189 | M12.036,26.617c-0.742-0.017-1.483-0.033-2.225-0.055c0-0.947,0-1.895,0.001-2.841c0.741,0.019,1.483,0.031,2.225,0.042
190 | C12.037,24.716,12.036,25.666,12.036,26.617z M12.035,27.683c0,0.957,0,1.916,0,2.873c-0.742-0.021-1.483-0.047-2.225-0.076
191 | c0-0.953,0-1.904,0-2.857C10.552,27.646,11.293,27.667,12.035,27.683z M12.035,31.621c0,0.957-0.001,1.914-0.001,2.871
192 | c-0.742-0.023-1.483-0.055-2.224-0.092c0-0.953,0-1.906,0-2.859C10.551,31.572,11.292,31.6,12.035,31.621z M12.033,35.56
193 | c0,0.956-0.001,1.914-0.001,2.871c-0.742-0.031-1.484-0.066-2.225-0.111c0-0.953,0.001-1.906,0.001-2.858
194 | C10.549,35.5,11.291,35.533,12.033,35.56z M12.031,39.498c0,0.955,0,1.914-0.001,2.869c-0.742-0.035-1.484-0.078-2.225-0.129
195 | c0-0.953,0-1.904,0.001-2.857C10.547,39.426,11.289,39.465,12.031,39.498z M12.03,43.435c0,0.951-0.001,1.901-0.001,2.854
196 | c-0.742-0.041-1.484-0.09-2.225-0.149c0-0.944,0.001-1.892,0.001-2.838C10.546,43.353,11.288,43.4,12.03,43.435z M13.077,43.482
197 | c0.743,0.031,1.486,0.053,2.228,0.067c0,0.956,0,1.91,0,2.864c-0.742-0.016-1.486-0.041-2.229-0.074
198 | C13.077,45.389,13.077,44.435,13.077,43.482z M15.305,47.486c0,0.961,0,1.922,0,2.883c-0.743-0.019-1.487-0.047-2.23-0.084
199 | c0-0.959,0-1.918,0.001-2.875C13.818,47.443,14.562,47.468,15.305,47.486z M16.353,47.504c0.745,0.009,1.49,0.009,2.234,0
200 | c0.001,0.96,0.001,1.924,0.001,2.883c-0.745,0.011-1.49,0.011-2.235,0C16.353,49.427,16.353,48.464,16.353,47.504z M19.639,47.486
201 | c0.741-0.018,1.483-0.043,2.227-0.076c0,0.957,0.002,1.916,0.002,2.875c-0.742,0.037-1.486,0.065-2.229,0.084
202 | C19.639,49.406,19.639,48.447,19.639,47.486z M19.637,46.414c0-0.954,0-1.908,0-2.864c0.742-0.015,1.484-0.036,2.229-0.067
203 | c0,0.953,0,1.905,0,2.857C21.122,46.373,20.379,46.398,19.637,46.414z M22.911,43.435c0.741-0.035,1.483-0.082,2.224-0.135
204 | c0,0.945,0,1.895,0.002,2.838c-0.74,0.059-1.482,0.107-2.226,0.15C22.911,45.336,22.911,44.386,22.911,43.435z M22.911,42.369
205 | c-0.001-0.957-0.001-1.914-0.002-2.871c0.741-0.032,1.483-0.069,2.225-0.117c0,0.954,0.001,1.906,0.001,2.857
206 | C24.395,42.289,23.652,42.333,22.911,42.369z M22.909,38.431c0-0.957-0.001-1.915-0.001-2.871c0.742-0.027,1.482-0.061,2.224-0.098
207 | c0.001,0.951,0.001,1.904,0.001,2.857C24.393,38.363,23.65,38.4,22.909,38.431z M22.908,34.494c0-0.957-0.002-1.916-0.002-2.871
208 | c0.742-0.021,1.482-0.051,2.225-0.079c0,0.952,0,1.903,0.001,2.856C24.391,34.437,23.648,34.468,22.908,34.494z M22.906,30.556
209 | c0-0.957,0-1.916-0.002-2.873c0.742-0.016,1.484-0.037,2.226-0.061c0,0.953,0.001,1.904,0.001,2.857
210 | C24.391,30.509,23.648,30.535,22.906,30.556z M22.904,26.617c0-0.951,0-1.901,0-2.854c0.74-0.011,1.482-0.025,2.224-0.042
211 | c0,0.946,0.001,1.894,0.001,2.841C24.389,26.583,23.646,26.601,22.904,26.617z M22.902,22.699c0-0.957,0-1.916,0-2.874
212 | c0.742-0.007,1.482-0.014,2.225-0.023c0.001,0.953,0.001,1.906,0.001,2.859C24.387,22.676,23.646,22.689,22.902,22.699z
213 | M22.902,18.76C22.9,17.802,22.9,16.845,22.9,15.887c0.742,0,1.481-0.003,2.225-0.004c0.001,0.953,0.001,1.906,0.002,2.858
214 | C24.385,18.75,23.643,18.756,22.902,18.76z M21.855,18.767c-0.742,0.004-1.482,0.007-2.225,0.009c0-0.961,0-1.922,0-2.884
215 | c0.741,0,1.482-0.001,2.225-0.002C21.855,16.849,21.855,17.808,21.855,18.767z M18.585,18.779c-0.743,0.001-1.486,0.001-2.229,0
216 | c0-0.961,0-1.923,0-2.885c0.742,0,1.486,0,2.229,0C18.585,16.855,18.585,17.817,18.585,18.779z M15.31,18.777
217 | c-0.742-0.002-1.483-0.005-2.225-0.009c0-0.959,0-1.918,0-2.877c0.742,0,1.483,0.001,2.225,0.002
218 | C15.31,16.854,15.31,17.815,15.31,18.777z M12.039,18.76c-0.742-0.005-1.483-0.011-2.225-0.019c0-0.953,0-1.905,0.001-2.858
219 | c0.742,0.001,1.483,0.004,2.224,0.004C12.039,16.845,12.039,17.803,12.039,18.76z M12.039,19.827c0,0.957-0.001,1.915-0.001,2.872
220 | c-0.741-0.01-1.483-0.021-2.224-0.035c0-0.953,0-1.906,0-2.859C10.555,19.813,11.296,19.819,12.039,19.827z M8.768,22.64
221 | c-0.741-0.018-1.482-0.035-2.223-0.057c0-0.943,0-1.887,0-2.831c0.741,0.013,1.482,0.025,2.223,0.036
222 | C8.768,20.739,8.768,21.689,8.768,22.64z M8.767,23.697c0,0.944,0,1.89,0,2.832c-0.741-0.024-1.482-0.053-2.223-0.084
223 | c0-0.938,0-1.873,0-2.811C7.284,23.658,8.026,23.679,8.767,23.697z M8.766,27.587c0,0.949-0.001,1.898-0.001,2.85
224 | c-0.74-0.033-1.481-0.068-2.222-0.111c0-0.942,0-1.887,0-2.83C7.284,27.529,8.025,27.56,8.766,27.587z M8.765,31.494
225 | c0,0.951-0.001,1.9-0.001,2.852c-0.74-0.04-1.481-0.087-2.221-0.139c0-0.943,0-1.887,0-2.831C7.283,31.42,8.023,31.459,8.765,31.494
226 | z M8.763,35.404c0,0.949,0,1.899,0,2.851c-0.741-0.052-1.481-0.104-2.22-0.168c0-0.942,0-1.886,0-2.829
227 | C7.282,35.31,8.022,35.361,8.763,35.404z M8.762,39.312c0,0.949,0,1.899-0.001,2.852c-0.741-0.059-1.48-0.123-2.219-0.195
228 | c0-0.943,0-1.889,0-2.83C7.281,39.203,8.021,39.26,8.762,39.312z M8.76,43.219c0,0.944,0,1.888-0.001,2.832
229 | c-0.74-0.065-1.479-0.14-2.218-0.224c0-0.938,0-1.875,0-2.812C7.281,43.092,8.02,43.16,8.76,43.219z M8.759,47.109
230 | c0,0.951,0,1.9,0,2.851c-0.741-0.073-1.48-0.158-2.219-0.253c0-0.942,0-1.887,0-2.828C7.279,46.964,8.019,47.039,8.759,47.109z
231 | M9.804,47.201c0.741,0.06,1.483,0.111,2.224,0.154c0,0.955,0,1.912,0,2.868c-0.742-0.045-1.484-0.103-2.225-0.166
232 | C9.804,49.107,9.804,48.154,9.804,47.201z M12.027,51.291c0,0.957,0,1.916,0,2.873c-0.742-0.053-1.484-0.114-2.225-0.188
233 | c0-0.951,0.001-1.904,0.001-2.857C10.544,51.187,11.285,51.244,12.027,51.291z M13.075,51.353c0.743,0.039,1.486,0.067,2.229,0.086
234 | c0,0.961,0,1.922,0,2.885c-0.743-0.021-1.487-0.053-2.229-0.094C13.075,53.269,13.075,52.312,13.075,51.353z M16.353,51.459
235 | c0.745,0.009,1.49,0.009,2.235,0c0,0.961,0,1.924,0,2.885c-0.745,0.013-1.491,0.013-2.235,0
236 | C16.353,53.382,16.353,52.42,16.353,51.459z M19.639,51.439c0.741-0.019,1.485-0.049,2.229-0.086c0,0.959,0,1.92,0.001,2.877
237 | c-0.743,0.041-1.485,0.072-2.229,0.094C19.639,53.361,19.639,52.4,19.639,51.439z M22.913,51.291
238 | c0.743-0.047,1.483-0.104,2.226-0.172c0,0.953,0,1.906,0,2.857c-0.74,0.073-1.481,0.135-2.224,0.188
239 | C22.914,53.205,22.914,52.248,22.913,51.291z M22.913,50.224c-0.001-0.956-0.001-1.912-0.001-2.869
240 | c0.742-0.043,1.484-0.095,2.225-0.154c0,0.953,0,1.906,0.002,2.857C24.396,50.123,23.654,50.179,22.913,50.224z M26.184,47.109
241 | c0.739-0.066,1.479-0.145,2.217-0.229c0,0.942,0,1.887,0,2.83c-0.736,0.092-1.478,0.177-2.217,0.252
242 | C26.184,49.009,26.184,48.06,26.184,47.109z M26.184,46.051c-0.002-0.944-0.002-1.888-0.002-2.832
243 | c0.739-0.06,1.48-0.127,2.219-0.202c0,0.938,0,1.873,0,2.811C27.662,45.912,26.923,45.986,26.184,46.051z M26.182,42.162
244 | c0-0.95-0.002-1.9-0.002-2.85c0.74-0.052,1.48-0.109,2.219-0.176c0.002,0.943,0.002,1.887,0.002,2.83
245 | C27.662,42.039,26.921,42.105,26.182,42.162z M26.18,38.253c0-0.95,0-1.9-0.002-2.852c0.742-0.041,1.482-0.093,2.221-0.146
246 | c0,0.942,0,1.887,0,2.829C27.66,38.15,26.92,38.203,26.18,38.253z M26.178,34.345c0-0.949,0-1.898,0-2.852
247 | c0.74-0.034,1.481-0.073,2.221-0.117c0,0.943,0,1.887,0,2.83C27.659,34.258,26.918,34.305,26.178,34.345z M26.177,30.437
248 | c0-0.949,0-1.9-0.001-2.85c0.741-0.027,1.481-0.059,2.221-0.092c0,0.943,0.002,1.888,0.002,2.83
249 | C27.659,30.367,26.918,30.404,26.177,30.437z M26.176,26.529c-0.001-0.942-0.001-1.888-0.001-2.832
250 | c0.742-0.018,1.482-0.039,2.222-0.063c0,0.938,0,1.873,0,2.811C27.657,26.476,26.917,26.503,26.176,26.529z M26.174,22.64
251 | c0-0.951-0.001-1.901-0.001-2.851c0.741-0.01,1.483-0.022,2.224-0.035c0,0.943,0,1.886,0,2.831
252 | C27.657,22.605,26.915,22.623,26.174,22.64z M8.769,15.881c0,0.95,0,1.9-0.001,2.85c-0.741-0.008-1.482-0.018-2.223-0.028
253 | c0-0.943,0-1.887,0-2.83C7.286,15.876,8.028,15.878,8.769,15.881z M6.54,50.758c0.738,0.097,1.478,0.183,2.218,0.258
254 | c0,0.95,0,1.901,0,2.853c-0.741-0.084-1.48-0.178-2.218-0.28C6.54,52.646,6.54,51.701,6.54,50.758z M26.184,53.869
255 | c0-0.95,0-1.899,0-2.853c0.739-0.075,1.479-0.163,2.217-0.259c0.002,0.941,0.002,1.889,0.002,2.83
256 | C27.663,53.693,26.925,53.785,26.184,53.869z"/>
257 | <path id="highlight_2_" opacity="0.17" fill="#FFFFFF" enable-background="new " d="M0,0.943h5.497c0,0,6.847-0.943,11.974-0.943
258 | C22.6,0,29.48,0.943,29.48,0.943h5.496v41.951c0,0-12.076-0.521-18.623-2.548C9.807,38.32,0,30.557,0,30.557V0.943z"/>
259 | </svg>
260 |
261 |
262 |
263 |
264 |
--------------------------------------------------------------------------------
/advanced/resources/hosts/hosts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ansible/training-content/a5e45373d919d90738afa64350d5303a69022147/advanced/resources/hosts/hosts.png
--------------------------------------------------------------------------------
/advanced/root.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Rackspace and Ansible
4 | title: Ansible Fundamentals
5 | description: Ansible Fundamentals
6 | slides: []
7 |
--------------------------------------------------------------------------------
/advanced_lab/.advanced_lab:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ansible/training-content/a5e45373d919d90738afa64350d5303a69022147/advanced_lab/.advanced_lab
--------------------------------------------------------------------------------
/advanced_lab/chapter_05/variable_override.yml:
--------------------------------------------------------------------------------
1 | - hosts: localhost
2 | connection: local
3 | vars:
4 | - local_var: "override me"
5 | tasks:
6 | - name: print out the variable
7 | debug: msg="This should not output 'override me' - {{ local_var }}"
8 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_07/secrets.yml:
--------------------------------------------------------------------------------
1 | ---
2 | password: thisisasecret
3 |
4 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_07/vault-test.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - hosts: localhost
3 | connection: local
4 |
5 | vars_files:
6 | - secrets.yml
7 |
8 | tasks:
9 | - debug: msg="I know a secret! {{ password }}"
10 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lab.yml:
--------------------------------------------------------------------------------
1 | You'll be creating a role named "db" in install mysql alongside the rest of the roles provided to ultimately create a full LAMP stack install.
2 |
3 | For guidance, you may consult https://github.com/ansible/ansible-examples.
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/README.md:
--------------------------------------------------------------------------------
1 | LAMP Stack + HAProxy: Example Playbooks
2 | -----------------------------------------------------------------------------
3 |
4 | - Requires Ansible 1.2
5 | - Expects CentOS/RHEL 6 hosts
6 |
7 | This example is an extension of the simple LAMP deployment. Here we'll install
8 | and configure a web server with an HAProxy load balancer in front, and deploy
9 | an application to the web servers. This set of playbooks also have the
10 | capability to dynamically add and remove web server nodes from the deployment.
11 | It also includes examples to do a rolling update of a stack without affecting
12 | the service.
13 |
14 | You can also optionally configure a Nagios monitoring node.
15 |
16 | ### Initial Site Setup
17 |
18 | First we configure the entire stack by listing our hosts in the 'hosts'
19 | inventory file, grouped by their purpose:
20 |
21 | [webservers]
22 | webserver1
23 | webserver2
24 |
25 | [dbservers]
26 | dbserver
27 |
28 | [lbservers]
29 | lbserver
30 |
31 | [monitoring]
32 | nagios
33 |
34 | After which we execute the following command to deploy the site:
35 |
36 | ansible-playbook -i hosts site.yml
37 |
38 | The deployment can be verified by accessing the IP address of your load
39 | balancer host in a web browser: http://:8888. Reloading the page
40 | should have you hit different webservers.
41 |
42 | ### Removing and Adding a Node
43 |
44 | Removal and addition of nodes to the cluster is as simple as editing the
45 | hosts inventory and re-running:
46 |
47 | ansible-playbook -i hosts site.yml
48 |
49 | ### Rolling Update
50 |
51 | Rolling updates are the preferred way to update the web server software or
52 | deployed application, since the load balancer can be dynamically configured
53 | to take the hosts to be updated out of the pool. This will keep the service
54 | running on other servers so that the users are not interrupted.
55 |
56 | In this example the hosts are updated in serial fashion, which means that
57 | only one server will be updated at one time. If you have a lot of web server
58 | hosts, this behaviour can be changed by setting the 'serial' keyword in
59 | webservers.yml file.
60 |
61 | Once the code has been updated in the source repository for your application
62 | which can be defined in the group_vars/all file, execute the following
63 | command:
64 |
65 | ansible-playbook -i hosts rolling_update.yml
66 |
67 | You can optionally pass: -e webapp_version=xxx to the rolling_update
68 | playbook to specify a specific version of the example webapp to deploy.
69 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/group_vars/all:
--------------------------------------------------------------------------------
1 | ---
2 | # Variables here are applicable to all host groups
3 |
4 | httpd_port: 80
5 | ntpserver: 192.168.1.2
6 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/group_vars/dbservers:
--------------------------------------------------------------------------------
1 | ---
2 | # The variables file used by the playbooks in the dbservers group.
3 | # These don't have to be explicitly imported by vars_files: they are autopopulated.
4 |
5 | mysqlservice: mysqld
6 | mysql_port: 3306
7 | dbuser: root
8 | dbname: foodb
9 | upassword: abc
10 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/group_vars/lbservers:
--------------------------------------------------------------------------------
1 | ---
2 | # Variables for the HAproxy configuration
3 |
4 | # HAProxy supports "http" and "tcp". For SSL, SMTP, etc, use "tcp".
5 | mode: http
6 |
7 | # Port on which HAProxy should listen
8 | listenport: 8888
9 |
10 | # A name for the proxy daemon, this wil be the suffix in the logs.
11 | daemonname: myapplb
12 |
13 | # Balancing Algorithm. Available options:
14 | # roundrobin, source, leastconn, source, uri
15 | # (if persistance is required use, "source")
16 | balance: roundrobin
17 |
18 | # Ethernet interface on which the load balancer should listen
19 | # Defaults to the first interface. Change this to:
20 | #
21 | # iface: eth1
22 | #
23 | # ...to override.
24 | #
25 | iface: '{{ ansible_default_ipv4.interface }}'
26 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/group_vars/webservers:
--------------------------------------------------------------------------------
1 | ---
2 | # Variables for the web server configuration
3 |
4 | # Ethernet interface on which the web server should listen.
5 | # Defaults to the first interface. Change this to:
6 | #
7 | # iface: eth1
8 | #
9 | # ...to override.
10 | #
11 | iface: '{{ ansible_default_ipv4.interface }}'
12 |
13 | # this is the repository that holds our sample webapp
14 | repository: http://github.com/bennojoy/mywebapp.git
15 |
16 | # this is the sha1sum of V5 of the test webapp.
17 | webapp_version: 351e47276cc66b018f4890a04709d4cc3d3edb0d
18 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/hosts:
--------------------------------------------------------------------------------
1 | [webservers]
2 | web3
3 | web2
4 |
5 | [dbservers]
6 | web3
7 |
8 | [lbservers]
9 | web2
10 |
11 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/roles/base-apache/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # This role installs httpd
3 |
4 | - name: Install http and php etc
5 | yum: name={{ item }} state=present
6 | with_items:
7 | - httpd
8 | - libsemanage-python
9 | - libselinux-python
10 |
11 | - name: http service state
12 | service: name=httpd state=started enabled=yes
13 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/roles/common/files/RPM-GPG-KEY-EPEL-6:
--------------------------------------------------------------------------------
1 | -----BEGIN PGP PUBLIC KEY BLOCK-----
2 | Version: GnuPG v1.4.5 (GNU/Linux)
3 |
4 | mQINBEvSKUIBEADLGnUj24ZVKW7liFN/JA5CgtzlNnKs7sBg7fVbNWryiE3URbn1
5 | JXvrdwHtkKyY96/ifZ1Ld3lE2gOF61bGZ2CWwJNee76Sp9Z+isP8RQXbG5jwj/4B
6 | M9HK7phktqFVJ8VbY2jfTjcfxRvGM8YBwXF8hx0CDZURAjvf1xRSQJ7iAo58qcHn
7 | XtxOAvQmAbR9z6Q/h/D+Y/PhoIJp1OV4VNHCbCs9M7HUVBpgC53PDcTUQuwcgeY6
8 | pQgo9eT1eLNSZVrJ5Bctivl1UcD6P6CIGkkeT2gNhqindRPngUXGXW7Qzoefe+fV
9 | QqJSm7Tq2q9oqVZ46J964waCRItRySpuW5dxZO34WM6wsw2BP2MlACbH4l3luqtp
10 | Xo3Bvfnk+HAFH3HcMuwdaulxv7zYKXCfNoSfgrpEfo2Ex4Im/I3WdtwME/Gbnwdq
11 | 3VJzgAxLVFhczDHwNkjmIdPAlNJ9/ixRjip4dgZtW8VcBCrNoL+LhDrIfjvnLdRu
12 | vBHy9P3sCF7FZycaHlMWP6RiLtHnEMGcbZ8QpQHi2dReU1wyr9QgguGU+jqSXYar
13 | 1yEcsdRGasppNIZ8+Qawbm/a4doT10TEtPArhSoHlwbvqTDYjtfV92lC/2iwgO6g
14 | YgG9XrO4V8dV39Ffm7oLFfvTbg5mv4Q/E6AWo/gkjmtxkculbyAvjFtYAQARAQAB
15 | tCFFUEVMICg2KSA8ZXBlbEBmZWRvcmFwcm9qZWN0Lm9yZz6JAjYEEwECACAFAkvS
16 | KUICGw8GCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRA7Sd8qBgi4lR/GD/wLGPv9
17 | qO39eyb9NlrwfKdUEo1tHxKdrhNz+XYrO4yVDTBZRPSuvL2yaoeSIhQOKhNPfEgT
18 | 9mdsbsgcfmoHxmGVcn+lbheWsSvcgrXuz0gLt8TGGKGGROAoLXpuUsb1HNtKEOwP
19 | Q4z1uQ2nOz5hLRyDOV0I2LwYV8BjGIjBKUMFEUxFTsL7XOZkrAg/WbTH2PW3hrfS
20 | WtcRA7EYonI3B80d39ffws7SmyKbS5PmZjqOPuTvV2F0tMhKIhncBwoojWZPExft
21 | HpKhzKVh8fdDO/3P1y1Fk3Cin8UbCO9MWMFNR27fVzCANlEPljsHA+3Ez4F7uboF
22 | p0OOEov4Yyi4BEbgqZnthTG4ub9nyiupIZ3ckPHr3nVcDUGcL6lQD/nkmNVIeLYP
23 | x1uHPOSlWfuojAYgzRH6LL7Idg4FHHBA0to7FW8dQXFIOyNiJFAOT2j8P5+tVdq8
24 | wB0PDSH8yRpn4HdJ9RYquau4OkjluxOWf0uRaS//SUcCZh+1/KBEOmcvBHYRZA5J
25 | l/nakCgxGb2paQOzqqpOcHKvlyLuzO5uybMXaipLExTGJXBlXrbbASfXa/yGYSAG
26 | iVrGz9CE6676dMlm8F+s3XXE13QZrXmjloc6jwOljnfAkjTGXjiB7OULESed96MR
27 | XtfLk0W5Ab9pd7tKDR6QHI7rgHXfCopRnZ2VVQ==
28 | =V/6I
29 | -----END PGP PUBLIC KEY BLOCK-----
30 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/roles/common/files/epel.repo:
--------------------------------------------------------------------------------
1 | [epel]
2 | name=Extra Packages for Enterprise Linux 6 - $basearch
3 | #baseurl=http://download.fedoraproject.org/pub/epel/6/$basearch
4 | mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch
5 | failovermethod=priority
6 | enabled=1
7 | gpgcheck=1
8 | gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6
9 |
10 | [epel-debuginfo]
11 | name=Extra Packages for Enterprise Linux 6 - $basearch - Debug
12 | #baseurl=http://download.fedoraproject.org/pub/epel/6/$basearch/debug
13 | mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-debug-6&arch=$basearch
14 | failovermethod=priority
15 | enabled=0
16 | gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6
17 | gpgcheck=1
18 |
19 | [epel-source]
20 | name=Extra Packages for Enterprise Linux 6 - $basearch - Source
21 | #baseurl=http://download.fedoraproject.org/pub/epel/6/SRPMS
22 | mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-source-6&arch=$basearch
23 | failovermethod=priority
24 | enabled=0
25 | gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6
26 | gpgcheck=1
27 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/roles/common/handlers/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # Handlers for common notifications
3 |
4 | - name: restart ntp
5 | service: name=ntpd state=restarted
6 |
7 | - name: restart iptables
8 | service: name=iptables state=restarted
9 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/roles/common/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # This role contains common plays that will run on all nodes.
3 |
4 | - name: Create the repository for EPEL
5 | copy: src=epel.repo dest=/etc/yum.repos.d/epel.repo
6 |
7 | - name: Create the GPG key for EPEL
8 | copy: src=RPM-GPG-KEY-EPEL-6 dest=/etc/pki/rpm-gpg
9 |
10 | - name: install some useful nagios plugins
11 | yum: name={{ item }} state=present
12 | with_items:
13 | - nagios-nrpe
14 | - nagios-plugins-swap
15 | - nagios-plugins-users
16 | - nagios-plugins-procs
17 | - nagios-plugins-load
18 | - nagios-plugins-disk
19 |
20 | - name: Install ntp
21 | yum: name=ntp state=present
22 | tags: ntp
23 |
24 | - name: Configure ntp file
25 | template: src=ntp.conf.j2 dest=/etc/ntp.conf
26 | tags: ntp
27 | notify: restart ntp
28 |
29 | - name: Start the ntp service
30 | service: name=ntpd state=started enabled=true
31 | tags: ntp
32 |
33 | - name: insert iptables template
34 | template: src=iptables.j2 dest=/etc/sysconfig/iptables
35 | notify: restart iptables
36 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/roles/common/templates/iptables.j2:
--------------------------------------------------------------------------------
1 | # {{ ansible_managed }}
2 | # Manual customization of this file is not recommended.
3 | *filter
4 | :INPUT ACCEPT [0:0]
5 | :FORWARD ACCEPT [0:0]
6 | :OUTPUT ACCEPT [0:0]
7 |
8 | {% if (inventory_hostname in groups['webservers']) or (inventory_hostname in groups['monitoring']) %}
9 | -A INPUT -p tcp --dport 80 -j ACCEPT
10 | {% endif %}
11 |
12 | {% if inventory_hostname in groups['dbservers'] %}
13 | -A INPUT -p tcp --dport 3306 -j ACCEPT
14 | {% endif %}
15 |
16 | {% if inventory_hostname in groups['lbservers'] %}
17 | -A INPUT -p tcp --dport {{ listenport }} -j ACCEPT
18 | {% endif %}
19 |
20 | {% for host in groups['monitoring'] %}
21 | -A INPUT -p tcp -s {{ hostvars[host].ansible_default_ipv4.address }} --dport 5666 -j ACCEPT
22 | {% endfor %}
23 |
24 | -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
25 | -A INPUT -p icmp -j ACCEPT
26 | -A INPUT -i lo -j ACCEPT
27 | -A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
28 | -A INPUT -j REJECT --reject-with icmp-host-prohibited
29 | -A FORWARD -j REJECT --reject-with icmp-host-prohibited
30 | COMMIT
31 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/roles/common/templates/ntp.conf.j2:
--------------------------------------------------------------------------------
1 |
2 | driftfile /var/lib/ntp/drift
3 |
4 | restrict 127.0.0.1
5 | restrict -6 ::1
6 |
7 | server {{ ntpserver }}
8 |
9 | includefile /etc/ntp/crypto/pw
10 |
11 | keys /etc/ntp/keys
12 |
13 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/roles/haproxy/handlers/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # Handlers for HAproxy
3 |
4 | - name: restart haproxy
5 | service: name=haproxy state=restarted
6 |
7 | - name: reload haproxy
8 | service: name=haproxy state=reloaded
9 |
10 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/roles/haproxy/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # This role installs HAProxy and configures it.
3 |
4 | - name: Download and install haproxy and socat
5 | yum: name={{ item }} state=present
6 | with_items:
7 | - haproxy
8 | - socat
9 |
10 | - name: Configure the haproxy cnf file with hosts
11 | template: src=haproxy.cfg.j2 dest=/etc/haproxy/haproxy.cfg
12 | notify: restart haproxy
13 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/roles/haproxy/templates/haproxy.cfg.j2:
--------------------------------------------------------------------------------
1 | global
2 | log 127.0.0.1 local2
3 |
4 | chroot /var/lib/haproxy
5 | pidfile /var/run/haproxy.pid
6 | maxconn 4000
7 | user root
8 | group root
9 | daemon
10 |
11 | # turn on stats unix socket
12 | stats socket /var/lib/haproxy/stats level admin
13 |
14 | defaults
15 | mode {{ mode }}
16 | log global
17 | option httplog
18 | option dontlognull
19 | option http-server-close
20 | option forwardfor except 127.0.0.0/8
21 | option redispatch
22 | retries 3
23 | timeout http-request 10s
24 | timeout queue 1m
25 | timeout connect 10s
26 | timeout client 1m
27 | timeout server 1m
28 | timeout http-keep-alive 10s
29 | timeout check 10s
30 | maxconn 3000
31 |
32 | backend app
33 | {% for host in groups['lbservers'] %}
34 | listen {{ daemonname }} {{ hostvars[host]['ansible_' + iface].ipv4.address }}:{{ listenport }}
35 | {% endfor %}
36 | balance {{ balance }}
37 | {% for host in groups['webservers'] %}
38 | server {{ hostvars[host].ansible_hostname }} {{ hostvars[host]['ansible_' + iface].ipv4.address }}:{{ httpd_port }}
39 | {% endfor %}
40 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/roles/nagios/files/ansible-managed-services.cfg:
--------------------------------------------------------------------------------
1 | # {{ ansible_managed }}
2 |
3 | # service checks to be applied to all hosts
4 |
5 | define service {
6 | use local-service
7 | host_name localhost
8 | service_description Root Partition
9 | check_command check_local_disk!20%!10%!/
10 | }
11 |
12 | define service {
13 | use local-service
14 | host_name *
15 | service_description Current Users
16 | check_command check_local_users!20!50
17 | }
18 |
19 |
20 | define service {
21 | use local-service
22 | host_name *
23 | service_description Total Processes
24 | check_command check_local_procs!250!400!RSZDT
25 | }
26 |
27 | define service {
28 | use local-service
29 | host_name *
30 | service_description Current Load
31 | check_command check_local_load!5.0,4.0,3.0!10.0,6.0,4.0
32 | }
33 |
34 | define service {
35 | use local-service
36 | host_name *
37 | service_description Swap Usage
38 | check_command check_local_swap!20!10
39 | }
40 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/roles/nagios/files/localhost.cfg:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # LOCALHOST.CFG - SAMPLE OBJECT CONFIG FILE FOR MONITORING THIS MACHINE
3 | #
4 | # Last Modified: 05-31-2007
5 | #
6 | # NOTE: This config file is intended to serve as an *extremely* simple
7 | # example of how you can create configuration entries to monitor
8 | # the local (Linux) machine.
9 | #
10 | ###############################################################################
11 |
12 |
13 |
14 |
15 | ###############################################################################
16 | ###############################################################################
17 | #
18 | # HOST DEFINITION
19 | #
20 | ###############################################################################
21 | ###############################################################################
22 |
23 | # Define a host for the local machine
24 |
25 | define host{
26 | use linux-server ; Name of host template to use
27 | ; This host definition will inherit all variables that are defined
28 | ; in (or inherited by) the linux-server host template definition.
29 | host_name localhost
30 | alias localhost
31 | address 127.0.0.1
32 | }
33 |
34 |
35 |
36 | ###############################################################################
37 | ###############################################################################
38 | #
39 | # HOST GROUP DEFINITION
40 | #
41 | ###############################################################################
42 | ###############################################################################
43 |
44 | # Define an optional hostgroup for Linux machines
45 |
46 | define hostgroup{
47 | hostgroup_name linux-servers ; The name of the hostgroup
48 | alias Linux Servers ; Long name of the group
49 | members localhost ; Comma separated list of hosts that belong to this group
50 | }
51 |
52 |
53 |
54 | ###############################################################################
55 | ###############################################################################
56 | #
57 | # SERVICE DEFINITIONS
58 | #
59 | ###############################################################################
60 | ###############################################################################
61 |
62 |
63 | # Define a service to "ping" the local machine
64 |
65 | define service{
66 | use local-service ; Name of service template to use
67 | host_name localhost
68 | service_description PING
69 | check_command check_ping!100.0,20%!500.0,60%
70 | }
71 |
72 |
73 | # Define a service to check the disk space of the root partition
74 | # on the local machine. Warning if < 20% free, critical if
75 | # < 10% free space on partition.
76 |
77 | define service{
78 | use local-service ; Name of service template to use
79 | host_name localhost
80 | service_description Root Partition
81 | check_command check_local_disk!20%!10%!/
82 | }
83 |
84 |
85 |
86 | # Define a service to check the number of currently logged in
87 | # users on the local machine. Warning if > 20 users, critical
88 | # if > 50 users.
89 |
90 | define service{
91 | use local-service ; Name of service template to use
92 | host_name localhost
93 | service_description Current Users
94 | check_command check_local_users!20!50
95 | }
96 |
97 |
98 | # Define a service to check the number of currently running procs
99 | # on the local machine. Warning if > 250 processes, critical if
100 | # > 400 users.
101 |
102 | define service{
103 | use local-service ; Name of service template to use
104 | host_name localhost
105 | service_description Total Processes
106 | check_command check_local_procs!250!400!RSZDT
107 | }
108 |
109 |
110 |
111 | # Define a service to check the load on the local machine.
112 |
113 | define service{
114 | use local-service ; Name of service template to use
115 | host_name localhost
116 | service_description Current Load
117 | check_command check_local_load!5.0,4.0,3.0!10.0,6.0,4.0
118 | }
119 |
120 |
121 |
122 | # Define a service to check the swap usage the local machine.
123 | # Critical if less than 10% of swap is free, warning if less than 20% is free
124 |
125 | define service{
126 | use local-service ; Name of service template to use
127 | host_name localhost
128 | service_description Swap Usage
129 | check_command check_local_swap!20!10
130 | }
131 |
132 |
133 |
134 | # Define a service to check SSH on the local machine.
135 | # Disable notifications for this service by default, as not all users may have SSH enabled.
136 |
137 | define service{
138 | use local-service ; Name of service template to use
139 | host_name localhost
140 | service_description SSH
141 | check_command check_ssh
142 | notifications_enabled 0
143 | }
144 |
145 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/roles/nagios/handlers/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # handlers for nagios
3 | - name: restart httpd
4 | service: name=httpd state=restarted
5 |
6 | - name: restart nagios
7 | service: name=nagios state=restarted
8 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/roles/nagios/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # This will install nagios
3 |
4 | - name: install nagios
5 | yum: pkg={{ item }} state=present
6 | with_items:
7 | - nagios
8 | - nagios-plugins
9 | - nagios-plugins-nrpe
10 | - nagios-plugins-ping
11 | - nagios-plugins-ssh
12 | - nagios-plugins-http
13 | - nagios-plugins-mysql
14 | - nagios-devel
15 | notify: restart httpd
16 |
17 | - name: create nagios config dir
18 | file: path=/etc/nagios/ansible-managed state=directory
19 |
20 | - name: configure nagios
21 | copy: src=nagios.cfg dest=/etc/nagios/nagios.cfg
22 | notify: restart nagios
23 |
24 | - name: configure localhost monitoring
25 | copy: src=localhost.cfg dest=/etc/nagios/objects/localhost.cfg
26 | notify: restart nagios
27 |
28 | - name: configure nagios services
29 | copy: src=ansible-managed-services.cfg dest=/etc/nagios/
30 |
31 | - name: create the nagios object files
32 | template: src={{ item + ".j2" }}
33 | dest=/etc/nagios/ansible-managed/
34 | with_items:
35 | - webservers.cfg
36 | - dbservers.cfg
37 | - lbservers.cfg
38 | notify: restart nagios
39 |
40 | - name: start nagios
41 | service: name=nagios state=started enabled=yes
42 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/roles/nagios/templates/dbservers.cfg.j2:
--------------------------------------------------------------------------------
1 | # {{ ansible_managed }}
2 |
3 | define hostgroup {
4 | hostgroup_name dbservers
5 | alias Database Servers
6 | }
7 |
8 | {% for host in groups['dbservers'] %}
9 | define host {
10 | use linux-server
11 | host_name {{ host }}
12 | alias {{ host }}
13 | address {{ hostvars[host].ansible_default_ipv4.address }}
14 | hostgroups dbservers
15 | }
16 | {% endfor %}
17 |
18 | #define service {
19 | # use local-service
20 | # hostgroup_name dbservers
21 | # service_description MySQL Database Server
22 | # check_command check_mysql
23 | # notifications_enabled 0
24 | #}
25 |
26 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/roles/nagios/templates/lbservers.cfg.j2:
--------------------------------------------------------------------------------
1 | # {{ ansible_managed }}
2 |
3 | define hostgroup {
4 | hostgroup_name loadbalancers
5 | alias Load Balancers
6 | }
7 |
8 | {% for host in groups['lbservers'] %}
9 | define host {
10 | use linux-server
11 | host_name {{ host }}
12 | alias {{ host }}
13 | address {{ hostvars[host].ansible_default_ipv4.address }}
14 | hostgroups loadbalancers
15 | }
16 | define service {
17 | use local-service
18 | host_name {{ host }}
19 | service_description HAProxy Load Balancer
20 | check_command check_http!-p{{ hostvars[host].listenport }}
21 | }
22 | {% endfor %}
23 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/roles/nagios/templates/webservers.cfg.j2:
--------------------------------------------------------------------------------
1 | # {{ ansible_managed }}
2 |
3 | define hostgroup {
4 | hostgroup_name webservers
5 | alias Web Servers
6 | }
7 |
8 | {% for host in groups['webservers'] %}
9 | define host {
10 | use linux-server
11 | host_name {{ host }}
12 | alias {{ host }}
13 | address {{ hostvars[host].ansible_default_ipv4.address }}
14 | hostgroups webservers
15 | }
16 | {% endfor %}
17 |
18 | # service checks to be applied to the web server
19 | define service {
20 | use local-service
21 | hostgroup_name webservers
22 | service_description webserver
23 | check_command check_http
24 | notifications_enabled 0
25 | }
26 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/roles/web/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | # httpd is handled by the base-apache role upstream
4 | - name: Install php and git
5 | yum: name={{ item }} state=present
6 | with_items:
7 | - php
8 | - php-mysql
9 | - git
10 |
11 | - name: Configure SELinux to allow httpd to connect to remote database
12 | seboolean: name=httpd_can_network_connect_db state=true persistent=yes
13 |
14 | - name: Copy the code from repository
15 | git: repo={{ repository }} version={{ webapp_version }} dest=/var/www/html/
16 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/rolling_update.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # This playbook does a rolling update for all webservers serially (one at a time).
3 | # Change the value of serial: to adjust the number of server to be updated.
4 | #
5 | # The three roles that apply to the webserver hosts will be applied: common,
6 | # base-apache, and web. So any changes to configuration, package updates, etc,
7 | # will be applied as part of the rolling update process.
8 | #
9 |
10 | # gather facts from monitoring nodes for iptables rules
11 | - hosts: monitoring
12 | tasks:
13 |
14 | - hosts: webservers
15 | user: root
16 | serial: 1
17 |
18 | # These are the tasks to run before applying updates:
19 | pre_tasks:
20 | - name: disable nagios alerts for this host webserver service
21 | nagios: action=disable_alerts host={{ ansible_hostname }} services=webserver
22 | delegate_to: "{{ item }}"
23 | with_items: groups.monitoring
24 |
25 | - name: disable the server in haproxy
26 | shell: echo "disable server myapplb/{{ ansible_hostname }}" | socat stdio /var/lib/haproxy/stats
27 | delegate_to: "{{ item }}"
28 | with_items: groups.lbservers
29 |
30 | roles:
31 | - common
32 | - base-apache
33 | - web
34 |
35 | # These tasks run after the roles:
36 | post_tasks:
37 | - name: Enable the server in haproxy
38 | shell: echo "enable server myapplb/{{ ansible_hostname }}" | socat stdio /var/lib/haproxy/stats
39 | delegate_to: "{{ item }}"
40 | with_items: groups.lbservers
41 |
42 | - name: re-enable nagios alerts
43 | nagios: action=enable_alerts host={{ ansible_hostname }} services=webserver
44 | delegate_to: "{{ item }}"
45 | with_items: groups.monitoring
46 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_08/lamp_haproxy/site.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # This playbook deploys the whole application stack in this site.
3 |
4 | # Apply common configuration to all hosts
5 | - hosts: all
6 | roles:
7 | - common
8 |
9 | # Configure and deploy database servers.
10 | - hosts: dbservers
11 | user: root
12 | roles:
13 | - db
14 |
15 | # Configure and deploy the web servers. Note that we include two roles here,
16 | # the 'base-apache' role which simply sets up Apache, and 'web' which includes
17 | # our example web application.
18 | - hosts: webservers
19 | user: root
20 |
21 | roles:
22 | - base-apache
23 | - web
24 |
25 | # Configure and deploy the load balancer(s).
26 | - hosts: lbservers
27 | user: root
28 | roles:
29 | - haproxy
30 |
31 | # Configure and deploy the Nagios monitoring node(s).
32 | - hosts: monitoring
33 | user: root
34 | roles:
35 | - base-apache
36 | - nagios
37 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_09/mysql-users.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: MySQL Users
3 | hosts: webservers
4 |
5 | tasks:
6 | - name: add a mysql user for the server
7 | mysql_user: name={{ db_username }} host={{ inventory_hostname }}
8 | password={{ db_password }} priv='ansible.*:ALL'
9 | state=present
10 | delegate_to: databases[0]
11 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_11/iptables.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - hosts: webservers
3 | gather_facts: yes
4 |
5 | - hosts: databases
6 | handlers:
7 | - name: Reload iptables
8 | service: name=iptables state=reloaded
9 |
10 | tasks:
11 | - name: Template /etc/sysconfig/iptables
12 | template: src=templates/iptables.j2 dest=/etc/sysconfig/iptables
13 | notify: Reload iptables
14 |
15 | - name: Ensure iptables is started and enabled
16 | service: name=iptables state=started enabled=yes
17 |
--------------------------------------------------------------------------------
/advanced_lab/chapter_11/templates/iptables.j2:
--------------------------------------------------------------------------------
1 | *filter
2 | :INPUT ACCEPT [0:0]
3 | :FORWARD ACCEPT [0:0]
4 | :OUTPUT ACCEPT [0:0]
5 |
6 | {% for server in groups['webservers'] %}
7 | -A INPUT -p tcp -s {{ hostvars[server].ansible_eth1.ipv4.address }} -i eth1 -d {{ ansible_eth1.ipv4.address }} --dport 3306 -j ACCEPT
8 | {% endfor %}
9 |
10 | {% for server in groups['databases'] %}
11 | {% if server != inventory_hostname %}
12 | -A INPUT -p tcp -s {{ hostvars[server].ansible_eth1.ipv4.address }} -i eth1 -d {{ ansible_eth1.ipv4.address }} --dport 3306 -j ACCEPT
13 | {% endif %}
14 | {% endfor %}
15 |
16 | -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
17 | -A INPUT -p icmp -j ACCEPT
18 | -A INPUT -i lo -j ACCEPT
19 | -A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
20 | -A INPUT -j REJECT --reject-with icmp-host-prohibited
21 | -A FORWARD -j REJECT --reject-with icmp-host-prohibited
22 | COMMIT
23 |
--------------------------------------------------------------------------------
/build.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - hosts: localhost
3 | connection: local
4 |
5 | tasks:
6 |
7 | - name: create reveal link
8 | command: ln -s revelator/reveal_js_261 ./reveal_js_261 creates=./reveal_js_261
9 |
10 | - name: create dest dir
11 | command: mkdir -p output
12 |
13 | - name: syntax check fundamentals
14 | shell: python syntax_check.py fundamentals/*.yml
15 |
16 | - name: syntax check operational
17 | shell: python syntax_check.py operational/*.yml
18 |
19 | - name: syntax check advanced
20 | shell: python syntax_check.py advanced/*.yml
21 |
22 | - name: build fundamentals
23 | shell: python build_single.py fundamentals > output/fundamentals.yml
24 |
25 | - name: build operational
26 | shell: python build_single.py operational > output/operational.yml
27 |
28 | - name: build advanced
29 | shell: python build_single.py advanced > output/advanced.yml
30 |
31 | - name: render fundamentals
32 | command: revelator/write_it output/fundamentals.yml output/fundamentals/
33 |
34 | - name: render operational
35 | command: revelator/write_it output/operational.yml output/operational/
36 |
37 | - name: render advanced
38 | command: revelator/write_it output/advanced.yml output/advanced/
39 |
--------------------------------------------------------------------------------
/build_single.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 |
4 | try:
5 | import yaml
6 | except ImportError:
7 | raise SystemExit('PyYAML python module is missing')
8 |
9 | # Allow specification of a path to look for YAML files
10 | # Fallback to dirname of this script itself
11 | try:
12 | path = sys.argv[1]
13 | except IndexError:
14 | path = os.path.dirname(os.path.abspath(__file__))
15 |
16 | allfiles = os.listdir(path)
17 |
18 | # Find all YAML chapter files. Files should have "chapter" in the name
19 | chapter_files = []
20 | for f in allfiles:
21 | root, ext = os.path.splitext(f)
22 | if ('chapter' in root.lower() and 'template' not in root.lower() and
23 | ext.lower() in ['.yml', '.yaml']):
24 | chapter_files.append(f)
25 |
26 | chapter_files.sort()
27 |
28 | # Open the root.yml file that is the root of the slides
29 | try:
30 | with open(os.path.join(path, 'root.yml')) as f:
31 | root = yaml.load(f)
32 | except:
33 | raise SystemExit('root.yml file not found')
34 |
35 | if 'slides' not in root:
36 | root['slides'] = []
37 |
38 | errors = []
39 | for chapter_file in chapter_files:
40 | try:
41 | with open(os.path.join(path, chapter_file)) as f:
42 | chapter = yaml.load(f)
43 | except:
44 | errors.append('*** Could not load/parse %s ***\n' % chapter_file)
45 | else:
46 | try:
47 | root['slides'].extend(chapter['slides'])
48 | except:
49 | errors.append('*** Could not find slides in %s ***\n' % chapter_file)
50 |
51 | print yaml.dump(root, indent=4, allow_unicode=True, default_flow_style=False)
52 |
53 | if errors:
54 | sys.stderr.write('\n'.join(errors))
55 | sys.exit(len(errors))
56 |
57 | sys.exit(0)
58 |
--------------------------------------------------------------------------------
/builder.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Build script that should simplify Jenkins configuration.
3 |
4 | # Exit if any command returns non-zero
5 | set -e
6 |
7 |
8 | if [ -d revelator ]; then
9 | echo "******** Checking for latest version of Revelator ********"
10 | cd revelator
11 | git pull
12 | cd ..
13 | else
14 | echo "******** Downloading Revelator ********"
15 | git clone https://github.com/mpdehaan/revelator.git
16 | ln -fs revelator/reveal_js_261
17 | fi
18 |
19 | echo "******** Looping over folders ********"
20 | for i in fundamentals operational advanced development
21 | do
22 | echo "******** Syntax Check on $i ********"
23 | python $DRONE_BUILD_DIR/syntax_check.py $DRONE_BUILD_DIR/$i/*.yml
24 | echo "******** Creating output folder for $i ********"
25 | mkdir -p output/$i
26 | echo "******** Build Single on $i ********"
27 | python $DRONE_BUILD_DIR/build_single.py $DRONE_BUILD_DIR/$i > $i_comp.yml
28 | echo "******** Generating Slides on $i ********"
29 | python revelator/write_it $i_comp.yml output/$i
30 | done
31 |
--------------------------------------------------------------------------------
/chapter_template.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Tim G
4 | title: Chapter Title
5 | description: Description of the chapter
6 |
7 | slides:
8 |
9 | -
10 | - nested:
11 |
12 | -
13 | - h1: chapter title slide
14 | - h3: subtitle/info
15 |
16 | -
17 | - h1: content slide
18 | - p: content content content
19 |
20 | - class_notes:
21 | these are speaker notes that will be hidden
22 |
23 | -
24 | - h1: content slide
25 | - p: more content
26 |
27 | -
28 | - h3: This is how ordered lists work
29 | - ol:
30 | - alpha
31 | - beta
32 | - gamma
33 |
34 | -
35 | - h3: And unordered lists are also a thing
36 | - ul:
37 | - duck
38 | - duck
39 | - goose
40 | - cow
41 |
42 | -
43 | - h3: Code highlighting demo
44 | - code: |
45 | import ansible
46 | ansible.all_the_things()
47 |
48 |
--------------------------------------------------------------------------------
/development/chapter_0.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Justin Phelps
4 | title: Ansible Development
5 | description: Ansible Development Course
6 |
7 | slides:
8 | -
9 | - nested:
10 | -
11 | - h1: Ansible Development
12 |
--------------------------------------------------------------------------------
/development/chapter_1.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: CC, PI
4 | title: Chapter 1, Ansible Fundamentals
5 | description: Ansible Fundamentals Course
6 |
7 | slides:
8 |
9 | - set_global:
10 | transition: rotate
11 | background: '#007777'
12 | #background: 'black'
13 |
14 | -
15 | - nested:
16 | -
17 | - h1: What is Ansible?
18 | - ul:
19 | - Clear
20 | - Fast
21 | - Complete
22 | - Efficient
23 | - Secure
24 |
25 | -
26 | - h2: Clear
27 | - p: 'A simple automation language allows Ansible to be used by anyone:'
28 | - ul:
29 | - sysadmins
30 | - developers
31 | - IT managers
32 | - p: It's easy to write, read, maintain, and evolve - without writing scripts or custom code.
33 | -
34 | - h2: Fast
35 | - p: Ansible is easy to learn.
36 | - p: Setup is fast.
37 | - class_notes: |
38 | 1. You can automate in under 30 minutes. Forget about how it works, just do it.
39 | 2. No agents. SSH keys are typically already in place.
40 | -
41 | - h2: Complete
42 | - p: 'Ansible is several tools in one:'
43 | - ul:
44 | - configuration management
45 | - application deployment
46 | - orchestration
47 | - provisioning
48 | - p: Hundreds of built-in modules.
49 | -
50 | - h2: Efficient
51 | - p: Ansible doesn't require a custom agent or software to install.
52 | - p: Ansible runs on OpenSSH.
53 | - class_notes: |
54 | 1. With no additional software infrastructure, you don't have to
55 | worry about managing the management tool.
56 | 2. That means anywhere SSH goes, Ansible goes.
57 | 3. It doesn't suck memory or CPU resources when it is not in use.
58 | 4. Designed from day one to automate no-downtime rolling updates
59 | and multi-tier orchestration.
60 | -
61 | - h2: Secure
62 | - p: No agent.
63 | - p: SSH transport.
64 | - p: Ansible plays can be read by anyone.
65 | - class_notes: |
66 | 1. It doesn't need additional ports or root level daemons.
67 | 2. It uses built-in OS authentication for better security - login
68 | as who you are, sudo if you want to sudo.
69 | 3. You can work with tools like Kerberos, LDAP, and sssd.
70 | 4. OpenSSH is the most peer-reviewed security component around.
71 | 5. This makes it auditable. You know what you're automating,
72 | and bugs have nowhere to hide.
73 |
--------------------------------------------------------------------------------
/development/chapter_2.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Mike Martin, Justin Phelps, Paul Durivage
4 | title: Chapter 2
5 | description: Ansible Fundamentals Course
6 |
7 | slides:
8 |
9 | -
10 | - nested:
11 | -
12 | - h1: Ansible Use Cases
13 | - p: Ask not what you can do for Ansible, but what Ansible can do for you!
14 | -
15 | - h2: Ansible Use Cases
16 | - ul:
17 | - Remote Execution / Ad-hoc Tasks
18 | - Configuration Management
19 | - Application Deployment & Orchestration
20 | - Provisioning Infrastructure Dynamically
21 | -
22 | - h2: Remote Execution
23 | - ul:
24 | - Replacement for traditional systems administration tasks. (i.e., SSH)
25 | - Checking system responsiveness and uptime.
26 | - Gathering information about a collection of systems.
27 | - Replace one off rsync scripts, fabric, or terminal multiplexing.
28 | - class_notes: |
29 | Ansible provides a command-line tool and framework capable of
30 | executing over a large number of hosts, eliminating the need for
31 | systems administrators to multiplex terminal sessions via SSH to
32 | execute concurrent tasks across multiple hosts. What may have
33 | been done in bash scripts, rsync scripts, etc. can be done via
34 | ad-hoc one-liners in the shell.
35 | -
36 | - h2: Remote Execution
37 | - code: |
38 | ansible -m user -a "name=bob state=present" webservers
39 | - code: |
40 | ansible -m apt -a "pkg=apache2 state=present" webservers
41 | - class_notes: |
42 | Example 1 is adding a user to all the systems defined in the
43 | webservers group. Example 2 is installing the apache2 package
44 | on all systems defined in the webservers group.
45 | -
46 | - h2: Config Management
47 | - ul:
48 | - Lengthy system configuration, to include adding users, ssh keys, installing and configuring services, and bootstrapping systems to a given state.
49 | - '"Configuration remediation" Consistent server configuration. Removes manual configuration errors.'
50 | - class_notes: |
51 | Servers need to be configured; Ansible configures servers.
52 | Using a combination of imperative and declarative syntax
53 | [described in detail--maybe using the GPS analogy], using
54 | concepts such as tasks, roles, plays, and playbooks, complex
55 | machine configurations are being assembled and converged by
56 | the Ansible toolchain rather than manually by administrators.
57 | Configuration is either set manually by the author or dynamically at runtime by Ansible, resulting in consistent configuration across large server sets.
58 | -
59 | - h2: Application Deployment & Orchestration
60 | - p: Ansible can be used to replace various deployment and orchestration tools.
61 | - ul:
62 | - Deploy your custom application.
63 | - Replacement for Capistrano and Fabric (i.e., git deployments)
64 | - Good for large, complex environments
65 | -
66 | - h2: Application Deployment & Orchestration
67 | - p: Application deployment includes two main schools of thought.
68 | - h2: Rolling Release
69 | ul:
70 | - Remove node from production, update components, and put back into rotation.
71 | - class_notes: |
72 | Make the point that you deploy often in the DevOps world, and
73 | why this is important for application development.
74 | -
75 | - h2: Application Deployment & Orchestration
76 | - p: Application deployment includes two main schools of thought.
77 | - h2: Fresh Start
78 | - ul:
79 | - Deploy entirely new infrastructure and replace current environment wholesale.
80 | - class_notes: |
81 | Make the point that you deploy often in the DevOps world, and
82 | why this is important for application development.
83 | -
84 | - h2: Provisioning Infrastructure Dynamically
85 | - ul:
86 | - Infrastructure is Data.
87 | - You can provision to various clouds.
88 | - Dynamic Inventory plugins for various providers (Rackspace, Amazon, Digital Ocean, OpenStack, Eucalyptus etc.)
89 | - class_notes: |
90 | Cover the various ways that infrastructure can be provisioned
91 | using Ansible. Mention that there are modules that provide
92 | he ability to deploy to various clouds. Include a high level
93 | overview of the dynamic inventory plugin system. (Creating
94 | Infrastructure is the same as Configuring Infrastructure.)
95 | -
96 | - h2: Who is your Ansible, and what does he do?
97 | - class_notes: |
98 | Have the class search the ansible documention and come up
99 | with something that Ansible does. Be that a specific module,
100 | or a high level concept.
101 |
--------------------------------------------------------------------------------
/development/chapter_3.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Jesse K and the DFed Experience
4 | title: Understand the concepts of Ansible
5 | description: Description of the chapter
6 |
7 | slides:
8 |
9 | -
10 | - nested:
11 | -
12 | - h1: Ansible Key Components
13 | - p: What makes Ansible tick!
14 | - class_notes: Let's delve into the concepts that drive Ansible.
15 | -
16 | - h2: Key components of Ansible
17 | - ul:
18 | - Inventory
19 | - Modules/Tasks
20 | - Plays
21 | - Playbooks
22 | - class_notes: These are some very key components you'll need to understand for using Ansible.
23 | -
24 | - h2: Inventory
25 | - ul:
26 | - Understanding Hosts and Groups
27 | - Inventory Sources
28 | - class_notes: |
29 | Ansible works against multiple systems in your infrastructure
30 | at the same time. It does this by selecting portions of systems
31 | listed in Ansible's inventory.
32 | -
33 | - h2: Inventory concepts
34 | - ul:
35 | - hosts
36 | - groupings
37 | - inventory-specific data
38 | - static or dynamic sources
39 | - class_notes: "Breaking down by topic, we'll cover four parts (Note the listed)"
40 | -
41 | - h2: "Inventory: Hosts"
42 | - p: "Hosts can have Ansible specific attributes such as:"
43 | - ul:
44 | - Connection IP addresses and ports
45 | - Remote user and sudo user
46 | - Connection types (Paramiko, OpenSSH, local, etc.)
47 | - Further limit targetd hosts using --limit
48 | - class_notes: |
49 | You have a lot of flexibility when you specify hosts in Inventory. You can
50 | set variables to determine connection types, host ip addresses and fully-qualified
51 | domain names, remote users and sudo users as well as any other variable you may
52 | come up with to use when interacting with your hosts, such as "apache_port" or
53 | "mysql ports".
54 | -
55 | - h2: "Inventory: Hosts"
56 | - p: "This is an example of a host entry in an inventory file:"
57 | - code: |
58 | web1.example.com ansible_ssh_port=5555 ansible_ssh_host=192.168.1.50
59 | - class_notes: As you can see, we have a host name, a specified SSH port and IP Address.
60 | -
61 | - h2: "Inventory: Host Entries Using Ranges"
62 | - p: "You can have ranges of machine names or letters like this:"
63 | - code: |
64 | www[01:50].example.com ansible_ssh_port=5555
65 | db-[a-f].example.com ansible_ssh_port=5555
66 | - class_notes: Here we see that we can bracket a range of alpha-numeric characters to shorten our entries in the file.
67 | -
68 | - h2: "Inventory: Groups"
69 | - p: "Inventory Host Organization: Groups"
70 | - ul:
71 | - Groups allow targeted operations against different types of hosts.
72 | - Groups can also have variables that apply to all hosts within them.
73 | - --limit allows you to specify only certain groups to act against
74 | - Hosts can exist in more than one group at once.
75 | - class_notes: |
76 | We can also act against groups of hosts in a similar manner to single hosts.
77 | This allows you to also have standard settings for lots of similar hosts, such
78 | as a standard set of ports for apache on all web servers. You can limit the execution of
79 | Ansible jobs just as you can single hosts with the "--limit" option. Hosts can exist
80 | in more than one group at once, letting you do interesting operations on the intersections
81 | of groups. For example, target all of the east coast web servers.
82 | -
83 | - h2: "Inventory: Groups"
84 | - p: Groups are represented in brackets above host lists in the inventory file.
85 | - code: |
86 | [webservers]
87 | www[01:50].example.com ansible_ssh_port=5555
88 | - class_notes: This is an example of a range of hosts specified via the bracket nomenclature.
89 | -
90 | - h2: "Dynamic Inventory: Ansible and the Cloud"
91 | - p: "Inventory can also be gathered on demand from other sources dynamically. Those sources include:"
92 | - ul:
93 | - Cloud API (Rackspace, Amazon, Digital Ocean, OpenStack, Eucalyptus etc.)
94 | - Cobbler
95 | - Create your own for fun and profit!
96 | - class_notes: |
97 | So we can also take inventory from a wide variety of sources on the fly. We can touch Rackspace,
98 | Openstack, Amazon EC2, Digital Ocean, and other provisioning systems like Cobbler. You can also
99 | create your own inventory module to interface with any custom CMDB systems you may have.
100 | -
101 | - h2: "Inventory: Ansible and the Cloud"
102 | - p: "Dynamic inventories also respect groups and other details."
103 | - ul:
104 | - Groups are auto-determined by instance tags, regions and other attributes.
105 | - Dynamic Inventories can be used alongside Static Inventories for a hybrid cloud approach.
106 | - class_notes: |
107 | Tagged instances automatically are put in a group based on that tag. Other attributes also
108 | become groups, such as regions deployed to, or other custom attributes.
109 | -
110 | - h2: Tasks and Modules
111 | - p: Tasks and Modules are the workhorse of Ansible.
112 | - p: "This topic will cover:"
113 | - ul:
114 | - Understanding what a task is
115 | - Understanding how tasks make use of modules
116 | -
117 | - h2: Tasks
118 | - p: A task is a discrete action that is a declaration about
119 | the state of a system.
120 | - p: "Example Tasks:"
121 | - ul:
122 | - Directory should exist
123 | - Package should be installed
124 | - Service should be running
125 | - Cloud Instance should exist
126 | - class_notes: These are examples of declarative tasks where the beginning state is disregarded in favor of ensuring end-state.
127 | -
128 | - h2: "Tasks: Examples"
129 | - p: ansible can execute single tasks on sets of hosts
130 | to fullfill an ad-hoc declarations
131 | - code: |
132 | $ ansible web-hosts -m file -a "path=/opt/cache state=directory"
133 | $ ansible web-hosts -m yum -a "name=nginx state=present"
134 | $ ansible web-hosts -m service -a "name=nginx enabled=yes state=started"
135 | - class_notes: |
136 | in the first we make sure opt/cache exists, the second we install nginx, third we make
137 | sure nginx is installed, chkconfig'ed on and the service is started.
138 | -
139 | - h2: "Tasks: Sources"
140 | - p: "Code for tasks can come from:"
141 | - ul:
142 | - existing modules
143 | - custom modules
144 | - raw ssh commands
145 | - class_notes: |
146 | Tasks use modules or commands to create their actions to apply to remote systems.
147 | You can create your own modules, use any of the over 200 included modules, or use the output from commands.
148 | -
149 | - h2: Modules
150 | - p: Modules are the bits of code copied to the target system
151 | to be executed to satisfy the task declaration.
152 | - p: "Key points:"
153 | - ul:
154 | - Code need not exist on remote host -- ansible copies it over
155 | - Many modules come with Ansible -- "batteries included"
156 | - Custom modules can be developed easily
157 | - command/shell modules exists for simple commands
158 | - script module exists for using existing code
159 | - raw module exists for executing raw commands over ssh
160 | - class_notes: |
161 | Modules essentially create python code out of the descriptions given via the tasks that are then sent to the
162 | remote machine and interpreted/executed by that host. Once executed, Ansible then cleans up after itself and
163 | removes the module and output from the remote system.
164 | -
165 | - h2: Module Interactions
166 | - p: Module listing and documentation via ansible-doc
167 | - code: |
168 | $ ansible-doc -l
169 | acl Sets and retrieves file ACL information.
170 | apt Manages apt-packages
171 | - code: |
172 | $ ansible-doc acl
173 | > ACL
174 |
175 | Sets and retrieves file ACL information.
176 |
177 | Options (= is mandatory):
178 |
179 | - entry
180 | The acl to set or remove. This must always be quoted in the [...]
181 | - class_notes: |
182 | Modules and tasks represent the core function of ansible. Modules are capable of idempotence --
183 | can be ran successively and understand change vs no change. In these examples we see how to use
184 | the command "ansible-doc" to review informtaion about specific modules that are included.
185 | -
186 | - h2: Module Interactions in Tasks
187 | - p: A series of tasks
188 | - code: |
189 | - name: add cache dir
190 | file: path=/opt/cache state=directory
191 |
192 | - name: install nginx
193 | yum: name=nginx state=present
194 |
195 | - name: start nginx
196 | service: name=nginx enabled=yes state=started
197 | - class_notes: |
198 | An ordered series of tasks can be described to form plays. Tasks utilize modules to act upon remote hosts.
199 | -
200 | - h2: Plays
201 | - p: Plays are ordered sets of tasks to execute against host selections from your inventory.
202 | - p: "This topic will cover:"
203 | - ul:
204 | - play naming
205 | - hosts selection
206 | - play arguments
207 | - variables
208 | - tasks
209 | - concurrency and order of operations
210 | - conditionals
211 | - error handling
212 | - inclusions
213 | -
214 | - h2: Play Naming
215 | - code: |
216 | - name: This is a Play
217 | - class_notes: General best practices are to name tasks in a way that shows what they do.
218 | -
219 | - h2: Hosts Selection
220 | - code: |
221 | - name: This is a Play
222 | hosts: web-servers
223 | - class_notes: This is how we specify in a play/plabook what hosts we will act upon based on group.
224 | -
225 | - h2: Play Arguments
226 | - code: |
227 | - name: This is a Play
228 | hosts: web-servers
229 | remote_user: fred
230 | sudo: yes
231 | connection: ssh
232 | - class_notes: |
233 | Furthermore, we can specify other variables as arguments.
234 | Such as what remote user to connect as, or whether we sudo to root to complete our task.
235 | -
236 | - h2: Variables
237 | - code: |
238 | - name: This is a Play
239 | hosts: web-servers
240 | remote_user: fred
241 | sudo: yes
242 | connection: ssh
243 | vars:
244 | http_port: 80
245 | cache_dir: /opt/cache
246 | - class_notes: |
247 | We gather facts before every run from hosts we are acting on. Facts become variables that
248 | contain information such as kernel level, host name, ip addresses and other standard information.
249 | -
250 | - h2: Tasks
251 | - code: |
252 | - name: This is a Play
253 | hosts: web-servers
254 | remote_user: fred
255 | sudo: yes
256 | connection: ssh
257 | gather_facts: no
258 | vars:
259 | http_port: 80
260 | cache_dir: /opt/cache
261 |
262 | tasks:
263 | - name: create cache dir
264 | file: path={{ cache_dir }} state=directory
265 |
266 | - name: install nginx
267 | yum: name=nginx state=installed
268 | - class_notes: |
269 | This is a compelte example of a play within a playbook. It contains arguments, variables,
270 | host groups to act on, two tasks and wheteher we use sudo on those tasks. It also uses the variables
271 | specified for the cache directory. Variables are represented in the Jinja2 format with double curly braces.
272 | -
273 | - h2: Concurrency and Order of Operations
274 | - code: |
275 | - name: This is a Play
276 | hosts: web-servers
277 | remote_user: fred
278 | sudo: yes
279 | connection: ssh
280 | vars:
281 | http_port: 80
282 | cache_dir: /opt/cache
283 |
284 | tasks:
285 | - name: create cache dir
286 | file: path={{ cache_dir }} state=directory
287 |
288 | - name: install nginx
289 | yum: name=nginx state=installed
290 | - class_notes: |
291 | You can specify number of concurrent machines to act upon via setting a number of forks. That will act upon
292 | that number of hosts at once, however the tasks within the play complete from top to botton, in order, one at a time.
293 | -
294 | - h2: Conditionals
295 | - code: |
296 | - name: This is a Play
297 | hosts: web-servers
298 | remote_user: fred
299 | sudo: yes
300 | connection: ssh
301 | vars:
302 | http_port: 80
303 | cache_dir: /opt/cache
304 |
305 | tasks:
306 | - name: create cache dir
307 | file: path={{ cache_dir }} state=directory
308 |
309 | - name: install nginx
310 | yum: name=httpd state=installed
311 | when: ansible_os_family == "RedHat"
312 |
313 | - name: install nginx
314 | apt: pkg=apache2 state=installed
315 | when: ansible_os_family == "Debian"
316 | - class_notes: |
317 | This is an example of a conditional. Conditionals allow for actions to be dependant on some fact or variable set.
318 | In this case, we see that we install nginx via Linux-Distro specific package managers. The variable "ansible_os_family"
319 | is a discovered fact gathered when we first run the play or playbook against hosts.
320 | -
321 | - h2: Error Handling
322 | - code: |
323 | - name: This is a Play
324 | hosts: web-servers
325 | remote_user: fred
326 | sudo: yes
327 | connection: ssh
328 | vars:
329 | http_port: 80
330 | cache_dir: /opt/cache
331 |
332 | tasks:
333 | - name: create cache dir
334 | file: path={{ cache_dir }} state=directory
335 |
336 | - name: install nginx
337 | yum: name=httpd state=installed
338 | when: ansible_os_family == "RedHat"
339 |
340 | - name: install nginx
341 | apt: pkg=apache2 state=installed
342 | when: ansible_os_family == "Debian"
343 |
344 | - name: failing command
345 | command: /bin/fail
346 | ignore_errors: yes
347 | - class_notes: |
348 | In this example we see the use of the "ignore_errors" setting, allowing users to dictate to ansible
349 | to ignore when the return codes of ansible-initiated tasks indicate failures or errors. Another way
350 | to do this is by using the "failed_when" options.
351 | -
352 | - h2: Inclusions
353 | - code: |
354 | - name: This is a Play
355 | hosts: web-servers
356 | remote_user: fred
357 | sudo: yes
358 | connection: ssh
359 | vars_files:
360 | - vars/nginx.yaml
361 |
362 | tasks:
363 | - name: create cache dir
364 | file: path={{ cache_dir }} state=directory
365 |
366 | - include: tasks/install-apache.yaml
367 |
368 | - name: failing command
369 | command: /bin/fail
370 | ignore_errors: yes
371 | - class_notes: |
372 | Take note of the "include" task: This allows us to include other playbooks at specific points in our
373 | run allowing for complicated aspects of orchestration to be seamless based on function or type of
374 | playbook. While this is useful, most often now you will use Roles for this functionality. We'll talk
375 | more about those in a bit.
376 | -
377 | - h2: Playbooks
378 | - p: Playbooks are ordered sets of plays to execute against inventory selections.
379 | - p: "This topic will cover:"
380 | - ul:
381 | - inventory selection
382 | - global variables
383 | - forks
384 | - inventory limits
385 | - inclusions
386 | - roles
387 | -
388 | - h2: Inventory Selection
389 | - code: |
390 | $ ansible-playbook -i production play.yaml
391 | $ ansible-playbook -i pre-prod play.yaml
392 | $ ansible-playbook -i hosts/dfw/ play.yaml
393 | - class_notes: |
394 | As you can see, we can specify different inventories to run the playbook "play.yaml" against.
395 | -
396 | - h2: Global Variables
397 | - code: |
398 | $ ansible-playbook -i pre-prod -e "cache_dir=/srv/cache/" play.yaml
399 | - class_notes: Variables declared in this manner from the command line override other values.
400 | -
401 | - h2: Forks
402 | - code: |
403 | $ ansible-playbook -f 30 -i pre-prod -e "cache_dir=/srv/cache/" play.yaml
404 | - class_notes: |
405 | This shows us declaring this playbook to be run against 30 hosts at a time by delcaring
406 | "-f 30" which is the flag for "forks equals 30 at a time."
407 | -
408 | - h2: Inventory-Limits
409 | - code: |
410 | $ ansible-playbook --limit dfw -f 30 -i pre-prod -e "cache_dir=/srv/cache/" play.yaml
411 | - class_notes: |
412 | This shows us running a playbook while declaring a limit to run only against "DFW"
413 | which could mean a single host named DFW, or a host group DFW.
414 | -
415 | - h2: Inclusions
416 | - code: |
417 | - name: This is a Play
418 | hosts: web-servers
419 | remote_user: fred
420 | sudo: yes
421 | connection: ssh
422 | gather_facts: no
423 | vars:
424 | http_port: 80
425 | cache_dir: /opt/cache
426 |
427 | tasks:
428 | - name: create cache dir
429 | file: path={{ cache_dir }} state=directory
430 |
431 | - include: playbook2.yaml
432 | - class_notes: |
433 | In this example we see that at the end of the playbook, we include another playbook. This allows
434 | us to continue against other playbooks using the already discovered facts and variables declared.
435 | -
436 | - h2: Roles
437 | - p: Roles are portable units of task organization in playbooks.
438 | - class_notes: |
439 | Roles are units of organization in Ansible. Assigning a role to a group of hosts
440 | (or a set of groups, or host patterns, etc.) implies that they should implement a
441 | specific behavior. A role may include applying certain variable values, certain tasks,
442 | and certain handlers - or just one or more of these things. Because of the file structure
443 | associated with a role, roles become redistributable units that allow you to share
444 | behavior among playbooks - or even with other users.
445 | -
446 | - h2: "Galaxy: Sharing is Caring"
447 | - p: The Galaxy is a site where you can share roles.
448 | - link: ['http://galaxy.ansible.com',
449 | 'http://galaxy.ansible.com']
450 | - class_notes: |
451 | Galaxy is our repository for general roles that can be shared among users. You can find it at the
452 | address provided above. You can share your roles, rate other people's roles, and download them
453 | via the command line using the ansible galaxy commads. You can also create an empty role to build
454 | by initializing an empty role, which will populate all the correct files and directories for you.
455 |
--------------------------------------------------------------------------------
/development/chapter_4.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Tim G
4 | title: Write and run a simple playbook
5 | description: "We have already shown a simple playbook in Chapter 3. Here we will write a playbook from scratch, incrementally, and the students can follow along if they are able."
6 |
7 | slides:
8 |
9 | -
10 | - nested:
11 | -
12 | - h1: Basic Playbook Structure
13 |
14 | - class_notes: In this chapter we'll cover the basic playbook structure, and write a simple playbook from scratch.
15 |
16 | -
17 | - h2: "Play Header"
18 | - code: |
19 | ---
20 | - name: this is the name of a play
21 | hosts: all
22 | user: root
23 |
24 | tasks: []
25 | - class_notes: As we covered earlier, a playbook is a series of plays. Each play needs a "hosts" keyword, which tells Ansible to which hosts hosts this play applies. You can define a lot of other parameters at the play level, including which user to log in as, whether these tasks should be run through sudo, which connection mechanism to use, etc.
26 |
27 | -
28 | - h2: Write the tasks
29 | - code: |
30 | ---
31 | - name: this is the name of a play
32 | hosts: all
33 | user: root
34 |
35 | tasks:
36 | - name: install nginx
37 | yum: package=nginx state=present
38 | - class_notes: Now that we have the "front matter" of the play defined, we can add the tasks, as shown. Each task can have a name that is human-readable. This isn't required, but it's recommended. Then you call the module, in this case "yum", and any arguments.
39 |
40 | -
41 | - h2: Run the playbook
42 |
43 | - class_notes: "Run the playbook. If you've written everything correctly, it should install nginx on the target systems, and return the results. Notice the \"Gathering Facts\" step that occurs at the top of the run. This is implicit, but you can turn it off with \"gather_facts: no\" in the play. At the end, a \"host recap\" will be printed out. This gives you a summary of tasks that completed successfully, tasks that changed something on the target system, any failures, or unreachable systems."
44 | -
45 | - image: "http://cdn2.hubspot.net/hub/330046/file-449187601-png/ansible_badge.png"
46 | - link: ['ansible.com',
47 | 'http://www.ansible.com']
48 |
--------------------------------------------------------------------------------
/development/root.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Rackspace and Ansible
4 | title: Ansible Fundamentals
5 | description: Ansible Fundamentals
6 | slides: []
7 |
--------------------------------------------------------------------------------
/fundamentals/chapter_0.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Justin Phelps
4 | title: Ansible Fundamentals
5 | description: Ansible Fundamentals Course
6 |
7 | slides:
8 | - set_global:
9 | transition: none
10 | -
11 | - nested:
12 | -
13 | - h1: Ansible Fundamentals
14 |
15 | -
16 | - h1: Audio and Chat
17 |
18 | - p: "Chat: #ansible-training on FreeNode (http://freenode.net/)"
19 |
20 | - p: ""
21 |
22 | - p: "Audio: click on the Join.me phone icon and follow directions."
--------------------------------------------------------------------------------
/fundamentals/chapter_1.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: CC, PI
4 | title: Chapter 1, Ansible Fundamentals
5 | description: Ansible Fundamentals Course
6 |
7 | slides:
8 |
9 | - set_global:
10 | transition: none
11 | background: '#007777'
12 | #background: 'black'
13 |
14 | -
15 | - nested:
16 | -
17 | - h1: What is Ansible?
18 | - ul:
19 | - Clear
20 | - Fast
21 | - Complete
22 | - Efficient
23 | - Secure
24 |
25 | -
26 | - h2: Clear
27 | - p: 'A simple automation language allows Ansible to be used by anyone:'
28 | - ul:
29 | - sysadmins
30 | - developers
31 | - IT managers
32 | - p: It's easy to write, read, maintain, and evolve - without writing scripts or custom code.
33 | -
34 | - h2: Fast
35 | - p: Ansible is easy to learn.
36 | - p: Setup is fast.
37 | - class_notes: |
38 | 1. You can automate in under 30 minutes. Forget about how it works, just do it.
39 | 2. No agents. SSH keys are typically already in place.
40 | -
41 | - h2: Complete
42 | - p: 'Ansible is several tools in one:'
43 | - ul:
44 | - configuration management
45 | - application deployment
46 | - orchestration
47 | - provisioning
48 | - p: Hundreds of built-in modules.
49 | -
50 | - h2: Efficient
51 | - p: Ansible doesn't require a custom agent or software to install.
52 | - p: Ansible runs on OpenSSH.
53 | - class_notes: |
54 | 1. With no additional software infrastructure, you don't have to
55 | worry about managing the management tool.
56 | 2. That means anywhere SSH goes, Ansible goes.
57 | 3. It doesn't suck memory or CPU resources when it is not in use.
58 | 4. Designed from day one to automate no-downtime rolling updates
59 | and multi-tier orchestration.
60 | -
61 | - h2: Secure
62 | - p: No agent.
63 | - p: SSH transport.
64 | - p: Ansible plays can be read by anyone.
65 | - class_notes: |
66 | 1. It doesn't need additional ports or root level daemons.
67 | 2. It uses built-in OS authentication for better security - login
68 | as who you are, sudo if you want to sudo.
69 | 3. You can work with tools like Kerberos, LDAP, and sssd.
70 | 4. OpenSSH is the most peer-reviewed security component around.
71 | 5. This makes it auditable. You know what you're automating,
72 | and bugs have nowhere to hide.
73 |
--------------------------------------------------------------------------------
/fundamentals/chapter_2.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Mike Martin, Justin Phelps, Paul Durivage
4 | title: Chapter 2
5 | description: Ansible Fundamentals Course
6 |
7 | slides:
8 | - set_global:
9 | transition: none
10 | -
11 | - nested:
12 | -
13 | - h1: Ansible Use Cases
14 | - p: Ask not what you can do for Ansible, but what Ansible can do for you!
15 | -
16 | - h2: Ansible Use Cases
17 | - ul:
18 | - Remote Execution / Ad-hoc Tasks
19 | - Configuration Management
20 | - Application Deployment & Orchestration
21 | - Provisioning Infrastructure Dynamically
22 | -
23 | - h2: Remote Execution
24 | - ul:
25 | - Replacement for traditional systems administration tasks. (i.e., SSH)
26 | - Checking system responsiveness and uptime.
27 | - Gathering information about a collection of systems.
28 | - Replace one off rsync scripts, fabric, or terminal multiplexing.
29 | - class_notes: |
30 | Ansible provides a command-line tool and framework capable of
31 | executing over a large number of hosts, eliminating the need for
32 | systems administrators to multiplex terminal sessions via SSH to
33 | execute concurrent tasks across multiple hosts. What may have
34 | been done in bash scripts, rsync scripts, etc. can be done via
35 | ad-hoc one-liners in the shell.
36 | -
37 | - h2: Remote Execution
38 | - code: |
39 | ansible -m user -a "name=bob state=present" webservers
40 | - code: |
41 | ansible -m apt -a "pkg=apache2 state=present" webservers
42 | - class_notes: |
43 | Example 1 is adding a user to all the systems defined in the
44 | webservers group. Example 2 is installing the apache2 package
45 | on all systems defined in the webservers group.
46 | -
47 | - h2: Config Management
48 | - ul:
49 | - Lengthy system configuration, to include adding users, ssh keys, installing and configuring services, and bootstrapping systems to a given state.
50 | - '"Configuration remediation" Consistent server configuration. Removes manual configuration errors.'
51 | - class_notes: |
52 | Servers need to be configured; Ansible configures servers.
53 | Using a combination of imperative and declarative syntax
54 | [described in detail--maybe using the GPS analogy], using
55 | concepts such as tasks, roles, plays, and playbooks, complex
56 | machine configurations are being assembled and converged by
57 | the Ansible toolchain rather than manually by administrators.
58 | Configuration is either set manually by the author or dynamically at runtime by Ansible, resulting in consistent configuration across large server sets.
59 | -
60 | - h2: Application Deployment & Orchestration
61 | - p: Ansible can be used to replace various deployment and orchestration tools.
62 | - ul:
63 | - Deploy your custom application.
64 | - Replacement for Capistrano and Fabric (i.e., git deployments)
65 | - Good for large, complex environments
66 | -
67 | - h2: Application Deployment & Orchestration
68 | - p: Application deployment includes two main schools of thought.
69 | - h2: Rolling Release
70 | ul:
71 | - Remove node from production, update components, and put back into rotation.
72 | - class_notes: |
73 | Make the point that you deploy often in the DevOps world, and
74 | why this is important for application development.
75 | -
76 | - h2: Application Deployment & Orchestration
77 | - p: Application deployment includes two main schools of thought.
78 | - h2: Fresh Start
79 | - ul:
80 | - Deploy entirely new infrastructure and replace current environment wholesale.
81 | - class_notes: |
82 | Make the point that you deploy often in the DevOps world, and
83 | why this is important for application development.
84 | -
85 | - h2: Provisioning Infrastructure Dynamically
86 | - ul:
87 | - Infrastructure is Data.
88 | - You can provision to various clouds.
89 | - Dynamic Inventory plugins for various providers (Rackspace, Amazon, Digital Ocean, OpenStack, Eucalyptus etc.)
90 | - class_notes: |
91 | Cover the various ways that infrastructure can be provisioned
92 | using Ansible. Mention that there are modules that provide
93 | he ability to deploy to various clouds. Include a high level
94 | overview of the dynamic inventory plugin system. (Creating
95 | Infrastructure is the same as Configuring Infrastructure.)
96 | -
97 | - h2: Who is your Ansible, and what does he do?
98 | - class_notes: |
99 | Have the class search the ansible documention and come up
100 | with something that Ansible does. Be that a specific module,
101 | or a high level concept.
102 |
--------------------------------------------------------------------------------
/fundamentals/chapter_3.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Jesse K and the DFed Experience
4 | title: Understand the concepts of Ansible
5 | description: Description of the chapter
6 |
7 | slides:
8 | - set_global:
9 | transition: none
10 | -
11 | - nested:
12 | -
13 | - h1: Ansible Key Components
14 | - p: What makes Ansible tick!
15 | - class_notes: Let's delve into the concepts that drive Ansible.
16 | -
17 | - h2: Key components of Ansible
18 | - ul:
19 | - Inventory
20 | - Modules/Tasks
21 | - Plays
22 | - Playbooks
23 | - class_notes: These are some very key components you'll need to understand for using Ansible.
24 | -
25 | - h2: Inventory
26 | - ul:
27 | - Understanding Hosts and Groups
28 | - Inventory Sources
29 | - class_notes: |
30 | Ansible works against multiple systems in your infrastructure
31 | at the same time. It does this by selecting portions of systems
32 | listed in Ansible's inventory.
33 | -
34 | - h2: Inventory concepts
35 | - ul:
36 | - hosts
37 | - groupings
38 | - inventory-specific data
39 | - static or dynamic sources
40 | - class_notes: "Breaking down by topic, we'll cover four parts (Note the listed)"
41 | -
42 | - h2: "Inventory: Hosts"
43 | - p: "Hosts can have Ansible specific attributes such as:"
44 | - ul:
45 | - Connection IP addresses and ports
46 | - Remote user and sudo user
47 | - Connection types (Paramiko, OpenSSH, local, etc.)
48 | - Further limit targetd hosts using --limit
49 | - class_notes: |
50 | You have a lot of flexibility when you specify hosts in Inventory. You can
51 | set variables to determine connection types, host ip addresses and fully-qualified
52 | domain names, remote users and sudo users as well as any other variable you may
53 | come up with to use when interacting with your hosts, such as "apache_port" or
54 | "mysql ports".
55 | -
56 | - h2: "Inventory: Hosts"
57 | - p: "This is an example of a host entry in an inventory file:"
58 | - code: |
59 | web1.example.com ansible_ssh_port=5555 ansible_ssh_host=192.168.1.50
60 | - class_notes: As you can see, we have a host name, a specified SSH port and IP Address.
61 | -
62 | - h2: "Inventory: Host Entries Using Ranges"
63 | - p: "You can have ranges of machine names or letters like this:"
64 | - code: |
65 | www[01:50].example.com ansible_ssh_port=5555
66 | db-[a-f].example.com ansible_ssh_port=5555
67 | - class_notes: Here we see that we can bracket a range of alpha-numeric characters to shorten our entries in the file.
68 | -
69 | - h2: "Inventory: Groups"
70 | - p: "Inventory Host Organization: Groups"
71 | - ul:
72 | - Groups allow targeted operations against different types of hosts.
73 | - Groups can also have variables that apply to all hosts within them.
74 | - --limit allows you to specify only certain groups to act against
75 | - Hosts can exist in more than one group at once.
76 | - class_notes: |
77 | We can also act against groups of hosts in a similar manner to single hosts.
78 | This allows you to also have standard settings for lots of similar hosts, such
79 | as a standard set of ports for apache on all web servers. You can limit the execution of
80 | Ansible jobs just as you can single hosts with the "--limit" option. Hosts can exist
81 | in more than one group at once, letting you do interesting operations on the intersections
82 | of groups. For example, target all of the east coast web servers.
83 | -
84 | - h2: "Inventory: Groups"
85 | - p: Groups are represented in brackets above host lists in the inventory file.
86 | - code: |
87 | [webservers]
88 | www[01:50].example.com ansible_ssh_port=5555
89 | - class_notes: This is an example of a range of hosts specified via the bracket nomenclature.
90 | -
91 | - h2: "Dynamic Inventory: Ansible and the Cloud"
92 | - p: "Inventory can also be gathered on demand from other sources dynamically. Those sources include:"
93 | - ul:
94 | - Cloud API (Rackspace, Amazon, Digital Ocean, OpenStack, Eucalyptus etc.)
95 | - Cobbler
96 | - Create your own for fun and profit!
97 | - class_notes: |
98 | So we can also take inventory from a wide variety of sources on the fly. We can touch Rackspace,
99 | Openstack, Amazon EC2, Digital Ocean, and other provisioning systems like Cobbler. You can also
100 | create your own inventory module to interface with any custom CMDB systems you may have.
101 | -
102 | - h2: "Inventory: Ansible and the Cloud"
103 | - p: "Dynamic inventories also respect groups and other details."
104 | - ul:
105 | - Groups are auto-determined by instance tags, regions and other attributes.
106 | - Dynamic Inventories can be used alongside Static Inventories for a hybrid cloud approach.
107 | - class_notes: |
108 | Tagged instances automatically are put in a group based on that tag. Other attributes also
109 | become groups, such as regions deployed to, or other custom attributes.
110 | -
111 | - h2: Tasks and Modules
112 | - p: Tasks and Modules are the workhorse of Ansible.
113 | - p: "This topic will cover:"
114 | - ul:
115 | - Understanding what a task is
116 | - Understanding how tasks make use of modules
117 | -
118 | - h2: Tasks
119 | - p: A task is a discrete action that is a declaration about
120 | the state of a system.
121 | - p: "Example Tasks:"
122 | - ul:
123 | - Directory should exist
124 | - Package should be installed
125 | - Service should be running
126 | - Cloud Instance should exist
127 | - class_notes: These are examples of declarative tasks where the beginning state is disregarded in favor of ensuring end-state.
128 | -
129 | - h2: "Tasks: Examples"
130 | - p: ansible can execute single tasks on sets of hosts
131 | to fullfill an ad-hoc declarations
132 | - code: |
133 | $ ansible web-hosts -m file -a "path=/opt/cache state=directory"
134 | $ ansible web-hosts -m yum -a "name=nginx state=present"
135 | $ ansible web-hosts -m service -a "name=nginx enabled=yes state=started"
136 | - class_notes: |
137 | in the first we make sure opt/cache exists, the second we install nginx, third we make
138 | sure nginx is installed, chkconfig'ed on and the service is started.
139 | -
140 | - h2: "Tasks: Sources"
141 | - p: "Code for tasks can come from:"
142 | - ul:
143 | - existing modules
144 | - custom modules
145 | - raw ssh commands
146 | - class_notes: |
147 | Tasks use modules or commands to create their actions to apply to remote systems.
148 | You can create your own modules, use any of the over 200 included modules, or use the output from commands.
149 | -
150 | - h2: Modules
151 | - p: Modules are the bits of code copied to the target system
152 | to be executed to satisfy the task declaration.
153 | - p: "Key points:"
154 | - ul:
155 | - Code need not exist on remote host -- ansible copies it over
156 | - Many modules come with Ansible -- "batteries included"
157 | - Custom modules can be developed easily
158 | - command/shell modules exists for simple commands
159 | - script module exists for using existing code
160 | - raw module exists for executing raw commands over ssh
161 | - class_notes: |
162 | Modules essentially create python code out of the descriptions given via the tasks that are then sent to the
163 | remote machine and interpreted/executed by that host. Once executed, Ansible then cleans up after itself and
164 | removes the module and output from the remote system.
165 | -
166 | - h2: Module Interactions
167 | - p: Module listing and documentation via ansible-doc
168 | - code: |
169 | $ ansible-doc -l
170 | acl Sets and retrieves file ACL information.
171 | apt Manages apt-packages
172 | - code: |
173 | $ ansible-doc acl
174 | > ACL
175 |
176 | Sets and retrieves file ACL information.
177 |
178 | Options (= is mandatory):
179 |
180 | - entry
181 | The acl to set or remove. This must always be quoted in the [...]
182 | - class_notes: |
183 | Modules and tasks represent the core function of ansible. Modules are capable of idempotence --
184 | can be ran successively and understand change vs no change. In these examples we see how to use
185 | the command "ansible-doc" to review informtaion about specific modules that are included.
186 | -
187 | - h2: Module Interactions in Tasks
188 | - p: A series of tasks
189 | - code: |
190 | - name: add cache dir
191 | file: path=/opt/cache state=directory
192 |
193 | - name: install nginx
194 | yum: name=nginx state=present
195 |
196 | - name: start nginx
197 | service: name=nginx enabled=yes state=started
198 | - class_notes: |
199 | An ordered series of tasks can be described to form plays. Tasks utilize modules to act upon remote hosts.
200 | -
201 | - h2: Plays
202 | - p: Plays are ordered sets of tasks to execute against host selections from your inventory.
203 | - p: "This topic will cover:"
204 | - ul:
205 | - play naming
206 | - hosts selection
207 | - play arguments
208 | - variables
209 | - tasks
210 | - concurrency and order of operations
211 | - conditionals
212 | - error handling
213 | - inclusions
214 | -
215 | - h2: Play Naming
216 | - code: |
217 | - name: This is a Play
218 | - class_notes: General best practices are to name tasks in a way that shows what they do.
219 | -
220 | - h2: Hosts Selection
221 | - code: |
222 | - name: This is a Play
223 | hosts: web-servers
224 | - class_notes: This is how we specify in a play/plabook what hosts we will act upon based on group.
225 | -
226 | - h2: Play Arguments
227 | - code: |
228 | - name: This is a Play
229 | hosts: web-servers
230 | remote_user: fred
231 | sudo: yes
232 | connection: ssh
233 | - class_notes: |
234 | Furthermore, we can specify other variables as arguments.
235 | Such as what remote user to connect as, or whether we sudo to root to complete our task.
236 | -
237 | - h2: Variables
238 | - code: |
239 | - name: This is a Play
240 | hosts: web-servers
241 | remote_user: fred
242 | sudo: yes
243 | connection: ssh
244 | vars:
245 | http_port: 80
246 | cache_dir: /opt/cache
247 | - class_notes: |
248 | We gather facts before every run from hosts we are acting on. Facts become variables that
249 | contain information such as kernel level, host name, ip addresses and other standard information.
250 | -
251 | - h2: Tasks
252 | - code: |
253 | - name: This is a Play
254 | hosts: web-servers
255 | remote_user: fred
256 | sudo: yes
257 | connection: ssh
258 | gather_facts: no
259 | vars:
260 | http_port: 80
261 | cache_dir: /opt/cache
262 |
263 | tasks:
264 | - name: create cache dir
265 | file: path={{ cache_dir }} state=directory
266 |
267 | - name: install nginx
268 | yum: name=nginx state=installed
269 | - class_notes: |
270 | This is a compelte example of a play within a playbook. It contains arguments, variables,
271 | host groups to act on, two tasks and wheteher we use sudo on those tasks. It also uses the variables
272 | specified for the cache directory. Variables are represented in the Jinja2 format with double curly braces.
273 | -
274 | - h2: Concurrency and Order of Operations
275 | - code: |
276 | - name: This is a Play
277 | hosts: web-servers
278 | remote_user: fred
279 | sudo: yes
280 | connection: ssh
281 | vars:
282 | http_port: 80
283 | cache_dir: /opt/cache
284 |
285 | tasks:
286 | - name: create cache dir
287 | file: path={{ cache_dir }} state=directory
288 |
289 | - name: install nginx
290 | yum: name=nginx state=installed
291 | - class_notes: |
292 | You can specify number of concurrent machines to act upon via setting a number of forks. That will act upon
293 | that number of hosts at once, however the tasks within the play complete from top to botton, in order, one at a time.
294 | -
295 | - h2: Conditionals
296 | - code: |
297 | - name: This is a Play
298 | hosts: web-servers
299 | remote_user: fred
300 | sudo: yes
301 | connection: ssh
302 | vars:
303 | http_port: 80
304 | cache_dir: /opt/cache
305 |
306 | tasks:
307 | - name: create cache dir
308 | file: path={{ cache_dir }} state=directory
309 |
310 | - name: install nginx
311 | yum: name=httpd state=installed
312 | when: ansible_os_family == "RedHat"
313 |
314 | - name: install nginx
315 | apt: pkg=apache2 state=installed
316 | when: ansible_os_family == "Debian"
317 | - class_notes: |
318 | This is an example of a conditional. Conditionals allow for actions to be dependant on some fact or variable set.
319 | In this case, we see that we install nginx via Linux-Distro specific package managers. The variable "ansible_os_family"
320 | is a discovered fact gathered when we first run the play or playbook against hosts.
321 | -
322 | - h2: Error Handling
323 | - code: |
324 | - name: This is a Play
325 | hosts: web-servers
326 | remote_user: fred
327 | sudo: yes
328 | connection: ssh
329 | vars:
330 | http_port: 80
331 | cache_dir: /opt/cache
332 |
333 | tasks:
334 | - name: create cache dir
335 | file: path={{ cache_dir }} state=directory
336 |
337 | - name: install nginx
338 | yum: name=httpd state=installed
339 | when: ansible_os_family == "RedHat"
340 |
341 | - name: install nginx
342 | apt: pkg=apache2 state=installed
343 | when: ansible_os_family == "Debian"
344 |
345 | - name: failing command
346 | command: /bin/fail
347 | ignore_errors: yes
348 | - class_notes: |
349 | In this example we see the use of the "ignore_errors" setting, allowing users to dictate to ansible
350 | to ignore when the return codes of ansible-initiated tasks indicate failures or errors. Another way
351 | to do this is by using the "failed_when" options.
352 | -
353 | - h2: Inclusions
354 | - code: |
355 | - name: This is a Play
356 | hosts: web-servers
357 | remote_user: fred
358 | sudo: yes
359 | connection: ssh
360 | vars_files:
361 | - vars/nginx.yaml
362 |
363 | tasks:
364 | - name: create cache dir
365 | file: path={{ cache_dir }} state=directory
366 |
367 | - include: tasks/install-apache.yaml
368 |
369 | - name: failing command
370 | command: /bin/fail
371 | ignore_errors: yes
372 | - class_notes: |
373 | Take note of the "include" task: This allows us to include other playbooks at specific points in our
374 | run allowing for complicated aspects of orchestration to be seamless based on function or type of
375 | playbook. While this is useful, most often now you will use Roles for this functionality. We'll talk
376 | more about those in a bit.
377 | -
378 | - h2: Playbooks
379 | - p: Playbooks are ordered sets of plays to execute against inventory selections.
380 | - p: "This topic will cover:"
381 | - ul:
382 | - inventory selection
383 | - global variables
384 | - forks
385 | - inventory limits
386 | - inclusions
387 | - roles
388 | -
389 | - h2: Inventory Selection
390 | - code: |
391 | $ ansible-playbook -i production play.yaml
392 | $ ansible-playbook -i pre-prod play.yaml
393 | $ ansible-playbook -i hosts/dfw/ play.yaml
394 | - class_notes: |
395 | As you can see, we can specify different inventories to run the playbook "play.yaml" against.
396 | -
397 | - h2: Global Variables
398 | - code: |
399 | $ ansible-playbook -i pre-prod -e "cache_dir=/srv/cache/" play.yaml
400 | - class_notes: Variables declared in this manner from the command line override other values.
401 | -
402 | - h2: Forks
403 | - code: |
404 | $ ansible-playbook -f 30 -i pre-prod -e "cache_dir=/srv/cache/" play.yaml
405 | - class_notes: |
406 | This shows us declaring this playbook to be run against 30 hosts at a time by delcaring
407 | "-f 30" which is the flag for "forks equals 30 at a time."
408 | -
409 | - h2: Inventory-Limits
410 | - code: |
411 | $ ansible-playbook --limit dfw -f 30 -i pre-prod -e "cache_dir=/srv/cache/" play.yaml
412 | - class_notes: |
413 | This shows us running a playbook while declaring a limit to run only against "DFW"
414 | which could mean a single host named DFW, or a host group DFW.
415 | -
416 | - h2: Inclusions
417 | - code: |
418 | - name: This is a Play
419 | hosts: web-servers
420 | remote_user: fred
421 | sudo: yes
422 | connection: ssh
423 | gather_facts: no
424 | vars:
425 | http_port: 80
426 | cache_dir: /opt/cache
427 |
428 | tasks:
429 | - name: create cache dir
430 | file: path={{ cache_dir }} state=directory
431 |
432 | - include: playbook2.yaml
433 | - class_notes: |
434 | In this example we see that at the end of the playbook, we include another playbook. This allows
435 | us to continue against other playbooks using the already discovered facts and variables declared.
436 | -
437 | - h2: Roles
438 | - p: Roles are portable units of task organization in playbooks.
439 | - class_notes: |
440 | Roles are units of organization in Ansible. Assigning a role to a group of hosts
441 | (or a set of groups, or host patterns, etc.) implies that they should implement a
442 | specific behavior. A role may include applying certain variable values, certain tasks,
443 | and certain handlers - or just one or more of these things. Because of the file structure
444 | associated with a role, roles become redistributable units that allow you to share
445 | behavior among playbooks - or even with other users.
446 | -
447 | - h2: "Galaxy: Sharing is Caring"
448 | - p: The Galaxy is a site where you can share roles.
449 | - link: ['http://galaxy.ansible.com',
450 | 'http://galaxy.ansible.com']
451 | - class_notes: |
452 | Galaxy is our repository for general roles that can be shared among users. You can find it at the
453 | address provided above. You can share your roles, rate other people's roles, and download them
454 | via the command line using the ansible galaxy commads. You can also create an empty role to build
455 | by initializing an empty role, which will populate all the correct files and directories for you.
456 |
--------------------------------------------------------------------------------
/fundamentals/chapter_4.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Tim G
4 | title: Write and run a simple playbook
5 | description: "We have already shown a simple playbook in Chapter 3. Here we will write a playbook from scratch, incrementally, and the students can follow along if they are able."
6 |
7 | slides:
8 | - set_global:
9 | transition: none
10 | -
11 | - nested:
12 | -
13 | - h1: Basic Playbook Structure
14 |
15 | - class_notes: In this chapter we'll cover the basic playbook structure, and write a simple playbook from scratch.
16 |
17 | -
18 | - h2: "Play Header"
19 | - code: |
20 | ---
21 | - name: this is the name of a play
22 | hosts: all
23 | user: root
24 |
25 | tasks: []
26 | - class_notes: As we covered earlier, a playbook is a series of plays. Each play needs a "hosts" keyword, which tells Ansible to which hosts hosts this play applies. You can define a lot of other parameters at the play level, including which user to log in as, whether these tasks should be run through sudo, which connection mechanism to use, etc.
27 |
28 | -
29 | - h2: Write the tasks
30 | - code: |
31 | ---
32 | - name: this is the name of a play
33 | hosts: all
34 | user: root
35 |
36 | tasks:
37 | - name: install nginx
38 | yum: package=nginx state=present
39 | - class_notes: Now that we have the "front matter" of the play defined, we can add the tasks, as shown. Each task can have a name that is human-readable. This isn't required, but it's recommended. Then you call the module, in this case "yum", and any arguments.
40 |
41 | -
42 | - h2: Run the playbook
43 |
44 | - class_notes: "Run the playbook. If you've written everything correctly, it should install nginx on the target systems, and return the results. Notice the \"Gathering Facts\" step that occurs at the top of the run. This is implicit, but you can turn it off with \"gather_facts: no\" in the play. At the end, a \"host recap\" will be printed out. This gives you a summary of tasks that completed successfully, tasks that changed something on the target system, any failures, or unreachable systems."
45 | -
46 | - image: "http://cdn2.hubspot.net/hub/330046/file-449187601-png/ansible_badge.png"
47 | - link: ['ansible.com',
48 | 'http://www.ansible.com']
49 |
--------------------------------------------------------------------------------
/fundamentals/root.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Rackspace and Ansible
4 | title: Ansible Fundamentals
5 | description: Ansible Fundamentals
6 | slides: []
7 |
--------------------------------------------------------------------------------
/operational/chapter_0.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Justin Phelps
4 | title: Operational Ansible
5 | description: Operational Ansible Course
6 |
7 | slides:
8 | -
9 | - nested:
10 | -
11 | - h1: Operational Ansible
12 |
--------------------------------------------------------------------------------
/operational/chapter_1.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: CC, PI
4 | title: Chapter 1, Ansible Operational
5 | description: Ansible Operational Course
6 |
7 | slides:
8 |
9 | - set_global:
10 | transition: rotate
11 | background: '#007777'
12 |
13 | -
14 | - nested:
15 | -
16 | - h1: Installing Ansible
17 | - ul:
18 | - Assessment Review
19 | - Environment
20 | - Installation
21 | - class_notes: Start with a brief overview of the Ansible assessment. Then orientation of users to the foundational information required to consume the course progressing directly into the Command Line Interface to begin installing Ansible.
22 |
23 | -
24 | - h2: Assessment Review
25 | - ul:
26 | - Brief review of the Ansible Fundamentals Assessment topics
27 | - "Q & A"
28 |
29 | -
30 | - h2: Environment
31 | - ul:
32 | - Options exist on class environments to leverage
33 | - Clouds (RAX, AWS, etc.)
34 | - Vagrant
35 | - Local machines (CentOS 6.4, Ubuntu LTS)
36 | - directly from git checkout (running from source)
37 |
38 | - class_notes: Students will be introduced to the classroom lab environment. Explore deployment options and the ones that we will be utilizing in this classroom environment.
39 |
40 | -
41 | - h2: Installation
42 | - ul:
43 | - Getting Started
44 | - Installation
45 | - link: ['http://docs.ansible.com/intro_getting_started.html',
46 | 'http://docs.ansible.com/intro_getting_started.html']
47 | - link: ['http://docs.ansible.com/intro_installation.html',
48 | 'http://docs.ansible.com/intro_installation.html']
49 | - link: ['http://releases.ansible.com/ansible/',
50 | 'http://releases.ansible.com/ansible/']
51 | - link: ['https://github.com/ansible/ansible/releases',
52 | 'https://github.com/ansible/ansible/releases']
53 | - class_notes: Given the chosen environment, install Ansible using best practices. The recommended installation method is using your operating systems package manager where applicable.
54 |
55 |
--------------------------------------------------------------------------------
/operational/chapter_2.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Matt Martz
4 | title: Managing Inventory
5 | description: Understand and discuss concepts around managing inventory through static INI formatted files or through dynamic inventory scripts
6 |
7 | slides:
8 |
9 | -
10 | - nested:
11 |
12 | -
13 | - h1: Inventory
14 | - p: Understand and discuss concepts around managing inventory through static INI formatted files or through dynamic inventory scripts
15 |
16 | -
17 | - h2: Static INI
18 | - p: Create an INI inventory file based off of instructor provided servers, specifying a human readable name and a connection IP address or hostname
19 | - class_notes: We should use a human readable name as the inventory hostname, and specify ansible_ssh_host for the actual IP. Ungrouped for now.
20 |
21 | -
22 | - h2: Static INI
23 | - code: |
24 | web1 ansible_ssh_host=10.10.10.10
25 | web2 ansible_ssh_host=20.20.20.20
26 |
27 | -
28 | - h2: Groups
29 | - p: Create a web group in the inventory file
30 |
31 | -
32 | - h2: Groups
33 | - code: |
34 | [web]
35 | web1 ansible_ssh_host=10.10.10.10
36 | web2 ansible_ssh_host=20.20.20.20
37 |
38 | -
39 | - h2: Dynamic Inventory
40 | - p: What are the use cases for dynamic inventory scripts
41 | - ul:
42 | - Limitations of a static inventory with a cloud like environment
43 | - Query nearly any data source for inventory
44 | - How ansible knows if the provided inventory is a script
45 | - class_notes: |
46 | Using a static inventory file with a "living" cloud like environment is inefficient, error prone and difficult to maintain.
47 |
48 | Due to the nature of an inventory script, they can mostly leverage the full power of the language they are implemented in. This would enable the script to communicate with nearly any data source for use as inventory.
49 |
50 | Ansible determines if the provided inventory is a script, by checking if the file is executable. If the file is not executable it is parsed as an INI file.
51 |
52 | -
53 | - h2: Dynamic Inventory Example
54 | - class_notes: Show the output of the dynamic inventory script of your choice
55 |
56 | -
57 | - h2: Start a basic playbook
58 | - p: Create a playbook that only has a "hosts" specification targeting all servers and then run it
59 | - class_notes: |
60 | ---
61 | hosts: all
62 |
63 | Students should see that the playbook runs an implicit fact gathering step, and should successfully communicate with all servers.
64 |
--------------------------------------------------------------------------------
/operational/chapter_3.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Mike Martin, Justin Phelps, Paul Durivage, Jesse Keating
4 | title: Chapter 3, Using Ansible for Ad-hoc Commands
5 | description: Ansible Operational Course
6 |
7 | slides:
8 | -
9 | - nested:
10 | -
11 | - h1: Ansible Ad-Hoc Commands
12 | - h3: A Review of Hosts, Tasks, and Modules
13 | -
14 | - h2: Targeting Hosts
15 | - ul:
16 | - all / *
17 | - Groups (webservers)
18 | - Exclusion (webservers:!nginxservers)
19 | - Intersection (webservers:&staging)
20 | - Combos
21 | - Hostname / IP
22 | - Regex
23 | - "--limit"
24 | - class_notes: |
25 | Go over the various methods for targeting hosts for ad-hoc commands.
26 | Include information on rolling release and complex targeting. Use
27 | '-i localhost,' for a quick way to target a single host without
28 | specifying an inventory file.
29 | -
30 | - h2: Executing a task
31 | - p: ad-hoc commands are single-task executions which leverage modules
32 | -
33 | - h2: Modules
34 | - p: Modules are code that is executed on the remote host
35 | - class_notes: |
36 | Discuss how ansible takes module code and bundles it with arguments,
37 | transfers it to the remote host and executes it (depending on
38 | connection method).
39 | -
40 | - h2: Modules
41 | - p: Ansible provided core modules are
42 | - ul:
43 | - Written in python
44 | - Are shipped by SSH to the target machine where they are executed
45 | - Return JSON data that is interpreted by ansible
46 | - class_notes: Modules can be written in other languages, but core ansible only uses python. We don't need to go into the mechanics of how modules are built before being shipped, just mention that they get copied to the remote machine using SCP/SFTP. The echo out JSON data, which gets interpreted by the ansible "control" machine.
47 | -
48 | - h2: Module Documentation
49 | - code: |
50 | ansible-doc -l
51 | - code: |
52 | ansible-doc setup
53 | ansible-doc copy
54 | - class_notes: |
55 | ansible-doc -l lists all the modules. ansible-doc
56 | to see the documentation for a specific module. The ansible-doc
57 | command makes it extremely easy to see all of the available ansible
58 | modules with corresponding documentation and examples.
59 | -
60 | - h2: Example Use Cases
61 | - p: Rebooting all servers
62 | - code: |
63 | ansible all -m command -a "/sbin/reboot"
64 | - class_notes: |
65 | This is a simple command that uses the command module to issue a reboot
66 | to all servers in your inventory.
67 | The -m dictates the module, the -a for arguments.
68 | -
69 | - h2: Example Use Cases
70 | - p: Setting fork level to 10
71 | - code: |
72 | ansible webservers -f 10 -m setup
73 | - class_notes: |
74 | Fork level means that Ansible will fork 10 times, and then reach out
75 | to up to 10 machines concurrently. Choose carefully the level of concurrency:
76 | higher concurrency executes tasks/plays/playbooks faster, but results in more
77 | resources being consumed.
78 | -
79 | - h2: Example Use Cases
80 | - p: Copy a file from the local host to inventory hosts
81 | - code: |
82 | ansible dbservers -m copy -a "src=/path/to/file dest=/path/to/dest"
83 | - class_notes: |
84 | Uses the copy module to copy a file from the local machine, where the ansible
85 | command is being run, to the destination.
86 | -
87 | - h2: Example Use Cases
88 | - p: Install nginx and add a user
89 | - code: |
90 | ansible all -m apt -a "pkg=nginx state=present"
91 | ansible all -m user -a "name=bob state=present"
92 | - class_notes: |
93 | Very simple; this uses the apt module to install nginx, and uses
94 | the user module to add user bob.
95 | -
96 | - h2: Example Use Cases
97 | - p: Cloning a git repo to a path
98 | - code: |
99 | ansible appservers -m git -a "repo=https://github.com/ansible/ansible dest=/home/user/ansible"
100 | - class_notes: |
101 | This is cloning a repo to a directory, optionally accepting tags and versions. Allows you
102 | to install software (or anything stored in Git) from source control, a cornerstone
103 | piece of functionality for any automation/config mgmt/orchestration tool.
104 | -
105 | - h2: Example Use Cases
106 | - p: Ensure httpd is started
107 | - code: |
108 | ansible -m service -a "name=httpd state=started"
109 | - class_notes: |
110 | The service module is used to ensure httpd is started. It does not restart, stop, reload
111 | or do anything but check that the process is running; if it is not running, it starts.
112 | -
113 | - h2: Example Use Cases
114 | - p: Backgrounding tasks, with optional polling every 60 seconds
115 | - code: |
116 | ansible all -B 3600 -a "/usr/bin/long_running_operation --do-stuff"
117 | ansible all -B 1800 -P 60 -a "/usr/bin/long_running_operation --do-stuff"
118 | - class_notes: |
119 | Initiate long running tasks with polling. Optionally kick off long running tasks
120 | with backgrounding and no polling, returning you to the shell, with the option of
121 | checking back in on the operation by setting -P to 0, which is otherwise a default of 15.
122 | -
123 | - h2: Example Use Cases
124 | - p: Running setup module to gather and display all facts about a machine known to Ansible
125 | - code: |
126 | ansible web1.example.com -m setup
127 | - class_notes: |
128 | Gathers a very large JSON object's worth of data about servers, to include
129 | network information, distro information, shell environment, devices,
130 | CPU, memory, etc. All facts returned by setup are prefixed with ansible_
131 | -
132 | - h2: Cowsay
133 | - image: 'http://i.imgur.com/rRBp5Ln.png?1'
134 | - class_notes: |
135 | Cowsay is used by default if enabled on the system, but can be disabled
136 | permanently in the ansible.cfg file, or skill installation of cowsay.
137 | -
138 | - h2: Labs
139 | - h3: Using the 'ansible' command
140 | - ul:
141 | - Install nginx and ensure that it is set to start at boot
142 | - Ensure that nginx is started
143 | - Create user www-data
144 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/operational/chapter_4.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: CC, PI, JLK
4 | title: Chapter 4, Using Ansible for Orchestrated Commands
5 | description: Ansible Operational Course
6 |
7 | slides:
8 |
9 | - set_global:
10 | transition: rotate
11 | background: '#007777'
12 |
13 | -
14 | - nested:
15 | -
16 | - h1: Ansible Orchestrated Commands
17 | - h3: A Review of Ansible Plays and Playbooks
18 | - class_notes: Students will walk through the process Ansible goes through to execute the desired jobs on targeted hosts when a Playbook gets run.
19 |
20 | -
21 | - h2: Plays
22 | - p: An ordered series of tasks executed on a selection of hosts
23 | - p: With controls over how the tasks operate
24 | - code: |
25 | - name: This is a Play
26 | hosts: web-servers
27 | remote_user: fred
28 | sudo: yes
29 | connection: ssh
30 | gather_facts: no
31 | vars:
32 | http_port: 80
33 | cache_dir: /opt/cache
34 |
35 | tasks:
36 | - name: create cache dir
37 | file: path={{ cache_dir }} state=directory
38 |
39 | - name: install nginx
40 | yum: name=nginx state=installed
41 | - class_notes: |
42 | Discuss play controls such as sudo, remote_user, etc.
43 | Discuss variables. Show the list of tasks and how
44 | all finish one before going on to the next. Mention serial
45 | as a way to control how hosts flow through the tasks.
46 | Multiple plays can be written into a playbook.
47 |
48 | -
49 | - h2: Playbooks
50 | - p: ansible-playbook is the tool used to select
51 | - ul:
52 | - an ordered set of plays
53 | - an inventory
54 | - global variables
55 | - forks
56 | - inventory limits
57 |
58 | -
59 | - h2: Playbooks
60 | - h3: Execution
61 | - code: |
62 | $ ansible-playbook play.yaml -i pre-prod -e "cache_dir=/srv/cache/" -f 30 -l dfw
63 |
64 | -
65 | - h2: Handlers
66 | - h3: "Actions triggered upon change"
67 |
--------------------------------------------------------------------------------
/operational/chapter_5.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Matt Martz
4 | title: Variables
5 | description: Understand the basics of variables, where they come from, how they get set, and how to evaluate and manipulate them
6 |
7 | slides:
8 |
9 | -
10 | - nested:
11 |
12 | -
13 | - h1: Variables
14 | - p: Understand the basics of variables, where they come from, how they get set, and how to evaluate and manipulate them
15 |
16 | -
17 | - h2: Host Variables
18 | - p: Host variables are "facts" about a server that contains info such as
19 | - ul:
20 | - Hostname
21 | - IP addresses
22 | - Date and Time information
23 | - CPU, Disk, Memory
24 | - Hardware Architecture
25 | - Operating System Information
26 | - class_notes: For an example the students can run 'ansible all -i localhost, -c local -m setup'
27 |
28 | -
29 | - h2: Host Variables
30 | - p: Where do they come from?
31 | - ul:
32 | - inventory
33 | - fact gathering (setup)
34 | - host_vars directory
35 |
36 | -
37 | - h2: Group Variables
38 | - p: '"facts" that apply to a grouping of servers'
39 |
40 | -
41 | - h2: Group Variables
42 | - p: Where do they come from?
43 | - ul:
44 | - inventory
45 | - group_vars directory
46 | - p: ""
47 | - p: The name of the files in the group_vars directory line up with the group name being targeted. "all" is a special keyword to apply facts to all hosts.
48 |
49 | -
50 | - h2: Variable Precedence
51 | - p: Precedence should simply feel natural
52 | - p: The most specific applied variable wins
53 |
54 | -
55 | - h2: Using Variables in YAML
56 | - p: Ansible uses "mustache" like variable expansion
57 | - h4: group_vars/all
58 | - code: |
59 | ---
60 | apache2_version: 2.2.22-1ubuntu1
61 | - h4: Task
62 | - code: '- apt: name="apache2={{ apache2_version }}" state=present'
63 |
64 | -
65 | - h2: Register
66 | - p: A special keyword "register" exists for all tasks, that will assign the output from a module to the variable of the specified name, for later manipulation or evaluation in use with other tasks
67 | - code: |
68 | - git: repo=git://github.com/ansible/ansible.git dest=/tmp/ansible
69 | register: ansible_git
70 | - class_notes: |
71 | Different modules produce different data structures. For example, command and shell return a data structure containing the return code of the command, the contents of stderr and stdout, etc. The next section talks about how to explore the contents of a register variable.
72 |
73 | -
74 | - h2: Inspecting Variables
75 | - p: Different modules produce different data structures. The 'debug' module will help you inspect that data structure.
76 | - code: |
77 | - debug: var=ansible_git
78 | - h4: Output Sample
79 | - code: |
80 | ok: [someserver] => {
81 | "ansible_git": {
82 | "after": "1b4ba5431b1070c63b9069d310f42e16f302db10",
83 | "before": "69b2d82be6ffe20f04070cddf11b7629aa8420e5",
84 | "changed": true,
85 | "invocation": {
86 | "module_args": "repo=git://github.com/ansible/ansible.git dest=/tmp/ansible",
87 | "module_name": "git"
88 | }
89 | }
90 | }
91 |
92 | -
93 | - h2: Module Output Structure
94 | - p: All modules should return a key titled "changed" with a boolean value of "true" or "false" defining whether the module made a change
95 | - p: Additionally, under a failure scenario, a module would set a key of "failed" with a boolean value of "true"
96 | - class_notes: A failed module may not have a changed key
97 |
98 | -
99 | - h2: Dynamically Adding Host Facts
100 | - p: During runtime you can run add additional host vars using the "set_fact" module
101 | - code: |
102 | - local_action:
103 | module: wait_for
104 | host: "{{ ansible_default_ipv4.address }}"
105 | port: 22
106 | delay: 1
107 | timeout: 1
108 | register: port_test
109 | failed_when: False
110 |
111 | - set_fact: ansible_ssh_port=2222
112 | when: port_test|failed
113 | - class_notes: This example uses the wait_for module to attempt communication with port 22 on the remote host via a local action. Don't fail if wait_for fails, and if wait_for fails, set ansible_ssh_port to port 2222 for future communciation with the server.
114 |
115 | -
116 | - h2: Magic Variables
117 | - p: There are several standard variables that are created and exposed by ansible
118 | - ul:
119 | - inventory_dir
120 | - inventory_hostname
121 | - inventory_hostname_short
122 | - inventory_file
123 | - playbook_dir
124 | - play_hosts
125 | - hostvars
126 | - groups
127 | - group_names
128 | - ansible_ssh_user
129 | - class_notes: |
130 | play_hosts is new to 1.5, there is also 'vars' and 'environment' but are not widely used or discussed
131 | http://docs.ansible.com/playbooks_variables.html#magic-variables-and-how-to-access-information-about-other-hosts
132 |
--------------------------------------------------------------------------------
/operational/chapter_6.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Tim G
4 | title: Chapter Title
5 | description: Description of the chapter
6 |
7 | slides:
8 |
9 | -
10 | - nested:
11 |
12 | -
13 | - h1: Variable Inclusion
14 | - h3: How to properly use include_vars and vars_files to include variables in your playbooks
15 |
16 | -
17 | - h2: vars_files
18 | - p: "vars_files is used in playbooks to include a file of variables outside of the usual variable locations"
19 | - ul:
20 | - Useful for keeping secrets and site specific data outside of your Ansible repository and version control
21 | - Not available for usage within roles, for that you will need the include_vars module
22 |
23 | - class_notes:
24 | The vars_files directive is useful because it allows for you to keep secrets and business specific data in a location outside your Ansible repository. This allows you to keep your Ansible playbooks very generic and portable. This means you can continue to benefit from changes upstream if it is a community contributed playbook, or you can safely push out updates to the playbook if you are contributing it to the community. Ultimately the variable include mechanisms are to provide flexibility in where your variables are located.
25 |
26 | -
27 | - h2: include_vars
28 | - p: "The include_vars module is similar to vars_files and allows for dynamic inclusion of variables within the context of a role."
29 | - ul:
30 | - |
31 | include variables based on the target Linux Distribution
32 | include_vars: "../vars/{{ansible_os_family}}.yml"
33 |
34 | - |
35 | include a directory of variable fragments
36 | include_vars: "{{ item }}.yml"
37 | with_fileglob: "../vars/*.yml"
38 |
39 | - class_notes:
40 | The include_vars module is very similar to vars_files, however include_vars is a module which means it can be used within the context of a role, whereas vars_files cannot. Some example use cases of include_vars are shown here, in the first example include_vars is used to pull in variables based upon the Linux distribution in use. In the second example include_vars is being used to collect a series of variables files from a directory. Don't think of these as the "correct" ways to handle variables, but rather as yet another tool at your disposal for flexibility when needed.
41 |
--------------------------------------------------------------------------------
/operational/chapter_7.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Tim G
4 | title: Task Control
5 | description: Ansible has a lot of ways to control the operation of specific tasks. You can use then "when" keyword to skip tasks according to certain conditions, loop over items in lists or hashes, and control the "failed" or "changed" responses of particular tasks. Local actions and delegation can be used to control where a task runs.
6 |
7 | slides:
8 |
9 | -
10 | - nested:
11 | -
12 | - h1: Task Control
13 | - ul:
14 | - "Conditionals: when"
15 | - "Loops: with_items, etc"
16 | - "Task status: failed_when, changed_when"
17 | - Local actions and delegation
18 |
19 | -
20 | - h2: Conditionals
21 | - h3: Useful for
22 | - ul:
23 | - Acting on results of previous tasks
24 | - Handling cross-distro/env differences
25 |
26 | -
27 | - h2: "An Example"
28 | - code: |
29 | - name: do something only on RedHat-style systems
30 | command: mycommand
31 | when: ansible_os_family == "RedHat"
32 |
33 | - class_notes: The when keyword, when applied to a task, can control execution of that task and skip it when certain conditions are set. Any variable can be used in a "when" condition, including register variables, facts, and group/host vars. Some particularly useful uses of this include skipping tasks based on the results of previous tasks, and handling cross-distro differences in package names/managers.
34 |
35 | -
36 | - h2: "Loops"
37 | - h3: "with_items: Loops over a list, one task per item"
38 |
39 | - class_notes: "Tasks can loop over lists using the with_items keyword. Each item in the list will be treated as a separate task, and you can use the special item variable name to access the current item. (Note: apt/yum modules collapse a list into a single package management transaction for speed)
40 |
41 | There are some other looping keywords, too. See http://docs.ansible.com/playbooks_loops.html for more.
42 |
43 | Class question: when would you need to use some of the other loop keywords, like with_together, with_sequence,with_random_choice, etc?"
44 |
45 | -
46 | - h2: "Status Control"
47 | - ul:
48 | - failed_when
49 | - changed_when
50 |
51 | - class_notes: "Ansible tasks can return a few different states: \"OK\" means that the task completed successfully but didn'/.t change anything on the target system. \"Changed\" means that the task completed, and changed something. \"Failed\" means that the task failed. (duh)
52 |
53 | When you're using \"command\" or \"shell\" to issue commands on the remote system, Ansible will detect the return code of the command. If it's non-zero, Ansible will treat it as a failure, but sometimes that's not what you want. There may be other circumstances with other modules where you see a change or a failure but want to continue on, or mark that task as just \"ok\", with no change. There are two keywords to control this. failed_when and changed_when. These work like the \"when\" keyword, but control the status of the task. For instance.
54 |
55 | - name: this command prints FAILED when it fails
56 | command: /usr/bin/example-command -x -y -z
57 | register: command_result
58 | failed_when: \"'FAILED' in command_result.stderr\"
59 | This will treat the command as a failure only when the string \"FAILED\" exists in the stderr of the command output.
60 |
61 | Some examples of changed_when:
62 |
63 | - shell: /usr/bin/billybass --mode=\"take me to the river\"
64 | register: bass_result
65 | changed_when: \"bass_result.rc != 2\"
66 |
67 | # this will never report 'changed' status
68 | - shell: wall beep
69 | changed_when: False
70 | "
71 | -
72 | - h2: Local actions
73 | - ul:
74 | - local_action (task)
75 | - "connection: local (play)"
76 |
77 | - class_notes:
78 | "Most Ansible tasks (actions) run on a remote machine: a Python program is assembled and sent across to the remote server, run, and the response is returned. But for some tasks, like API calls to remote services, it doesn't make sense to run that task on a remote machine--this is what local actions are for. This runs the task locally on the Ansible machine, but still \"on behalf\" of the machine currently being operated upon."
79 |
80 | -
81 | - h2: Delegation
82 | - p: Run a task on another server, on behalf of the server we are currently operating on.
83 |
84 | - class_notes: A delegated task is similar. You can be running a play that operates upon, say, "webservers", but for a particular task within that play, run the action on a different server. As an example, you may be going through an app deployment on the webservers group, but you may need to contact the monitoring server to turn off monitoring for that host while it's being updated. So, you would want to delegate_to a different server, in a play ordinarily targeting webservers.
85 |
--------------------------------------------------------------------------------
/operational/chapter_8.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Jesse K and David F
4 | title: Best Practices
5 | description: A discussion of the best operational practices to use with Ansible.
6 |
7 | slides:
8 |
9 | -
10 | - nested:
11 | -
12 | - h1: Best Practices
13 | - ul:
14 | - content organization
15 | - version control
16 | - role based access control
17 | - platform variance in playbooks
18 | - proper naming of plays, tasks, and handlers
19 | - playbook formatting
20 | - class_notes: |
21 | Best practices are not just conformity for conformity sake.
22 | They will help simplify code, smooth out collaboration, and
23 | avoid gotchas.
24 | -
25 | - h2: Content Organization
26 | - p: Magic happens when you put your files in the right locations
27 | - ul:
28 | - ansible.cfg
29 | - inventory
30 | - variables and inclusions
31 | - tasks
32 | - handlers
33 | - playbooks
34 | - templates and files for use in tasks
35 | - custom modules
36 | - roles
37 | - class_notes: |
38 | Ansible looks in ANSIBLE_CONFIG, ./ansible.cfg, ./.ansible.cfg
39 | and /etc/ansible/ansible.cfg in that order. (1.5 switched
40 | ANSIBLE_CONFIG and ./ansible.cfg order)
41 | Inventory is looked for in config directive, ANSIBLE_HOSTS,
42 | /etc/ansible/hosts in that order.
43 | host_vars / group_vars relative to inventory and playbook
44 | basedirs
45 | file inclusions are relative to the playbook (vars, tasks,
46 | handlers, playbooks, templates, etc...)
47 | Custom modules go in library/ relative to playbook
48 | roles are in roles/ relative to playbook, and have
49 | files, templates, tasks, handlers, vars, meta all relative
50 | to the role itself, making for portability.
51 |
52 | -
53 | - h2: Version Control
54 | - p: Version control and Ansible go hand in hand. This topic will walk through many of the benefits of storing your ansible content in SCM and why this is itself a best practice.
55 | -
56 | - h2: Version Control
57 | - h3: audit trail / RBAC
58 | - class_notes: |
59 | Version control provides a record of who changed what, when, and
60 | why, the audit trail. It can also be a part of RBAC strategy,
61 | providing a gateway to who can commit to the playbook content.
62 | -
63 | - h2: Version Control
64 | - h3: collaboration and preservation
65 | - class_notes: |
66 | A centralized (or distributed) store of the content protects
67 | against localized disaster. It also allows for better collaboration
68 | than just passing files back and forth, or co-editing a single
69 | directory.
70 | -
71 | - h2: Version Control
72 | - h3: DevOps tie-in
73 | - class_notes: DevOps best practices dictate code to be deployed is already in SCM, natural extension to put code that does the deploying in SCM as well
74 | -
75 | - h2: Version Control
76 | - h3: Galaxy, Git, and You!
77 | - ul:
78 | - role sharing
79 | - joys of modular playbooks
80 | - deploying code with the git module in a role
81 | - class_notes: GALAXY!
82 | -
83 | - h2: Version Control
84 | - h3: Sensitive information handling
85 | - class_notes: VAULT!
86 | -
87 | - h2: Version Control
88 | - h3: Barriers to entry
89 | - ul:
90 | - pull requests
91 | - automatic gateway tests
92 | - local validation checks
93 | - class_notes: |
94 | All these things can work together to add quality assurance to your
95 | content. Using pull or change requests gives a human the
96 | opportunity to review. Automated tests can tie into them, or be
97 | ran post-commit to continuously validate. Localized hooks can be
98 | used to validate after pulling changes in.
99 | -
100 | - h2: RBAC and execution model
101 | - p: A discussion of RBAC, Ansible, and your team, as well as a comparison of execution stratagies
102 | -
103 | - h2: RBAC and execution model
104 | - h3: RBAC
105 | - class_notes: |
106 | Role Based Access Control is used in many organizations
107 | to seperate out who has access to do what within environments.
108 | Often required for parts of public companies. Sometimes at
109 | odds with DevOps philosophy of self-service.
110 | -
111 | - h2: RBAC and execution model
112 | - h3: Execution models
113 | - ul:
114 | - centralized
115 | - distributed
116 | - class_notes: A comparison and contrast of centralized and distributed execution models. Not to be confused with push and pull.
117 | -
118 | - h2: RBAC and execution model
119 | - h3: Centralized
120 | - ul:
121 | - access defined by company standards
122 | - layer of protection against accidents and malice
123 | - repeatability and guaranteed working environment
124 | - ITIL/Change Control process friendly
125 | - class_notes: |
126 | A single point from which to either push changes from, or
127 | have ansible-pull fetch changes from. Can configure systems to
128 | only allow Ansible logins from this host with a particular key
129 | Host can be locked down and managed to ensure unwanted changes
130 | don't creep in and disrupt ability to do repeat runs
131 | -
132 | - h2: RBAC and execution model
133 | - h3: Distributed
134 | - ul:
135 | - rapid development and execution loop
136 | - change control put in hands of playbook/code devs
137 | - turns operational support from gatekeeping to enabling
138 | - aligns with other self-service IT services
139 | - you built it, you deploy it
140 | - class_notes: |
141 | Each developer could be a distributor, or individual
142 | systems could point to individual sources for ansible-pull
143 | Higher security risk, higher risk of run environment change
144 | but tradeoff for more flexibility and rapid dev/deploy times
145 | -
146 | - h2: Platform Variance in playbooks
147 | - p: Best practices for dealing with the challenge of heterogeneous environments
148 | -
149 | - h2: Platform Variance in playbooks
150 | - h3: group_by
151 | - p: Create dyanmic groups matching certain criteria
152 | - code: |
153 | - name: grouping play
154 | hosts: all
155 | tasks:
156 | - name: create distro groups
157 | group_by: key={{ ansible_distribution }}
158 |
159 | - name: CentOS play
160 | hosts: CentOS
161 | gather_facts: False
162 | tasks:
163 | - # tasks that only happen on CentOS go here
164 | - class_notes: Note that roles could also be used here, driven by group_by.
165 | -
166 | - h2: Platform Variance in playbooks
167 | - h3: task conditionals
168 | - code: |
169 | - name: install nginx
170 | yum: name=nginx state=present
171 | when: ansible_distribution == 'CentOS'
172 |
173 | - name: install nginx
174 | apt: pkg=nginx state=present
175 | when: ansible_distribution == 'Debian'
176 | - class_notes: A more simple way to deal, could clutter up a large playbook / role set.
177 | -
178 | - h2: Proper naming of plays, tasks, and handlers
179 | - p: Names have significance
180 | - ul:
181 | - --start-at-task
182 | - handler notification
183 | - output review
184 | - code: |
185 | $ ansible-playbook play.yaml --start-at-task="a good task"
186 |
187 | - name: a good task
188 | file: path=/etc/foobar state=absent
189 | notify: bounce foo service
190 |
191 | handlers:
192 | - name: bounce foo service
193 | service: name=foo state=restarted
194 | - class_notes: |
195 | Names have meaning. task names in --start-at-task,
196 | handler names for notify. Play names are less important
197 | but uniqueness helps when debugging output
198 | -
199 | - h2: Playbook formatting
200 | - p: whitespace, yaml, line lengths, oh my!
201 | -
202 | - h2: Playbook formatting
203 | - h3: order and style of playbook directives
204 | - ul:
205 | - use a name
206 | - hosts next
207 | - other options
208 | - tags
209 | - vars after a blank line
210 | - tasks after a blank line
211 | - code: |
212 | - name: Generate env/cell specific content
213 | hosts: localhost
214 | connection: local
215 | gather_facts: false
216 | tags:
217 | - localprep
218 |
219 | vars:
220 | - cachedir: cache/
221 |
222 | tasks:
223 | - name: stuff
224 | - class_notes: |
225 | There is no hard order that things must appear in a playbook,
226 | however if anybody ever looks at your files they will expect
227 | an order. Blank lines help to visually separate logical blocks
228 | of the play and between plays.
229 | -
230 | - h2: Playbook formatting
231 | - h3: whitespace, line lengths, continuations
232 | - ul:
233 | - blank lines encouraged
234 | - less than 80 chars wide
235 | - blocks can continue on new lines with proper spacing
236 | - code: |
237 | tasks:
238 | - name: one task
239 | command: echo
240 |
241 | - name: lots of arguments
242 | rax_dns_record: credentials=/path/to/my/creds type=A
243 | data=4.2.2.2 name=www.nodomain.not
244 | - class_notes: |
245 | Playbook syntax is friendly to line continuation, make use of that
246 | to keep your lines under 80 chars. Wrap the text to be at the same
247 | indent level as the preceeding data block, as seen in the example
248 | -
249 | - h2: Playbook formatting
250 | - h3: to quote or not to quote
251 | - ul:
252 | - "quote strings that have a : in them"
253 | - "quote variables if they come directly after a :"
254 | - "quote strings that use * directly after a :"
255 | - quote entire string if first character is a quote
256 | - code: |
257 | - name: "My name has a : in it"
258 | command: "{{ variable_here }}"
259 | when: "'some_string' in varaible_here"
260 |
261 | hosts: "*-webs"
262 | - class_notes: |
263 | quoting is a yaml gotcha. It often trips people up. These
264 | rules here will help you avoid most/all quoting gotchas.
265 | -
266 | - h2: Playbook formatting
267 | - h3: variable referencing
268 | - ul:
269 | - use {{ }} almost always
270 | - do not use {{ }} in conditionals and other task controllers
271 | - code: |
272 | - name: name here
273 | command: echo {{ variable here }}
274 | register: output
275 | when: variable != "derp"
276 | failed_when: output.stderr == "FAILURE"
277 | - class_notes: |
278 | Variable decoration is another gotcha. Task controllers can be
279 | treated like lines of python, where variables are referenced
280 | without decoration and raw strings need quotes.
281 | -
282 | - h2: Playbook formatting
283 | - h3: YAML gotchas
284 | - ul:
285 | - |
286 | Booleans: /^(y|yes|n|no|true|false|on|off)$/i
287 | - class_notes: |
288 | Assume the scenario where you are configuring sshd_config, and you create a variable to disable root login via "PermitRootLogin: no". In this case 'no', evaluates to the boolean False, so you end up literally inserting "PermitRootLogin False" in your config file. To use 'no' as a string literal it must be quoted such as "PermitRootLogin: 'no'".
289 |
290 | -
291 | - image: "http://cdn2.hubspot.net/hub/330046/file-449187601-png/ansible_badge.png"
292 | - link: ['ansible.com',
293 | 'http://www.ansible.com']
294 |
--------------------------------------------------------------------------------
/operational/root.yml:
--------------------------------------------------------------------------------
1 | ---
2 | header:
3 | author: Rackspace and Ansible
4 | title: Ansible Operational
5 | description: Ansible Operational
6 | slides: []
7 |
--------------------------------------------------------------------------------
/operational_lab/adhoc_commands.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # adhoc_commands.sh
3 |
4 | # Install nginx (EL first) and ensure that it is set to start at boot
5 |
6 | # First we upload the repo file for nginx
7 | ansible all -i hosts -u root -m copy -a "src=nginx.repo dest=/etc/yum.repos.d/nginx.repo owner=root mode=0655"
8 |
9 | # Install the RPM GPG Key
10 | ansible all -i hosts -u root -m rpm_key -a "key=http://nginx.org/keys/nginx_signing.key"
11 |
12 | # Now let's install the package
13 | ansible all -i hosts -u root -m yum -a "name=nginx state=present"
14 |
15 | # Last, enable the package to run at boot
16 | ansible all -i hosts -u root -m service -a "name=nginx enabled=yes"
17 |
--------------------------------------------------------------------------------
/operational_lab/group_vars/all:
--------------------------------------------------------------------------------
1 | nginx_workers: 2
2 | nginx_access_log: /var/log/nginx/access.log
3 | nginx_error_log: /var/log/nginx/error.log
4 | domains:
5 | - example.com
6 | - hamsandwich.com
7 | - moo.com
8 | - ansible.com
9 |
--------------------------------------------------------------------------------
/operational_lab/lab3-7.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # Lab 3
3 | - name: Ansible Operational Labs
4 | hosts: all
5 | tasks:
6 | # This is boilerplate for dealing with an apt module that is not installing
7 | # python-apt for you. This checks for the existence of python-apt
8 | - name: Check if python-apt installed on Debian-based machines
9 | command: dpkg -s python-apt
10 | register: pythonapt
11 | when: "ansible_os_family == 'Debian'"
12 | ignore_errors: yes
13 |
14 | # This checks the output of the previous command and runs an install of
15 | # python-apt if not already installed
16 | - name: Install python-apt for Debian based machines
17 | shell: apt-get update && apt-get -y install python-apt
18 | when: "ansible_os_family == 'Debian' and pythonapt.stderr"
19 |
20 | # Install python-pycurl for apt_repository because of missing python-pycurl package
21 | - name: Install python-software-properties
22 | apt: pkg=python-pycurl state=present
23 | when: "ansible_os_family == 'Debian'"
24 |
25 | - name: Add repo for Debian based machines
26 | apt_repository: repo="deb http://nginx.org/packages/ubuntu/ {{ ansible_distribution_release }} nginx" state=present update_cache=yes
27 | when: "ansible_os_family == 'Debian'"
28 |
29 | - name: Add key for Debian based machines
30 | apt_key: url=http://nginx.org/keys/nginx_signing.key state=present
31 | when: "ansible_os_family == 'Debian'"
32 |
33 | - name: Install package for Debian-based machines
34 | apt: pkg=nginx state=present
35 | when: "ansible_os_family == 'Debian'"
36 |
37 | - name: Add repo for EL-based machines
38 | copy: src=nginx.repo dest=/etc/yum.repos.d/nginx.repo owner=root mode=0644
39 | when: "ansible_os_family == 'RedHat'"
40 |
41 | - name: Add key for EL-based machines
42 | rpm_key: "key=http://nginx.org/keys/nginx_signing.key"
43 | when: "ansible_os_family == 'RedHat'"
44 |
45 | - name: Install package for Debian-based machines
46 | yum: name=nginx state=present
47 | when: "ansible_os_family == 'RedHat'"
48 |
49 | - name: Add user www-data
50 | user: name=www-data state=present
51 |
52 | - name: Enable nginx at boot
53 | service: name=nginx enabled=yes state=started
54 |
55 | # Lab 5
56 | - name: Install nginx.conf
57 | template: src=templates/nginx.conf dest=/etc/nginx/nginx.conf owner=root mode=0644
58 |
59 | # Lab 6
60 | - name: Create web directories
61 | file: path="/var/www/{{ item }}" state=directory owner=www-data mode=0755
62 | with_items: domains
63 |
64 | - name: Install nginx vhost configs
65 | template: src=templates/vhost.conf dest="/etc/nginx/conf.d/{{ item }}.conf" owner=root mode=0644
66 | with_items: domains
67 | # Lab 7
68 | notify: Restart nginx
69 |
70 | handlers:
71 | - name: Restart nginx
72 | service: name=nginx state=restarted
--------------------------------------------------------------------------------
/operational_lab/labs.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # Lab 1
3 | - name: Ansible Operational Labs
4 | hosts: all
5 | # Lab 2
6 | tasks:
7 | - name: Add nginx repo to servers
8 | copy: src=nginx.repo dest=/etc/yum.repos.d/nginx.repo owner=root mode=0644
9 |
10 | - name: Install nginx
11 | yum: name=nginx state=present
12 |
13 | - name: Enable nginx to start at boot
14 | service: name=nginx enabled=yes
15 |
16 | # Lab 3
17 |
--------------------------------------------------------------------------------
/operational_lab/labs1_2.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # Lab 1
3 | - name: Ansible Operational Labs
4 | hosts: all
5 | # Lab 2
6 | tasks:
7 | - name: Add nginx repo to servers
8 | copy: src=nginx.repo dest=/etc/yum.repos.d/nginx.repo owner=root mode=0655
9 |
10 | - name: Install nginx
11 | yum: name=nginx state=present
12 |
13 | - name: Enable nginx to start at boot
14 | service: name=nginx enabled=yes
15 |
16 | # Lab 3
--------------------------------------------------------------------------------
/operational_lab/nginx.repo:
--------------------------------------------------------------------------------
1 | [nginx]
2 | name=nginx repo
3 | baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
4 | gpgcheck=0
5 | enabled=1
6 |
--------------------------------------------------------------------------------
/operational_lab/templates/nginx.conf:
--------------------------------------------------------------------------------
1 | user www-data;
2 | worker_processes {{ nginx_workers }};
3 | pid /var/run/nginx.pid;
4 |
5 | events {
6 | worker_connections 768;
7 | # multi_accept on;
8 | }
9 |
10 | http {
11 |
12 | ##
13 | # Basic Settings
14 | ##
15 |
16 | sendfile on;
17 | tcp_nopush on;
18 | tcp_nodelay on;
19 | keepalive_timeout 65;
20 | types_hash_max_size 2048;
21 | # server_tokens off;
22 |
23 | # server_names_hash_bucket_size 64;
24 | # server_name_in_redirect off;
25 |
26 | include /etc/nginx/mime.types;
27 | default_type application/octet-stream;
28 |
29 | ##
30 | # Logging Settings
31 | ##
32 |
33 | access_log {{ nginx_access_log }};
34 | error_log {{ nginx_error_log }};
35 |
36 | ##
37 | # Gzip Settings
38 | ##
39 |
40 | gzip on;
41 | gzip_disable "msie6";
42 |
43 | # gzip_vary on;
44 | # gzip_proxied any;
45 | # gzip_comp_level 6;
46 | # gzip_buffers 16 8k;
47 | # gzip_http_version 1.1;
48 | # gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
49 |
50 | ##
51 | # nginx-naxsi config
52 | ##
53 | # Uncomment it if you installed nginx-naxsi
54 | ##
55 |
56 | #include /etc/nginx/naxsi_core.rules;
57 |
58 | ##
59 | # nginx-passenger config
60 | ##
61 | # Uncomment it if you installed nginx-passenger
62 | ##
63 |
64 | #passenger_root /usr;
65 | #passenger_ruby /usr/bin/ruby;
66 |
67 | ##
68 | # Virtual Host Configs
69 | ##
70 |
71 | include /etc/nginx/conf.d/*.conf;
72 | include /etc/nginx/sites-enabled/*;
73 | }
74 |
--------------------------------------------------------------------------------
/operational_lab/templates/vhost.conf:
--------------------------------------------------------------------------------
1 | server {
2 | listen 80;
3 | server_name {{ item }} *.{{ item }};
4 | root /var/www/{{ item }};
5 | index index.html index.htm;
6 | try_files $uri $uri/ $uri.htm $uri.html =404;
7 |
8 | location ~* \.htaccess {
9 | return 400;
10 | }
11 | }
--------------------------------------------------------------------------------
/syntax_check.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import yaml
3 |
4 | exit = 0
5 | for yml in sys.argv[1:]:
6 | try:
7 | with open(yml) as f:
8 | yaml.load(f)
9 | except (yaml.parser.ParserError, yaml.scanner.ScannerError) as e:
10 | print '********\n%s\n********' % e
11 | exit += 1
12 | else:
13 | print '%s: Syntax OK' % yml
14 |
15 | sys.exit(exit)
16 |
--------------------------------------------------------------------------------