Ansible

Ansible

Ansible Tower is the commercial version. Control multiple devices from a single place.

Installing Ansible

Nothing to install on client devices. SSH is required, python is recommended on clients
  • username - consistent across all devices
  • sudo or root - sudo to escalate privilege is recommended
  • passwordless keys or ssh-agent (cache credentials)
ansible localhost -m ping

Configuring Ansible Clients

  • Ideal to have all usernames the same
  • Clients need to be able to use sudo without password
ssh-keygen ssh-copy-id -i .ssh/id_rsa.pub user@192.168.1.2 sudo visudo user ALL=(ALL) NOPASSWD: ALL ## CentOS su - visudo user ALL=(ALL) NOPASSWD: ALL
sudo vi /etc/ansible/hosts hostname hostname ansible_user=administrator 172.20.0.[1:6] [Group Name]
  • Can be in multiple groups
  • Range in hostname or IP [01:05]
  • Need username if not the same as local user
  • ansible_port - if not 22
## If the client doesn't have python, send a raw command ansible -m raw -a '/usr/bin/uptime' all

Ad-Hoc Operations

-a Action (Does not escalate privilege)
-b Become (Sudo)
ansible all -a 'uptime' ansible all -b -a 'whoami'
-m Module
Defaults to command module
Service module doesn’t check if service exists before enabling it
ansible all -b -m apt -a 'name=apache2 state=present' ansible all -b -m yum -a 'name=httpd state=present' ## present, absent, latest ansible all -b -m service -a 'name=apache2 enabled=true' ansible all -b -m service -a 'name=apache2 state=started'
Command
  • doesn’t use shell, directly runs commands
  • can’t use pipes or redirects
Shell
  • supports pipes and redirects
  • can get messed up by user settings
raw
  • just sends commands over ssh
  • doesn’t need python
# Delete file ansible all -b -m file -a 'path=/root/hello.txt state=absent' #Sent file ansible all -b -m copy -a 'src=/etc/hosts dest=/etc/hosts'

Playbooks

yaml - yet another markup language. First line needs 3 dashes, whitespace is important, no tabs.
Group tasks together. If one task fails playbook is aborted.
--- - hosts: servers tasks: - name: do a uname shell: uname -a > /home/user/Desktop/results.txt - name: whoami shell: whoami >> /home/user/Desktop/results.txt
ansible-playbook test.yaml #run as root ansible-playbook -b test.yaml #or add either under hosts in playbook yaml become: yes become: true

Handlers

After all tasks completed, any handler that is called runs.
Handlers only run once even if called by multiple tasks.
Handlers are only called if task result is changed.
Handler name needs to match notify
--- - hosts: servers become: yes tasks: - name: installed vsftpd on ubuntu apt: name=vsftpd update_cache=yes state=latest ignore_errors: yes notify: start vsftpd - name: installed vsftpd on centos yum: name=vsftpd state=latest ignore_errors: yes notify: start vsftpd handlers: - name: start vsftpd service: name=vsftpd enabled=yes state=started

Variables and Facts

--- - hosts: ubuntu vars: - var1: test1 - var2: testing tasks: - name: echo shell: echo "{{ var1 }} test {{ var2 }}"
Facts
  • CPU Type, numbers of cores
  • OS Family
  • Amount of RAM
  • IP Address
Return entire Facts in adhoc mode
ansible ubuntu -m setup ansible ubuntu -m setup -a "filter=*family*"
Use fact name the same as variables in playbooks

Debug Module

Register saves output JSON to a variable
--- - hosts: centos var: - var_thing: "never" tasks: - name: echo command: echo -e "hello\nline 2\n{{ var_thing }}" register: results - name: show results debug: msg="{{ results.stdout_lines }}"

Conditionals

When - only do task if condition is met
Result Filter
--- - hosts: servers become: yes tasks: - name: install apache2 apt: name=apache2 update_cache=yes state=latest ignore_errors: yes register: results - name: install httpd yum: name=httpd state=latest when: results|failed
Comparison
--- - hosts: servers become: yes tasks: - name: install apache2 apt: name=apache2 update_cache=yes state=latest when: ansible_os_family == "Debian" - name: install httpd yum: name=httpd state=latest when: ansible_os_family == "RedHat"

Loops

Standard Loop
--- - hosts: ubuntu become: yes tasks: - name: install apt: name={{ item }} update_cache=yes state=latest with_items: - vim - nano - apache2
File Loop
--- - hosts: ubuntu become: yes tasks: - name: show file contents debug: msg={{ item }} with_file: - file1.txt - file2.txt
Sequence Loop
--- - hosts: ubuntu become: yes tasks: - name: show file contents debug: msg={{ item }} with_sequence: start=1 end=10

Templates

Jinja2
--- - hosts: servers become: yes vars: file_version: 1.0 tasks: - name: install index template: src: index.html.j2 dest: /var/www/html/index.html mode: 0777
<html> <h1> Hostname is {{ ansible_hostename }} </h2> <h3> It is running {{ ansible_os_family }} </h3> {# this comment will not end up in the output file #} </html>

Ansible Vault

Encrypts entire playbook with a vault password
ansible-vault create test.yaml # Interactive ansible-playbook test.yaml --ask-vault-pass # Password file (chmod 400) ansible-playbook test.yaml --vault-password-file password.txt ansible-vault edit test.yaml

Include

Playbooks can have multiple plays, starts with a new hosts section.
include plays (at beginning)
include tasks (in the task definition)
--- - include: Desktop/update_systems.yaml - hosts: servers become: yes tasks: - include: Desktop/instal_apache.yaml

Ansible Roles

folder structure. Automatically include files
File extension is usually yml when using roles not yaml
common is name of the role
site.yml #master playbook webservers.yml #playbook for webserver tier roles/common/tasks/main.yml roles/common/handlers/main.yml roles/common/templates/index.html.j2 roles/common/files/test.txt roles/common/vars/main.yml roles/common/defauls/main.yml
--- - hosts: servers become: yes roles: - apache

Ansible Galaxy

Publicly shared roles
By default saved to /etc/ansible/roles. needs root access to write to this folder
ansible-galaxy search apache
auther . name of role. Sorted by most downloaded.
galaxy.ansible.com shows more details
ansible-galaxy install geerlingguy.apache geerlingguy.mysql
--- - hosts: servers become: yes roles: - geerlingguy.apache - geerlingguy.mysql