#>whoami
● currently: ansible core team member (bcoca)
● helpdesk/application support
● programmer/analyst/software engineer
● QA, systems & network administrator
● release manager, DBA, information security,
● “Tech Janitor”
#>apropos ansible
● Configuration management
● Release management
● Automation framework
● Orchestration system
● Distributed batch executor
____________________/ It runs a TASK * x \ \ on a HOST * x / -------------------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
#LIVE>multiply_shell
● allows you to reuse your shell magic
● must be non interactive
● plays well with traditional unix tools
● just multiply by ### hosts
● requires some work for nicer outputs
● -t == json file database per host
#LIVE>ansible_shell#>ansible webs -m shell -a "awk '{print \$9}' /var/log/nginx/access.log|sort |uniq -c |sort -k1,1nr 2>/dev/null|column -t"
web1 | success | rc=0 >>204417 20048108 3048550 3026541 3011696 404269 206
web2 | success | rc=0 >>205807 20043762 304
...
#LIVE>procmail-- procmail
:0 #send back http code live report
* ^From.*@example.com* ^Subject:.*500 report
|ansible-playbook ~/plays/report.yml
--- #report.yml
…
- shell: "awk '{print \$9}' …
register: report
- mail: to={{lookup(‘env’,’FROM’)}} body={{report}} …
______________ < you got mail > -------------- \ , , \ /( )` \ \ \___ / | /- _ `-/ ' (/\/ \ \ /\ / / | ` \ O O ) / | `-^--'`< ' (_.) _ ) / `.___/` / `-----' /<----. __ / __ \<----|====O)))==) \) /====<----' `--' `.__,' \ | | \ / ______( (_ / \______ ,' ,-----' | \ `--{__________) \/
#UTIL>small_scripts
● tries not to be a programming language
● but … sometimes its very useful as such
● plays can wrap existing roles/task lists
● vars_prompt/pause allow for interactivity
● -e “var=val” for completely batch
● -e @file.json: you can use json data files
#UTIL>/sbin/departed#!/usr/bin/ansible-playbook---- name: Ensure only valid users hosts: all gather_facts: False sudo: True
vars_files: #departed: [ alan, bcoca, isaac, mathew, willy ] - /etc/departed_users.yml tasks: - name: Delete departed user and all it’s files user: name={{item}} state=absent remove=yes with_items: “{{departed}}”
#UTIL>/bin/release_apps#!/usr/bin/ansible-playbook
- hosts: localhost vars_prompt: - name: app_name prompt: “Which app do you want to deploy?” - name: app_version prompt: “Choose version/tag (default HEAD)” default: ‘HEAD’ tasks: - git: repo=git@myreposerver/{{app_version}} version={{app_version}} ......
- hosts: app_servers serial: 1 tasks:
- pause: "are you sure you want to stop all services?"
- name: shush nagios nagios: action=silence host={{inventory_hostname}} delegate_to: {{monitor}}
- name: nginx graceful stop service: name=nginx state=stopped
- name: stop uwsgi service name=uwsgi state=stopped …
...
______________________/ for reusability, use \\ includes and roles / ---------------------- \ \ __ UooU\.'@@@@@@`. \__/(@@@@@@@@@@) (@@@@@@@@) `YY~~~~YY' || ||
#QA>verify
● The same way I do things , I can check them
● Gentle learning curve for your test creator
● Checks don’t normally need root
● check_mode and diff_mode
● assert/fail, no need to read the output!
#QA>check_server- hosts: app_server
tasks:
- users: name=appuser state=present
name: verify that app user is present
- file: path=/to/app/dir owner=appuser mode=0700
name: check that app dir has proper permissions
- service: name={{item}} state=started
name: check that services are running
with_items: [‘nginx’, ‘uwsgi’]
- postgres_user: name=dbapp1 password=secretrole_attr_flags=NOSUPERUSER name: check app user is accessible via app server
____________________________________ / or if your playbook is idempotent, \\ just run it again Sam! / ------------------------------------ \ \ \ \ /\ ( ) .( o ).
#QA>check_app- hosts: app_servers
tasks:
- stat: path=/var/run/tomcat/webapps/myapp.jar
register: jar
- assert:
that:
- jar.checksum == lookup(‘consul_kv’,‘myapp_csum’)
- stat: path=/var/run/app2.pid
- wait_for: port=8080
- uri: return_content=’app1 OK’
#AUDIT>verify --- qa?
● The same way I do, I can check
● Gentle learning curve for your auditor
● Checks don’t normally need root
● check_mode and diff_mode
#AUDIT>check_firewall# verify firewall after manual config
- wait_for:
port: “{{item}}”
host: prod.example.com
delegate_to: outside.host.com
with_items: [‘80, ‘443’]
- wait_for: port={{item}} host=prod.example.com
delegate_to: outside.host.com
failed_when: not left_door_open|failed
register: left_door_open
when: item not in [‘80’, ‘443’]
with_sequence: start=1 end=1024
______________ < or call nmap > -------------- \ \ ___ {~._.~} ( Y ) ()~*~() (_)-(_)
#AUDIT>check_file_changes # from vars today_file: checks/{{inventory_hostname}}/{{today}}.txt
- find: paths=/etc recurse=Y size=1 age=1d
registered: fchanged
- assert:
that:
- fchanged|length == 0
- assert:
that:
- item.checksum == lookup(‘pipe’, ‘grep ‘ + item + ‘ /checks/latest| cut -f2’)
with_items: “{{fchanged}}”
- local_action: template src=checksums.j2 dest={{today_file}}
- local_action: file src={{today_file}} path=/checks/latest state=link
______________________ / Just until you setup \\ aide|osiris|tripwire / ---------------------- \ \ /\_)o< | \ | O . O| \_____/
#AUDIT>facts_drift
● set fact caching to use jsonfile
● make git repo or checkout in cache dir
● set incron to commit when file changes
● now git log shows facts change over time
● filter out time facts (or not)
● … so ... tower will do this for me?
#AUDIT>file_changes_xattr
● {{ansible_managed}} (changed or lack info)
● use xattr to keep metadata with the file
● requires user_xattr on mount
● great ETL, can keep correct file transforms
● does not affect copy/template ‘changed’
#HACK>expand_ansible
● roles: as shared libraries
● plugins: there are more than modules
● callbacks: send events
● notification modules: specific events
● dynamic modules: if you crave abstraction
#HACK>tidy# tidy_expected: [‘conf1.cfg’, conf2.cfg’]
- find: paths={{tidy_path}} #/etc/myapp
register: existing
- file: path={{item.path}} state=absent
when: item.path|basename not in tidy_expected
with_items: “{{existing.files|default([ ])}}”
register: removed
- mail: body=“{{removed}}”
#HACK>ansible_eventssyslog_json callback plugin
def __init__(self): self.logger = logging.getLogger('ansible logger') self.logger.setLevel(logging.DEBUG)
self.handler = logging.handlers.SysLogHandler( address = (os.getenv('SYSLOG_SERVER','locahost'), os.getenv('SYSLOG_PORT',514)), facility=logging.handlers.SysLogHandler.LOG_USER ) self.logger.addHandler(handler) ....
def runner_on_ok(self, host, res): self.logger.info('RUNNER_ON_OK ' + host + ' ' \
+ json.dumps(res, sort_keys=True))
def runner_on_skipped(self, host, item=None): self.logger.info('RUNNER_ON_SKIPPED ' + host)
#HACK>ansible_eventsosx_say callback plugin
def say(msg, voice): subprocess.call([SAY_CMD, msg, "--voice=%s" % (voice)])
def __init__(self):
# plugin disable itself if say is not present if not os.path.exists(SAY_CMD): self.disabled = True print "%s does not exist, plugin %s disabled" % \ (SAY_CMD, os.path.basename(__file__))
…
def runner_on_failed(self, host, res, ignore_errors=False): say("Failure on host %s" % host, FAILED_VOICE)
def runner_on_ok(self, host, res): say("pew", LASER_VOICE)
________________________________________________ / https://github.com/mpdehaan/ansible-and-juliet \\ / ------------------------------------------------ \ \ ,;;;;;;;, ;;;;;;;;;;;, ;;;;;'_____;' ;;;(/))))|((\ _;;((((((|)))) / |_\\\\\\\\\\\\ .--~( \ ~)))))))))))) / \ `\-(((((((((((\\ | | `\ ) |\ /|) | | `. _/ \_____/ | | , `\~ / | \ \ / | `. `\| / | ~- `\ / \____~._/~ -_, (\ |-----|\ \ ';; | | :;;;' \ | / | | | | |
#HACK>executing tasks- action:
module: <module name>
- action: <module name>
- <module name>:
● optionally ‘local_action’ instead of ‘action’
● module name as a variable {{mymodule}}
#HACK>abstract package- include_vars: “{{ansible_os_distribution|default(‘default’)}}.yml”
- name: install apache
action: “{{ansible_pkg_mgr}} name={{item}} state=present”
with_items: “{{apache_pkgs}}”
- template:
src: “{{apache_config}}.j2”
dest: /etc/{{apache_config}}
owner: “{{apache_user}}”
group: “{{apache_group}}”
notify: “apache_restart”
#HACK>abstract package
Redhat.yml
---
apache_user: httpd
apache_group: httpd
apache_config: /etc/httpd/conf/httpd.conf
apache_pkgs:
- httpd
- mod_ssl
- php-fpm
apache_service: httpd
#HACK>abstract package
Debian.yml
---
apache_user: www-data
apache_group: www-data
apache_config: /etc/apache2/httpd.conf
apache_pkgs:
- apache2-mpm
- libapache2-mod-ssl
- php5-fpm
apache_service: apache2
__________________ / can break \ \ apachectl utils / ------------------ \ \ .--. |o_o | |:_/ | // \ \ (| | ) /'\_ _/`\ \___)=(___/
#THE END>wait 6 && exit
● Ansible was born to play well with Unix
● Roles allow for reuse and sharing
● Plugins are where you code
● Plugins are useful to non programmers.
● callbacks, lookups, filters, etc are also plugins
● Many ways to make Ansible work for you
__________ < goodbye! > ---------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
Top Related