PyCon Day 0: Ansible 101
Ansible 101
Part 1: Exposition
- Playbooks
- A collection of tasks (but more)
- If you have 10 servers and want to do them all at the same time, you need to specify which hosts you’ll do what
- “inventory” is a way to specify what hosts are available
- There are plugins for dynamic inventory (e.g. getting server lists from EC2)
- Can also tag things based on the tag in EC2
- Facts
- Information about a machine (e.g. your IP addresss… you need this to write an /etc/hosts file or whatever)
- nearly always start with “ansible_” (e.g. ansible_os_family: Debian, RedHat, etc.)
- Exercise: create a playbook
- Tasks
- The fundamental building block of Ansible
- Describes the state which shall have obtained (past perfect tense: happened in the past and is still in effect) on the machine
- Idempotency!
- Is NOT “machine, go thou and do X”.
- Does mean, “machine, go thou and ensure that X is done”.
- It’s not useful to us to have an orchestration layer that can only run once and then errors any time thereafter. That’s bad.
- Described in YAML in a list
- Each item is executed in sequence
- If any task fails, Ansible ends
----
- name: Ensure that my user exists. (This is like a comment)
user:
home: /home/luke
name: luke
shell: /bin/bash
state: present
system: no
- Tasks (cont)
- Can be run in any language and returns JSON
- Modules take arguments
- debug takes a msg argument, user takes about 20
- Arguments are required, optional, or mutually exclusive
- Language is idempotent language. e.g. “state: present”
- Sometimes tasks are conditional
- …only if the OS is Debian/Ubuntu
- …only if it hasn’t run before
- the when key takes an expresssion and runs it if it’s true
----
- name Install Python 3.
apt:
pkg: python3
state: present
when: ansible_os_family == 'Debian'
- Tasks (cont)
- Idempotency
- Should be idempotent whenever possible
- Most provided Ansible modules are idepmotenet with little or no effort on your part
- shell isn’t (obviously) because it cannot be
- Opinions
- Use the indented form for modules, not the long string form (Readability counts).
- Doing this with shell requires args
- When applicable, provide state explicitly
- “started/loaded/stopped/latest”
- Be consistent about the name
- The name shows up in the Ansible run. It is your documentation and comments
- Use the indented form for modules, not the long string form (Readability counts).
- Exercise
- Create a user for you on the machine
- Install python3 package from apt
- Copy a file containing the text “Hello, world!” from your local machine to /home/you/hi.txt (copy module)
- Conditional Execution
- Idempotency
---
- name: Install Python 3 (Debian)
apt:
pkg: python3
state: present
when: ansible_os_family == 'Debian'
- Loops
- Usually, loops perform the task a separate time for each item in the list
---
- name: Say hello to all the places.
debug:
msg: Hello
with:
- foo
- bar
- blah
- Canada
- Exercise
- Create a user for you and for me on the machine
- install the python3, python3-dev and python3-pip packages from apt
- in both cases, this should be a single task, using with_items
- Roles
- Ansible’s mechanism to provide reusable content
- Roles must contain tasks
- Roles may contain handlers, files, templates, etc.
- They exists for encapsulation, and putting groups of tasks together and moving them around
- Anatomy of a role
- tasks
- handlers
- defaults, vars (vars gets preferences over defaults)
- files, templates
- Most of these directories should contain main.yml if they exist at all. (Exceptions: files, templates)
- Relative paths look for things within the role, where you expect them
- E.g. when using copy omdule, Ansible looks for files within the file dir
- Reusability
- Mix of reusable and non-reusable
- Common uses for reusable roles:
- compile and install software
- configure utilities
- e.g. install Python3 on every server we have
- Application specific roles usually tie everything together at the end
- Usually one non-reusable role per project that has all of the reusable ones as dependencies
- “What is the scope where the role should be usable?” (E.g. what OS?)
- “What configuration does the role require / allow?”
- Templates
- Mechanism to write files to a machine that include….
- Variables look like: $$
- Control block look like this:
- Common blocks are if and for
- Exercise
- Write a file to /tmp/ with the following:
- The machine hostname (ansible_hostname)
- Each IPv4 address, one per line (ansible_all_ipv4_addresses)
- Each IPv6 address one per line (ansible_all_ipv6_addresses)
- Handlers
- A way of having tasks be triggered at the end of a run (e.g. restarting services)
- Special tasks using ‘notify’ and the handler’s name
- Handlers are triggered ony if the triggering task causes a change
- Use –force-handlers to still run handlers in the event of a failure
---
- name: apache.restart
service:
name: apache2
state: restarted
- Modules
- You can write it in any language. Emits JSON on standard out.
- Inheritance isn’t a thing. That’s not how it works.
- There are common args that need to be used in lots of modules (e.g. owner, mode)
- Exercise? Skipped
- Plugins
- Run on the machine running Ansible, not on the machine being orchestrated
- Most of plugins you will never, ever use. Unless you’re doing really high-level orchestration.
- Callback Plugins
- Lookup Plugins
- Author uses these the most
- Custom ways to loop over things (e.g. with_)
- E.g. wrote a custom plugin to loopup all of the users that were available on the system. Then you can say with_users in any playbook.
- Module must have init and run methods
- Filter Plugins
- E.g. the default filter plugin where if a variable isn’t defined, it sets a default
- You can define your own
Part 2: Project
- Make your server run Minecraft
- Slides will be on SpeakerDeck in a few minutes
blog comments powered by Disqus